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