00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define _CRT_SECURE_NO_DEPRECATE
00043
00044
00045 #include "ntlm.h"
00046 #include "misc.h"
00047
00048 #define WORD unsigned short
00049
00050
00051
00052 #ifndef _BYTEORDER_H
00053 #define _BYTEORDER_H
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 #define RW_PCVAL(read,inbuf,outbuf,len) \
00130 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
00131 else { PSCVAL(inbuf,0,outbuf,len); } }
00132
00133 #define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
00134 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
00135 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
00136
00137 #define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
00138 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
00139 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
00140
00141 #define RW_CVAL(read, inbuf, outbuf, offset) \
00142 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
00143 else { SCVAL(inbuf,offset,outbuf); } }
00144
00145 #define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
00146 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
00147 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
00148
00149 #define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
00150 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
00151 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
00152
00153 #undef CAREFUL_ALIGNMENT
00154
00155
00156
00157 #ifdef __i386__
00158 #define CAREFUL_ALIGNMENT 0
00159 #endif
00160
00161 #ifndef CAREFUL_ALIGNMENT
00162 #define CAREFUL_ALIGNMENT 1
00163 #endif
00164
00165 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
00166 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
00167 #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
00168
00169
00170 #if CAREFUL_ALIGNMENT
00171
00172 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
00173 #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
00174 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
00175 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
00176 #define SVALS(buf,pos) ((int16)SVAL(buf,pos))
00177 #define IVALS(buf,pos) ((int32)IVAL(buf,pos))
00178 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
00179 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
00180 #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
00181 #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
00182
00183 #else
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 #define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
00194 #define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
00195 #define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
00196 #define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
00197
00198
00199 #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val))
00200 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
00201 #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val))
00202 #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val))
00203
00204 #endif
00205
00206
00207
00208 #define SMBMACRO(macro,buf,pos,val,len,size) \
00209 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
00210
00211 #define SSMBMACRO(macro,buf,pos,val,len,size) \
00212 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
00213
00214
00215 #define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
00216 #define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
00217 #define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
00218 #define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
00219 #define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
00220 #define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
00221
00222
00223 #define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
00224 #define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
00225 #define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
00226 #define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
00227 #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
00228 #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
00229
00230
00231
00232 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
00233 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
00234
00235 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))
00236 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))
00237 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))
00238 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))
00239 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
00240 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
00241 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
00242 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
00243
00244
00245 #define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
00246 #define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
00247 #define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
00248 #define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
00249
00250
00251 #define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
00252 #define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
00253 #define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
00254 #define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
00255
00256 #define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
00257 { RW_PCVAL(read,inbuf,outbuf,len) \
00258 DEBUG(5,("%s%04x %s: ", \
00259 tab_depth(depth), base,string)); \
00260 if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
00261 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
00262 DEBUG(5,("\n")); }
00263
00264 #define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
00265 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
00266 DEBUG(5,("%s%04x %s: ", \
00267 tab_depth(depth), base,string)); \
00268 if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
00269 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
00270 DEBUG(5,("\n")); }
00271
00272 #define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
00273 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
00274 DEBUG(5,("%s%04x %s: ", \
00275 tab_depth(depth), base,string)); \
00276 if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
00277 { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
00278 DEBUG(5,("\n")); }
00279
00280 #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
00281 { RW_CVAL(read,inbuf,outbuf,0) \
00282 DEBUG(5,("%s%04x %s: %02x\n", \
00283 tab_depth(depth), base, string, outbuf)); }
00284
00285 #define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
00286 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
00287 DEBUG(5,("%s%04x %s: %04x\n", \
00288 tab_depth(depth), base, string, outbuf)); }
00289
00290 #define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
00291 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
00292 DEBUG(5,("%s%04x %s: %08x\n", \
00293 tab_depth(depth), base, string, outbuf)); }
00294
00295 #endif
00296
00297
00298
00299
00300
00301
00302
00303
00304 static uint32 A, B, C, D;
00305
00306 static uint32 F(uint32 X, uint32 Y, uint32 Z)
00307 {
00308 return (X&Y) | ((~X)&Z);
00309 }
00310
00311 static uint32 G(uint32 X, uint32 Y, uint32 Z)
00312 {
00313 return (X&Y) | (X&Z) | (Y&Z);
00314 }
00315
00316 static uint32 H(uint32 X, uint32 Y, uint32 Z)
00317 {
00318 return X^Y^Z;
00319 }
00320
00321 static uint32 lshift(uint32 x, int s)
00322 {
00323 x &= 0xFFFFFFFF;
00324 return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
00325 }
00326
00327 #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
00328 #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
00329 #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
00330
00331
00332 static void mdfour64(uint32 *M)
00333 {
00334 int j;
00335 uint32 AA, BB, CC, DD;
00336 uint32 X[16];
00337
00338 for (j=0;j<16;j++)
00339 X[j] = M[j];
00340
00341 AA = A; BB = B; CC = C; DD = D;
00342
00343 ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
00344 ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
00345 ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
00346 ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
00347 ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
00348 ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
00349 ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
00350 ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
00351
00352 ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
00353 ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
00354 ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
00355 ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
00356 ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
00357 ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
00358 ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
00359 ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
00360
00361 ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
00362 ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
00363 ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
00364 ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
00365 ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
00366 ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
00367 ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
00368 ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
00369
00370 A += AA; B += BB; C += CC; D += DD;
00371
00372 A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
00373 C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
00374
00375 for (j=0;j<16;j++)
00376 X[j] = 0;
00377 }
00378
00379 static void copy64(uint32 *M, unsigned char *in)
00380 {
00381 int i;
00382
00383 for (i=0;i<16;i++)
00384 M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
00385 (in[i*4+1]<<8) | (in[i*4+0]<<0);
00386 }
00387
00388 static void copy4(unsigned char *out,uint32 x)
00389 {
00390 out[0] = x&0xFF;
00391 out[1] = (x>>8)&0xFF;
00392 out[2] = (x>>16)&0xFF;
00393 out[3] = (x>>24)&0xFF;
00394 }
00395
00396
00397 void mdfour(unsigned char *out, unsigned char *in, int n)
00398 {
00399 unsigned char buf[128];
00400 uint32 M[16];
00401 uint32 b = n * 8;
00402 int i;
00403
00404 A = 0x67452301;
00405 B = 0xefcdab89;
00406 C = 0x98badcfe;
00407 D = 0x10325476;
00408
00409 while (n > 64) {
00410 copy64(M, in);
00411 mdfour64(M);
00412 in += 64;
00413 n -= 64;
00414 }
00415
00416 for (i=0;i<128;i++)
00417 buf[i] = 0;
00418 memcpy(buf, in, n);
00419 buf[n] = 0x80;
00420
00421 if (n <= 55) {
00422 copy4(buf+56, b);
00423 copy64(M, buf);
00424 mdfour64(M);
00425 } else {
00426 copy4(buf+120, b);
00427 copy64(M, buf);
00428 mdfour64(M);
00429 copy64(M, buf+64);
00430 mdfour64(M);
00431 }
00432
00433 for (i=0;i<128;i++)
00434 buf[i] = 0;
00435 copy64(M, buf);
00436
00437 copy4(out, A);
00438 copy4(out+4, B);
00439 copy4(out+8, C);
00440 copy4(out+12, D);
00441
00442 A = B = C = D = 0;
00443 }
00444
00445
00446
00447 #define uchar unsigned char
00448 #define int16 signed short
00449 typedef int BOOL;
00450 #define False 0
00451 #define True 1
00452
00453 static uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9,
00454 1, 58, 50, 42, 34, 26, 18,
00455 10, 2, 59, 51, 43, 35, 27,
00456 19, 11, 3, 60, 52, 44, 36,
00457 63, 55, 47, 39, 31, 23, 15,
00458 7, 62, 54, 46, 38, 30, 22,
00459 14, 6, 61, 53, 45, 37, 29,
00460 21, 13, 5, 28, 20, 12, 4};
00461
00462 static uchar perm2[48] = {14, 17, 11, 24, 1, 5,
00463 3, 28, 15, 6, 21, 10,
00464 23, 19, 12, 4, 26, 8,
00465 16, 7, 27, 20, 13, 2,
00466 41, 52, 31, 37, 47, 55,
00467 30, 40, 51, 45, 33, 48,
00468 44, 49, 39, 56, 34, 53,
00469 46, 42, 50, 36, 29, 32};
00470
00471 static uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
00472 60, 52, 44, 36, 28, 20, 12, 4,
00473 62, 54, 46, 38, 30, 22, 14, 6,
00474 64, 56, 48, 40, 32, 24, 16, 8,
00475 57, 49, 41, 33, 25, 17, 9, 1,
00476 59, 51, 43, 35, 27, 19, 11, 3,
00477 61, 53, 45, 37, 29, 21, 13, 5,
00478 63, 55, 47, 39, 31, 23, 15, 7};
00479
00480 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
00481 4, 5, 6, 7, 8, 9,
00482 8, 9, 10, 11, 12, 13,
00483 12, 13, 14, 15, 16, 17,
00484 16, 17, 18, 19, 20, 21,
00485 20, 21, 22, 23, 24, 25,
00486 24, 25, 26, 27, 28, 29,
00487 28, 29, 30, 31, 32, 1};
00488
00489 static uchar perm5[32] = { 16, 7, 20, 21,
00490 29, 12, 28, 17,
00491 1, 15, 23, 26,
00492 5, 18, 31, 10,
00493 2, 8, 24, 14,
00494 32, 27, 3, 9,
00495 19, 13, 30, 6,
00496 22, 11, 4, 25};
00497
00498
00499 static uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
00500 39, 7, 47, 15, 55, 23, 63, 31,
00501 38, 6, 46, 14, 54, 22, 62, 30,
00502 37, 5, 45, 13, 53, 21, 61, 29,
00503 36, 4, 44, 12, 52, 20, 60, 28,
00504 35, 3, 43, 11, 51, 19, 59, 27,
00505 34, 2, 42, 10, 50, 18, 58, 26,
00506 33, 1, 41, 9, 49, 17, 57, 25};
00507
00508
00509 static uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
00510
00511 static uchar sbox[8][4][16] = {
00512 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
00513 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
00514 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
00515 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
00516
00517 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
00518 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
00519 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
00520 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
00521
00522 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
00523 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
00524 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
00525 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
00526
00527 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
00528 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
00529 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
00530 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
00531
00532 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
00533 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
00534 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
00535 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
00536
00537 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
00538 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
00539 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
00540 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
00541
00542 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
00543 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
00544 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
00545 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
00546
00547 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
00548 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
00549 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
00550 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
00551
00552 static void permute(char *out, char *in, uchar *p, int n)
00553 {
00554 int i;
00555 for (i=0;i<n;i++)
00556 out[i] = in[p[i]-1];
00557 }
00558
00559 static void l_shift(char *d, int count, int n)
00560 {
00561 char out[64];
00562 int i;
00563 for (i=0;i<n;i++)
00564 out[i] = d[(i+count)%n];
00565 for (i=0;i<n;i++)
00566 d[i] = out[i];
00567 }
00568
00569 static void concat(char *out, char *in1, char *in2, int l1, int l2)
00570 {
00571 while (l1--)
00572 *out++ = *in1++;
00573 while (l2--)
00574 *out++ = *in2++;
00575 }
00576
00577 static void xorFunction(char *out, char *in1, char *in2, int n)
00578 {
00579
00580 int i;
00581 for (i=0; i < n; i++)
00582 out[i] = in1[i] ^ in2[i];
00583
00584 }
00585
00586 static void dohash(char *out, char *in, char *key, int forw)
00587 {
00588 int i, j, k;
00589 char pk1[56];
00590 char c[28];
00591 char d[28];
00592 char cd[56];
00593 char ki[16][48];
00594 char pd1[64];
00595 char l[32], r[32];
00596 char rl[64];
00597
00598
00599 permute(pk1, key, perm1, 56);
00600
00601 for (i=0;i<28;i++)
00602 c[i] = pk1[i];
00603 for (i=0;i<28;i++)
00604 d[i] = pk1[i+28];
00605
00606 for (i=0;i<16;i++) {
00607 l_shift(c, sc[i], 28);
00608 l_shift(d, sc[i], 28);
00609
00610 concat(cd, c, d, 28, 28);
00611 permute(ki[i], cd, perm2, 48);
00612 }
00613
00614 permute(pd1, in, perm3, 64);
00615
00616 for (j=0;j<32;j++) {
00617 l[j] = pd1[j];
00618 r[j] = pd1[j+32];
00619 }
00620
00621 for (i=0;i<16;i++) {
00622 char er[48];
00623 char erk[48];
00624 char b[8][6];
00625 char cb[32];
00626 char pcb[32];
00627 char r2[32];
00628
00629 permute(er, r, perm4, 48);
00630
00631 xorFunction(erk, er, ki[(forw ? i : 15 - i)], 48);
00632
00633 for (j=0;j<8;j++)
00634 for (k=0;k<6;k++)
00635 b[j][k] = erk[j*6 + k];
00636
00637 for (j=0;j<8;j++) {
00638 int m, n;
00639 m = (b[j][0]<<1) | b[j][5];
00640
00641 n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
00642
00643 for (k=0;k<4;k++)
00644 b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
00645 }
00646
00647 for (j=0;j<8;j++)
00648 for (k=0;k<4;k++)
00649 cb[j*4+k] = b[j][k];
00650
00651 permute(pcb, cb, perm5, 32);
00652
00653 xorFunction( r2, l, pcb, 32);
00654
00655 for (j=0;j<32;j++)
00656 l[j] = r[j];
00657
00658 for (j=0;j<32;j++)
00659 r[j] = r2[j];
00660 }
00661
00662 concat(rl, r, l, 32, 32);
00663
00664 permute(out, rl, perm6, 64);
00665 }
00666
00667 static void str_to_key(unsigned char *str,unsigned char *key)
00668 {
00669 int i;
00670
00671 key[0] = str[0]>>1;
00672 key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
00673 key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
00674 key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
00675 key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
00676 key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
00677 key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
00678 key[7] = str[6]&0x7F;
00679 for (i=0;i<8;i++) {
00680 key[i] = (key[i]<<1);
00681 }
00682 }
00683
00684
00685 static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
00686 {
00687 int i;
00688 char outb[64];
00689 char inb[64];
00690 char keyb[64];
00691 unsigned char key2[8];
00692
00693 str_to_key(key, key2);
00694
00695 for (i=0;i<64;i++) {
00696 inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
00697 keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
00698 outb[i] = 0;
00699 }
00700
00701 dohash(outb, inb, keyb, forw);
00702
00703 for (i=0;i<8;i++) {
00704 out[i] = 0;
00705 }
00706
00707 for (i=0;i<64;i++) {
00708 if (outb[i])
00709 out[i/8] |= (1<<(7-(i%8)));
00710 }
00711 }
00712
00713 void E_P16(unsigned char *p14,unsigned char *p16)
00714 {
00715 unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
00716 smbhash(p16, sp8, p14, 1);
00717 smbhash(p16+8, sp8, p14+7, 1);
00718 }
00719
00720 void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
00721 {
00722 smbhash(p24, c8, p21, 1);
00723 smbhash(p24+8, c8, p21+7, 1);
00724 smbhash(p24+16, c8, p21+14, 1);
00725 }
00726
00727 void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
00728 {
00729 smbhash(out, in, p14, 0);
00730 smbhash(out+8, in+8, p14+7, 0);
00731 }
00732
00733 void E_old_pw_hash( unsigned char *p14, unsigned char *in, unsigned char *out)
00734 {
00735 smbhash(out, in, p14, 1);
00736 smbhash(out+8, in+8, p14+7, 1);
00737 }
00738
00739 void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
00740 {
00741 unsigned char buf[8];
00742
00743 smbhash(buf, in, key, 1);
00744 smbhash(out, buf, key+9, 1);
00745 }
00746
00747 void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
00748 {
00749 unsigned char buf[8];
00750 static unsigned char key2[8];
00751
00752 smbhash(buf, in, key, 1);
00753 key2[0] = key[7];
00754 smbhash(out, buf, key2, 1);
00755 }
00756
00757 void cred_hash3(unsigned char *out,unsigned char *in,unsigned char *key, int forw)
00758 {
00759 static unsigned char key2[8];
00760
00761 smbhash(out, in, key, forw);
00762 key2[0] = key[7];
00763 smbhash(out + 8, in + 8, key2, forw);
00764 }
00765
00766 void SamOEMhash( unsigned char *data, unsigned char *key, int val)
00767 {
00768 unsigned char s_box[256];
00769 unsigned char index_i = 0;
00770 unsigned char index_j = 0;
00771 unsigned char j = 0;
00772 int ind;
00773
00774 for (ind = 0; ind < 256; ind++)
00775 {
00776 s_box[ind] = (unsigned char)ind;
00777 }
00778
00779 for( ind = 0; ind < 256; ind++)
00780 {
00781 unsigned char tc;
00782
00783 j += (s_box[ind] + key[ind%16]);
00784
00785 tc = s_box[ind];
00786 s_box[ind] = s_box[j];
00787 s_box[j] = tc;
00788 }
00789 for( ind = 0; ind < (val ? 516 : 16); ind++)
00790 {
00791 unsigned char tc;
00792 unsigned char t;
00793
00794 index_i++;
00795 index_j += s_box[index_i];
00796
00797 tc = s_box[index_i];
00798 s_box[index_i] = s_box[index_j];
00799 s_box[index_j] = tc;
00800
00801 t = s_box[index_i] + s_box[index_j];
00802 data[ind] = data[ind] ^ s_box[t];
00803 }
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 char *StrnCpy(char *dest,const char *src, size_t n)
00815 {
00816 char *d = dest;
00817 if (!dest) return(NULL);
00818 if (!src) {
00819 *dest = 0;
00820 return(dest);
00821 }
00822 while (n-- && (*d++ = *src++)) ;
00823 *d = 0;
00824 return(dest);
00825 }
00826
00827 size_t skip_multibyte_char(char c)
00828 {
00829 return 0;
00830 }
00831
00832
00833
00834
00835
00836
00837 #define DEBUG(a,b) ;
00838 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
00839 {
00840 size_t len;
00841
00842 if (!dest) {
00843 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
00844 return NULL;
00845 }
00846
00847 if (!src) {
00848 *dest = 0;
00849 return dest;
00850 }
00851
00852 len = strlen(src);
00853
00854 if (len > maxlength) {
00855 DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
00856 (int)(len-maxlength), src));
00857 len = maxlength;
00858 }
00859
00860 memcpy(dest, src, len);
00861 dest[len] = 0;
00862 return dest;
00863 }
00864
00865
00866 void strupper(char *s)
00867 {
00868 while (*s)
00869 {
00870 {
00871 size_t skip = skip_multibyte_char( *s );
00872 if( skip != 0 )
00873 s += skip;
00874 else
00875 {
00876 if (islower(*s))
00877 *s = toupper(*s);
00878 s++;
00879 }
00880 }
00881 }
00882 }
00883
00884 extern void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]);
00885
00886
00887
00888
00889
00890
00891
00892 void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
00893 {
00894 uchar p14[15], p21[21];
00895
00896 memset(p21,'\0',21);
00897 memset(p14,'\0',14);
00898 StrnCpy((char *)p14,(char *)passwd,14);
00899
00900 strupper((char *)p14);
00901 E_P16(p14, p21);
00902
00903 SMBOWFencrypt(p21, c8, p24);
00904
00905 #ifdef DEBUG_PASSWORD
00906 DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
00907 dump_data(100, (char *)p21, 16);
00908 dump_data(100, (char *)c8, 8);
00909 dump_data(100, (char *)p24, 24);
00910 #endif
00911 }
00912
00913
00914 static int _my_wcslen(int16 *str)
00915 {
00916 int len = 0;
00917 while(*str++ != 0)
00918 len++;
00919 return len;
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929 static int _my_mbstowcs(int16 *dst, uchar *src, int len)
00930 {
00931 int i;
00932 int16 val;
00933
00934 for(i = 0; i < len; i++) {
00935 val = *src;
00936 SSVAL(dst,0,val);
00937 dst++;
00938 src++;
00939 if(val == 0)
00940 break;
00941 }
00942 return i;
00943 }
00944
00945
00946
00947
00948
00949 void E_md4hash(uchar *passwd, uchar *p16)
00950 {
00951 int len;
00952 int16 wpwd[129];
00953
00954
00955 len = (int) strlen((char *)passwd);
00956 if(len > 128)
00957 len = 128;
00958
00959 _my_mbstowcs(wpwd, passwd, len);
00960 wpwd[len] = 0;
00961
00962 len = _my_wcslen(wpwd) * sizeof(int16);
00963
00964 mdfour(p16, (unsigned char *)wpwd, len);
00965 }
00966
00967
00968 void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16])
00969 {
00970 char passwd[130];
00971
00972 memset(passwd,'\0',130);
00973 safe_strcpy( passwd, pwd, sizeof(passwd)-1);
00974
00975
00976 memset(nt_p16, '\0', 16);
00977 E_md4hash((uchar *)passwd, nt_p16);
00978
00979 #ifdef DEBUG_PASSWORD
00980 DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
00981 dump_data(120, passwd, strlen(passwd));
00982 dump_data(100, (char *)nt_p16, 16);
00983 #endif
00984
00985
00986 passwd[14] = '\0';
00987 strupper(passwd);
00988
00989
00990
00991 memset(p16, '\0', 16);
00992 E_P16((uchar *) passwd, (uchar *)p16);
00993
00994 #ifdef DEBUG_PASSWORD
00995 DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
00996 dump_data(120, passwd, strlen(passwd));
00997 dump_data(100, (char *)p16, 16);
00998 #endif
00999
01000 memset(passwd, '\0', sizeof(passwd));
01001 }
01002
01003
01004 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
01005 {
01006 uchar p21[21];
01007
01008 memset(p21,'\0',21);
01009
01010 memcpy(p21, passwd, 16);
01011 E_P24(p21, c8, p24);
01012 }
01013
01014
01015 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
01016 {
01017 uchar p21[21];
01018
01019 memset(p21,'\0',21);
01020 memcpy(p21, passwd, 8);
01021 memset(p21 + 8, 0xbd, 8);
01022
01023 E_P24(p21, ntlmchalresp, p24);
01024 #ifdef DEBUG_PASSWORD
01025 DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n"));
01026 dump_data(100, (char *)p21, 21);
01027 dump_data(100, (char *)ntlmchalresp, 8);
01028 dump_data(100, (char *)p24, 24);
01029 #endif
01030 }
01031
01032
01033
01034
01035 void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
01036 {
01037 uchar p21[21];
01038
01039 memset(p21,'\0',21);
01040
01041 E_md4hash(passwd, p21);
01042 SMBOWFencrypt(p21, c8, p24);
01043
01044 #ifdef DEBUG_PASSWORD
01045 DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
01046 dump_data(100, (char *)p21, 16);
01047 dump_data(100, (char *)c8, 8);
01048 dump_data(100, (char *)p24, 24);
01049 #endif
01050 }
01051
01052 #if 0
01053
01054 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
01055 {
01056 int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
01057
01058 if (new_pw_len > 512)
01059 {
01060 DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
01061 return False;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070 generate_random_buffer((unsigned char *)data, 516, False);
01071 if (unicode)
01072 {
01073 struni2( &data[512 - new_pw_len], passwd);
01074 }
01075 else
01076 {
01077 fstrcpy( &data[512 - new_pw_len], passwd);
01078 }
01079 SIVAL(data, 512, new_pw_len);
01080
01081 #ifdef DEBUG_PASSWORD
01082 DEBUG(100,("make_oem_passwd_hash\n"));
01083 dump_data(100, data, 516);
01084 #endif
01085 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
01086
01087 return True;
01088 }
01089
01090 #endif
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 #define AddBytes(ptr, header, buf, count) \
01124 { \
01125 if (buf && count) \
01126 { \
01127 SSVAL(&ptr->header.len,0,count); \
01128 SSVAL(&ptr->header.maxlen,0,count); \
01129 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8*)ptr)) + ptr->bufIndex)); \
01130 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
01131 ptr->bufIndex += count; \
01132 } \
01133 else \
01134 { \
01135 ptr->header.len = \
01136 ptr->header.maxlen = 0; \
01137 SIVAL(&ptr->header.offset,0,ptr->bufIndex); \
01138 } \
01139 }
01140
01141 #define AddString(ptr, header, string) \
01142 { \
01143 char *p = string; \
01144 int len = 0; \
01145 if (p) len = strlen(p); \
01146 AddBytes(ptr, header, ((unsigned char*)p), len); \
01147 }
01148
01149 #define AddUnicodeString(ptr, header, string) \
01150 { \
01151 char *p = string; \
01152 unsigned char *b = NULL; \
01153 int len = 0; \
01154 if (p) \
01155 { \
01156 len = strlen(p); \
01157 b = strToUnicode(p); \
01158 } \
01159 AddBytes(ptr, header, b, len*2); \
01160 }
01161
01162
01163 #define GetUnicodeString(structPtr, header) \
01164 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
01165 #define GetString(structPtr, header) \
01166 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
01167 #define DumpBuffer(fp, structPtr, header) \
01168 dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
01169
01170
01171 static void dumpRaw(FILE *fp, unsigned char *buf, size_t len)
01172 {
01173 int i;
01174
01175 for (i=0; i<(signed int)len; ++i)
01176 printf("%02x ",buf[i]);
01177
01178 printf("\n");
01179 }
01180
01181 static char *unicodeToString(char *p, size_t len)
01182 {
01183 int i;
01184 static char buf[16384];
01185
01186 assert(len+1 < sizeof buf);
01187
01188 for (i=0; i<(signed int)len; ++i)
01189 {
01190 buf[i] = *p & 0x7f;
01191 p += 2;
01192 }
01193
01194 buf[i] = '\0';
01195 return buf;
01196 }
01197
01198 static unsigned char *strToUnicode(char *p)
01199 {
01200 static unsigned char buf[16384];
01201 size_t l = strlen(p);
01202 int i = 0;
01203
01204 assert(l*2 < sizeof buf);
01205
01206 while (l--)
01207 {
01208 buf[i++] = *p++;
01209 buf[i++] = 0;
01210 }
01211
01212 return buf;
01213 }
01214
01215 static unsigned char *toString(char *p, size_t len)
01216 {
01217 static unsigned char buf[16384];
01218
01219 assert(len+1 < sizeof buf);
01220
01221 memcpy(buf,p,len);
01222 buf[len] = 0;
01223 return buf;
01224 }
01225
01226
01227
01228
01229 void BuildAuthRequest(tSmbNtlmAuthRequest *request, long flags, char *host, char *domain)
01230 {
01231 char *h = NULL;
01232 char *p = NULL;
01233
01234
01235 if (host == NULL) host = "";
01236 if (domain == NULL) domain = "";
01237
01238 h = _strdup(host);
01239 p = strchr(h,'@');
01240 if (p)
01241 {
01242 if (!domain)
01243 domain = p+1;
01244 *p = '\0';
01245 }
01246 if (flags ==0) flags = 0x0000b207;
01247 request->bufIndex = 0;
01248 memcpy(request->ident,"NTLMSSP\0\0\0",8);
01249 SIVAL(&request->msgType,0,1);
01250 SIVAL(&request->flags,0,flags);
01251
01252 assert(strlen(host) < 128);
01253 AddString(request,host,h);
01254 assert(strlen(domain) < 128);
01255 AddString(request,domain,domain);
01256 free(h);
01257 }
01258
01259 #include <openssl/md4.h>
01260 #include <openssl/des.h>
01261 #ifdef WIN32
01262 #pragma comment(lib, "libeay32.lib")
01263 #pragma comment(lib, "ssleay32.lib")
01264 #endif
01265
01266
01267
01268
01269
01270 void setup_des_key(unsigned char key_56[], des_key_schedule ksch){
01271 des_cblock key;
01272
01273 key[0] = key_56[0];
01274 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
01275 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
01276 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
01277 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
01278 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
01279 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
01280 key[7] = (key_56[6] << 1) & 0xFF;
01281
01282 des_set_odd_parity(&key);
01283 des_set_key(&key, ksch);
01284 }
01285
01286
01287
01288
01289
01290
01291 void calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results){
01292 des_key_schedule ks;
01293
01294 setup_des_key(keys, ks);
01295 des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) results, ks, DES_ENCRYPT);
01296
01297 setup_des_key(keys+7, ks);
01298 des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+8), ks, DES_ENCRYPT);
01299
01300 setup_des_key(keys+14, ks);
01301 des_ecb_encrypt((des_cblock*) plaintext, (des_cblock*) (results+16), ks, DES_ENCRYPT);
01302 }
01303 void buildAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, long flags, char *user, char *password, char *domainname, char *host, tSmbNtlmAuthResponse* OptionalNtlmPacket3)
01304 {
01305
01306
01307
01308 uint8 lmRespData[24];
01309 uint8 ntRespData[24];
01310 char *u = _strdup(user);
01311 char *p = strchr(u,'@');
01312 char *w = NULL;
01313 char *d = _strdup(GetUnicodeString(challenge,uDomain));
01314 char *domain = d;
01315 if ((domainname!= NULL) && (strlen(domainname)>0) ) domain = domainname;
01316
01317
01318 if (host == NULL) host = "";
01319 w = _strdup(host);
01320
01321 if (p)
01322 {
01323 domain = p+1;
01324 *p = '\0';
01325 } else {
01326 p = strchr(u,'\\');
01327 if (p) {
01328 domain=u;
01329 u= _strdup(p+1);
01330 p[0]='\0';
01331 }
01332 }
01333
01334
01335 if (OptionalNtlmPacket3==NULL) {
01336 if (*password!=':')
01337 {
01338
01339 SMBencrypt((uchar*)password, challenge->challengeData, lmRespData);
01340 SMBNTencrypt((uchar*)password, challenge->challengeData, ntRespData);
01341 } else {
01342
01343 unsigned char hash[21];
01344 int i;
01345 char n,tmp[3];
01346 tmp[2]='\0';
01347 for(i=0;i<16;i++){
01348 memcpy(tmp,password+i*2+1,2);
01349 hash[i]=n=strtol(tmp, 0, 16);
01350 }
01351 memset(hash+16,0,5);
01352 SMBOWFencrypt((unsigned char*)hash, challenge->challengeData, ntRespData);
01353 memcpy(lmRespData,ntRespData,sizeof(ntRespData));
01354 }
01355 } else {
01356
01357 #define ChallengeHash( structPtr, header) ((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0)
01358 memcpy(lmRespData,ChallengeHash(OptionalNtlmPacket3,lmResponse),sizeof(lmRespData));
01359
01360 if (OptionalNtlmPacket3->ntResponse.len>24) {
01361 printf("\n\nWARNING NTLMV2 packet\n\n");
01362 memcpy(ntRespData,ChallengeHash(OptionalNtlmPacket3,lmResponse),sizeof(ntRespData));
01363 } else {
01364 memcpy(ntRespData,ChallengeHash(OptionalNtlmPacket3,ntResponse),sizeof(ntRespData));
01365
01366 }
01367 }
01368
01369
01370
01371 response->bufIndex = 0;
01372 memcpy((char*)response->ident,"NTLMSSP\0\0\0",8);
01373 SIVAL(&response->msgType,0,3);
01374 AddBytes(response,lmResponse,lmRespData,24);
01375 AddBytes(response,ntResponse,ntRespData,24);
01376 AddUnicodeString(response,uDomain,domain);
01377 AddUnicodeString(response,uUser,u);
01378 AddUnicodeString(response,uWks,w);
01379 AddString(response,sessionKey,NULL);
01380 if (flags != 0) challenge->flags = flags;
01381 else response->flags =0x0000b207;
01382 if(d) free(d);
01383 if(u) free(u);
01384
01385 }
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396 void dumpAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request)
01397 {
01398 printf("NTLM Request:\n");
01399 printf(" Ident = %s\n",request->ident);
01400 printf(" mType = %d\n",IVAL(&request->msgType,0));
01401 if (request->msgType!=0x01) {
01402 printf("[-] NTLM PACKET ERROR. Message Type unexpected\n");
01403 return;
01404 }
01405 printf(" Flags = %08x\n",IVAL(&request->flags,0));
01406 printf(" Host = %s\n",GetString(request,host));
01407 printf(" Domain = %s\n",GetString(request,domain));
01408 }
01409
01410 void Widetochar(char *destination, char *source, int len)
01411 {
01412 int i;
01413 for(i=0;i<len/2;i++)
01414 {
01415 destination[i]=(char) source[i*2];
01416 if (destination[i]=='\0') return;
01417 }
01418 destination[i]='\0';
01419
01420 }
01421
01422 void chartoWide(char *destination, char *source, int len)
01423 {
01424 int i;
01425 for(i=0;i<len;i++)
01426 {
01427 destination[i*2]=(char) source[i];
01428 }
01429
01430 }
01431
01432 __inline void SetChallengeKey(tSmbNtlmAuthChallenge *challenge, uint8 *SpoofedChallenge)
01433 {
01434 memcpy((char*)&challenge->challengeData,(char*)SpoofedChallenge,sizeof(challenge->challengeData));
01435 }
01436
01437
01438
01439
01440
01441
01442 void BuildAuthChallenge(tSmbNtlmAuthChallenge *pChallenge, char *DomainName, char *ServerName, char *DNS, char *FQDN, uint8 flags, uint8 *SpoofedChallenge)
01443 {
01444
01445 char *AltDomainName="SMBRELAY3";
01446 tSmbStrItem Item;
01447
01448 memcpy(pChallenge->ident,"NTLMSSP\0\0\0",8);
01449 pChallenge->msgType=2;
01450 if (flags){
01451 pChallenge->flags=flags;
01452 } else {
01453 pChallenge->flags=0xb207;
01454 }
01455
01456 if (SpoofedChallenge) memcpy((char*)&pChallenge->challengeData, (char*)&SpoofedChallenge,8);
01457 else memcpy((char*)&pChallenge->challengeData, "\x11\x22\x33\x44\x55\x66\x77\x88",8);
01458
01459 if (DomainName) AltDomainName=DomainName;
01460
01461 memset(pChallenge->reserved,'\0',sizeof(pChallenge->reserved));
01462 pChallenge->uDomain.len=strlen(AltDomainName)*2;
01463 pChallenge->uDomain.maxlen=strlen(AltDomainName)*2;
01464 pChallenge->uDomain.offset=(uint8) ((char*)&pChallenge->buffer[0] - (char*)&pChallenge);
01465 chartoWide((char*)&pChallenge->buffer, AltDomainName,strlen(AltDomainName));
01466
01467 pChallenge->emptyString.offset= pChallenge->uDomain.offset + pChallenge->uDomain.maxlen;
01468 pChallenge->emptyString.len=0;
01469 pChallenge->emptyString.maxlen=0;
01470
01471
01472 if (DomainName) {
01473 Item.ItemType=DOMAINNAMEITEM;
01474 Item.ItemLength=strlen(DomainName)*2;
01475 chartoWide((char*)&Item.buffer, DomainName,strlen(DomainName));
01476 memcpy((char*)&pChallenge->buffer+pChallenge->uDomain.maxlen+pChallenge->emptyString.len,(void*)&Item,4+Item.ItemLength);
01477 pChallenge->emptyString.len+=Item.ItemLength + 4;
01478 pChallenge->emptyString.maxlen+=Item.ItemLength + 4;
01479 }
01480
01481 if (DNS) {
01482 Item.ItemType=DNSITEM;
01483 Item.ItemLength=strlen(DNS)*2;
01484 chartoWide((char*)&Item.buffer, DNS,strlen(DNS));
01485 memcpy((char*)&pChallenge->buffer+pChallenge->uDomain.maxlen+pChallenge->emptyString.len,(void*)&Item,4+Item.ItemLength);
01486 pChallenge->emptyString.len+=Item.ItemLength + 4;
01487 pChallenge->emptyString.maxlen+=Item.ItemLength + 4;
01488 }
01489
01490 if (ServerName) {
01491 Item.ItemType=SERVERNAMEITEM;
01492 Item.ItemLength=strlen(ServerName)*2;
01493 chartoWide((char*)&Item.buffer, ServerName,strlen(ServerName));
01494 memcpy((char*)&pChallenge->buffer+pChallenge->uDomain.maxlen+pChallenge->emptyString.len,(void*)&Item,4+Item.ItemLength);
01495 pChallenge->emptyString.len+=Item.ItemLength + 4;
01496 pChallenge->emptyString.maxlen+=Item.ItemLength + 4;
01497 }
01498
01499 if (FQDN) {
01500 Item.ItemType=FQDNITEM;
01501 Item.ItemLength=strlen(FQDN)*2;
01502 chartoWide((char*)&Item.buffer, FQDN,strlen(FQDN));
01503 memcpy((char*)&pChallenge->buffer+pChallenge->uDomain.maxlen+pChallenge->emptyString.len,(void*)&Item,4+Item.ItemLength);
01504 pChallenge->emptyString.len+=Item.ItemLength + 4;
01505 pChallenge->emptyString.maxlen+=Item.ItemLength + 4;
01506 }
01507
01508 pChallenge->emptyString.len+=4;
01509 pChallenge->emptyString.maxlen+=4;
01510 memset((char*)&pChallenge->buffer+pChallenge->uDomain.maxlen+pChallenge->emptyString.maxlen,'\0',4);
01511
01512 }
01513
01514
01515
01516 void dumpAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge)
01517 {
01518
01519 WORD securityBuffer;
01520 WORD securityBufferOffsetToData;
01521 char* ServerName="";
01522 char* DomainName="";
01523 char* DnsName="";
01524 char* FQDNName="";
01525
01526 WORD domainnamelen;
01527
01528 WORD tipo;
01529 WORD len;
01530 char *offset;
01531
01532 char *buf=(char*)challenge;
01533 printf("NTLM Challenge:\n\n");
01534 printf(" Ident = %s\n",challenge->ident);
01535 printf(" mType = %d\n",IVAL(&challenge->msgType,0));
01536 if (challenge->msgType!=0x02) {
01537 printf("[-] NTLM PACKET ERROR. Message Type unexpected\n");
01538 return;
01539 }
01540 printf(" Domain = %s\n",GetUnicodeString(challenge,uDomain));
01541 printf(" Flags = %08x\n",IVAL(&challenge->flags,0));
01542 printf(" Challenge = "); dumpRaw(fp, challenge->challengeData,8);
01543
01544 memcpy((char*)&securityBuffer,buf+12,2);
01545 printf(" SecBuffer = %i\n",securityBuffer);
01546 memcpy((char*)&securityBufferOffsetToData,buf+(12+4),2);
01547 printf(" SBOffset = %i\n",securityBufferOffsetToData);
01548 memcpy((char*)&domainnamelen,buf+(12),2);
01549 printf(" DomainLen = %i\n",domainnamelen);
01550
01551
01552 ServerName=(char*)malloc(domainnamelen/2+1);
01553 Widetochar(ServerName,buf+(securityBufferOffsetToData),domainnamelen);
01554
01555
01556 offset=(char*)buf+(securityBufferOffsetToData+domainnamelen);
01557 free(ServerName);
01558
01559 do
01560 {
01561 tipo=0;
01562 memcpy((char*)&tipo,offset,2);
01563 memcpy((char*)&len,offset+2,2);
01564 switch (tipo)
01565 {
01566 case 0x01:
01567 ServerName=(char*)malloc(len/2+1);
01568 Widetochar(ServerName,offset+4,len);
01569 printf(" ServerName = %s\n",ServerName);
01570 free(ServerName);
01571 break;
01572 case 0x02:
01573 DomainName=(char*)malloc(len/2+1);
01574 Widetochar(DomainName,offset+4,len);
01575 printf(" DomainName = %s\n",DomainName);
01576 free(DomainName);
01577 break;
01578 case 0x03:
01579 FQDNName=(char*)malloc(len/2+1);
01580 Widetochar(FQDNName,offset+4,len);
01581 printf(" FQDNName = %s\n",FQDNName);
01582 free(FQDNName);
01583 break;
01584 case 0x04:
01585 DnsName=(char*)malloc(len/2+1);
01586 Widetochar(DnsName,offset+4,len);
01587 printf(" DnsName = %s\n",DnsName);
01588 free(DnsName);
01589 break;
01590 }
01591 offset+=2+2+len;
01592
01593 } while (tipo!=0);
01594 }
01595
01596 void dumpAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response)
01597 {
01598 printf("NTLM Response:\n");
01599 printf(" Ident = %s\n",response->ident);
01600 printf(" mType = %d\n",IVAL(&response->msgType,0));
01601 if (response->msgType!=0x03) {
01602 printf("[-] NTLM PACKET ERROR. Message Type unexpected\n");
01603 return;
01604 }
01605
01606 printf(" LmResp = "); DumpBuffer(fp,response,lmResponse);
01607 if (response->ntResponse.len== 24) {
01608 printf(" NTResp = "); DumpBuffer(fp,response,ntResponse);
01609 } else {
01610
01611 #ifdef _DBG_
01612 printf(" NTLMv2 HMAC = "); dumpRaw(fp, ((NtlmV2Packet*)response+response->ntResponse.offset)->HMAC,16);
01613 printf(" NTLMv2 Header = 0x%8.8x\n",((NtlmV2Packet*)response+response->ntResponse.offset)->Header );
01614 printf(" NTLMv2 Challenge = "); dumpRaw(fp, ((NtlmV2Packet*)response+response->ntResponse.offset)->ClientChallenge,8);
01615 printf(" NTLMv2 Time = "); dumpRaw(fp, ((NtlmV2Packet*)response+response->ntResponse.offset)->Filetime,8);
01616 #endif
01617 }
01618 printf(" Domain = %s\n",GetUnicodeString(response,uDomain));
01619 printf(" User = %s\n",GetUnicodeString(response,uUser));
01620 printf(" Wks = %s\n",GetUnicodeString(response,uWks));
01621 printf(" sKey = "); DumpBuffer(fp, response,sessionKey);
01622 printf(" Flags = %08x\n",IVAL(&response->flags,0));
01623 }
01624
01625
01626
01627 void GetNTLMPacketInfo(tSmbNtlmAuthResponse* NtlmAuthResponse, char* UserName, char *DomainName, char *WorkstationName, int verbose)
01628 {
01629 if (NtlmAuthResponse->msgType==3) {
01630 Widetochar(UserName,(char*)NtlmAuthResponse+NtlmAuthResponse->uUser.offset,NtlmAuthResponse->uUser.len);
01631 Widetochar(DomainName,(char*)NtlmAuthResponse+NtlmAuthResponse->uDomain.offset,NtlmAuthResponse->uDomain.len);
01632 Widetochar(WorkstationName,(char*)NtlmAuthResponse+NtlmAuthResponse->uWks.offset,NtlmAuthResponse->uWks.len);
01633 } else return;
01634 if (verbose) {
01635 printf("Username:\t %s\n",UserName);
01636 printf("DomainName:\t %s\n",DomainName);
01637 printf("WorkstationName: %s\n",WorkstationName);
01638 }
01639
01640 }
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658 static const char base64digits[] =
01659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
01660
01661 #define BAD -1
01662 static const char base64val[] = {
01663 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
01664 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
01665 BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
01666 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
01667 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
01668 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD,
01669 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
01670 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD
01671 };
01672 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
01673
01674 void to64frombits(unsigned char *out, const unsigned char *in, int inlen)
01675
01676 {
01677 for (; inlen >= 3; inlen -= 3)
01678 {
01679 *out++ = base64digits[in[0] >> 2];
01680 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
01681 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
01682 *out++ = base64digits[in[2] & 0x3f];
01683 in += 3;
01684 }
01685 if (inlen > 0)
01686 {
01687 unsigned char fragment;
01688
01689 *out++ = base64digits[in[0] >> 2];
01690 fragment = (in[0] << 4) & 0x30;
01691 if (inlen > 1)
01692 fragment |= in[1] >> 4;
01693 *out++ = base64digits[fragment];
01694 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
01695 *out++ = '=';
01696 }
01697 *out = '\0';
01698 }
01699
01700 int from64tobits(char *out, const char *in)
01701
01702 {
01703 int len = 0;
01704 register unsigned char digit1, digit2, digit3, digit4;
01705
01706 if (in[0] == '+' && in[1] == ' ')
01707 in += 2;
01708 if (*in == '\r')
01709 return(0);
01710
01711 do {
01712 digit1 = in[0];
01713 if (DECODE64(digit1) == BAD)
01714 return(-1);
01715 digit2 = in[1];
01716 if (DECODE64(digit2) == BAD)
01717 return(-1);
01718 digit3 = in[2];
01719 if (digit3 != '=' && DECODE64(digit3) == BAD)
01720 return(-1);
01721 digit4 = in[3];
01722 if (digit4 != '=' && DECODE64(digit4) == BAD)
01723 return(-1);
01724 in += 4;
01725 *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
01726 ++len;
01727 if (digit3 != '=')
01728 {
01729 *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
01730 ++len;
01731 if (digit4 != '=')
01732 {
01733 *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
01734 ++len;
01735 }
01736 }
01737 } while
01738 (*in && *in != '\r' && digit4 != '=');
01739
01740 return (len);
01741 }
01742
01743
01744
01745