Lines 74-82
camel_sasl_ntlm_get_type (void)
Link Here
|
74 |
|
74 |
|
75 |
#define NTLM_REQUEST "NTLMSSP\x00\x01\x00\x00\x00\x06\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00" |
75 |
#define NTLM_REQUEST "NTLMSSP\x00\x01\x00\x00\x00\x06\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00" |
76 |
|
76 |
|
77 |
#define NTLM_CHALLENGE_NONCE_OFFSET 24 |
77 |
#define NTLM_CHALLENGE_DOMAIN_OFFSET 12 |
78 |
#define NTLM_CHALLENGE_DOMAIN_OFFSET 48 |
78 |
#define NTLM_CHALLENGE_NONCE_OFFSET 24 |
79 |
#define NTLM_CHALLENGE_DOMAIN_LEN_OFFSET 44 |
|
|
80 |
|
79 |
|
81 |
#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" |
80 |
#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" |
82 |
#define NTLM_RESPONSE_FLAGS "\x82\x01" |
81 |
#define NTLM_RESPONSE_FLAGS "\x82\x01" |
Lines 93-114
static void ntlm_calc_response (const
Link Here
|
93 |
guchar results[24]); |
92 |
guchar results[24]); |
94 |
static void ntlm_lanmanager_hash (const char *password, char hash[21]); |
93 |
static void ntlm_lanmanager_hash (const char *password, char hash[21]); |
95 |
static void ntlm_nt_hash (const char *password, char hash[21]); |
94 |
static void ntlm_nt_hash (const char *password, char hash[21]); |
96 |
static void ntlm_set_string (GByteArray *ba, int offset, |
95 |
|
97 |
const char *data, int len); |
96 |
typedef struct { |
|
|
97 |
guint16 length; |
98 |
guint16 allocated; |
99 |
guint32 offset; |
100 |
} SecurityBuffer; |
101 |
|
102 |
static GString * |
103 |
ntlm_get_string (GByteArray *ba, int offset) |
104 |
{ |
105 |
SecurityBuffer *secbuf; |
106 |
GString *string; |
107 |
gchar *buf_string; |
108 |
guint16 buf_length; |
109 |
guint32 buf_offset; |
110 |
|
111 |
secbuf = (SecurityBuffer *) &ba->data[offset]; |
112 |
buf_length = GUINT16_FROM_LE (secbuf->length); |
113 |
buf_offset = GUINT32_FROM_LE (secbuf->offset); |
114 |
|
115 |
if (ba->len < buf_offset + buf_length) |
116 |
return NULL; |
117 |
|
118 |
string = g_string_sized_new (buf_length); |
119 |
buf_string = (gchar *) &ba->data[buf_offset]; |
120 |
g_string_append_len (string, buf_string, buf_length); |
121 |
|
122 |
return string; |
123 |
} |
124 |
|
125 |
static void |
126 |
ntlm_set_string (GByteArray *ba, int offset, const char *data, int len) |
127 |
{ |
128 |
SecurityBuffer *secbuf; |
129 |
|
130 |
secbuf = (SecurityBuffer *) &ba->data[offset]; |
131 |
secbuf->length = GUINT16_TO_LE (len); |
132 |
secbuf->offset = GUINT32_TO_LE (ba->len); |
133 |
secbuf->allocated = secbuf->length; |
134 |
|
135 |
g_byte_array_append (ba, (guint8 *) data, len); |
136 |
} |
98 |
|
137 |
|
99 |
static GByteArray * |
138 |
static GByteArray * |
100 |
ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) |
139 |
ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) |
101 |
{ |
140 |
{ |
102 |
GByteArray *ret; |
141 |
GByteArray *ret; |
103 |
guchar nonce[8], hash[21], lm_resp[24], nt_resp[24]; |
142 |
guchar nonce[8], hash[21], lm_resp[24], nt_resp[24]; |
|
|
143 |
GString *domain; |
104 |
|
144 |
|
105 |
ret = g_byte_array_new (); |
145 |
ret = g_byte_array_new (); |
106 |
|
146 |
|
107 |
if (!token || !token->len) { |
147 |
if (!token || token->len < NTLM_CHALLENGE_NONCE_OFFSET + 8) |
108 |
g_byte_array_append (ret, (guint8 *) NTLM_REQUEST, |
148 |
goto fail; |
109 |
sizeof (NTLM_REQUEST) - 1); |
|
|
110 |
return ret; |
111 |
} |
112 |
|
149 |
|
113 |
memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8); |
150 |
memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8); |
114 |
ntlm_lanmanager_hash (sasl->service->url->passwd, (char *) hash); |
151 |
ntlm_lanmanager_hash (sasl->service->url->passwd, (char *) hash); |
Lines 116-122
ntlm_challenge (CamelSasl *sasl, GByteAr
Link Here
|
116 |
ntlm_nt_hash (sasl->service->url->passwd, (char *) hash); |
153 |
ntlm_nt_hash (sasl->service->url->passwd, (char *) hash); |
117 |
ntlm_calc_response (hash, nonce, nt_resp); |
154 |
ntlm_calc_response (hash, nonce, nt_resp); |
118 |
|
155 |
|
119 |
ret = g_byte_array_new (); |
156 |
domain = ntlm_get_string (token, NTLM_CHALLENGE_DOMAIN_OFFSET); |
|
|
157 |
if (domain == NULL) |
158 |
goto fail; |
159 |
|
160 |
/* Don't jump to 'fail' label after this point. */ |
120 |
g_byte_array_set_size (ret, NTLM_RESPONSE_BASE_SIZE); |
161 |
g_byte_array_set_size (ret, NTLM_RESPONSE_BASE_SIZE); |
121 |
memset (ret->data, 0, NTLM_RESPONSE_BASE_SIZE); |
162 |
memset (ret->data, 0, NTLM_RESPONSE_BASE_SIZE); |
122 |
memcpy (ret->data, NTLM_RESPONSE_HEADER, |
163 |
memcpy (ret->data, NTLM_RESPONSE_HEADER, |
Lines 125-132
ntlm_challenge (CamelSasl *sasl, GByteAr
Link Here
|
125 |
NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1); |
166 |
NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1); |
126 |
|
167 |
|
127 |
ntlm_set_string (ret, NTLM_RESPONSE_DOMAIN_OFFSET, |
168 |
ntlm_set_string (ret, NTLM_RESPONSE_DOMAIN_OFFSET, |
128 |
(const char *) token->data + NTLM_CHALLENGE_DOMAIN_OFFSET, |
169 |
domain->str, domain->len); |
129 |
atoi ((char *) token->data + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET)); |
|
|
130 |
ntlm_set_string (ret, NTLM_RESPONSE_USER_OFFSET, |
170 |
ntlm_set_string (ret, NTLM_RESPONSE_USER_OFFSET, |
131 |
sasl->service->url->user, |
171 |
sasl->service->url->user, |
132 |
strlen (sasl->service->url->user)); |
172 |
strlen (sasl->service->url->user)); |
Lines 138-143
ntlm_challenge (CamelSasl *sasl, GByteAr
Link Here
|
138 |
(const char *) nt_resp, sizeof (nt_resp)); |
178 |
(const char *) nt_resp, sizeof (nt_resp)); |
139 |
|
179 |
|
140 |
sasl->authenticated = TRUE; |
180 |
sasl->authenticated = TRUE; |
|
|
181 |
|
182 |
g_string_free (domain, TRUE); |
183 |
|
184 |
goto exit; |
185 |
|
186 |
fail: |
187 |
/* If the challenge is malformed, restart authentication. |
188 |
* XXX A malicious server could make this loop indefinitely. */ |
189 |
g_byte_array_append (ret, (guint8 *) NTLM_REQUEST, |
190 |
sizeof (NTLM_REQUEST) - 1); |
191 |
|
192 |
exit: |
141 |
return ret; |
193 |
return ret; |
142 |
} |
194 |
} |
143 |
|
195 |
|
Lines 201-217
ntlm_nt_hash (const char *password, char
Link Here
|
201 |
g_free (buf); |
253 |
g_free (buf); |
202 |
} |
254 |
} |
203 |
|
255 |
|
204 |
static void |
|
|
205 |
ntlm_set_string (GByteArray *ba, int offset, const char *data, int len) |
206 |
{ |
207 |
ba->data[offset ] = ba->data[offset + 2] = len & 0xFF; |
208 |
ba->data[offset + 1] = ba->data[offset + 3] = (len >> 8) & 0xFF; |
209 |
ba->data[offset + 4] = ba->len & 0xFF; |
210 |
ba->data[offset + 5] = (ba->len >> 8) & 0xFF; |
211 |
g_byte_array_append (ba, (guint8 *) data, len); |
212 |
} |
213 |
|
214 |
|
215 |
#define KEYBITS(k,s) \ |
256 |
#define KEYBITS(k,s) \ |
216 |
(((k[(s)/8] << ((s)%8)) & 0xFF) | (k[(s)/8+1] >> (8-(s)%8))) |
257 |
(((k[(s)/8] << ((s)%8)) & 0xFF) | (k[(s)/8+1] >> (8-(s)%8))) |
217 |
|
258 |
|