debug_winbindd.sh: use fuser, don't rely on process name to detect the idmap child
[slow/toolbox.git] / ntlm.c
1 /*
2  * https://msdn.microsoft.com/en-us/library/cc245828.aspx
3  * http://buchananweb.co.uk/security50.aspx
4  * http://ubiqx.org/cifs/examples/SMB/listing06.html
5  * http://davenport.sourceforge.net/ntlm.html#theType1Message
6  */
7
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <stdbool.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <dirent.h>
17 #include <sys/types.h>
18 #include <ctype.h>
19
20 #include <talloc.h>
21 #include <gcrypt.h>
22 #include <openssl/des.h>
23
24 #define ERR_USAGE       1
25 #define ERR_SYSCALL     2
26 #define ERR_CALL        3
27 #define ERR_FATAL       4
28
29 #define MIN(a,b) ((a)<(b)?(a):(b))
30
31 #define ERROR(err, ...)                                                 \
32         do {                                                            \
33                 do_log(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);  \
34                 exit(err);                                              \
35         } while (0)
36
37 #define LOG(...)                                                        \
38         do {                                                            \
39                 do_log(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);  \
40         } while (0)
41
42 #define FREE(p)                         \
43         do {                            \
44                 free(p);                \
45                 p = 0;                  \
46         } while (0)
47
48 static void do_log(const char *file, int line, const char *func,
49                    const char *fmt, ...)
50 {
51         char *message;
52         va_list args;
53         int len;
54
55         va_start(args, fmt);
56         len = vasprintf(&message, fmt, args);
57         va_end(args);
58         if (len == -1) {
59                 exit(ERR_FATAL);
60         }
61
62         printf("%s:%d(%s): %s\n", file, line, func, message);
63         free(message);
64 }
65
66 static void print_asc(const uint8_t *buf, int len)
67 {
68         int i;
69         char s[2];
70         s[1] = 0;
71
72         for (i=0; i<len; i++) {
73                 s[0] = isprint(buf[i]) ? buf[i] : '.';
74                 printf(s);
75         }
76 }
77
78 /**
79  * Write dump of binary data to a callback
80  */
81 static void dump_data(const uint8_t *buf, size_t len)
82 {
83         int i = 0;
84         static const uint8_t empty[16] = { 0, };
85         bool skipped = false;
86         char tmp[16];
87
88         if (len == 0) {
89                 return;
90         }
91
92         for (i = 0; i < len; ) {
93
94                 if (i%16 == 0) {
95                         if (i<len)  {
96                                 printf("[%04X] ", i);
97                         }
98                 }
99
100                 printf("%02X ", (int)buf[i]);
101                 i++;
102                 if (i%8 == 0) {
103                         printf("  ");
104                 }
105                 if (i%16 == 0) {
106
107                         print_asc(&buf[i-16], 8);
108                         printf(" ");
109                         print_asc(&buf[i-8], 8);
110                         printf("\n");
111                 }
112         }
113
114         if (i%16) {
115                 int n;
116                 n = 16 - (i%16);
117                 printf("  ");
118                 if (n>8) {
119                         printf(" ");
120                 }
121                 while (n--) {
122                         printf("   ");
123                 }
124                 n = MIN(8,i%16);
125                 print_asc(&buf[i-(i%16)], n);
126                 printf(" ");
127                 n = (i%16) - n;
128                 if (n>0) {
129                         print_asc(&buf[i-n], n);
130                 }
131                 printf("\n");
132         }
133
134 }
135
136 static uint8_t parity(uint8_t _c) {
137         uint8_t bits_set = 0;
138         uint8_t parity_needed = 0;
139         uint8_t c = _c;
140
141         while (c > 0) {
142                 bits_set += c & 1 ? 1 : 0;
143                 c >>= 1;
144         }
145
146         parity_needed = bits_set & 1 ? 0 : 1;
147         return parity_needed;
148 }
149
150 static char *make_des_key(TALLOC_CTX *mem_ctx, uint8_t *key56)
151 {
152         uint8_t *key64 = NULL;
153         int i;
154
155         key64 = talloc_array(mem_ctx, uint8_t, 8);
156         if (key64 == NULL) {
157                 ERROR(ERR_CALL, "talloc_array\n");
158         }
159
160         key64[0] = key56[0]>>1;
161         key64[1] = ((key56[0]&0x01)<<6) | (key56[1]>>2);
162         key64[2] = ((key56[1]&0x03)<<5) | (key56[2]>>3);
163         key64[3] = ((key56[2]&0x07)<<4) | (key56[3]>>4);
164         key64[4] = ((key56[3]&0x0F)<<3) | (key56[4]>>5);
165         key64[5] = ((key56[4]&0x1F)<<2) | (key56[5]>>6);
166         key64[6] = ((key56[5]&0x3F)<<1) | (key56[6]>>7);
167         key64[7] = key56[6]&0x7F;
168         for (i=0;i<8;i++) {
169                 key64[i] = (key64[i]<<1);
170         }
171
172 #if 0
173         key64[0] = key56[0] & 0xFE;
174         key64[1] = (key56[0] << 7) | (key56[1] >> 1) & 0xFE;
175         key64[2] = (key56[1] << 6) | (key56[2] >> 2) & 0xFE;
176         key64[3] = (key56[2] << 5) | (key56[3] >> 3) & 0xFE;
177         key64[4] = (key56[3] << 4) | (key56[4] >> 4) & 0xFE;
178         key64[5] = (key56[4] << 3) | (key56[5] >> 5) & 0xFE;
179         key64[6] = (key56[5] << 2) | (key56[6] >> 6) & 0xFE;
180         key64[7] = key56[6] << 1;
181 #endif
182         for (i= 0; i < 8; i++) {
183                 key64[i] |= parity(key64[i]) & 1;
184         }
185
186         return key64;
187 }
188
189 static char *lm_hash_gcrypt(TALLOC_CTX *mem_ctx, const char *_pwd)
190 {
191         gcry_error_t gcry_err;
192         gcry_cipher_hd_t gcry_hd;
193         const char *lm_str = "KGS!@#$%";
194         char lm_hash1[8];
195         char lm_hash2[8];
196         char *lm_hash = NULL;
197         char *des_key = NULL;
198         int i;
199         char pwd[14] = { 0 };
200
201         strncpy(pwd, _pwd, 14);
202
203         for (i = 0; pwd[i] != '\0'; i++) {
204                 if (!isascii(pwd[i])) {
205                         LOG("Password contains non-ASCII characters, "
206                             "skipping LM hash\n");
207                         return NULL;
208                 }
209                 pwd[i] = toupper(pwd[i]);
210         }
211
212         lm_hash = talloc_array(mem_ctx, char, 16);
213         if (lm_hash == NULL) {
214                 ERROR(3, "talloc error\n");
215         }
216
217         gcry_err = gcry_cipher_open(&gcry_hd,
218                                     GCRY_CIPHER_DES,
219                                     GCRY_CIPHER_MODE_ECB,
220                                     0);
221         if (gcry_err != 0) {
222                 ERROR(3, ("gcry_cipher_open: %s\n", gcry_strerror(gcry_err)));
223         }
224
225         des_key = make_des_key(mem_ctx, pwd);
226         if (des_key == NULL) {
227                 ERROR(ERR_CALL, "make_des_key\n");
228         }
229
230         gcry_err = gcry_cipher_setkey(gcry_hd, des_key, 8);
231         if (gcry_err != 0) {
232                 ERROR(3, ("gcry_cipher_setkey: %s\n", gcry_strerror(gcry_err)));
233         }
234
235         TALLOC_FREE(des_key);
236
237         gcry_err = gcry_cipher_encrypt(gcry_hd, lm_hash1, 8, lm_str, 8);
238         if (gcry_err != 0) {
239                 ERROR(3, ("gcry_cipher_encrypt: %s\n", gcry_strerror(gcry_err)));
240         }
241
242         gcry_cipher_close(gcry_hd);
243
244         gcry_err = gcry_cipher_open(&gcry_hd,
245                                     GCRY_CIPHER_DES,
246                                     GCRY_CIPHER_MODE_ECB,
247                                     0);
248         if (gcry_err != 0) {
249                 ERROR(3, ("gcry_cipher_open: %s\n", gcry_strerror(gcry_err)));
250         }
251
252         des_key = make_des_key(mem_ctx, pwd + 7);
253         if (des_key == NULL) {
254                 ERROR(ERR_CALL, "make_des_key\n");
255         }
256
257         gcry_err = gcry_cipher_setkey(gcry_hd, des_key, 8);
258         if (gcry_err != 0) {
259                 ERROR(3, ("gcry_cipher_setkey: %s\n", gcry_strerror(gcry_err)));
260         }
261
262         TALLOC_FREE(des_key);
263
264         gcry_err = gcry_cipher_encrypt(gcry_hd, lm_hash2, 8, lm_str, 8);
265         if (gcry_err != 0) {
266                 ERROR(3, ("gcry_cipher_encrypt: %s\n", gcry_strerror(gcry_err)));
267         }
268
269         gcry_cipher_close(gcry_hd);
270
271         memcpy(lm_hash, lm_hash1, 8);
272         memcpy(lm_hash + 8 ,lm_hash2, 8);
273         printf("libgcrypt LM Hash:\n");
274         dump_data(lm_hash, 16);
275
276         return lm_hash;
277 }
278
279 static char *lm_hash_openssl(TALLOC_CTX *mem_ctx, const char *_pwd)
280 {
281         const_DES_cblock des_key1, des_key2;
282         DES_cblock lm_hash1, lm_hash2, lm_magic;
283         DES_key_schedule des_sched1, des_sched2;
284         const char *lm_str = "KGS!@#$%";
285         char *lm_hash = NULL;
286         char *des_key = NULL;
287         int i;
288         char pwd1[8] = { 0 };
289         char pwd2[8] = { 0 };
290
291         memcpy(pwd1, _pwd, 7);
292         memcpy(pwd2, _pwd + 7, 7);
293         memcpy(lm_magic, lm_str, 8);
294
295         for (i = 0; i < 7; i++) {
296                 if (!isascii(pwd1[i]) || !isascii(pwd2[i])) {
297                         LOG("Password contains non-ASCII characters, "
298                             "skipping LM hash\n");
299                         return NULL;
300                 }
301                 pwd1[i] = toupper(pwd1[i]);
302                 pwd2[i] = toupper(pwd2[i]);
303         }
304
305         lm_hash = talloc_array(mem_ctx, char, 16);
306         if (lm_hash == NULL) {
307                 ERROR(3, "talloc error\n");
308         }
309
310         des_key = make_des_key(mem_ctx, pwd1);
311         if (des_key == NULL) {
312                 ERROR(ERR_CALL, "make_des_key\n");
313         }
314         memcpy(des_key1, des_key, 8);
315         TALLOC_FREE(des_key);
316
317         DES_set_key_unchecked(&des_key1, &des_sched1);
318
319         des_key = make_des_key(mem_ctx, pwd2);
320         if (des_key == NULL) {
321                 ERROR(ERR_CALL, "make_des_key\n");
322         }
323         memcpy(des_key2, des_key, 8);
324         TALLOC_FREE(des_key);
325
326         DES_set_key_unchecked(&des_key2, &des_sched2);
327
328         DES_ecb_encrypt(&lm_magic, &lm_hash1, &des_sched1, DES_ENCRYPT);
329         DES_ecb_encrypt(&lm_magic, &lm_hash2, &des_sched2, DES_ENCRYPT);
330
331         memcpy(lm_hash, lm_hash1, 8);
332         memcpy(lm_hash + 8 ,lm_hash2, 8);
333         printf("OpenSSL LM Hash:\n");
334         dump_data(lm_hash, 16);
335
336         return lm_hash;
337 }
338
339 int main(int argc, char **argv)
340 {
341         TALLOC_CTX *mem_ctx = NULL;
342         bool ok;
343         char pwdbuf[256];
344         int pwdlen;
345         char *p;
346         char *lm_hash_str = NULL;
347
348         mem_ctx = talloc_init("ntlm");
349         if (mem_ctx == NULL) {
350                 ERROR(2, "talloc_init\n");
351         }
352
353         memset(pwdbuf, 0, sizeof(pwdbuf));
354
355         ok = gcry_check_version(GCRYPT_VERSION);
356         if (!ok) {
357                 fputs("libgcrypt version mismatch\n", stderr);
358                 exit(1);
359         }
360
361         printf("Enter password: ");
362
363         p = fgets(pwdbuf, sizeof(pwdbuf), stdin);
364         if (p == NULL) {
365                 ERROR(2, "fgets: %s\n", strerror(errno));
366         }
367
368         pwdlen = strlen(pwdbuf);
369         if (pwdbuf[pwdlen - 1] == '\n') {
370                 pwdbuf[pwdlen - 1] = '\0';
371                 pwdlen--;
372         }
373
374         lm_hash_str = lm_hash_gcrypt(mem_ctx, pwdbuf);
375         if (lm_hash_str == NULL) {
376                 ERROR(2, "lm_hash\n");
377         }
378         TALLOC_FREE(lm_hash_str);
379
380         lm_hash_str = lm_hash_openssl(mem_ctx, pwdbuf);
381         if (lm_hash_str == NULL) {
382                 ERROR(2, "lm_hash\n");
383         }
384
385         TALLOC_FREE(mem_ctx);
386         return 0;
387 }