smbencrypt.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:7k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB parameters and setup
  5.    Copyright (C) Andrew Tridgell 1992-1998
  6.    Modified by Jeremy Allison 1995.
  7.    
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.    
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.    
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. #define DEBUG(a,b) ;
  23. extern int DEBUGLEVEL;
  24. #include <unistd.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include "smbbyteorder.h"
  29. #include "smbdes.h"
  30. #include "smbmd4.h"
  31. #ifndef _AIX
  32. typedef unsigned char uchar;
  33. #endif
  34. typedef signed short int16;
  35. typedef unsigned short uint16;
  36. typedef int BOOL;
  37. #define False 0
  38. #define True  1
  39. /****************************************************************************
  40.  Like strncpy but always null terminates. Make sure there is room!
  41.  The variable n should always be one less than the available size.
  42. ****************************************************************************/
  43. char *StrnCpy(char *dest,const char *src, size_t n)
  44. {
  45.   char *d = dest;
  46.   if (!dest) return(NULL);
  47.   if (!src) {
  48.     *dest = 0;
  49.     return(dest);
  50.   }
  51.   while (n-- && (*d++ = *src++)) ;
  52.   *d = 0;
  53.   return(dest);
  54. }
  55. size_t skip_multibyte_char(char c)
  56. {
  57. return 0;
  58. }
  59. /*******************************************************************
  60. safe string copy into a known length string. maxlength does not
  61. include the terminating zero.
  62. ********************************************************************/
  63. char *safe_strcpy(char *dest,const char *src, size_t maxlength)
  64. {
  65.     size_t len;
  66.     if (!dest) {
  67.         DEBUG(0,("ERROR: NULL dest in safe_strcpyn"));
  68.         return NULL;
  69.     }
  70.     if (!src) {
  71.         *dest = 0;
  72.         return dest;
  73.     }  
  74.     len = strlen(src);
  75.     if (len > maxlength) {
  76.             DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]n",
  77.                      (int)(len-maxlength), src));
  78.             len = maxlength;
  79.     }
  80.       
  81.     memcpy(dest, src, len);
  82.     dest[len] = 0;
  83.     return dest;
  84. }  
  85. void strupper(char *s)
  86. {
  87. while (*s)
  88.   {
  89.     {
  90.     size_t skip = skip_multibyte_char( *s );
  91.     if( skip != 0 )
  92.       s += skip;
  93.     else
  94.       {
  95.       if (islower(*s))
  96. *s = toupper(*s);
  97.       s++;
  98.       }
  99.     }
  100.   }
  101. }
  102. extern void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]);
  103. /*
  104.  This implements the X/Open SMB password encryption
  105.  It takes a password, a 8 byte "crypt key" and puts 24 bytes of 
  106.  encrypted password into p24 
  107.  */
  108. void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
  109.   {
  110.   uchar p14[15], p21[21];
  111.   
  112.   memset(p21,'',21);
  113.   memset(p14,'',14);
  114.   StrnCpy((char *)p14,(char *)passwd,14);
  115.   
  116.   strupper((char *)p14);
  117.   E_P16(p14, p21); 
  118.   
  119.   SMBOWFencrypt(p21, c8, p24);
  120.   
  121. #ifdef DEBUG_PASSWORD
  122.   DEBUG(100,("SMBencrypt: lm#, challenge, responsen"));
  123.   dump_data(100, (char *)p21, 16);
  124.   dump_data(100, (char *)c8, 8);
  125.   dump_data(100, (char *)p24, 24);
  126. #endif
  127.   }
  128. /* Routines for Windows NT MD4 Hash functions. */
  129. static int _my_wcslen(int16 *str)
  130. {
  131. int len = 0;
  132. while(*str++ != 0)
  133. len++;
  134. return len;
  135. }
  136. /*
  137.  * Convert a string into an NT UNICODE string.
  138.  * Note that regardless of processor type 
  139.  * this must be in intel (little-endian)
  140.  * format.
  141.  */
  142.  
  143. static int _my_mbstowcs(int16 *dst, uchar *src, int len)
  144. {
  145. int i;
  146. int16 val;
  147.  
  148. for(i = 0; i < len; i++) {
  149. val = *src;
  150. SSVAL(dst,0,val);
  151. dst++;
  152. src++;
  153. if(val == 0)
  154. break;
  155. }
  156. return i;
  157. }
  158. /* 
  159.  * Creates the MD4 Hash of the users password in NT UNICODE.
  160.  */
  161.  
  162. void E_md4hash(uchar *passwd, uchar *p16)
  163. {
  164. int len;
  165. int16 wpwd[129];
  166. /* Password cannot be longer than 128 characters */
  167. len = strlen((char *)passwd);
  168. if(len > 128)
  169. len = 128;
  170. /* Password must be converted to NT unicode */
  171. _my_mbstowcs(wpwd, passwd, len);
  172. wpwd[len] = 0; /* Ensure string is null terminated */
  173. /* Calculate length in bytes */
  174. len = _my_wcslen(wpwd) * sizeof(int16);
  175. mdfour(p16, (unsigned char *)wpwd, len);
  176. }
  177. /* Does both the NT and LM owfs of a user's password */
  178. void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16])
  179. {
  180. char passwd[130];
  181. memset(passwd,'',130);
  182. safe_strcpy( passwd, pwd, sizeof(passwd)-1);
  183. /* Calculate the MD4 hash (NT compatible) of the password */
  184. memset(nt_p16, '', 16);
  185. E_md4hash((uchar *)passwd, nt_p16);
  186. #ifdef DEBUG_PASSWORD
  187. DEBUG(100,("nt_lm_owf_gen: pwd, nt#n"));
  188. dump_data(120, passwd, strlen(passwd));
  189. dump_data(100, (char *)nt_p16, 16);
  190. #endif
  191. /* Mangle the passwords into Lanman format */
  192. passwd[14] = '';
  193. strupper(passwd);
  194. /* Calculate the SMB (lanman) hash functions of the password */
  195. memset(p16, '', 16);
  196. E_P16((uchar *) passwd, (uchar *)p16);
  197. #ifdef DEBUG_PASSWORD
  198. DEBUG(100,("nt_lm_owf_gen: pwd, lm#n"));
  199. dump_data(120, passwd, strlen(passwd));
  200. dump_data(100, (char *)p16, 16);
  201. #endif
  202. /* clear out local copy of user's password (just being paranoid). */
  203. memset(passwd, '', sizeof(passwd));
  204. }
  205. /* Does the des encryption from the NT or LM MD4 hash. */
  206. void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24])
  207. {
  208. uchar p21[21];
  209.  
  210. memset(p21,'',21);
  211.  
  212. memcpy(p21, passwd, 16);    
  213. E_P24(p21, c8, p24);
  214. }
  215. /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
  216. void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24])
  217. {
  218. uchar p21[21];
  219.  
  220. memset(p21,'',21);
  221. memcpy(p21, passwd, 8);    
  222. memset(p21 + 8, 0xbd, 8);    
  223. E_P24(p21, ntlmchalresp, p24);
  224. #ifdef DEBUG_PASSWORD
  225. DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24n"));
  226. dump_data(100, (char *)p21, 21);
  227. dump_data(100, (char *)ntlmchalresp, 8);
  228. dump_data(100, (char *)p24, 24);
  229. #endif
  230. }
  231. /* Does the NT MD4 hash then des encryption. */
  232.  
  233. void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
  234. {
  235. uchar p21[21];
  236.  
  237. memset(p21,'',21);
  238.  
  239. E_md4hash(passwd, p21);    
  240. SMBOWFencrypt(p21, c8, p24);
  241. #ifdef DEBUG_PASSWORD
  242. DEBUG(100,("SMBNTencrypt: nt#, challenge, responsen"));
  243. dump_data(100, (char *)p21, 16);
  244. dump_data(100, (char *)c8, 8);
  245. dump_data(100, (char *)p24, 24);
  246. #endif
  247. }
  248. #if 0
  249. BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
  250. {
  251. int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
  252. if (new_pw_len > 512)
  253. {
  254. DEBUG(0,("make_oem_passwd_hash: new password is too long.n"));
  255. return False;
  256. }
  257. /*
  258.  * Now setup the data area.
  259.  * We need to generate a random fill
  260.  * for this area to make it harder to
  261.  * decrypt. JRA.
  262.  */
  263. generate_random_buffer((unsigned char *)data, 516, False);
  264. if (unicode)
  265. {
  266. struni2( &data[512 - new_pw_len], passwd);
  267. }
  268. else
  269. {
  270. fstrcpy( &data[512 - new_pw_len], passwd);
  271. }
  272. SIVAL(data, 512, new_pw_len);
  273. #ifdef DEBUG_PASSWORD
  274. DEBUG(100,("make_oem_passwd_hashn"));
  275. dump_data(100, data, 516);
  276. #endif
  277. SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
  278. return True;
  279. }
  280. #endif