Mercurial > pidgin
comparison src/protocols/simple/ntlm.c @ 11353:0f03b5492130
[gaim-migrate @ 13572]
ntlm support for sip
committer: Tailor Script <tailor@pidgin.im>
author | Thomas Butter <tbutter> |
---|---|
date | Sat, 27 Aug 2005 09:25:15 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
11352:0bd2edda4f12 | 11353:0f03b5492130 |
---|---|
1 /** | |
2 * @file ntlm.c | |
3 * | |
4 * gaim | |
5 * | |
6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> | |
7 * | |
8 * hashing done according to description of NTLM on | |
9 * http://www.innovation.ch/java/ntlm.html | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 | |
26 #include "util.h" | |
27 #include "ntlm.h" | |
28 #include "cipher.h" | |
29 #include <string.h> | |
30 | |
31 gchar *ntlm_type1_message(gchar *hostname, gchar *domain) { | |
32 char *msg = g_malloc0(sizeof(struct type1_message) + strlen(hostname) + strlen(domain)); | |
33 struct type1_message *tmsg = (struct type1_message*)msg; | |
34 tmsg->protocol[0] = 'N'; | |
35 tmsg->protocol[1] = 'T'; | |
36 tmsg->protocol[2] = 'L'; | |
37 tmsg->protocol[3] = 'M'; | |
38 tmsg->protocol[4] = 'S'; | |
39 tmsg->protocol[5] = 'S'; | |
40 tmsg->protocol[6] = 'P'; | |
41 tmsg->protocol[7] = '\0'; | |
42 tmsg->type= 0x01; | |
43 tmsg->flags = 0xb203; | |
44 tmsg->dom_len1 = tmsg->dom_len2 = strlen(domain); | |
45 tmsg->dom_off = 32+strlen(hostname); | |
46 tmsg->host_len1 = tmsg->host_len2 = strlen(hostname); | |
47 tmsg->host_off= 32; | |
48 memcpy(msg+sizeof(struct type1_message),hostname,strlen(hostname)); | |
49 memcpy(msg+sizeof(struct type1_message)+strlen(hostname),domain,strlen(domain)); | |
50 | |
51 return gaim_base64_encode(msg, sizeof(struct type1_message) + strlen(hostname) + strlen(domain)); | |
52 } | |
53 | |
54 gchar *ntlm_get_nonce(gchar *type2) { | |
55 int retlen; | |
56 static gchar nonce[8]; | |
57 struct type2_message *tmsg = (struct type2_message*)gaim_base64_decode(type2, &retlen); | |
58 memcpy(nonce, tmsg->nonce, 8); | |
59 g_free(tmsg); | |
60 return nonce; | |
61 } | |
62 | |
63 static void setup_des_key(unsigned char key_56[], char *key) | |
64 { | |
65 key[0] = key_56[0]; | |
66 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); | |
67 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); | |
68 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); | |
69 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); | |
70 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); | |
71 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); | |
72 key[7] = (key_56[6] << 1) & 0xFF; | |
73 } | |
74 | |
75 /* | |
76 * helper function for gaim cipher.c | |
77 */ | |
78 static void des_ecb_encrypt(char *plaintext, char *result, char *key) { | |
79 GaimCipher *cipher; | |
80 GaimCipherContext *context; | |
81 int outlen; | |
82 | |
83 cipher = gaim_ciphers_find_cipher("des"); | |
84 context = gaim_cipher_context_new(cipher, NULL); | |
85 gaim_cipher_context_set_key(context, key); | |
86 gaim_cipher_context_encrypt(context, plaintext, 8, result, &outlen); | |
87 gaim_cipher_context_destroy(context); | |
88 } | |
89 | |
90 /* | |
91 * takes a 21 byte array and treats it as 3 56-bit DES keys. The | |
92 * 8 byte plaintext is encrypted with each key and the resulting 24 | |
93 * bytes are stored in the results array. | |
94 */ | |
95 static void calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results) | |
96 { | |
97 gchar key[8]; | |
98 setup_des_key(keys, key); | |
99 des_ecb_encrypt(plaintext, results, key); | |
100 | |
101 setup_des_key(keys+7, key); | |
102 des_ecb_encrypt(plaintext, (results+8), key); | |
103 | |
104 setup_des_key(keys+14, key); | |
105 des_ecb_encrypt(plaintext, (results+16), key); | |
106 } | |
107 | |
108 gchar *ntlm_type3_message(gchar *username, gchar *passw, gchar *hostname, gchar *domain, gchar *nonce) { | |
109 char lm_pw[14]; | |
110 unsigned char lm_hpw[21]; | |
111 gchar key[8]; | |
112 int len = strlen(passw); | |
113 unsigned char lm_resp[24], nt_resp[24]; | |
114 unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; | |
115 unsigned char nt_hpw[21]; | |
116 int lennt; | |
117 char nt_pw[128]; | |
118 GaimCipher *cipher; | |
119 GaimCipherContext *context; | |
120 int idx = 0; | |
121 | |
122 if (len > 14) len = 14; | |
123 | |
124 for (idx=0; idx<len; idx++) | |
125 lm_pw[idx] = g_ascii_toupper(passw[idx]); | |
126 for (; idx<14; idx++) | |
127 lm_pw[idx] = 0; | |
128 | |
129 setup_des_key(lm_pw, key); | |
130 des_ecb_encrypt(magic, lm_hpw, key); | |
131 | |
132 setup_des_key(lm_pw+7, key); | |
133 des_ecb_encrypt(magic, lm_hpw+8, key); | |
134 | |
135 memset(lm_hpw+16, 0, 5); | |
136 | |
137 | |
138 lennt = strlen(passw); | |
139 for (idx=0; idx<lennt; idx++) | |
140 { | |
141 nt_pw[2*idx] = passw[idx]; | |
142 nt_pw[2*idx+1] = 0; | |
143 } | |
144 | |
145 cipher = gaim_ciphers_find_cipher("md4"); | |
146 context = gaim_cipher_context_new(cipher, NULL); | |
147 gaim_cipher_context_append(context, nt_pw, 2*lennt); | |
148 gaim_cipher_context_digest(context, 21, nt_hpw, NULL); | |
149 gaim_cipher_context_destroy(context); | |
150 | |
151 memset(nt_hpw+16, 0, 5); | |
152 | |
153 | |
154 calc_resp(lm_hpw, nonce, lm_resp); | |
155 calc_resp(nt_hpw, nonce, nt_resp); | |
156 return NULL; | |
157 } |