C:/fscan/HTTPCore/Authentication/ntlm.cpp

Go to the documentation of this file.
00001 
00002 /* $Id$
00003    Single file NTLM system to create and parse authentication messages.
00004 
00005    http://www.reversing.org
00006    ilo-- [email protected]  
00007 
00008    I did copy&paste&modify several files to leave independent NTLM code 
00009    that compile in cygwin/linux environment. Most of the code was ripped 
00010    from Samba implementation so I left the Copying statement. Samba core
00011    code was left unmodified from 1.9 version.
00012 
00013    Also libntlm was ripped but rewrote, due to fixed and useless interface.
00014    Library oriented code was removed. (c) goes to: Simon Josefsson.
00015 
00016    Information about interface to this ntlm-system is in ntlm.h file.
00017 
00018    Unix SMB/Netbios implementation.
00019    Version 1.9.
00020    SMB parameters and setup
00021    Copyright (C) Andrew Tridgell 1992-1998
00022    Modified by Jeremy Allison 1995.
00023    
00024    This program is free software; you can redistribute it and/or modify
00025    it under the terms of the GNU General Public License as published by
00026    the Free Software Foundation; either version 2 of the License, or
00027    (at your option) any later version.
00028    
00029    This program is distributed in the hope that it will be useful,
00030    but WITHOUT ANY WARRANTY; without even the implied warranty of
00031    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00032    GNU General Public License for more details.
00033    
00034    You should have received a copy of the GNU General Public License
00035    along with this program; if not, write to the Free Software
00036    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00037 
00038    */
00039 
00040 #include "../Build.h"
00041 
00042 #ifndef __WIN32__RELEASE__
00043  #include <unistd.h>
00044 #endif
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <ctype.h>
00048 #include <assert.h>
00049 #include <string.h>
00050 #include "ntlm.h"
00051 
00052 
00053 /* Byte order macros */
00054 #ifndef _BYTEORDER_H
00055 #define _BYTEORDER_H
00056 
00057 /*
00058    This file implements macros for machine independent short and 
00059    int manipulation
00060 
00061 Here is a description of this file that I emailed to the samba list once:
00062 
00063 > I am confused about the way that byteorder.h works in Samba. I have
00064 > looked at it, and I would have thought that you might make a distinction
00065 > between LE and BE machines, but you only seem to distinguish between 386
00066 > and all other architectures.
00067 > 
00068 > Can you give me a clue?
00069 
00070 sure.
00071 
00072 The distinction between 386 and other architectures is only there as
00073 an optimisation. You can take it out completely and it will make no
00074 difference. The routines (macros) in byteorder.h are totally byteorder
00075 independent. The 386 optimsation just takes advantage of the fact that
00076 the x86 processors don't care about alignment, so we don't have to
00077 align ints on int boundaries etc. If there are other processors out
00078 there that aren't alignment sensitive then you could also define
00079 CAREFUL_ALIGNMENT=0 on those processors as well.
00080 
00081 Ok, now to the macros themselves. I'll take a simple example, say we
00082 want to extract a 2 byte integer from a SMB packet and put it into a
00083 type called uint16 that is in the local machines byte order, and you
00084 want to do it with only the assumption that uint16 is _at_least_ 16
00085 bits long (this last condition is very important for architectures
00086 that don't have any int types that are 2 bytes long)
00087 
00088 You do this:
00089 
00090 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
00091 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
00092 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
00093 
00094 then to extract a uint16 value at offset 25 in a buffer you do this:
00095 
00096 char *buffer = foo_bar();
00097 uint16 xx = SVAL(buffer,25);
00098 
00099 We are using the byteoder independence of the ANSI C bitshifts to do
00100 the work. A good optimising compiler should turn this into efficient
00101 code, especially if it happens to have the right byteorder :-)
00102 
00103 I know these macros can be made a bit tidier by removing some of the
00104 casts, but you need to look at byteorder.h as a whole to see the
00105 reasoning behind them. byteorder.h defines the following macros:
00106 
00107 SVAL(buf,pos) - extract a 2 byte SMB value
00108 IVAL(buf,pos) - extract a 4 byte SMB value
00109 SVALS(buf,pos) signed version of SVAL()
00110 IVALS(buf,pos) signed version of IVAL()
00111 
00112 SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer
00113 SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer
00114 SSVALS(buf,pos,val) - signed version of SSVAL()
00115 SIVALS(buf,pos,val) - signed version of SIVAL()
00116 
00117 RSVAL(buf,pos) - like SVAL() but for NMB byte ordering
00118 RSVALS(buf,pos) - like SVALS() but for NMB byte ordering
00119 RIVAL(buf,pos) - like IVAL() but for NMB byte ordering
00120 RIVALS(buf,pos) - like IVALS() but for NMB byte ordering
00121 RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering
00122 RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering
00123 RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering
00124 
00125 it also defines lots of intermediate macros, just ignore those :-)
00126 
00127 */
00128 
00129 /* some switch macros that do both store and read to and from SMB buffers */
00130 
00131 #define RW_PCVAL(read,inbuf,outbuf,len) \
00132         { if (read) { PCVAL (inbuf,0,outbuf,len); } \
00133         else      { PSCVAL(inbuf,0,outbuf,len); } }
00134 
00135 #define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
00136         { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
00137         else      { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
00138 
00139 #define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
00140         { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
00141         else      { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
00142 
00143 #define RW_CVAL(read, inbuf, outbuf, offset) \
00144         { if (read) { (outbuf) = CVAL (inbuf,offset); } \
00145         else      { SCVAL(inbuf,offset,outbuf); } }
00146 
00147 #define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
00148         { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
00149         else      { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
00150 
00151 #define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
00152         { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
00153         else      { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
00154 
00155 #undef CAREFUL_ALIGNMENT
00156 
00157 /* we know that the 386 can handle misalignment and has the "right" 
00158    byteorder */
00159 #ifdef __i386__
00160 #define CAREFUL_ALIGNMENT 0
00161 #endif
00162 
00163 #ifndef CAREFUL_ALIGNMENT
00164 #define CAREFUL_ALIGNMENT 1
00165 #endif
00166 
00167 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
00168 #define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
00169 #define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
00170 
00171 
00172 #if CAREFUL_ALIGNMENT
00173 
00174 #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
00175 #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
00176 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
00177 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
00178 #define SVALS(buf,pos) ((int16)SVAL(buf,pos))
00179 #define IVALS(buf,pos) ((int32)IVAL(buf,pos))
00180 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
00181 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
00182 #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
00183 #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
00184 
00185 #else /* CAREFUL_ALIGNMENT */
00186 
00187 /* this handles things for architectures like the 386 that can handle
00188    alignment errors */
00189 /*
00190    WARNING: This section is dependent on the length of int16 and int32
00191    being correct 
00192 */
00193 
00194 /* get single value from an SMB buffer */
00195 #define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
00196 #define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
00197 #define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
00198 #define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
00199 
00200 /* store single value in an SMB buffer */
00201 #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val))
00202 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
00203 #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val))
00204 #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val))
00205 
00206 #endif /* CAREFUL_ALIGNMENT */
00207 
00208 /* macros for reading / writing arrays */
00209 
00210 #define SMBMACRO(macro,buf,pos,val,len,size) \
00211 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
00212 
00213 #define SSMBMACRO(macro,buf,pos,val,len,size) \
00214 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
00215 
00216 /* reads multiple data from an SMB buffer */
00217 #define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
00218 #define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
00219 #define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
00220 #define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
00221 #define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
00222 #define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
00223 
00224 /* stores multiple data in an SMB buffer */
00225 #define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
00226 #define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
00227 #define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
00228 #define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
00229 #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
00230 #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
00231 
00232 
00233 /* now the reverse routines - these are used in nmb packets (mostly) */
00234 #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
00235 #define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
00236 
00237 #define RSVAL(buf,pos) SREV(SVAL(buf,pos))
00238 #define RSVALS(buf,pos) SREV(SVALS(buf,pos))
00239 #define RIVAL(buf,pos) IREV(IVAL(buf,pos))
00240 #define RIVALS(buf,pos) IREV(IVALS(buf,pos))
00241 #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
00242 #define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
00243 #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
00244 #define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
00245 
00246 /* reads multiple data from an SMB buffer (big-endian) */
00247 #define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
00248 #define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
00249 #define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
00250 #define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
00251 
00252 /* stores multiple data in an SMB buffer (big-endian) */
00253 #define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
00254 #define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
00255 #define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
00256 #define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
00257 
00258 #define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
00259         { RW_PCVAL(read,inbuf,outbuf,len) \
00260         DEBUG(5,("%s%04x %s: ", \
00261              tab_depth(depth), base,string)); \
00262     if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
00263         { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
00264         DEBUG(5,("\n")); } 
00265 
00266 #define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
00267         { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
00268         DEBUG(5,("%s%04x %s: ", \
00269              tab_depth(depth), base,string)); \
00270     if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
00271         { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
00272         DEBUG(5,("\n")); }
00273 
00274 #define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
00275         { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
00276         DEBUG(5,("%s%04x %s: ", \
00277              tab_depth(depth), base,string)); \
00278     if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
00279         { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
00280         DEBUG(5,("\n")); }
00281 
00282 #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
00283         { RW_CVAL(read,inbuf,outbuf,0) \
00284         DEBUG(5,("%s%04x %s: %02x\n", \
00285              tab_depth(depth), base, string, outbuf)); }
00286 
00287 #define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
00288         { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
00289         DEBUG(5,("%s%04x %s: %04x\n", \
00290              tab_depth(depth), base, string, outbuf)); }
00291 
00292 #define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
00293         { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
00294         DEBUG(5,("%s%04x %s: %08x\n", \
00295              tab_depth(depth), base, string, outbuf)); }
00296 
00297 #endif /* _BYTEORDER_H */
00298 
00299 
00300 /* Samba MD4 implementation */
00301 /* NOTE: This code makes no attempt to be fast! 
00302 
00303    It assumes that a int is at least 32 bits long
00304 */
00305 
00306 static uint32 A, B, C, D;
00307 
00308 static uint32 F(uint32 X, uint32 Y, uint32 Z)
00309 {
00310         return (X&Y) | ((~X)&Z);
00311 }
00312 
00313 static uint32 G(uint32 X, uint32 Y, uint32 Z)
00314 {
00315         return (X&Y) | (X&Z) | (Y&Z); 
00316 }
00317 
00318 static uint32 H(uint32 X, uint32 Y, uint32 Z)
00319 {
00320         return X^Y^Z;
00321 }
00322 
00323 static uint32 lshift(uint32 x, int s)
00324 {
00325         x &= 0xFFFFFFFF;
00326         return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
00327 }
00328 
00329 #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
00330 #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
00331 #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
00332 
00333 /* this applies md4 to 64 byte chunks */
00334 static void mdfour64(uint32 *M)
00335 {
00336         int j;
00337         uint32 AA, BB, CC, DD;
00338         uint32 X[16];
00339 
00340         for (j=0;j<16;j++)
00341                 X[j] = M[j];
00342 
00343         AA = A; BB = B; CC = C; DD = D;
00344 
00345         ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);  
00346         ROUND1(C,D,A,B,  2, 11);  ROUND1(B,C,D,A,  3, 19);
00347         ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);  
00348         ROUND1(C,D,A,B,  6, 11);  ROUND1(B,C,D,A,  7, 19);
00349         ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);  
00350         ROUND1(C,D,A,B, 10, 11);  ROUND1(B,C,D,A, 11, 19);
00351         ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);  
00352         ROUND1(C,D,A,B, 14, 11);  ROUND1(B,C,D,A, 15, 19);      
00353 
00354         ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);  
00355         ROUND2(C,D,A,B,  8,  9);  ROUND2(B,C,D,A, 12, 13);
00356         ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);  
00357         ROUND2(C,D,A,B,  9,  9);  ROUND2(B,C,D,A, 13, 13);
00358         ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);  
00359         ROUND2(C,D,A,B, 10,  9);  ROUND2(B,C,D,A, 14, 13);
00360         ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);  
00361         ROUND2(C,D,A,B, 11,  9);  ROUND2(B,C,D,A, 15, 13);
00362 
00363         ROUND3(A,B,C,D,  0,  3);  ROUND3(D,A,B,C,  8,  9);  
00364         ROUND3(C,D,A,B,  4, 11);  ROUND3(B,C,D,A, 12, 15);
00365         ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);  
00366         ROUND3(C,D,A,B,  6, 11);  ROUND3(B,C,D,A, 14, 15);
00367         ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);  
00368         ROUND3(C,D,A,B,  5, 11);  ROUND3(B,C,D,A, 13, 15);
00369         ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);  
00370         ROUND3(C,D,A,B,  7, 11);  ROUND3(B,C,D,A, 15, 15);
00371 
00372         A += AA; B += BB; C += CC; D += DD;
00373         
00374         A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
00375         C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
00376 
00377         for (j=0;j<16;j++)
00378                 X[j] = 0;
00379 }
00380 
00381 static void copy64(uint32 *M, unsigned char *in)
00382 {
00383         int i;
00384 
00385         for (i=0;i<16;i++)
00386                 M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
00387                         (in[i*4+1]<<8) | (in[i*4+0]<<0);
00388 }
00389 
00390 static void copy4(unsigned char *out,uint32 x)
00391 {
00392         out[0] = x&0xFF;
00393         out[1] = (x>>8)&0xFF;
00394         out[2] = (x>>16)&0xFF;
00395         out[3] = (x>>24)&0xFF;
00396 }
00397 
00398 /* produce a md4 message digest from data of length n bytes */
00399 void mdfour(unsigned char *out, unsigned char *in, int n)
00400 {
00401         unsigned char buf[128];
00402         uint32 M[16];
00403         uint32 b = n * 8;
00404         int i;
00405 
00406         A = 0x67452301;
00407         B = 0xefcdab89;
00408         C = 0x98badcfe;
00409         D = 0x10325476;
00410 
00411         while (n > 64) {
00412                 copy64(M, in);
00413                 mdfour64(M);
00414                 in += 64;
00415                 n -= 64;
00416         }
00417 
00418         for (i=0;i<128;i++)
00419                 buf[i] = 0;
00420         memcpy(buf, in, n);
00421         buf[n] = 0x80;
00422         
00423         if (n <= 55) {
00424                 copy4(buf+56, b);
00425                 copy64(M, buf);
00426                 mdfour64(M);
00427         } else {
00428                 copy4(buf+120, b); 
00429                 copy64(M, buf);
00430                 mdfour64(M);
00431                 copy64(M, buf+64);
00432                 mdfour64(M);
00433         }
00434 
00435         for (i=0;i<128;i++)
00436                 buf[i] = 0;
00437         copy64(M, buf);
00438 
00439         copy4(out, A);
00440         copy4(out+4, B);
00441         copy4(out+8, C);
00442         copy4(out+12, D);
00443 
00444         A = B = C = D = 0;
00445 }
00446 
00447 
00448 /* Samba DES implementation */
00449 #define uchar unsigned char
00450 #define int16 signed short
00451 //typedef int BOOL;
00452 #define False 0
00453 #define True  1
00454 
00455 static uchar perm1[56] = {57, 49, 41, 33, 25, 17,  9,
00456                          1, 58, 50, 42, 34, 26, 18,
00457                         10,  2, 59, 51, 43, 35, 27,
00458                         19, 11,  3, 60, 52, 44, 36,
00459                         63, 55, 47, 39, 31, 23, 15,
00460                          7, 62, 54, 46, 38, 30, 22,
00461                         14,  6, 61, 53, 45, 37, 29,
00462                         21, 13,  5, 28, 20, 12,  4};
00463 
00464 static uchar perm2[48] = {14, 17, 11, 24,  1,  5,
00465                          3, 28, 15,  6, 21, 10,
00466                         23, 19, 12,  4, 26,  8,
00467                         16,  7, 27, 20, 13,  2,
00468                         41, 52, 31, 37, 47, 55,
00469                         30, 40, 51, 45, 33, 48,
00470                         44, 49, 39, 56, 34, 53,
00471                         46, 42, 50, 36, 29, 32};
00472 
00473 static uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
00474                         60, 52, 44, 36, 28, 20, 12,  4,
00475                         62, 54, 46, 38, 30, 22, 14,  6,
00476                         64, 56, 48, 40, 32, 24, 16,  8,
00477                         57, 49, 41, 33, 25, 17,  9,  1,
00478                         59, 51, 43, 35, 27, 19, 11,  3,
00479                         61, 53, 45, 37, 29, 21, 13,  5,
00480                         63, 55, 47, 39, 31, 23, 15,  7};
00481 
00482 static uchar perm4[48] = {   32,  1,  2,  3,  4,  5,
00483                             4,  5,  6,  7,  8,  9,
00484                             8,  9, 10, 11, 12, 13,
00485                            12, 13, 14, 15, 16, 17,
00486                            16, 17, 18, 19, 20, 21,
00487                            20, 21, 22, 23, 24, 25,
00488                            24, 25, 26, 27, 28, 29,
00489                            28, 29, 30, 31, 32,  1};
00490 
00491 static uchar perm5[32] = {      16,  7, 20, 21,
00492                               29, 12, 28, 17,
00493                                1, 15, 23, 26,
00494                                5, 18, 31, 10,
00495                                2,  8, 24, 14,
00496                               32, 27,  3,  9,
00497                               19, 13, 30,  6,
00498                               22, 11,  4, 25};
00499 
00500 
00501 static uchar perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
00502                         39,  7, 47, 15, 55, 23, 63, 31,
00503                         38,  6, 46, 14, 54, 22, 62, 30,
00504                         37,  5, 45, 13, 53, 21, 61, 29,
00505                         36,  4, 44, 12, 52, 20, 60, 28,
00506                         35,  3, 43, 11, 51, 19, 59, 27,
00507                         34,  2, 42, 10, 50, 18, 58, 26,
00508                         33,  1, 41,  9, 49, 17, 57, 25};
00509 
00510 
00511 static uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
00512 
00513 static uchar sbox[8][4][16] = {
00514         {{14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},
00515          {0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},
00516          {4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},
00517          {15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13}},
00518 
00519         {{15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},
00520          {3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},
00521          {0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},
00522          {13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9}},
00523 
00524         {{10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},
00525          {13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},
00526          {13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},
00527          {1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12}},
00528 
00529         {{7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},
00530          {13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},
00531          {10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},
00532          {3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14}},
00533 
00534         {{2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},
00535          {14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},
00536          {4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},
00537          {11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3}},
00538 
00539         {{12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},
00540          {10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},
00541          {9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},
00542          {4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13}},
00543 
00544         {{4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},
00545          {13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},
00546          {1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},
00547          {6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12}},
00548 
00549         {{13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},
00550          {1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},
00551          {7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},
00552          {2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}}};
00553 
00554 static void permute(char *out, char *in, uchar *p, int n)
00555 {
00556         int i;
00557         for (i=0;i<n;i++)
00558                 out[i] = in[p[i]-1];
00559 }
00560 
00561 static void l_shift(char *d, int count, int n)
00562 {
00563         char out[64];
00564         int i;
00565         for (i=0;i<n;i++)
00566                 out[i] = d[(i+count)%n];
00567         for (i=0;i<n;i++)
00568                 d[i] = out[i];
00569 }
00570 
00571 static void concat(char *out, char *in1, char *in2, int l1, int l2)
00572 {
00573         while (l1--)
00574                 *out++ = *in1++;
00575         while (l2--)
00576                 *out++ = *in2++;
00577 }
00578 
00579 static void xorfunction(char *out, char *in1, char *in2, int n)
00580 {
00581         int i;
00582         for (i=0;i<n;i++)
00583                 out[i] = in1[i] ^ in2[i];
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         permute(pk1, key, perm1, 56);
00599 
00600         for (i=0;i<28;i++)
00601                 c[i] = pk1[i];
00602         for (i=0;i<28;i++)
00603                 d[i] = pk1[i+28];
00604 
00605         for (i=0;i<16;i++) {
00606                 l_shift(c, sc[i], 28);
00607                 l_shift(d, sc[i], 28);
00608 
00609                 concat(cd, c, d, 28, 28); 
00610                 permute(ki[i], cd, perm2, 48); 
00611         }
00612 
00613         permute(pd1, in, perm3, 64);
00614 
00615         for (j=0;j<32;j++) {
00616                 l[j] = pd1[j];
00617                 r[j] = pd1[j+32];
00618         }
00619 
00620         for (i=0;i<16;i++) {
00621                 char er[48];
00622                 char erk[48];
00623                 char b[8][6];
00624                 char cb[32];
00625                 char pcb[32];
00626                 char r2[32];
00627 
00628                 permute(er, r, perm4, 48);
00629 
00630                 xorfunction(erk, er, ki[forw ? i : 15 - i], 48);
00631 
00632                 for (j=0;j<8;j++)
00633                         for (k=0;k<6;k++)
00634                                 b[j][k] = erk[j*6 + k];
00635 
00636                 for (j=0;j<8;j++) {
00637                         int m, n;
00638                         m = (b[j][0]<<1) | b[j][5];
00639 
00640                         n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; 
00641 
00642                         for (k=0;k<4;k++) 
00643                                 b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; 
00644                 }
00645 
00646                 for (j=0;j<8;j++)
00647                         for (k=0;k<4;k++)
00648                                 cb[j*4+k] = b[j][k];
00649                 permute(pcb, cb, perm5, 32);
00650 
00651                 xorfunction(r2, l, pcb, 32);
00652 
00653                 for (j=0;j<32;j++)
00654                         l[j] = r[j];
00655 
00656                 for (j=0;j<32;j++)
00657                         r[j] = r2[j];
00658         }
00659 
00660         concat(rl, r, l, 32, 32);
00661 
00662         permute(out, rl, perm6, 64);
00663 }
00664 
00665 static void str_to_key(unsigned char *str,unsigned char *key)
00666 {
00667         int i;
00668 
00669         key[0] = str[0]>>1;
00670         key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
00671         key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
00672         key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
00673         key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
00674         key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
00675         key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
00676         key[7] = str[6]&0x7F;
00677         for (i=0;i<8;i++) {
00678                 key[i] = (key[i]<<1);
00679         }
00680 }
00681 
00682 
00683 static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
00684 {
00685         int i;
00686         char outb[64];
00687         char inb[64];
00688         char keyb[64];
00689         unsigned char key2[8];
00690 
00691         str_to_key(key, key2);
00692 
00693         for (i=0;i<64;i++) {
00694                 inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
00695                 keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
00696                 outb[i] = 0;
00697         }
00698 
00699         dohash(outb, inb, keyb, forw);
00700 
00701         for (i=0;i<8;i++) {
00702                 out[i] = 0;
00703         }
00704 
00705         for (i=0;i<64;i++) {
00706                 if (outb[i])
00707                         out[i/8] |= (1<<(7-(i%8)));
00708         }
00709 }
00710 
00711 void E_P16(unsigned char *p14,unsigned char *p16)
00712 {
00713         unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
00714         smbhash(p16, sp8, p14, 1);
00715         smbhash(p16+8, sp8, p14+7, 1);
00716 }
00717 
00718 void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
00719 {
00720         smbhash(p24, c8, p21, 1);
00721         smbhash(p24+8, c8, p21+7, 1);
00722         smbhash(p24+16, c8, p21+14, 1);
00723 }
00724 
00725 void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
00726 {
00727         smbhash(out, in, p14, 0);
00728         smbhash(out+8, in+8, p14+7, 0);
00729 }
00730 
00731 void E_old_pw_hash( unsigned char *p14, unsigned char *in, unsigned char *out)
00732 {
00733         smbhash(out, in, p14, 1);
00734         smbhash(out+8, in+8, p14+7, 1);
00735 }
00736 
00737 void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
00738 {
00739         unsigned char buf[8];
00740 
00741         smbhash(buf, in, key, 1);
00742         smbhash(out, buf, key+9, 1);
00743 }
00744 
00745 void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
00746 {
00747         unsigned char buf[8];
00748         static unsigned char key2[8];
00749 
00750         smbhash(buf, in, key, 1);
00751         key2[0] = key[7];
00752         smbhash(out, buf, key2, 1);
00753 }
00754 
00755 void cred_hash3(unsigned char *out,unsigned char *in,unsigned char *key, int forw)
00756 {
00757         static unsigned char key2[8];
00758 
00759         smbhash(out, in, key, forw);
00760         key2[0] = key[7];
00761         smbhash(out + 8, in + 8, key2, forw);
00762 }
00763 
00764 void SamOEMhash( unsigned char *data, unsigned char *key, int val)
00765 {
00766   unsigned char s_box[256];
00767   unsigned char index_i = 0;
00768   unsigned char index_j = 0;
00769   unsigned char j = 0;
00770   int ind;
00771 
00772   for (ind = 0; ind < 256; ind++)
00773   {
00774     s_box[ind] = (unsigned char)ind;
00775   }
00776 
00777   for( ind = 0; ind < 256; ind++)
00778   {
00779      unsigned char tc;
00780 
00781      j += (s_box[ind] + key[ind%16]);
00782 
00783      tc = s_box[ind];
00784      s_box[ind] = s_box[j];
00785      s_box[j] = tc;
00786   }
00787   for( ind = 0; ind < (val ? 516 : 16); ind++)
00788   {
00789     unsigned char tc;
00790     unsigned char t;
00791 
00792     index_i++;
00793     index_j += s_box[index_i];
00794 
00795     tc = s_box[index_i];
00796     s_box[index_i] = s_box[index_j];
00797     s_box[index_j] = tc;
00798 
00799     t = s_box[index_i] + s_box[index_j];
00800     data[ind] = data[ind] ^ s_box[t];
00801   }
00802 }
00803 
00804 /* Samba encryption implementation*/
00805 
00806 
00807 /****************************************************************************
00808  Like strncpy but always null terminates. Make sure there is room!
00809  The variable n should always be one less than the available size.
00810 ****************************************************************************/
00811 
00812 char *StrnCpy(char *dest,const char *src, size_t n)
00813 {
00814   char *d = dest;
00815   if (!dest) return(NULL);
00816   if (!src) {
00817     *dest = 0;
00818     return(dest);
00819   }
00820   while (n-- && (*d++ = *src++)) ;
00821   *d = 0;
00822   return(dest);
00823 }
00824 
00825 size_t skip_multibyte_char(char c)
00826 {
00827 return 0;
00828 }
00829 
00830 
00831 /*******************************************************************
00832 safe string copy into a known length string. maxlength does not
00833 include the terminating zero.
00834 ********************************************************************/
00835 #define DEBUG(a,b) ;
00836 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
00837 {
00838     size_t len;
00839 
00840     if (!dest) {
00841         DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
00842         return NULL;
00843     }
00844 
00845     if (!src) {
00846         *dest = 0;
00847         return dest;
00848     }  
00849 
00850     len = strlen(src);
00851 
00852     if (len > maxlength) {
00853             DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
00854                      (int)(len-maxlength), src));
00855             len = maxlength;
00856     }
00857       
00858     memcpy(dest, src, len);
00859     dest[len] = 0;
00860     return dest;
00861 }  
00862 
00863 
00864 void strupper(char *s)
00865 {
00866 while (*s)
00867   {
00868     {
00869     size_t skip = skip_multibyte_char( *s );
00870     if( skip != 0 )
00871       s += skip;
00872     else
00873       {
00874       if (islower(*s))
00875         *s = toupper(*s);
00876       s++;
00877       }
00878     }
00879   }
00880 }
00881 
00882 extern void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]);
00883 
00884 /*
00885  This implements the X/Open SMB password encryption
00886  It takes a password, a 8 byte "crypt key" and puts 24 bytes of 
00887  encrypted password into p24 
00888  */
00889 
00890 void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
00891   {
00892   uchar p14[15], p21[21];
00893   
00894   memset(p21,'\0',21);
00895   memset(p14,'\0',14);
00896   StrnCpy((char *)p14,(char *)passwd,14);
00897   
00898   strupper((char *)p14);
00899   E_P16(p14, p21); 
00900   
00901   SMBOWFencrypt(p21, c8, p24);
00902   
00903 #ifdef DEBUG_PASSWORD
00904   DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
00905   dump_data(100, (char *)p21, 16);
00906   dump_data(100, (char *)c8, 8);
00907   dump_data(100, (char *)p24, 24);
00908 #endif
00909   }
00910 
00911 /* Routines for Windows NT MD4 Hash functions. */
00912 static int _my_wcslen(int16 *str)
00913 {
00914         int len = 0;
00915         while(*str++ != 0)
00916                 len++;
00917         return len;
00918 }
00919 
00920 /*
00921  * Convert a string into an NT UNICODE string.
00922  * Note that regardless of processor type 
00923  * this must be in intel (little-endian)
00924  * format.
00925  */
00926  
00927 static int _my_mbstowcs(int16 *dst, uchar *src, int len)
00928 {
00929         int i;
00930         int16 val;
00931  
00932         for(i = 0; i < len; i++) {
00933                 val = *src;
00934                 SSVAL(dst,0,val);
00935                 dst++;
00936                 src++;
00937                 if(val == 0)
00938                         break;
00939         }
00940         return i;
00941 }
00942 
00943 /* 
00944  * Creates the MD4 Hash of the users password in NT UNICODE.
00945  */
00946  
00947 void E_md4hash(uchar *passwd, uchar *p16)
00948 {
00949         int len;
00950         int16 wpwd[129];
00951         
00952         /* Password cannot be longer than 128 characters */
00953         len = (int) strlen((char *)passwd);
00954         if(len > 128)
00955                 len = 128;
00956         /* Password must be converted to NT unicode */
00957         _my_mbstowcs(wpwd, passwd, len);
00958         wpwd[len] = 0; /* Ensure string is null terminated */
00959         /* Calculate length in bytes */
00960         len = _my_wcslen(wpwd) * sizeof(int16);
00961 
00962         mdfour(p16, (unsigned char *)wpwd, len);
00963 }
00964 
00965 /* Does both the NT and LM owfs of a user's password */
00966 void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16])
00967 {
00968         char passwd[130];
00969 
00970         memset(passwd,'\0',130);
00971         safe_strcpy( passwd, pwd, sizeof(passwd)-1);
00972 
00973         /* Calculate the MD4 hash (NT compatible) of the password */
00974         memset(nt_p16, '\0', 16);
00975         E_md4hash((uchar *)passwd, nt_p16);
00976 
00977 #ifdef DEBUG_PASSWORD
00978         DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
00979         dump_data(120, passwd, strlen(passwd));
00980         dump_data(100, (char *)nt_p16, 16);
00981 #endif
00982 
00983         /* Mangle the passwords into Lanman format */
00984         passwd[14] = '\0';
00985         strupper(passwd);
00986 
00987         /* Calculate the SMB (lanman) hash functions of the password */
00988 
00989         memset(p16, '\0', 16);
00990         E_P16((uchar *) passwd, (uchar *)p16);
00991 
00992 #ifdef DEBUG_PASSWORD
00993         DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
00994         dump_data(120, passwd, strlen(passwd));
00995         dump_data(100, (char *)p16, 16);
00996 #endif
00997         /* clear out local copy of user's password (just being paranoid). */
00998         memset(passwd, '\0', sizeof(passwd));
00999 }
01000 
01001 /* Does the des encryption from the NT or LM MD4 hash. */
01002 void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
01003 {
01004         uchar p21[21];
01005  
01006         memset(p21,'\0',21);
01007  
01008         memcpy(p21, passwd, 16);    
01009         E_P24(p21, c8, p24);
01010 }
01011 
01012 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
01013 void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
01014 {
01015         uchar p21[21];
01016  
01017         memset(p21,'\0',21);
01018         memcpy(p21, passwd, 8);    
01019         memset(p21 + 8, 0xbd, 8);    
01020 
01021         E_P24(p21, ntlmchalresp, p24);
01022 #ifdef DEBUG_PASSWORD
01023         DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n"));
01024         dump_data(100, (char *)p21, 21);
01025         dump_data(100, (char *)ntlmchalresp, 8);
01026         dump_data(100, (char *)p24, 24);
01027 #endif
01028 }
01029 
01030 
01031 /* Does the NT MD4 hash then des encryption. */
01032  
01033 void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
01034 {
01035         uchar p21[21];
01036  
01037         memset(p21,'\0',21);
01038  
01039         E_md4hash(passwd, p21);    
01040         SMBOWFencrypt(p21, c8, p24);
01041 
01042 #ifdef DEBUG_PASSWORD
01043         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
01044         dump_data(100, (char *)p21, 16);
01045         dump_data(100, (char *)c8, 8);
01046         dump_data(100, (char *)p24, 24);
01047 #endif
01048 }
01049 
01050 #if 0
01051 
01052 BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
01053 {
01054         int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
01055 
01056         if (new_pw_len > 512)
01057         {
01058                 DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
01059                 return False;
01060         }
01061 
01062         /*
01063          * Now setup the data area.
01064          * We need to generate a random fill
01065          * for this area to make it harder to
01066          * decrypt. JRA.
01067          */
01068         generate_random_buffer((unsigned char *)data, 516, False);
01069         if (unicode)
01070         {
01071                 struni2( &data[512 - new_pw_len], passwd);
01072         }
01073         else
01074         {
01075                 fstrcpy( &data[512 - new_pw_len], passwd);
01076         }
01077         SIVAL(data, 512, new_pw_len);
01078 
01079 #ifdef DEBUG_PASSWORD
01080         DEBUG(100,("make_oem_passwd_hash\n"));
01081         dump_data(100, data, 516);
01082 #endif
01083         SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
01084 
01085         return True;
01086 }
01087 
01088 #endif
01089 
01090 /* libtnlm copyrigth was left here, anyway the interface was slightly modified */
01091 /* included libntlm-3.2.9 (c) even if this code is based in 2.1 version*/
01092 /*
01093 Libntlm AUTHORS -- information about the authors
01094 Copyright (C) 2002, 2003, 2004 Simon Josefsson
01095 See the end for copying conditions.
01096 
01097 Grant Edwards <[email protected]>
01098 Original author of libntlm
01099 
01100 Andrew Tridgell
01101 Wrote functions borrowed from SMB.
01102 
01103 Simon Josefsson <[email protected]>
01104 Build environment, maintainer.
01105 
01106 Frediano Ziglio
01107 Contributed LGPL versions of some of the GPL'd Samba files.
01108 */
01109 
01110 /* The [IS]VAL macros are to take care of byte order for non-Intel
01111  * Machines -- I think this file is OK, but it hasn't been tested.
01112  * The other files (the ones stolen from Samba) should be OK.
01113  * I am not crazy about these macros -- they seem to have gotten
01114  * a bit complex.  A new scheme for handling string/buffer fields
01115  * in the structures probably needs to be designed
01116  */
01117 
01118 #define AddBytes(ptr, header, buf, count) \
01119 { \
01120 if (buf && count) \
01121   { \
01122   SSVAL(&ptr->header.len,0,count); \
01123   SSVAL(&ptr->header.maxlen,0,count); \
01124   SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8*)ptr)) + ptr->bufIndex)); \
01125   memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
01126   ptr->bufIndex += count; \
01127   } \
01128 else \
01129   { \
01130   ptr->header.len = \
01131   ptr->header.maxlen = 0; \
01132   SIVAL(&ptr->header.offset,0,ptr->bufIndex); \
01133   } \
01134 }
01135 
01136 #define AddString(ptr, header, string) \
01137 { \
01138 char *p = string; \
01139 int len = 0; \
01140 if (p) len = strlen(p); \
01141 AddBytes(ptr, header, ((unsigned char*)p), len); \
01142 }
01143 
01144 #define AddUnicodeString(ptr, header, string) \
01145 { \
01146 char *p = string; \
01147 unsigned char *b = NULL; \
01148 int len = 0; \
01149 if (p) \
01150   { \
01151   len = strlen(p); \
01152   b = strToUnicode(p); \
01153   } \
01154 AddBytes(ptr, header, b, len*2); \
01155 }
01156 
01157 
01158 #define GetUnicodeString(structPtr, header) \
01159 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
01160 #define GetString(structPtr, header) \
01161 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
01162 #define DumpBuffer(fp, structPtr, header) \
01163 dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
01164 
01165 
01166 static void dumpRaw(FILE *fp, unsigned char *buf, size_t len)
01167   {
01168   int i;
01169   
01170   for (i=0; i<(signed int)len; ++i)
01171    printf("%02x ",buf[i]);
01172     
01173    printf("\n");
01174   }
01175 
01176 static char *unicodeToString(char *p, size_t len)
01177   {
01178   int i;
01179   static char buf[1024];
01180 
01181   assert(len+1 < sizeof buf);
01182   
01183   for (i=0; i<(signed int)len; ++i)
01184     {  
01185     buf[i] = *p & 0x7f;
01186     p += 2;
01187     }
01188 
01189   buf[i] = '\0';
01190   return buf;
01191   }
01192 
01193 static unsigned char *strToUnicode(char *p)
01194   {
01195   static unsigned char buf[1024];
01196   size_t l = strlen(p);
01197   int i = 0;
01198   
01199   assert(l*2 < sizeof buf);
01200   
01201   while (l--)
01202     {
01203     buf[i++] = *p++;
01204     buf[i++] = 0;
01205     }
01206   
01207   return buf;
01208   }
01209 
01210 static unsigned char *toString(char *p, size_t len)
01211   {
01212   static unsigned char buf[1024];
01213   
01214   assert(len+1 < sizeof buf);
01215   
01216   memcpy(buf,p,len);
01217   buf[len] = 0;
01218   return buf;
01219   }
01220 
01221 
01222 void BuildAuthRequest(tSmbNtlmAuthRequest *request, long flags, char *host, char *domain)
01223   {
01224     char *h = NULL;//strdup(host);
01225     char *p = NULL;//strchr(h,'@');
01226 //TODO: review default flags
01227 
01228     if (host == NULL)   host = "";
01229     if (domain == NULL) domain = "";
01230 
01231     h = _strdup(host);
01232     p = strchr(h,'@');
01233     if (p)
01234       {
01235         if (!domain) 
01236           domain = p+1;
01237         *p = '\0';
01238       }
01239     if (flags ==0) flags = 0x0000b207; /* Lowest security options to avoid negotiation */
01240     request->bufIndex = 0;
01241     memcpy(request->ident,"NTLMSSP\0\0\0",8);
01242     SIVAL(&request->msgType,0,1);
01243     SIVAL(&request->flags,0,flags);  
01244         
01245         assert(strlen(host) < 128);
01246     AddString(request,host,h);
01247         assert(strlen(domain) < 128);
01248     AddString(request,domain,domain);
01249     free(h);
01250   }
01251 
01252 void buildAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, long flags, char *user, char *password, char *domainname, char *host)
01253   {
01254     uint8 lmRespData[24];
01255     uint8 ntRespData[24];
01256     char *u = _strdup(user);
01257     char *p = strchr(u,'@');
01258     char *w = NULL;
01259     char *d = _strdup(GetUnicodeString(challenge,uDomain));
01260     char *domain = d;
01261         if (domainname != NULL) domain = domainname;
01262 
01263         if (host == NULL) host = "";
01264         w = _strdup(host);
01265 
01266     if (p)
01267       {
01268         domain = p+1;
01269         *p = '\0';
01270       }
01271    
01272     SMBencrypt((uchar*)password,   challenge->challengeData, lmRespData);
01273     SMBNTencrypt((uchar*)password, challenge->challengeData, ntRespData);
01274     
01275     response->bufIndex = 0;
01276     memcpy(response->ident,"NTLMSSP\0\0\0",8);
01277     SIVAL(&response->msgType,0,3);
01278     
01279     AddBytes(response,lmResponse,lmRespData,24);
01280     AddBytes(response,ntResponse,ntRespData,24);
01281 
01282         assert(strlen(domain) < 128);
01283     AddUnicodeString(response,uDomain,domain);
01284         assert(strlen(u) < 128);
01285     AddUnicodeString(response,uUser,u);
01286         assert(strlen(w) < 128);
01287     AddUnicodeString(response,uWks,w);
01288 
01289     AddString(response,sessionKey,NULL);
01290 
01291         if (flags != 0) challenge->flags = flags; /* Overide flags! */
01292     response->flags = challenge->flags;
01293     
01294     if(d) free(d);
01295     if(u) free(u);
01296         if (w) free(w);
01297   }
01298 
01299 
01300 
01301 
01302 
01303 // info functions
01304 void dumpAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request);
01305 void dumpAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge);
01306 void dumpAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response);
01307 
01308 void dumpAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request)
01309   {
01310  printf("NTLM Request:\n");
01311  printf("      Ident = %s\n",request->ident);
01312  printf("      mType = %d\n",IVAL(&request->msgType,0));
01313  printf("      Flags = %08x\n",IVAL(&request->flags,0));
01314  printf("       Host = %s\n",GetString(request,host));
01315  printf("     Domain = %s\n",GetString(request,domain));
01316   }
01317 
01318 void dumpAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge)
01319   {
01320  printf("NTLM Challenge:\n");
01321  printf("      Ident = %s\n",challenge->ident);
01322  printf("      mType = %d\n",IVAL(&challenge->msgType,0));
01323  printf("     Domain = %s\n",GetUnicodeString(challenge,uDomain));
01324  printf("      Flags = %08x\n",IVAL(&challenge->flags,0));
01325  printf("  Challenge = "); dumpRaw(fp, challenge->challengeData,8);
01326  printf("  Uncomplete!! parse optional parameters\n");
01327   }
01328 
01329 void dumpAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response)
01330   {
01331  printf("NTLM Response:\n");
01332  printf("      Ident = %s\n",response->ident);
01333  printf("      mType = %d\n",IVAL(&response->msgType,0));
01334  printf("     LmResp = "); DumpBuffer(fp,response,lmResponse);
01335  printf("     NTResp = "); DumpBuffer(fp,response,ntResponse);
01336  printf("     Domain = %s\n",GetUnicodeString(response,uDomain));
01337  printf("       User = %s\n",GetUnicodeString(response,uUser));
01338  printf("        Wks = %s\n",GetUnicodeString(response,uWks));
01339  printf("       sKey = "); DumpBuffer(fp, response,sessionKey);
01340  printf("      Flags = %08x\n",IVAL(&response->flags,0));
01341   }
01342 
01343 
01344 
01345 
01346 
01347 
01348 
01349 /*
01350  * base64.c -- base-64 conversion routines.
01351  *
01352  * For license terms, see the file COPYING in this directory.
01353  *
01354  * This base 64 encoding is defined in RFC2045 section 6.8,
01355  * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
01356  * scheme used here.
01357  */
01358 
01359 /*
01360  * This code borrowed from fetchmail sources
01361  */
01362 
01363 
01364 static const char base64digits[] =
01365    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
01366 
01367 #define BAD     -1
01368 static const char base64val[] = {
01369     BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
01370     BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
01371     BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
01372      52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
01373     BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
01374      15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,BAD, BAD,BAD,BAD,BAD,
01375     BAD, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
01376      41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,BAD, BAD,BAD,BAD,BAD
01377 };
01378 #define DECODE64(c)  (isascii(c) ? base64val[c] : BAD)
01379 
01380 void to64frombits(unsigned char *out, const unsigned char *in, int inlen)
01381 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
01382 {
01383     for (; inlen >= 3; inlen -= 3)
01384     {
01385         *out++ = base64digits[in[0] >> 2];
01386         *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
01387         *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
01388         *out++ = base64digits[in[2] & 0x3f];
01389         in += 3;
01390     }
01391     if (inlen > 0)
01392     {
01393         unsigned char fragment;
01394     
01395         *out++ = base64digits[in[0] >> 2];
01396         fragment = (in[0] << 4) & 0x30;
01397         if (inlen > 1)
01398             fragment |= in[1] >> 4;
01399         *out++ = base64digits[fragment];
01400         *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
01401         *out++ = '=';
01402     }
01403     *out = '\0';
01404 }
01405 
01406 int from64tobits(char *out, const char *in)
01407 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
01408 {
01409     int len = 0;
01410     register unsigned char digit1, digit2, digit3, digit4;
01411 
01412     if (in[0] == '+' && in[1] == ' ')
01413         in += 2;
01414     if (*in == '\r')
01415         return(0);
01416 
01417     do {
01418         digit1 = in[0];
01419         if (DECODE64(digit1) == BAD)
01420             return(-1);
01421         digit2 = in[1];
01422         if (DECODE64(digit2) == BAD)
01423             return(-1);
01424         digit3 = in[2];
01425         if (digit3 != '=' && DECODE64(digit3) == BAD)
01426             return(-1); 
01427         digit4 = in[3];
01428         if (digit4 != '=' && DECODE64(digit4) == BAD)
01429             return(-1);
01430         in += 4;
01431         *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
01432         ++len;
01433         if (digit3 != '=')
01434         {
01435             *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
01436             ++len;
01437             if (digit4 != '=')
01438             {
01439                 *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
01440                 ++len;
01441             }
01442         }
01443     } while 
01444         (*in && *in != '\r' && digit4 != '=');
01445 
01446     return (len);
01447 }
01448 
01449 /* base64.c ends here */

Generated on Sun Jan 18 00:32:03 2009 for Fast HTTP Vulnerability Scanner by  doxygen 1.5.4