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