.NET FISHER

专注.NET, Sharepoint, MCMS, WinFX, Ajax....
posts - 12, comments - 28, trackbacks - 0, articles - 1

2006年3月8日

有许多种办法可以判断一个字符串是否为空,如 s == ""; s.Length == 0; s.IsNullOrEmpty(); 等等。那种最好呢?自己试一下吧 (C# 2.0).

using System.Diagnostics;
namespace POC
{
        class Pragram
        {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                TestStringLength();
                Console.WriteLine("------------------");
            }

              Console.Write("Press any key to exit...");
              Console.Read();
        }
        private static void TestStringLength()
        {

            string s = "abc";
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                if (s.Equals("")) ;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);


            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                if (s == "") ;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);

            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                if (s.Length > 0) ;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);

            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                if (s!=null && s.Length > 0) ;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);

            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                if (!string.IsNullOrEmpty(s)) ;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }
        }
}

posted @ 2006-03-08 12:15 FISHER 阅读(2390) 评论(10) 编辑

2005年4月16日

在一个Sharepoint的项目中,需要暂时禁止访问一些网站。因此我做了一webservice完成此功能.代码如下:


[WebMethod]
public bool SuspendSite(string virtualServerUrl, string siteRelativeUrl, bool suspend)
{
 
 Microsoft.SharePoint.Administration.SPGlobalAdmin ga = new Microsoft.SharePoint.Administration.SPGlobalAdmin();
 Microsoft.SharePoint.Administration.SPVirtualServer server = ga.OpenVirtualServer(new Uri(virtualServerUrl));

 if(server == null) return false;

 Microsoft.SharePoint.SPSite spSite = server.Sites[relatedUrl];
 spSite.AllowUnsafeUpdates = true;
    
 spSite.WriteLocked = false;
 spSite.ReadLocked = suspend;
 if(suspend)
 {
  spSite.RootWeb.AllowUnsafeUpdates = true;
  spSite.LockIssue = "Unknown";
 }
 spSite.AllowUnsafeUpdates = false;
 spSite.Close();
 spSite.Dispose();
 return true;
}


要注意几点:
1. 网站必须是顶级网站.
2. 不能从 GetContextSite(Context) 或 new SPSite(url) 得到 SPSite, 必须从SPGlobalAdmin中找出此SPSite,因为此为Global Admin中的功能.否则将有Access Denied的错误.(我也不理解为何要如此,估计是Microsoft的愚蠢吧)
3. WebService的App Pool Account必须有足够的权限.

posted @ 2005-04-16 11:30 FISHER 阅读(1279) 评论(1) 编辑

我们在目前的项目中间使用了Sharepoint Portal作为索引引擎去crawling我们的MCMS (Microsoft Content

Management) 网站上的内容。 MCMS上的内容我们用了一些Meta tag.但是我们发现Sharepoint Portal 搜索引擎在索

引这些Meta Data的时候,不能够很好处理日期类型的Meta Data.例如:

在某些网页上,有一些Meta tag如:

<META content="2005-1-1" name="N.eventstartdate">
<META content="2005-1-20" name="N.eventenddate">


当我们用Sharepoint Search Service,并使用类似

"urn:schemas.microsoft.com:htmlinfo:metainfo:DATE" < GetGMTDate()


的Query语句去查询,得不到任何结果。同样,在Sharepoint Portal的Advanced Search中,也得不到任何结果。

Sharepoint Portal的搜索引擎crawling和Indexing网站或网页内容的时候,使用了一种叫IFilter的技术。例如使用

了nthtml.dll作为HTML IFilter处理HTML的内容。但是,nthtml.dll不能够自动转换类似"2005-1-1"的内容到日期

型.所以用日期型去查询讲得不到任何结果.


在微软的Platform SDK中有一个IFilter的例子叫HTMLProp能很好的处理日期类型的Meta tag.用它来替代nthtml.dll将能解决上述搜索的问题.下面是我安装HTMLProp.dll的步骤:


1. 编译HTMLProp.dll的例子 (在Platform SDK中能找到)

2. 拷贝HTMLProp.dll到 C:\Windows\System32.

3. 拷贝HTMLProp.ini到 C:\Windows\System32.

4. 修改HTMLProp.ini为


n.eventstartdate (VT_FILETIME) = d1b5d3f0-c0b3-11cf-9a92-00a0c908dbf1 n.eventstartdate
n.eventenddate (VT_FILETIME) = d1b5d3f0-c0b3-11cf-9a92-00a0c908dbf1 n.eventenddate


5. 停下Microsoft SharepointPS Search Service和正在clawling的Job.

6. 打开Registry,修改 HKLM\SYSTEM\CurrentControlSet\Control\ContentIndex\DLLsToRegister,加入一行 C:\WINDOWS\system32\htmlprop.dll

7. 运行 "regsvr32.exe %windir%\System32\HtmlProp.dll".

8. 找到HKLM\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\Extension\.htm 和 HKLM\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\Extension\.html,把原值 {E0CA5340-4534-11CF-B952-00AA0051FE20} 替换为 {f4309e80-a1db-11d1-a8fb-00e098006ed3}

9. 察看HKLM\SOFTWARE\Microsoft\SPSSearch\ContentIndexCommon\Filters\CLSID\ 下的所有Key, 把值 {E0CA5340-4534-11CF-B952-00AA0051FE20} 全部替换为 {f4309e80-a1db-11d1-a8fb-00e098006ed3}

10. 在 Sharepoint Portal 的 Site Settings 中, 选择 "Manage Properties of Crawled Content", 删除 urn:schemas.microsoft.com:htmlinfo:metainfo:N.eventstartdate 和 urn:schemas.microsoft.com:htmlinfo:metainfo:N.eventenddate。

11. Reset 所有的 Content Indexes.

12. Full update 所有的 Content Indexes.

13. 在 "Manage Properties of Crawled Content"中,打开 urn:schemas.microsoft.com:htmlinfo:metainfo:N.eventstartdate 和 urn:schemas.microsoft.com:htmlinfo:metainfo:N.eventenddate 并选择 "Included in the Advanced Search".

14. 重新 Reset 和 Full update 所有的 Content Indexes.


日期类型的Metadata 就能够很好的工作了.

posted @ 2005-04-16 01:51 FISHER 阅读(986) 评论(0) 编辑

2005年3月5日

String formatting in C#

I couldn't find a quick reference to .NET string formatting using the String.Format() function, so I created this one.

When I started working with the .NET framework, one thing puzzled me. I couldn't find sprintf(). sprintf() is the C function that takes an output buffer, a format string, and any number of arguments, and builds a string for you. For example:

char szError[256];
sprintf(szError, "Error %d occurred.\n", nError);

This would write "Error 12 occurred." into the szError buffer (assuming nError was 12). It's a basic part of C programming and most C++ programmers still use it though better functionality is available in the STL because sprintf is simple to use and clear. The STL equivalent would be:

str << "Error " << nError << " occurred." << endl;

Or something close to that. It's type-safe, and more OO than sprintf, but not as easy to read and not as easy to localize.

The .NET framework handles strings very nicely - but it takes some getting used to. The rough equivalent of sprintf in .NET is the static String.Format function, which takes a format string and some arguments, and generates an output string. (This is a nice improvement over sprintf since there's no chance you'll overflow the output buffer). For example:

string errorString = String.Format("Error {0} occurred.", nError);

Teeming with metadata, the .NET environment doesn't need the format string to say what type of data you're formatting, just where you want it. (A common sprintf bug is supplying the wrong data type - there's no protection from using %s instead of %d and having your program crash when sprintf is called).

The {0} in the string above is replaced with the value of nError, but what if you want to specify the number of digits to use? Or the base (hexadecimal etc)? The framework supports all this, but where it seemed confusing is that it's not the String.Format function that does the string formatting, but rather the types themselves.

Every object has a method called ToString that returns a string representation of the object. The ToString method can accept a string parameter, which tells the object how to format itself - in the String.Format call, the formatting string is passed after the position, for example, "{0:##}"

The text inside the curly braces is {index[,alignment][:formatString]}. If alignment is positive, the text is right-aligned in a field the given number of spaces; if it's negative, it's left-aligned.

Strings

There really isn't any formatting within a strong, beyond it's alignment. Alignment works for any argument being printed in a String.Format call.

Sample Generates
String.Format("->{1,10}<-", "Hello"); -> Hello<-
String.Format("->{1,-10}<-", "Hello"); ->Hello <-

Numbers

Basic number formatting specifiers:

Specifier Type Format Output (Passed Double 1.42) Output (Passed Int -12400)
c Currency {0:c} $1.42 -$12,400
d Decimal (Whole number) {0:d} System.FormatException -12400
e Scientific {0:e} 1.420000e+000 -1.240000e+004
f Fixed point {0:f} 1.42 -12400.00
g General {0:g} 1.42 -12400
n Number with commas for thousands {0:n} 1.42 -12,400
r Round trippable {0:r} 1.42 System.FormatException
x Hexadecimal {0:x4} System.FormatException cf90

Custom number formatting:

Specifier Type Example Output (Passed Double 1500.42) Note
0 Zero placeholder {0:00.0000} 1500.4200 Pads with zeroes.
# Digit placeholder {0:(#).##} (1500).42
. Decimal point {0:0.0} 1500.4
, Thousand separator {0:0,0} 1,500 Must be between two zeroes.
,. Number scaling {0:0,.} 2 Comma adjacent to Period scales by 1000.
% Percent {0:0%} 150042% Multiplies by 100, adds % sign.
e Exponent placeholder {0:00e+0} 15e+2 Many exponent formats available.
; Group separator see below

The group separator is especially useful for formatting currency values which require that negative values be enclosed in parentheses. This currency formatting example at the bottom of this document makes it obvious:

Dates

Note that date formatting is especially dependant on the system's regional settings; the example strings here are from my local locale.

Specifier Type Example (Passed System.DateTime.Now)
d Short date 10/12/2002
D Long date December 10, 2002
t Short time 10:11 PM
T Long time 10:11:29 PM
f Full date & time December 10, 2002 10:11 PM
F Full date & time (long) December 10, 2002 10:11:29 PM
g Default date & time 10/12/2002 10:11 PM
G Default date & time (long) 10/12/2002 10:11:29 PM
M Month day pattern December 10
r RFC1123 date string Tue, 10 Dec 2002 22:11:29 GMT
s Sortable date string 2002-12-10T22:11:29
u Universal sortable, local time 2002-12-10 22:13:50Z
U Universal sortable, GMT December 11, 2002 3:13:50 AM
Y Year month pattern December, 2002

The 'U' specifier seems broken; that string certainly isn't sortable.

Custom date formatting:

Specifier Type Example Example Output
dd Day {0:dd} 10
ddd Day name {0:ddd} Tue
dddd Full day name {0:dddd} Tuesday
f, ff, ... Second fractions {0:fff} 932
gg, ... Era {0:gg} A.D.
hh 2 digit hour {0:hh} 10
HH 2 digit hour, 24hr format {0:HH} 22
mm Minute 00-59 {0:mm} 38
MM Month 01-12 {0:MM} 12
MMM Month abbreviation {0:MMM} Dec
MMMM Full month name {0:MMMM} December
ss Seconds 00-59 {0:ss} 46
tt AM or PM {0:tt} PM
yy Year, 2 digits {0:yy} 02
yyyy Year {0:yyyy} 2002
zz Timezone offset, 2 digits {0:zz} -05
zzz Full timezone offset {0:zzz} -05:00
: Separator {0:hh:mm:ss} 10:43:20
/ Separator {0:dd/MM/yyyy} 10/12/2002

Enumerations

Specifier Type
g Default (Flag names if available, otherwise decimal)
f Flags always
d Integer always
x Eight digit hex.

Some Useful Examples

String.Format("{0:$#,##0.00;($#,##0.00);Zero}", value);

This will output "$1,240.00" if passed 1243.50. It will output the same format but in parentheses if the number is negative, and will output the string "Zero" if the number is zero.

String.Format("{0:(###) ###-####}", 18005551212);

This will output "(800) 555-1212".

If you have any questions about string formatting, or pretty much anything related, drop by the Forum and ask it there. It's an easier place to talk than in the comments section here.

posted on Thursday, October 16, 2003 4:51 PM

posted @ 2005-03-05 03:01 FISHER 阅读(1460) 评论(1) 编辑

2004年12月15日

NTLM Authentication Scheme for HTTP

Introduction

This is an attempt at documenting the undocumented NTLM authentication scheme used by M$'s browsers, proxies, and servers (MSIE and IIS); this scheme is also sometimes referred to as the NT challenge/response (NTCR) scheme. Most of the info here is derived from three sources (see also the Resources section at the end of this document): Paul Ashton's work on the NTLM security holes, the encryption documentation from Samba, and network snooping. Since most of this info is reverse-engineered it is bound to contain errors; however, at least one client and one server have been implemented according to this data and work successfully in conjunction with M$'s browsers, proxies and servers.

Note that this scheme is not as secure as Digest and some other schemes; it is slightly better than the Basic authentication scheme, however.

Also note that this scheme is not an http authentication scheme - it's a connection authentication scheme which happens to (mis-)use http status codes and headers (and even those incorrectly).

NTLM Handshake

When a client needs to authenticate itself to a proxy or server using the NTLM scheme then the following 4-way handshake takes place (only parts of the request and status line and the relevant headers are shown here; "C" is the client, "S" the server):

    1: C  --> S   GET ...
    
    2: C <--  S   401 Unauthorized
                  WWW-Authenticate: NTLM
    
    3: C  --> S   GET ...
                  Authorization: NTLM <base64-encoded type-1-message>
    
    4: C <--  S   401 Unauthorized
                  WWW-Authenticate: NTLM <base64-encoded type-2-message>
    
    5: C  --> S   GET ...
                  Authorization: NTLM <base64-encoded type-3-message>
    
    6: C <--  S   200 Ok

Messages

The three messages sent in the handshake are binary structures. Each one is described below as a pseudo-C struct and in a memory layout diagram. byte is an 8-bit field; short is a 16-bit field. All fields are unsigned. Numbers are stored in little-endian order. Struct fields named zero contain all zeroes. An array length of "*" indicates a variable length field. Hexadecimal numbers and quoted characters in the comments of the struct indicate fixed values for the given field.

The field flags is presumed to contain flags, but their significance is unknown; the values given are just those found in the packet traces.

Type-1 Message

This message contains the host name and the NT domain name of the client.

    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x01
        byte    zero[3];
        short   flags;           // 0xb203
        byte    zero[2];

        short   dom_len;         // domain string length
        short   dom_len;         // domain string length
        short   dom_off;         // domain string offset
        byte    zero[2];

        short   host_len;        // host string length
        short   host_len;        // host string length
        short   host_off;        // host string offset (always 0x20)
        byte    zero[2];

        byte    host[*];         // host string (ASCII)
        byte    dom[*];          // domain string (ASCII)
    } type-1-message
                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   1   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  | 0x03  | 0xb2  |   0   |   0   |
             +-------+-------+-------+-------+
        16:  | domain length | domain length |
             +-------+-------+-------+-------+
        20:  | domain offset |   0   |   0   |
             +-------+-------+-------+-------+
        24:  |  host length  |  host length  |
             +-------+-------+-------+-------+
        28:  |  host offset  |   0   |   0   |
             +-------+-------+-------+-------+
        32:  |  host string                  |
             +                               +
             .                               .
             .                               .
             +             +-----------------+
             |             | domain string   |
             +-------------+                 +
             .                               .
             .                               .
             +-------+-------+-------+-------+
The host and domain strings are ASCII (or possibly ISO-8859-1), are uppercased, and are not nul-terminated. The host name is only the host name, not the FQDN (e.g. just "GOOFY", not "GOOFY.DISNEY.COM"). The offsets refer to the offset of the specific field within the message, and the lengths are the length of specified field. For example, in the above message host_off = 32 and dom_off = host_off + host_len. Note that the lengths are included twice (for some unfathomable reason).

Type-2 Message

This message contains the server's NTLM challenge.

    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x02
        byte    zero[7];
        short   msg_len;         // 0x28
        byte    zero[2];
        short   flags;           // 0x8201
        byte    zero[2];

        byte    nonce[8];        // nonce
        byte    zero[8];
    } type-2-message
                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   2   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        16:  |  message len  |   0   |   0   |
             +-------+-------+-------+-------+
        20:  | 0x01  | 0x82  |   0   |   0   |
             +-------+-------+-------+-------+
        24:  |                               |
             +          server nonce         |
        28:  |                               |
             +-------+-------+-------+-------+
        32:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        36:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
The nonce is used by the client to create the LanManager and NT responses (see Password Hashes). It is an array of 8 arbitrary bytes. The message length field contains the length of the complete message, which in this case is always 40.

Type-3 Message

This message contains the username, host name, NT domain name, and the two "responses".

    struct {
        byte    protocol[8];     // 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'
        byte    type;            // 0x03
        byte    zero[3];

        short   lm_resp_len;     // LanManager response length (always 0x18)
        short   lm_resp_len;     // LanManager response length (always 0x18)
        short   lm_resp_off;     // LanManager response offset
        byte    zero[2];

        short   nt_resp_len;     // NT response length (always 0x18)
        short   nt_resp_len;     // NT response length (always 0x18)
        short   nt_resp_off;     // NT response offset
        byte    zero[2];

        short   dom_len;         // domain string length
        short   dom_len;         // domain string length
        short   dom_off;         // domain string offset (always 0x40)
        byte    zero[2];

        short   user_len;        // username string length
        short   user_len;        // username string length
        short   user_off;        // username string offset
        byte    zero[2];

        short   host_len;        // host string length
        short   host_len;        // host string length
        short   host_off;        // host string offset
        byte    zero[6];

        short   msg_len;         // message length
        byte    zero[2];

        short   flags;           // 0x8201
        byte    zero[2];

        byte    dom[*];          // domain string (unicode UTF-16LE)
        byte    user[*];         // username string (unicode UTF-16LE)
        byte    host[*];         // host string (unicode UTF-16LE)
        byte    lm_resp[*];      // LanManager response
        byte    nt_resp[*];      // NT response
    } type-3-message
                 0       1       2       3
             +-------+-------+-------+-------+
         0:  |  'N'  |  'T'  |  'L'  |  'M'  |
             +-------+-------+-------+-------+
         4:  |  'S'  |  'S'  |  'P'  |   0   |
             +-------+-------+-------+-------+
         8:  |   3   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        12:  |  LM-resp len  |  LM-Resp len  |
             +-------+-------+-------+-------+
        16:  |  LM-resp off  |   0   |   0   |
             +-------+-------+-------+-------+
        20:  |  NT-resp len  |  NT-Resp len  |
             +-------+-------+-------+-------+
        24:  |  NT-resp off  |   0   |   0   |
             +-------+-------+-------+-------+
        28:  | domain length | domain length |
             +-------+-------+-------+-------+
        32:  | domain offset |   0   |   0   |
             +-------+-------+-------+-------+
        36:  |  user length  |  user length  |
             +-------+-------+-------+-------+
        40:  |  user offset  |   0   |   0   |
             +-------+-------+-------+-------+
        44:  |  host length  |  host length  |
             +-------+-------+-------+-------+
        48:  |  host offset  |   0   |   0   |
             +-------+-------+-------+-------+
        52:  |   0   |   0   |   0   |   0   |
             +-------+-------+-------+-------+
        56:  |  message len  |   0   |   0   |
             +-------+-------+-------+-------+
        60:  | 0x01  | 0x82  |   0   |   0   |
             +-------+-------+-------+-------+
        64:  | domain string                 |
             +                               +
             .                               .
             .                               .
             +           +-------------------+
             |           | user string       |
             +-----------+                   +
             .                               .
             .                               .
             +                 +-------------+
             |                 | host string |
             +-----------------+             +
             .                               .
             .                               .
             +   +---------------------------+
             |   | LanManager-response       |
             +---+                           +
             .                               .
             .                               .
             +            +------------------+
             |            | NT-response      |
             +------------+                  +
             .                               .
             .                               .
             +-------+-------+-------+-------+

The host, domain, and username strings are in Unicode (UTF-16, little-endian) and are not nul-terminated; the host and domain names are in upper case. The lengths of the response strings are 24.

Password Hashes

To calculate the two response strings two password hashes are used: the LanManager password hash and the NT password hash. These are described in detail at the beginning of the Samba ENCRYPTION.html document. However, a few things are not clear (such as what the magic constant for the LanManager hash is), so here is some almost-C code which calculates the two responses. Inputs are passw and nonce, the results are in lm_resp and nt_resp.

    /* setup LanManager password */

    char  lm_pw[14];
    int   len = strlen(passw);
    if (len > 14)  len = 14;

    for (idx=0; idx<len; idx++)
        lm_pw[idx] = toupper(passw[idx]);
    for (; idx<14; idx++)
        lm_pw[idx] = 0;


    /* create LanManager hashed password */

    unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
    unsigned char lm_hpw[21];
    des_key_schedule ks;

    setup_des_key(lm_pw, ks);
    des_ecb_encrypt(magic, lm_hpw, ks);

    setup_des_key(lm_pw+7, ks);
    des_ecb_encrypt(magic, lm_hpw+8, ks);

    memset(lm_hpw+16, 0, 5);


    /* create NT hashed password */

    int   len = strlen(passw);
    char  nt_pw[2*len];
    for (idx=0; idx<len; idx++)
    {
        nt_pw[2*idx]   = passw[idx];
        nt_pw[2*idx+1] = 0;
    }

    unsigned char nt_hpw[21];
    MD4_CTX context;
    MD4Init(&context);
    MD4Update(&context, nt_pw, 2*len);
    MD4Final(nt_hpw, &context);

    memset(nt_hpw+16, 0, 5);


    /* create responses */

    unsigned char lm_resp[24], nt_resp[24];
    calc_resp(lm_hpw, nonce, lm_resp);
    calc_resp(nt_hpw, nonce, nt_resp);

Helpers:

    /*
     * takes a 21 byte array and treats it as 3 56-bit DES keys. The
     * 8 byte plaintext is encrypted with each key and the resulting 24
     * bytes are stored in the results array.
     */
    void calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
    {
        des_key_schedule ks;

        setup_des_key(keys, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) results, ks, DES_ENCRYPT);

        setup_des_key(keys+7, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+8), ks, DES_ENCRYPT);

        setup_des_key(keys+14, ks);
        des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+16), ks, DES_ENCRYPT);
    }


    /*
     * turns a 56 bit key into the 64 bit, odd parity key and sets the key.
     * The key schedule ks is also set.
     */
    void setup_des_key(unsigned char key_56[], des_key_schedule ks)
    {
        des_cblock key;

        key[0] = key_56[0];
        key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
        key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
        key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
        key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
        key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
        key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
        key[7] =  (key_56[6] << 1) & 0xFF;

        des_set_odd_parity(&key);
        des_set_key(&key, ks);
    }

Keeping the connection alive

As mentioned above, this scheme authenticates connections, not requests. This manifests itself in that the network connection must be kept alive during the second part of the handshake, i.e. between the receiving of the type-2 message from the server (step 4) and the sending of the type-3 message (step 5). Each time the connection is closed this second part (steps 3 through 6) must be repeated over the new connection (i.e. it's not enough to just keep sending the last type-3 message). Also, once the connection is authenticated, the Authorization header need not be sent anymore while the connection stays open, no matter what resource is accessed.

For implementations wishing to work with M$'s software this means that they must make sure they use either HTTP/1.0 keep-alive's or HTTP/1.1 persistent connections, and that they must be prepared to do the second part of the handshake each time the connection was closed and is reopened. Server implementations must also make sure that HTTP/1.0 responses contain a Content-length header (as otherwise the connection must be closed after the response), and that HTTP/1.1 responses either contain a Content-length header or use the chunked transfer encoding.

Example

Here is an actual example of all the messages. Assume the host name is "LightCity", the NT domain name is "Ursa-Minor", the username is "Zaphod", the password is "Beeblebrox", and the server sends the nonce "SrvNonce". Then the handshake is:

    C -> S   GET ...
    
    S -> C   401 Unauthorized
             WWW-Authenticate: NTLM
    
    C -> S   GET ...
             Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
    
    S -> C   401 Unauthorized
             WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
    
    C -> S   GET ...
             Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
    
    S -> C   200 Ok

and the unencoded messages are:

Type-1 Message:

       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 01 00 00 00 03 b2 00 00  "NTLMSSP........."
  10:  0a 00 0a 00 29 00 00 00 09 00 09 00 20 00 00 00  "....)....... ..."
  20:  4c 49 47 48 54 43 49 54 59 55 52 53 41 2d 4d 49  "LIGHTCITYURSA-MI"
  30:  4e 4f 52                                         "NOR"

Type-2 Message:

       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 02 00 00 00 00 00 00 00  "NTLMSSP........."
  10:  28 00 00 00 01 82 00 00 53 72 76 4e 6f 6e 63 65  "(.......SrvNonce"
  20:  00 00 00 00 00 00 00 00                          "........"

Type-3 Message:

       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
   0:  4e 54 4c 4d 53 53 50 00 03 00 00 00 18 00 18 00  "NTLMSSP........."
  10:  72 00 00 00 18 00 18 00 8a 00 00 00 14 00 14 00  "r..............."
  20:  40 00 00 00 0c 00 0c 00 54 00 00 00 12 00 12 00  "@.......T......."
  30:  60 00 00 00 00 00 00 00 a2 00 00 00 01 82 00 00  "`..............."
  40:  55 00 52 00 53 00 41 00 2d 00 4d 00 49 00 4e 00  "U.R.S.A.-.M.I.N."
  50:  4f 00 52 00 5a 00 61 00 70 00 68 00 6f 00 64 00  "O.R.Z.a.p.h.o.d."
  60:  4c 00 49 00 47 00 48 00 54 00 43 00 49 00 54 00  "L.I.G.H.T.C.I.T."
  70:  59 00 ad 87 ca 6d ef e3 46 85 b9 c4 3c 47 7a 8c  "Y....m..F...<Gz."
  80:  42 d6 00 66 7d 68 92 e7 e8 97 e0 e0 0d e3 10 4a  "B..f}h.........J"
  90:  1b f2 05 3f 07 c7 dd a8 2d 3c 48 9a e9 89 e1 b0  "...?....-<H....."
  a0:  00 d3                                            ".."

For reference, the intermediate hashed passwords are:

lm_hpw (LanManager hashed password):
91 90 16 f6 4e c7 b0 0b a2 35 02 8c a5 0c 7a 03 00 00 00 00 00
nt_hpw (NT hashed password):
8c 1b 59 e3 2e 66 6d ad f1 75 74 5f ad 62 c1 33 00 00 00 00 00

posted @ 2004-12-15 06:10 FISHER 阅读(871) 评论(0) 编辑

2004年12月14日

http://blogs.msdn.com/bowerm/articles/211757.aspx

posted @ 2004-12-14 23:47 FISHER 阅读(838) 评论(1) 编辑

2004年11月30日

摘要: *** Problem Description ***Customer wanted to implement ASP.NET forms authentication across his entire web app which consisted of ASP.NET *and* classic ASP content.<><><><><...阅读全文

posted @ 2004-11-30 23:40 FISHER 阅读(634) 评论(1) 编辑

摘要: A useful actical for web part development basichttp://www.devx.com/dotnet/Article/17518/0/page/1 sharepoint securityhttp://www.15seconds.com/issue/040511.htm object model security In a comment to my p...阅读全文

posted @ 2004-11-30 01:45 FISHER 阅读(650) 评论(1) 编辑

摘要: Running an application command line with different credentialsrunas /user:Administrator program.exe Enabling ASP.NET to run as another user on Windows XP ProfessionalAs an Administrator, edit the attr...阅读全文

posted @ 2004-11-30 00:57 FISHER 阅读(464) 评论(0) 编辑

2004年11月26日

摘要: Sharepoint是一种非常新而且很有用的技术. 现在微软把基本的功能集成到了Windows 2003 Server里, 那就是Windows Sharepoint Service简称WSS. 他使开发个性化的复杂的应用程序变得非常简单. 在我的经验里, Sharepoint的开发主要分为三部分: 定制(customization), Web Part, 配置和集成. (这里不包括Sharepo...阅读全文

posted @ 2004-11-26 14:03 FISHER 阅读(1778) 评论(1) 编辑