1 /*
2 * OpenConnect (SSL + DTLS) VPN client
3 *
4 * Copyright © 2008-2015 Intel Corporation.
5 *
6 * Author: David Woodhouse <dwmw2@infradead.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
17
18 #include <config.h>
19
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <time.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <ctype.h>
31 #ifdef HAVE_ALLOCA_H
32 #include <alloca.h>
33 #endif
34 #ifndef _WIN32
35 #include <sys/wait.h>
36 #endif
37
38 #include "openconnect-internal.h"
39
40 #define NTLM_SSO_REQ 2 /* SSO type1 packet sent */
41 #define NTLM_MANUAL 3 /* SSO challenge/response sent or skipped; manual next */
42 #define NTLM_MANUAL_REQ 4 /* manual type1 packet sent */
43
44 #ifdef _WIN32
ntlm_sspi(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf,const char * challenge)45 static int ntlm_sspi(struct openconnect_info *vpninfo, int proxy,
46 struct http_auth_state *auth_state,
47 struct oc_text_buf *buf, const char *challenge)
48 {
49 SECURITY_STATUS status;
50 SecBufferDesc input_desc, output_desc;
51 SecBuffer in_token, out_token;
52 ULONG ret_flags;
53
54 if (challenge) {
55 int token_len = -EINVAL;
56
57 input_desc.cBuffers = 1;
58 input_desc.pBuffers = &in_token;
59 input_desc.ulVersion = SECBUFFER_VERSION;
60
61 in_token.BufferType = SECBUFFER_TOKEN;
62 in_token.pvBuffer = openconnect_base64_decode(&token_len, challenge);
63 if (!in_token.pvBuffer)
64 return token_len;
65 in_token.cbBuffer = token_len;
66 }
67
68 output_desc.cBuffers = 1;
69 output_desc.pBuffers = &out_token;
70 output_desc.ulVersion = SECBUFFER_VERSION;
71
72 out_token.BufferType = SECBUFFER_TOKEN;
73 out_token.cbBuffer = 0;
74 out_token.pvBuffer = NULL;
75
76 status = InitializeSecurityContextW(&auth_state->ntlm_sspi_cred,
77 challenge ? &auth_state->ntlm_sspi_ctx : NULL,
78 (SEC_WCHAR *)L"",
79 ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION,
80 0, SECURITY_NETWORK_DREP,
81 challenge ? &input_desc : NULL,
82 0, &auth_state->ntlm_sspi_ctx,
83 &output_desc, &ret_flags, NULL);
84
85 if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
86 vpn_progress(vpninfo, PRG_ERR,
87 _("InitializeSecurityContext() failed: %lx\n"), status);
88 return -EIO;
89 }
90
91 buf_append(buf, "%sAuthorization: NTLM ", proxy ? "Proxy-" : "");
92 buf_append_base64(buf, out_token.pvBuffer, out_token.cbBuffer);
93 buf_append(buf, "\r\n");
94
95 FreeContextBuffer(out_token.pvBuffer);
96
97 return 0;
98 }
99
ntlm_helper_spawn(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf)100 static int ntlm_helper_spawn(struct openconnect_info *vpninfo, int proxy,
101 struct http_auth_state *auth_state,
102 struct oc_text_buf *buf)
103 {
104 SECURITY_STATUS status;
105 int ret;
106
107 status = AcquireCredentialsHandleW(NULL, (SEC_WCHAR *)L"NTLM",
108 SECPKG_CRED_OUTBOUND, NULL, NULL,
109 NULL, NULL,
110 &auth_state->ntlm_sspi_cred, NULL);
111 if (status != SEC_E_OK) {
112 vpn_progress(vpninfo, PRG_ERR,
113 _("AcquireCredentialsHandle() failed: %lx\n"), status);
114 return -EIO;
115 }
116
117 ret = ntlm_sspi(vpninfo, proxy, auth_state, buf, NULL);
118 if (ret)
119 FreeCredentialsHandle(&auth_state->ntlm_sspi_cred);
120
121 return ret;
122 }
123
ntlm_helper_challenge(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf)124 static int ntlm_helper_challenge(struct openconnect_info *vpninfo, int proxy,
125 struct http_auth_state *auth_state,
126 struct oc_text_buf *buf)
127 {
128 return ntlm_sspi(vpninfo, proxy, auth_state, buf, auth_state->challenge);
129 }
130
cleanup_ntlm_auth(struct openconnect_info * vpninfo,struct http_auth_state * auth_state)131 void cleanup_ntlm_auth(struct openconnect_info *vpninfo,
132 struct http_auth_state *auth_state)
133 {
134 if (auth_state->state == NTLM_SSO_REQ) {
135 FreeCredentialsHandle(&auth_state->ntlm_sspi_cred);
136 DeleteSecurityContext(&auth_state->ntlm_sspi_ctx);
137 }
138 }
139
140 #else /* !_WIN32 */
141
ntlm_helper_spawn(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf)142 static int ntlm_helper_spawn(struct openconnect_info *vpninfo, int proxy,
143 struct http_auth_state *auth_state,
144 struct oc_text_buf *buf)
145 {
146 char *username;
147 int pipefd[2];
148 pid_t pid;
149 char helperbuf[4096];
150 int len;
151
152 if (access("/usr/bin/ntlm_auth", X_OK))
153 return -errno;
154
155 username = vpninfo->proxy_user;
156 if (!username)
157 username = getenv("NTLMUSER");
158 if (!username)
159 username = getenv("USER");
160 if (!username)
161 return -EINVAL;
162
163 #ifdef SOCK_CLOEXEC
164 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, pipefd))
165 #endif
166 {
167 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd))
168 return -errno;
169 set_fd_cloexec(pipefd[0]);
170 set_fd_cloexec(pipefd[1]);
171 }
172 pid = fork();
173 if (pid == -1)
174 return -errno;
175
176 if (!pid) {
177 int i;
178 char *p;
179 const char *argv[9];
180
181 /* Fork again to detach grandchild */
182 if (fork())
183 exit(1);
184
185 close(pipefd[1]);
186 /* The duplicated fd does not have O_CLOEXEC */
187 dup2(pipefd[0], 0);
188 dup2(pipefd[0], 1);
189 /* Should we leave stderr open? */
190 for (i = 3; i < 1024 ; i++)
191 close(i);
192
193
194 i = 0;
195 argv[i++] = "/usr/bin/ntlm_auth";
196 argv[i++] = "--helper-protocol";
197 argv[i++] = "ntlmssp-client-1";
198 argv[i++] = "--use-cached-creds";
199 argv[i++] = "--username";
200 p = strchr(username, '\\');
201 if (p) {
202 argv[i++] = p+1;
203 argv[i++] = "--domain";
204 argv[i++] = strndup(username, p - username);
205 } else
206 argv[i++] = username;
207 argv[i++] = NULL;
208
209 execv(argv[0], (char **)argv);
210 exit(1);
211 }
212 waitpid(pid, NULL, 0);
213 close(pipefd[0]);
214
215 if (write(pipefd[1], "YR\n", 3) != 3) {
216 close(pipefd[1]);
217 return -EIO;
218 }
219
220 len = read(pipefd[1], helperbuf, sizeof(helperbuf));
221 if (len < 4 || helperbuf[0] != 'Y' || helperbuf[1] != 'R' ||
222 helperbuf[2] != ' ' || helperbuf[len - 1] != '\n') {
223 close(pipefd[1]);
224 return -EIO;
225 }
226 helperbuf[len - 1] = 0;
227 buf_append(buf, "%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "",
228 helperbuf + 3);
229 auth_state->ntlm_helper_fd = pipefd[1];
230 return 0;
231 }
232
ntlm_helper_challenge(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf)233 static int ntlm_helper_challenge(struct openconnect_info *vpninfo, int proxy,
234 struct http_auth_state *auth_state,
235 struct oc_text_buf *buf)
236 {
237 char helperbuf[4096];
238 int len;
239
240 if (!auth_state->challenge ||
241 write(auth_state->ntlm_helper_fd, "TT ", 3) != 3 ||
242 write(auth_state->ntlm_helper_fd, auth_state->challenge,
243 strlen(auth_state->challenge)) != strlen(auth_state->challenge) ||
244 write(auth_state->ntlm_helper_fd, "\n", 1) != 1) {
245 err:
246 vpn_progress(vpninfo, PRG_ERR, _("Error communicating with ntlm_auth helper\n"));
247 close(auth_state->ntlm_helper_fd);
248 auth_state->ntlm_helper_fd = -1;
249 return -EAGAIN;
250 }
251 len = read(auth_state->ntlm_helper_fd, helperbuf, sizeof(helperbuf));
252 /* Accept both 'KK' and 'AF'. It should be the latter but see
253 https://bugzilla.samba.org/show_bug.cgi?id=10691 */
254 if (len < 4 || (!(helperbuf[0] == 'K' && helperbuf[1] == 'K') &&
255 !(helperbuf[0] == 'A' && helperbuf[1] == 'F')) ||
256 helperbuf[2] != ' ' || helperbuf[len - 1] != '\n') {
257 goto err;
258 }
259 helperbuf[len - 1] = 0;
260 buf_append(buf, "%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "",
261 helperbuf + 3);
262
263 if (proxy)
264 vpn_progress(vpninfo, PRG_INFO,
265 _("Attempting HTTP NTLM authentication to proxy (single-sign-on)\n"));
266 else
267 vpn_progress(vpninfo, PRG_INFO,
268 _("Attempting HTTP NTLM authentication to server '%s' (single-sign-on)\n"),
269 vpninfo->hostname);
270 return 0;
271
272 }
273
cleanup_ntlm_auth(struct openconnect_info * vpninfo,struct http_auth_state * auth_state)274 void cleanup_ntlm_auth(struct openconnect_info *vpninfo,
275 struct http_auth_state *auth_state)
276 {
277 if (auth_state->state == NTLM_SSO_REQ) {
278 close(auth_state->ntlm_helper_fd);
279 auth_state->ntlm_helper_fd = -1;
280 }
281 }
282 #endif /* !_WIN32 */
283
284 /*
285 * NTLM implementation taken from libsoup / Evolution Data Server
286 * Copyright (C) 2007 Red Hat, Inc.
287 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
288 */
289
290 /* DES */
291 typedef uint32_t DES_KS[16][2]; /* Single-key DES key schedule */
292
293 /*
294 * MD4 encoder. (The one everyone else uses is not GPL-compatible;
295 * this is a reimplementation from spec.) This doesn't need to be
296 * efficient for our purposes, although it would be nice to fix
297 * it to not malloc()...
298 */
299
300 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
301 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
302 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
303 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
304
md4sum(struct oc_text_buf * buf,unsigned char digest[16])305 static int md4sum (struct oc_text_buf *buf, unsigned char digest[16])
306 {
307 int nbytes = buf->pos;
308 unsigned char *M;
309 uint32_t A, B, C, D, AA, BB, CC, DD, X[16];
310 int pbytes, nbits = nbytes * 8, i, j;
311
312 /* There is *always* padding of at least one bit. */
313 pbytes = ((119 - (nbytes % 64)) % 64) + 1;
314
315 if (buf_ensure_space (buf, pbytes + 8))
316 return -ENOMEM;
317
318 M = (void *)buf->data;
319 memset (M + nbytes, 0, pbytes + 8);
320 M[nbytes] = 0x80;
321 store_le32(&M[nbytes + pbytes], nbits);
322
323 A = 0x67452301;
324 B = 0xEFCDAB89;
325 C = 0x98BADCFE;
326 D = 0x10325476;
327
328 for (i = 0; i < nbytes + pbytes + 8; i += 64) {
329 for (j = 0; j < 16; j++)
330 X[j] = load_le32(&M[i + j * 4]);
331
332 AA = A;
333 BB = B;
334 CC = C;
335 DD = D;
336
337 A = ROT (A + F (B, C, D) + X[0], 3);
338 D = ROT (D + F (A, B, C) + X[1], 7);
339 C = ROT (C + F (D, A, B) + X[2], 11);
340 B = ROT (B + F (C, D, A) + X[3], 19);
341 A = ROT (A + F (B, C, D) + X[4], 3);
342 D = ROT (D + F (A, B, C) + X[5], 7);
343 C = ROT (C + F (D, A, B) + X[6], 11);
344 B = ROT (B + F (C, D, A) + X[7], 19);
345 A = ROT (A + F (B, C, D) + X[8], 3);
346 D = ROT (D + F (A, B, C) + X[9], 7);
347 C = ROT (C + F (D, A, B) + X[10], 11);
348 B = ROT (B + F (C, D, A) + X[11], 19);
349 A = ROT (A + F (B, C, D) + X[12], 3);
350 D = ROT (D + F (A, B, C) + X[13], 7);
351 C = ROT (C + F (D, A, B) + X[14], 11);
352 B = ROT (B + F (C, D, A) + X[15], 19);
353
354 A = ROT (A + G (B, C, D) + X[0] + 0x5A827999, 3);
355 D = ROT (D + G (A, B, C) + X[4] + 0x5A827999, 5);
356 C = ROT (C + G (D, A, B) + X[8] + 0x5A827999, 9);
357 B = ROT (B + G (C, D, A) + X[12] + 0x5A827999, 13);
358 A = ROT (A + G (B, C, D) + X[1] + 0x5A827999, 3);
359 D = ROT (D + G (A, B, C) + X[5] + 0x5A827999, 5);
360 C = ROT (C + G (D, A, B) + X[9] + 0x5A827999, 9);
361 B = ROT (B + G (C, D, A) + X[13] + 0x5A827999, 13);
362 A = ROT (A + G (B, C, D) + X[2] + 0x5A827999, 3);
363 D = ROT (D + G (A, B, C) + X[6] + 0x5A827999, 5);
364 C = ROT (C + G (D, A, B) + X[10] + 0x5A827999, 9);
365 B = ROT (B + G (C, D, A) + X[14] + 0x5A827999, 13);
366 A = ROT (A + G (B, C, D) + X[3] + 0x5A827999, 3);
367 D = ROT (D + G (A, B, C) + X[7] + 0x5A827999, 5);
368 C = ROT (C + G (D, A, B) + X[11] + 0x5A827999, 9);
369 B = ROT (B + G (C, D, A) + X[15] + 0x5A827999, 13);
370
371 A = ROT (A + H (B, C, D) + X[0] + 0x6ED9EBA1, 3);
372 D = ROT (D + H (A, B, C) + X[8] + 0x6ED9EBA1, 9);
373 C = ROT (C + H (D, A, B) + X[4] + 0x6ED9EBA1, 11);
374 B = ROT (B + H (C, D, A) + X[12] + 0x6ED9EBA1, 15);
375 A = ROT (A + H (B, C, D) + X[2] + 0x6ED9EBA1, 3);
376 D = ROT (D + H (A, B, C) + X[10] + 0x6ED9EBA1, 9);
377 C = ROT (C + H (D, A, B) + X[6] + 0x6ED9EBA1, 11);
378 B = ROT (B + H (C, D, A) + X[14] + 0x6ED9EBA1, 15);
379 A = ROT (A + H (B, C, D) + X[1] + 0x6ED9EBA1, 3);
380 D = ROT (D + H (A, B, C) + X[9] + 0x6ED9EBA1, 9);
381 C = ROT (C + H (D, A, B) + X[5] + 0x6ED9EBA1, 11);
382 B = ROT (B + H (C, D, A) + X[13] + 0x6ED9EBA1, 15);
383 A = ROT (A + H (B, C, D) + X[3] + 0x6ED9EBA1, 3);
384 D = ROT (D + H (A, B, C) + X[11] + 0x6ED9EBA1, 9);
385 C = ROT (C + H (D, A, B) + X[7] + 0x6ED9EBA1, 11);
386 B = ROT (B + H (C, D, A) + X[15] + 0x6ED9EBA1, 15);
387
388 A += AA;
389 B += BB;
390 C += CC;
391 D += DD;
392 }
393
394 store_le32(digest, A);
395 store_le32(digest + 4, B);
396 store_le32(digest + 8, C);
397 store_le32(digest + 12, D);
398
399 return 0;
400 }
401
402 /* Public domain DES implementation from Phil Karn */
403 static const uint32_t Spbox[8][64] = {
404 { 0x01010400, 0x00000000, 0x00010000, 0x01010404,
405 0x01010004, 0x00010404, 0x00000004, 0x00010000,
406 0x00000400, 0x01010400, 0x01010404, 0x00000400,
407 0x01000404, 0x01010004, 0x01000000, 0x00000004,
408 0x00000404, 0x01000400, 0x01000400, 0x00010400,
409 0x00010400, 0x01010000, 0x01010000, 0x01000404,
410 0x00010004, 0x01000004, 0x01000004, 0x00010004,
411 0x00000000, 0x00000404, 0x00010404, 0x01000000,
412 0x00010000, 0x01010404, 0x00000004, 0x01010000,
413 0x01010400, 0x01000000, 0x01000000, 0x00000400,
414 0x01010004, 0x00010000, 0x00010400, 0x01000004,
415 0x00000400, 0x00000004, 0x01000404, 0x00010404,
416 0x01010404, 0x00010004, 0x01010000, 0x01000404,
417 0x01000004, 0x00000404, 0x00010404, 0x01010400,
418 0x00000404, 0x01000400, 0x01000400, 0x00000000,
419 0x00010004, 0x00010400, 0x00000000, 0x01010004 },
420 { 0x80108020, 0x80008000, 0x00008000, 0x00108020,
421 0x00100000, 0x00000020, 0x80100020, 0x80008020,
422 0x80000020, 0x80108020, 0x80108000, 0x80000000,
423 0x80008000, 0x00100000, 0x00000020, 0x80100020,
424 0x00108000, 0x00100020, 0x80008020, 0x00000000,
425 0x80000000, 0x00008000, 0x00108020, 0x80100000,
426 0x00100020, 0x80000020, 0x00000000, 0x00108000,
427 0x00008020, 0x80108000, 0x80100000, 0x00008020,
428 0x00000000, 0x00108020, 0x80100020, 0x00100000,
429 0x80008020, 0x80100000, 0x80108000, 0x00008000,
430 0x80100000, 0x80008000, 0x00000020, 0x80108020,
431 0x00108020, 0x00000020, 0x00008000, 0x80000000,
432 0x00008020, 0x80108000, 0x00100000, 0x80000020,
433 0x00100020, 0x80008020, 0x80000020, 0x00100020,
434 0x00108000, 0x00000000, 0x80008000, 0x00008020,
435 0x80000000, 0x80100020, 0x80108020, 0x00108000 },
436 { 0x00000208, 0x08020200, 0x00000000, 0x08020008,
437 0x08000200, 0x00000000, 0x00020208, 0x08000200,
438 0x00020008, 0x08000008, 0x08000008, 0x00020000,
439 0x08020208, 0x00020008, 0x08020000, 0x00000208,
440 0x08000000, 0x00000008, 0x08020200, 0x00000200,
441 0x00020200, 0x08020000, 0x08020008, 0x00020208,
442 0x08000208, 0x00020200, 0x00020000, 0x08000208,
443 0x00000008, 0x08020208, 0x00000200, 0x08000000,
444 0x08020200, 0x08000000, 0x00020008, 0x00000208,
445 0x00020000, 0x08020200, 0x08000200, 0x00000000,
446 0x00000200, 0x00020008, 0x08020208, 0x08000200,
447 0x08000008, 0x00000200, 0x00000000, 0x08020008,
448 0x08000208, 0x00020000, 0x08000000, 0x08020208,
449 0x00000008, 0x00020208, 0x00020200, 0x08000008,
450 0x08020000, 0x08000208, 0x00000208, 0x08020000,
451 0x00020208, 0x00000008, 0x08020008, 0x00020200 },
452 { 0x00802001, 0x00002081, 0x00002081, 0x00000080,
453 0x00802080, 0x00800081, 0x00800001, 0x00002001,
454 0x00000000, 0x00802000, 0x00802000, 0x00802081,
455 0x00000081, 0x00000000, 0x00800080, 0x00800001,
456 0x00000001, 0x00002000, 0x00800000, 0x00802001,
457 0x00000080, 0x00800000, 0x00002001, 0x00002080,
458 0x00800081, 0x00000001, 0x00002080, 0x00800080,
459 0x00002000, 0x00802080, 0x00802081, 0x00000081,
460 0x00800080, 0x00800001, 0x00802000, 0x00802081,
461 0x00000081, 0x00000000, 0x00000000, 0x00802000,
462 0x00002080, 0x00800080, 0x00800081, 0x00000001,
463 0x00802001, 0x00002081, 0x00002081, 0x00000080,
464 0x00802081, 0x00000081, 0x00000001, 0x00002000,
465 0x00800001, 0x00002001, 0x00802080, 0x00800081,
466 0x00002001, 0x00002080, 0x00800000, 0x00802001,
467 0x00000080, 0x00800000, 0x00002000, 0x00802080 },
468 { 0x00000100, 0x02080100, 0x02080000, 0x42000100,
469 0x00080000, 0x00000100, 0x40000000, 0x02080000,
470 0x40080100, 0x00080000, 0x02000100, 0x40080100,
471 0x42000100, 0x42080000, 0x00080100, 0x40000000,
472 0x02000000, 0x40080000, 0x40080000, 0x00000000,
473 0x40000100, 0x42080100, 0x42080100, 0x02000100,
474 0x42080000, 0x40000100, 0x00000000, 0x42000000,
475 0x02080100, 0x02000000, 0x42000000, 0x00080100,
476 0x00080000, 0x42000100, 0x00000100, 0x02000000,
477 0x40000000, 0x02080000, 0x42000100, 0x40080100,
478 0x02000100, 0x40000000, 0x42080000, 0x02080100,
479 0x40080100, 0x00000100, 0x02000000, 0x42080000,
480 0x42080100, 0x00080100, 0x42000000, 0x42080100,
481 0x02080000, 0x00000000, 0x40080000, 0x42000000,
482 0x00080100, 0x02000100, 0x40000100, 0x00080000,
483 0x00000000, 0x40080000, 0x02080100, 0x40000100 },
484 { 0x20000010, 0x20400000, 0x00004000, 0x20404010,
485 0x20400000, 0x00000010, 0x20404010, 0x00400000,
486 0x20004000, 0x00404010, 0x00400000, 0x20000010,
487 0x00400010, 0x20004000, 0x20000000, 0x00004010,
488 0x00000000, 0x00400010, 0x20004010, 0x00004000,
489 0x00404000, 0x20004010, 0x00000010, 0x20400010,
490 0x20400010, 0x00000000, 0x00404010, 0x20404000,
491 0x00004010, 0x00404000, 0x20404000, 0x20000000,
492 0x20004000, 0x00000010, 0x20400010, 0x00404000,
493 0x20404010, 0x00400000, 0x00004010, 0x20000010,
494 0x00400000, 0x20004000, 0x20000000, 0x00004010,
495 0x20000010, 0x20404010, 0x00404000, 0x20400000,
496 0x00404010, 0x20404000, 0x00000000, 0x20400010,
497 0x00000010, 0x00004000, 0x20400000, 0x00404010,
498 0x00004000, 0x00400010, 0x20004010, 0x00000000,
499 0x20404000, 0x20000000, 0x00400010, 0x20004010 },
500 { 0x00200000, 0x04200002, 0x04000802, 0x00000000,
501 0x00000800, 0x04000802, 0x00200802, 0x04200800,
502 0x04200802, 0x00200000, 0x00000000, 0x04000002,
503 0x00000002, 0x04000000, 0x04200002, 0x00000802,
504 0x04000800, 0x00200802, 0x00200002, 0x04000800,
505 0x04000002, 0x04200000, 0x04200800, 0x00200002,
506 0x04200000, 0x00000800, 0x00000802, 0x04200802,
507 0x00200800, 0x00000002, 0x04000000, 0x00200800,
508 0x04000000, 0x00200800, 0x00200000, 0x04000802,
509 0x04000802, 0x04200002, 0x04200002, 0x00000002,
510 0x00200002, 0x04000000, 0x04000800, 0x00200000,
511 0x04200800, 0x00000802, 0x00200802, 0x04200800,
512 0x00000802, 0x04000002, 0x04200802, 0x04200000,
513 0x00200800, 0x00000000, 0x00000002, 0x04200802,
514 0x00000000, 0x00200802, 0x04200000, 0x00000800,
515 0x04000002, 0x04000800, 0x00000800, 0x00200002 },
516 { 0x10001040, 0x00001000, 0x00040000, 0x10041040,
517 0x10000000, 0x10001040, 0x00000040, 0x10000000,
518 0x00040040, 0x10040000, 0x10041040, 0x00041000,
519 0x10041000, 0x00041040, 0x00001000, 0x00000040,
520 0x10040000, 0x10000040, 0x10001000, 0x00001040,
521 0x00041000, 0x00040040, 0x10040040, 0x10041000,
522 0x00001040, 0x00000000, 0x00000000, 0x10040040,
523 0x10000040, 0x10001000, 0x00041040, 0x00040000,
524 0x00041040, 0x00040000, 0x10041000, 0x00001000,
525 0x00000040, 0x10040040, 0x00001000, 0x00041040,
526 0x10001000, 0x00000040, 0x10000040, 0x10040000,
527 0x10040040, 0x10000000, 0x00040000, 0x10001040,
528 0x00000000, 0x10041040, 0x00040040, 0x10000040,
529 0x10040000, 0x10001000, 0x10001040, 0x00000000,
530 0x10041040, 0x00041000, 0x00041000, 0x00001040,
531 0x00001040, 0x00040040, 0x10000000, 0x10041000 }
532 };
533
534 #undef F
535 #define F(l,r,key){\
536 work = ((r >> 4) | (r << 28)) ^ key[0];\
537 l ^= Spbox[6][work & 0x3f];\
538 l ^= Spbox[4][(work >> 8) & 0x3f];\
539 l ^= Spbox[2][(work >> 16) & 0x3f];\
540 l ^= Spbox[0][(work >> 24) & 0x3f];\
541 work = r ^ key[1];\
542 l ^= Spbox[7][work & 0x3f];\
543 l ^= Spbox[5][(work >> 8) & 0x3f];\
544 l ^= Spbox[3][(work >> 16) & 0x3f];\
545 l ^= Spbox[1][(work >> 24) & 0x3f];\
546 }
547
548 /* Encrypt or decrypt a block of data in ECB mode */
des(uint32_t ks[16][2],unsigned char block[8])549 static void des (uint32_t ks[16][2], unsigned char block[8])
550 {
551 uint32_t left, right, work;
552
553 /* Read input block and place in left/right in big-endian order */
554 left = load_be32(block);
555 right = load_be32(block + 4);
556
557 /* Hoey's clever initial permutation algorithm, from Outerbridge
558 * (see Schneier p 478)
559 *
560 * The convention here is the same as Outerbridge: rotate each
561 * register left by 1 bit, i.e., so that "left" contains permuted
562 * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
563 * (using origin-1 numbering as in the FIPS). This allows us to avoid
564 * one of the two rotates that would otherwise be required in each of
565 * the 16 rounds.
566 */
567 work = ((left >> 4) ^ right) & 0x0f0f0f0f;
568 right ^= work;
569 left ^= work << 4;
570 work = ((left >> 16) ^ right) & 0xffff;
571 right ^= work;
572 left ^= work << 16;
573 work = ((right >> 2) ^ left) & 0x33333333;
574 left ^= work;
575 right ^= (work << 2);
576 work = ((right >> 8) ^ left) & 0xff00ff;
577 left ^= work;
578 right ^= (work << 8);
579 right = (right << 1) | (right >> 31);
580 work = (left ^ right) & 0xaaaaaaaa;
581 left ^= work;
582 right ^= work;
583 left = (left << 1) | (left >> 31);
584
585 /* Now do the 16 rounds */
586 F (left,right,ks[0]);
587 F (right,left,ks[1]);
588 F (left,right,ks[2]);
589 F (right,left,ks[3]);
590 F (left,right,ks[4]);
591 F (right,left,ks[5]);
592 F (left,right,ks[6]);
593 F (right,left,ks[7]);
594 F (left,right,ks[8]);
595 F (right,left,ks[9]);
596 F (left,right,ks[10]);
597 F (right,left,ks[11]);
598 F (left,right,ks[12]);
599 F (right,left,ks[13]);
600 F (left,right,ks[14]);
601 F (right,left,ks[15]);
602
603 /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
604 right = (right << 31) | (right >> 1);
605 work = (left ^ right) & 0xaaaaaaaa;
606 left ^= work;
607 right ^= work;
608 left = (left >> 1) | (left << 31);
609 work = ((left >> 8) ^ right) & 0xff00ff;
610 right ^= work;
611 left ^= work << 8;
612 work = ((left >> 2) ^ right) & 0x33333333;
613 right ^= work;
614 left ^= work << 2;
615 work = ((right >> 16) ^ left) & 0xffff;
616 left ^= work;
617 right ^= work << 16;
618 work = ((right >> 4) ^ left) & 0x0f0f0f0f;
619 left ^= work;
620 right ^= work << 4;
621
622 /* Put the block back into the user's buffer with final swap */
623 store_be32(block, right);
624 store_be32(block + 4, left);
625 }
626
627 /* Key schedule-related tables from FIPS-46 */
628
629 /* permuted choice table (key) */
630 static const unsigned char pc1[] = {
631 57, 49, 41, 33, 25, 17, 9,
632 1, 58, 50, 42, 34, 26, 18,
633 10, 2, 59, 51, 43, 35, 27,
634 19, 11, 3, 60, 52, 44, 36,
635
636 63, 55, 47, 39, 31, 23, 15,
637 7, 62, 54, 46, 38, 30, 22,
638 14, 6, 61, 53, 45, 37, 29,
639 21, 13, 5, 28, 20, 12, 4
640 };
641
642 /* number left rotations of pc1 */
643 static const unsigned char totrot[] = {
644 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
645 };
646
647 /* permuted choice key (table) */
648 static const unsigned char pc2[] = {
649 14, 17, 11, 24, 1, 5,
650 3, 28, 15, 6, 21, 10,
651 23, 19, 12, 4, 26, 8,
652 16, 7, 27, 20, 13, 2,
653 41, 52, 31, 37, 47, 55,
654 30, 40, 51, 45, 33, 48,
655 44, 49, 39, 56, 34, 53,
656 46, 42, 50, 36, 29, 32
657 };
658
659 /* End of DES-defined tables */
660
661 /* bit 0 is left-most in byte */
662 static const int bytebit[] = {
663 0200,0100,040,020,010,04,02,01
664 };
665
666 /* Generate key schedule for encryption or decryption
667 * depending on the value of "decrypt"
668 */
deskey(DES_KS k,unsigned char * key,int decrypt)669 static void deskey (DES_KS k, unsigned char *key, int decrypt)
670 {
671 unsigned char pc1m[56]; /* place to modify pc1 into */
672 unsigned char pcr[56]; /* place to rotate pc1 into */
673 register int i,j,l;
674 int m;
675 unsigned char ks[8];
676
677 for (j=0; j<56; j++) { /* convert pc1 to bits of key */
678 l=pc1[j]-1; /* integer bit location */
679 m = l & 07; /* find bit */
680 pc1m[j]=(key[l>>3] & /* find which key byte l is in */
681 bytebit[m]) /* and which bit of that byte */
682 ? 1 : 0; /* and store 1-bit result */
683 }
684 for (i=0; i<16; i++) { /* key chunk for each iteration */
685 memset (ks,0,sizeof (ks)); /* Clear key schedule */
686 for (j=0; j<56; j++) /* rotate pc1 the right amount */
687 pcr[j] = pc1m[(l = j + totrot[decrypt? 15 - i : i]) < (j < 28? 28 : 56) ? l: l - 28];
688 /* rotate left and right halves independently */
689 for (j=0; j<48; j++){ /* select bits individually */
690 /* check bit that goes to ks[j] */
691 if (pcr[pc2[j]-1]) {
692 /* mask it in if it's there */
693 l= j % 6;
694 ks[j / 6] |= bytebit[l] >> 2;
695 }
696 }
697 /* Now convert to packed odd/even interleaved form */
698 k[i][0] = ((uint32_t) ks[0] << 24)
699 | ((uint32_t) ks[2] << 16)
700 | ((uint32_t) ks[4] << 8)
701 | ((uint32_t) ks[6]);
702 k[i][1] = ((uint32_t) ks[1] << 24)
703 | ((uint32_t) ks[3] << 16)
704 | ((uint32_t) ks[5] << 8)
705 | ((uint32_t) ks[7]);
706 }
707 }
708
709 #define HIKEYBITS(k,s) ((k[(s) / 8] << ((s) % 8)) & 0xFF)
710 #define LOKEYBITS(k,s) (k[(s) / 8 + 1] >> (8 - (s) % 8))
711
712 /* DES utils */
713 /* Set up a key schedule based on a 56bit key */
setup_schedule(const unsigned char * key_56,DES_KS ks)714 static void setup_schedule (const unsigned char *key_56, DES_KS ks)
715 {
716 unsigned char key[8];
717 int i, c, bit;
718
719 for (i = 0; i < 8; i++) {
720 key[i] = HIKEYBITS (key_56, i * 7);
721 /* Mask in the low bits only if they're used. It doesn't
722 * matter if we get an unwanted bit 0; it's going to be
723 * overwritten with parity anyway. */
724 if (i && i < 7)
725 key[i] |= LOKEYBITS(key_56, i * 7);
726
727 /* Fix parity */
728 for (c = bit = 0; bit < 8; bit++)
729 if (key[i] & (1 << bit))
730 c++;
731 if (!(c & 1))
732 key[i] ^= 0x01;
733 }
734
735 deskey (ks, key, 0);
736 }
737
738 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
739 "\x4B\x47\x53\x21\x40\x23\x24\x25" \
740 "\x00\x00\x00\x00\x00"
741
ntlm_lanmanager_hash(const char * password,char hash[21])742 static void ntlm_lanmanager_hash (const char *password, char hash[21])
743 {
744 unsigned char lm_password[15];
745 DES_KS ks;
746 int i;
747
748 for (i = 0; i < 14 && password[i]; i++)
749 lm_password[i] = toupper ((unsigned char) password[i]);
750
751 for (; i < 15; i++)
752 lm_password[i] = '\0';
753
754 memcpy (hash, LM_PASSWORD_MAGIC, 21);
755
756 setup_schedule (lm_password, ks);
757 des (ks, (unsigned char *) hash);
758
759 setup_schedule (lm_password + 7, ks);
760 des (ks, (unsigned char *) hash + 8);
761
762 memset(lm_password, 0, sizeof(lm_password));
763 }
764
ntlm_nt_hash(const char * pass,char hash[21])765 static int ntlm_nt_hash (const char *pass, char hash[21])
766 {
767 struct oc_text_buf *utf16pass = buf_alloc();
768 int ret;
769
770 /* Preallocate just to ensure md4sum() doesn't have to realloc, which
771 would leave a copy of the password lying around. There is always
772 at least one byte of padding, then 8 bytes of length, and round up
773 to the next multiple of 64. */
774 ret = buf_ensure_space(utf16pass, ((strlen(pass) * 2) + 1 + 8 + 63) & ~63);
775 if (ret)
776 goto out;
777
778 ret = buf_append_utf16le(utf16pass, pass);
779 if (ret < 0)
780 goto wipe;
781
782 ret = buf_error(utf16pass);
783 if (ret)
784 goto wipe;
785
786 ret = md4sum(utf16pass, (unsigned char *) hash);
787 if (ret)
788 goto wipe;
789
790 memset(hash + 16, 0, 5);
791 wipe:
792 memset(utf16pass->data, 0, utf16pass->pos);
793 out:
794 buf_free(utf16pass);
795 return 0;
796 }
797
ntlm_calc_response(const unsigned char key[21],const unsigned char plaintext[8],unsigned char results[24])798 static void ntlm_calc_response (const unsigned char key[21],
799 const unsigned char plaintext[8],
800 unsigned char results[24])
801 {
802 DES_KS ks;
803
804 memcpy (results, plaintext, 8);
805 memcpy (results + 8, plaintext, 8);
806 memcpy (results + 16, plaintext, 8);
807
808 setup_schedule (key, ks);
809 des (ks, results);
810
811 setup_schedule (key + 7, ks);
812 des (ks, results + 8);
813
814 setup_schedule (key + 14, ks);
815 des (ks, results + 16);
816 }
817
818 #define NTLM_CHALLENGE_DOMAIN_OFFSET 12
819 #define NTLM_CHALLENGE_FLAGS_OFFSET 20
820 #define NTLM_CHALLENGE_NONCE_OFFSET 24
821
822 #define NTLM_RESPONSE_BASE_SIZE 64
823 #define NTLM_RESPONSE_LM_RESP_OFFSET 12
824 #define NTLM_RESPONSE_NT_RESP_OFFSET 20
825 #define NTLM_RESPONSE_DOMAIN_OFFSET 28
826 #define NTLM_RESPONSE_USER_OFFSET 36
827 #define NTLM_RESPONSE_HOST_OFFSET 44
828 #define NTLM_RESPONSE_FLAGS_OFFSET 60
829
830 static const char ntlm_response_base[NTLM_RESPONSE_BASE_SIZE] = {
831 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00,
832 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00
839 };
840
ntlm_set_string_utf8(struct oc_text_buf * buf,int offset,const char * data)841 static void ntlm_set_string_utf8(struct oc_text_buf *buf, int offset,
842 const char *data)
843 {
844 int oldpos = buf->pos;
845 int len = buf_append_utf16le(buf, data);
846
847 /* Fill in the SecurityBuffer pointing to the string */
848 store_le16(buf->data + offset, len); /* len */
849 store_le16(buf->data + offset + 2, len); /* allocated */
850 store_le32(buf->data + offset + 4, oldpos); /* offset */
851 }
852
ntlm_set_string_binary(struct oc_text_buf * buf,int offset,const void * data,int len)853 static void ntlm_set_string_binary(struct oc_text_buf *buf, int offset,
854 const void *data, int len)
855 {
856 /* Fill in the SecurityBuffer pointing to the string */
857 store_le16(buf->data + offset, len); /* len */
858 store_le16(buf->data + offset + 2, len); /* allocated */
859 store_le32(buf->data + offset + 4, buf->pos); /* offset */
860
861 buf_append_bytes(buf, data, len);
862 }
863
ntlm_manual_challenge(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * hdrbuf,const char * domuser,const char * pass)864 static int ntlm_manual_challenge(struct openconnect_info *vpninfo, int proxy,
865 struct http_auth_state *auth_state,
866 struct oc_text_buf *hdrbuf,
867 const char *domuser, const char *pass)
868 {
869 struct oc_text_buf *resp;
870 char *user;
871 unsigned char nonce[8], hash[21], lm_resp[24], nt_resp[24];
872 unsigned char *token;
873 int token_len = -EINVAL;
874 int ntlmver;
875
876 if (!auth_state->challenge)
877 return -EINVAL;
878
879 if (ntlm_nt_hash (pass, (char *) hash))
880 return -EINVAL;
881
882 token = openconnect_base64_decode(&token_len,
883 auth_state->challenge);
884 if (!token)
885 return token_len;
886
887 if (token_len < NTLM_CHALLENGE_NONCE_OFFSET + 8 || token[0] != 'N' ||
888 token[1] != 'T' || token[2] != 'L' || token[3] != 'M' ||
889 token[4] != 'S' || token[5] != 'S' || token[6] != 'P' ||
890 token[7] || token[8] != 2 || token[9] || token[10] || token[11]) {
891 free(token);
892 return -EINVAL;
893 }
894
895 /* 0x00080000: Negotiate NTLM2 Key */
896 if (token[NTLM_CHALLENGE_FLAGS_OFFSET + 2] & 8) {
897 /* NTLM2 session response */
898 struct {
899 uint32_t srv[2];
900 uint32_t clnt[2];
901 } sess_nonce;
902 unsigned char digest[16];
903
904 ntlmver = 2;
905 if (openconnect_random(sess_nonce.clnt, sizeof(sess_nonce.clnt))) {
906 free(token);
907 return -EIO;
908 }
909
910 /* LM response is 8-byte client nonce, NUL-padded to 24 */
911 memcpy (lm_resp, sess_nonce.clnt, 8);
912 memset (lm_resp + 8, 0, 16);
913
914 /* Session nonce is client nonce + server nonce */
915 memcpy (sess_nonce.srv,
916 token + NTLM_CHALLENGE_NONCE_OFFSET, 8);
917
918 /* Take MD5 of session nonce */
919 if (openconnect_md5(digest, &sess_nonce, sizeof(sess_nonce))) {
920 free(token);
921 return -EIO;
922 }
923 ntlm_calc_response (hash, digest, nt_resp);
924 } else {
925 /* NTLM1 */
926 ntlmver = 1;
927 memcpy (nonce, token + NTLM_CHALLENGE_NONCE_OFFSET, 8);
928 ntlm_calc_response (hash, nonce, nt_resp);
929 ntlm_lanmanager_hash (pass, (char *) hash);
930 ntlm_calc_response (hash, nonce, lm_resp);
931 }
932
933 resp = buf_alloc();
934 buf_append_bytes(resp, ntlm_response_base, sizeof(ntlm_response_base));
935 if (buf_error(resp)) {
936 free(token);
937 return buf_free(resp);
938 }
939 /* Mask in the NTLM2SESSION flag */
940 resp->data[NTLM_RESPONSE_FLAGS_OFFSET + 2] = token[NTLM_CHALLENGE_FLAGS_OFFSET + 2] & 8;
941
942 user = strchr(domuser, '\\');
943 if (user) {
944 *user = 0;
945 ntlm_set_string_utf8(resp, NTLM_RESPONSE_DOMAIN_OFFSET, domuser);
946 *user = '\\';
947 user++;
948 } else {
949 int offset = load_le32(token + NTLM_CHALLENGE_DOMAIN_OFFSET + 4);
950 int len = load_le16(token + NTLM_CHALLENGE_DOMAIN_OFFSET);
951 if (!len || offset + len >= token_len) {
952 free(token);
953 buf_free(resp);
954 return -EINVAL;
955 }
956 ntlm_set_string_binary(resp, NTLM_RESPONSE_DOMAIN_OFFSET, token + offset, len);
957
958 user = (char *)domuser;
959 }
960
961 ntlm_set_string_utf8(resp, NTLM_RESPONSE_USER_OFFSET, user);
962 ntlm_set_string_utf8(resp, NTLM_RESPONSE_HOST_OFFSET, "UNKNOWN");
963 ntlm_set_string_binary(resp, NTLM_RESPONSE_LM_RESP_OFFSET, lm_resp, sizeof(lm_resp));
964 ntlm_set_string_binary(resp, NTLM_RESPONSE_NT_RESP_OFFSET, nt_resp, sizeof(nt_resp));
965
966 free(token);
967
968 if (buf_error(resp))
969 return buf_free(resp);
970
971 buf_append(hdrbuf, "%sAuthorization: NTLM ", proxy ? "Proxy-" : "");
972 buf_append_base64(hdrbuf, resp->data, resp->pos);
973 buf_append(hdrbuf, "\r\n");
974
975 buf_free(resp);
976 if (proxy)
977 vpn_progress(vpninfo, PRG_INFO,
978 _("Attempting HTTP NTLMv%d authentication to proxy\n"),
979 ntlmver);
980 else
981 vpn_progress(vpninfo, PRG_INFO,
982 _("Attempting HTTP NTLMv%d authentication to server '%s'\n"),
983 ntlmver, vpninfo->hostname);
984 return 0;
985 }
986
ntlm_authorization(struct openconnect_info * vpninfo,int proxy,struct http_auth_state * auth_state,struct oc_text_buf * buf)987 int ntlm_authorization(struct openconnect_info *vpninfo, int proxy,
988 struct http_auth_state *auth_state, struct oc_text_buf *buf)
989 {
990 const char *user, *pass;
991
992 if (proxy) {
993 user = vpninfo->proxy_user;
994 pass = vpninfo->proxy_pass;
995 } else {
996 user = pass = NULL;
997 }
998
999 if (auth_state->state == AUTH_AVAILABLE) {
1000 auth_state->state = NTLM_MANUAL;
1001 /* Don't attempt automatic NTLM auth if we were given a password */
1002 if (!pass && !ntlm_helper_spawn(vpninfo, proxy, auth_state, buf)) {
1003 auth_state->state = NTLM_SSO_REQ;
1004 return 0;
1005 }
1006 }
1007 if (auth_state->state == NTLM_SSO_REQ) {
1008 int ret;
1009 ret = ntlm_helper_challenge(vpninfo, proxy, auth_state, buf);
1010 /* Clean up after it. We're done here, whether it worked or not */
1011 cleanup_ntlm_auth(vpninfo, auth_state);
1012 auth_state->state = NTLM_MANUAL;
1013 if (ret == -EAGAIN) {
1014 /* Don't let it reset our state when it reconnects */
1015 if (proxy)
1016 vpninfo->proxy_close_during_auth = 1;
1017 return ret;
1018 }
1019 if (!ret)
1020 return ret;
1021 }
1022 if (auth_state->state == NTLM_MANUAL && user && pass) {
1023 buf_append(buf, "%sAuthorization: NTLM %s\r\n", proxy ? "Proxy-" : "",
1024 "TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
1025 auth_state->state = NTLM_MANUAL_REQ;
1026 return 0;
1027 }
1028 if (auth_state->state == NTLM_MANUAL_REQ && user && pass &&
1029 !ntlm_manual_challenge(vpninfo, proxy, auth_state, buf, user, pass)) {
1030 /* Leave the state as it is. If we come back there'll be no
1031 challenge string and we'll fail then. */
1032 return 0;
1033 }
1034 auth_state->state = AUTH_FAILED;
1035 return -EAGAIN;
1036 }
1037