]> Pileus Git - ~andy/fetchmail/blob - smbencrypt.c
Fix typo repsonsible -> responsible.
[~andy/fetchmail] / smbencrypt.c
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
23 #define DEBUG(a,b) ;
24
25 extern int DEBUGLEVEL;
26
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include "smbbyteorder.h"
33 #include "smbdes.h"
34 #include "smbencrypt.h"
35 #include "smbmd4.h"
36
37 typedef int BOOL;
38 #define False 0
39 #define True  1
40
41 /****************************************************************************
42  Like strncpy but always null terminates. Make sure there is room!
43  The variable n should always be one less than the available size.
44 ****************************************************************************/
45
46 static char *StrnCpy(char *dest,const char *src, size_t n)
47 {
48   char *d = dest;
49   if (!dest) return(NULL);
50   if (!src) {
51     *dest = 0;
52     return(dest);
53   }
54   while (n-- && (*d++ = *src++)) ;
55   *d = 0;
56   return(dest);
57 }
58
59 static size_t skip_multibyte_char(char c)
60 {
61     (void)c;
62     return 0;
63 }
64
65 static void strupper(char *s)
66 {
67 while (*s)
68   {
69     {
70     size_t skip = skip_multibyte_char( *s );
71     if( skip != 0 )
72       s += skip;
73     else
74       {
75       if (islower((unsigned char)*s))
76         *s = toupper((unsigned char)*s);
77       s++;
78       }
79     }
80   }
81 }
82
83 extern void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, unsigned char p24[24]);
84
85 /*
86  This implements the X/Open SMB password encryption
87  It takes a password, a 8 byte "crypt key" and puts 24 bytes of 
88  encrypted password into p24 
89  */
90
91 void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
92   {
93   unsigned char p14[15], p21[21];
94   
95   memset(p21,'\0',21);
96   memset(p14,'\0',14);
97   StrnCpy((char *)p14,(char *)passwd,14);
98   
99   strupper((char *)p14);
100   E_P16(p14, p21); 
101   
102   SMBOWFencrypt(p21, c8, p24);
103   
104 #ifdef DEBUG_PASSWORD
105   DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
106   dump_data(100, (char *)p21, 16);
107   dump_data(100, (char *)c8, 8);
108   dump_data(100, (char *)p24, 24);
109 #endif
110   }
111
112 /* Routines for Windows NT MD4 Hash functions. */
113 static int _my_wcslen(int16_t *str)
114 {
115         int len = 0;
116         while(*str++ != 0)
117                 len++;
118         return len;
119 }
120
121 /*
122  * Convert a string into an NT UNICODE string.
123  * Note that regardless of processor type 
124  * this must be in intel (little-endian)
125  * format.
126  */
127  
128 static int _my_mbstowcs(int16_t *dst, unsigned char *src, int len)
129 {
130         int i;
131         int16_t val;
132  
133         for(i = 0; i < len; i++) {
134                 val = *src;
135                 SSVAL(dst,0,val);
136                 dst++;
137                 src++;
138                 if(val == 0)
139                         break;
140         }
141         return i;
142 }
143
144 /* 
145  * Creates the MD4 Hash of the users password in NT UNICODE.
146  */
147  
148 static void E_md4hash(unsigned char *passwd, unsigned char *p16)
149 {
150         int len;
151         int16_t wpwd[129];
152         
153         /* Password cannot be longer than 128 characters */
154         len = strlen((char *)passwd);
155         if(len > 128)
156                 len = 128;
157         /* Password must be converted to NT unicode */
158         _my_mbstowcs(wpwd, passwd, len);
159         wpwd[len] = 0; /* Ensure string is null terminated */
160         /* Calculate length in bytes */
161         len = _my_wcslen(wpwd) * sizeof(int16_t);
162
163         mdfour(p16, (unsigned char *)wpwd, len);
164 }
165
166 /* Does the des encryption from the NT or LM MD4 hash. */
167 void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, unsigned char p24[24])
168 {
169         unsigned char p21[21];
170  
171         memset(p21,'\0',21);
172  
173         memcpy(p21, passwd, 16);    
174         E_P24(p21, c8, p24);
175 }
176
177 /* Does the NT MD4 hash then des encryption. */
178 void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
179 {
180         unsigned char p21[21];
181  
182         memset(p21,'\0',21);
183  
184         E_md4hash(passwd, p21);    
185         SMBOWFencrypt(p21, c8, p24);
186
187 #ifdef DEBUG_PASSWORD
188         DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n"));
189         dump_data(100, (char *)p21, 16);
190         dump_data(100, (char *)c8, 8);
191         dump_data(100, (char *)p24, 24);
192 #endif
193 }