• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-auth-ntlm.c: HTTP NTLM Authentication helper
4  *
5  * Copyright (C) 2007 Red Hat, Inc.
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 
17 #include <glib.h>
18 
19 #include "soup-auth-ntlm.h"
20 #include "soup.h"
21 #include "soup-message-private.h"
22 
23 static void        soup_ntlm_lanmanager_hash   (const char  *password,
24 						guchar       hash[21]);
25 static void        soup_ntlm_nt_hash           (const char  *password,
26 						guchar       hash[21]);
27 static char       *soup_ntlm_request           (void);
28 static gboolean    soup_ntlm_parse_challenge   (const char  *challenge,
29 						char       **nonce,
30 						char       **default_domain,
31 						gboolean    *ntlmv2_session,
32 						gboolean    *negotiate_target,
33 						char		**target_info,
34 						size_t		*target_info_sz);
35 static char       *soup_ntlm_response          (const char  *nonce,
36 						const char  *user,
37 						guchar       nt_hash[21],
38 						guchar       lm_hash[21],
39 						const char  *host,
40 						const char  *domain,
41 						gboolean     ntlmv2_session,
42 						gboolean     negotiate_target,
43 						const char	*target_info,
44 						size_t		target_info_sz);
45 
46 typedef enum {
47 	SOUP_NTLM_NEW,
48 	SOUP_NTLM_SSO_FAILED,
49 	SOUP_NTLM_SENT_REQUEST,
50 	SOUP_NTLM_RECEIVED_CHALLENGE,
51 	SOUP_NTLM_SENT_RESPONSE,
52 	SOUP_NTLM_FAILED
53 } SoupNTLMState;
54 
55 typedef struct {
56 	SoupNTLMState state;
57 	char *nonce;
58 	char *response_header;
59 	gboolean ntlmv2_session;
60 	gboolean negotiate_target;
61 	char *target_info;
62 	size_t target_info_sz;
63 } SoupNTLMConnectionState;
64 
65 typedef enum {
66 	SOUP_NTLM_PASSWORD_NONE,
67 	SOUP_NTLM_PASSWORD_PROVIDED,
68 	SOUP_NTLM_PASSWORD_ACCEPTED,
69 	SOUP_NTLM_PASSWORD_REJECTED
70 } SoupNTLMPasswordState;
71 
72 typedef struct {
73 	char *username, *domain;
74 	guchar nt_hash[21], lm_hash[21];
75 	SoupNTLMPasswordState password_state;
76 
77 #ifdef USE_NTLM_AUTH
78 	/* Use Samba's 'winbind' daemon to support NTLM single-sign-on,
79 	 * by delegating the NTLM challenge/response protocal to a helper
80 	 * in ntlm_auth.
81 	 * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
82 	 * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
83 	 * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
84 	 */
85 	gboolean sso_available;
86 	int fd_in;
87 	int fd_out;
88 #endif
89 } SoupAuthNTLMPrivate;
90 
91 #ifdef USE_NTLM_AUTH
92 static gboolean ntlm_auth_available, ntlm_auth_debug;
93 static void sso_ntlm_close (SoupAuthNTLMPrivate *priv);
94 #endif
95 
96 /**
97  * SOUP_TYPE_AUTH_NTLM:
98  *
99  * A #GType corresponding to HTTP-based NTLM authentication.
100  * #SoupSessions do not support this type by default; if you want to
101  * enable support for it, call soup_session_add_feature_by_type(),
102  * passing %SOUP_TYPE_AUTH_NTLM.
103  *
104  * Since: 2.34
105  */
106 
G_DEFINE_TYPE_WITH_PRIVATE(SoupAuthNTLM,soup_auth_ntlm,SOUP_TYPE_CONNECTION_AUTH)107 G_DEFINE_TYPE_WITH_PRIVATE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_CONNECTION_AUTH)
108 
109 static void
110 soup_auth_ntlm_init (SoupAuthNTLM *ntlm)
111 {
112 #ifdef USE_NTLM_AUTH
113 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (ntlm);
114 	const char *username = NULL, *slash;
115 
116 	priv->sso_available = TRUE;
117 	priv->fd_in = -1;
118 	priv->fd_out = -1;
119 
120 	username = getenv ("NTLMUSER");
121 	if (!username)
122 		username = g_get_user_name ();
123 
124 	slash = strpbrk (username, "\\/");
125 	if (slash) {
126 		priv->username = g_strdup (slash + 1);
127 		priv->domain = g_strndup (username, slash - username);
128 	} else {
129 		priv->username = g_strdup (username);
130 		priv->domain = NULL;
131 	}
132 #endif
133 }
134 
135 static void
soup_auth_ntlm_finalize(GObject * object)136 soup_auth_ntlm_finalize (GObject *object)
137 {
138 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (SOUP_AUTH_NTLM (object));
139 
140 	g_free (priv->username);
141 	g_free (priv->domain);
142 
143 	memset (priv->nt_hash, 0, sizeof (priv->nt_hash));
144 	memset (priv->lm_hash, 0, sizeof (priv->lm_hash));
145 
146 #ifdef USE_NTLM_AUTH
147 	sso_ntlm_close (priv);
148 #endif
149 
150 	G_OBJECT_CLASS (soup_auth_ntlm_parent_class)->finalize (object);
151 }
152 
153 #ifdef USE_NTLM_AUTH
154 static void
sso_ntlm_close(SoupAuthNTLMPrivate * priv)155 sso_ntlm_close (SoupAuthNTLMPrivate *priv)
156 {
157 	if (priv->fd_in != -1) {
158 		close (priv->fd_in);
159 		priv->fd_in = -1;
160 	}
161 
162 	if (priv->fd_out != -1) {
163 		close (priv->fd_out);
164 		priv->fd_out = -1;
165 	}
166 }
167 
168 static gboolean
sso_ntlm_initiate(SoupAuthNTLMPrivate * priv)169 sso_ntlm_initiate (SoupAuthNTLMPrivate *priv)
170 {
171 	char *argv[9];
172 	gboolean ret;
173 
174 	if (!priv->sso_available)
175 		return FALSE;
176 
177 	if (!ntlm_auth_available && !ntlm_auth_debug) {
178 		priv->sso_available = FALSE;
179 		return FALSE;
180 	}
181 
182 	/* Return if ntlm_auth execution process exist already */
183 	if (priv->fd_in != -1 && priv->fd_out != -1)
184 		return TRUE;
185 	else {
186 		/* Clean all sso data before re-initiate */
187 		sso_ntlm_close (priv);
188 	}
189 
190 	if (ntlm_auth_debug) {
191 		argv[0] = (char *) g_getenv ("SOUP_NTLM_AUTH_DEBUG");
192 		if (!*argv[0]) {
193 			priv->sso_available = FALSE;
194 			return FALSE;
195 		}
196 	} else
197 		argv[0] = NTLM_AUTH;
198 	argv[1] = "--helper-protocol";
199 	argv[2] = "ntlmssp-client-1";
200 	argv[3] = "--use-cached-creds";
201 	argv[4] = "--username";
202 	argv[5] = priv->username;
203 	argv[6] = priv->domain ? "--domain" : NULL;
204 	argv[7] = priv->domain;
205 	argv[8] = NULL;
206 
207 	ret = g_spawn_async_with_pipes (NULL, argv, NULL,
208 					G_SPAWN_STDERR_TO_DEV_NULL,
209 					NULL, NULL,
210 					NULL, &priv->fd_in, &priv->fd_out,
211 					NULL, NULL);
212 	if (!ret)
213 		priv->sso_available = FALSE;
214 	return ret;
215 }
216 
217 static char *
sso_ntlm_response(SoupAuthNTLMPrivate * priv,const char * input,SoupNTLMState conn_state)218 sso_ntlm_response (SoupAuthNTLMPrivate *priv, const char *input, SoupNTLMState conn_state)
219 {
220 	ssize_t size;
221 	char buf[1024];
222 	char *tmpbuf = buf;
223 	size_t	len_in = strlen (input), len_out = sizeof (buf);
224 
225 	while (len_in > 0) {
226 		int written = write (priv->fd_in, input, len_in);
227 		if (written == -1) {
228 			if (errno == EINTR)
229 				continue;
230 			/* write failed if other errors happen */
231 			return NULL;
232 		}
233 		input += written;
234 		len_in -= written;
235 	}
236 	/* Read one line */
237 	while (len_out > 0) {
238 		size = read (priv->fd_out, tmpbuf, len_out);
239 		if (size == -1) {
240 			if (errno == EINTR)
241 				continue;
242 			return NULL;
243 		} else if (size == 0)
244 			return NULL;
245 		else if (tmpbuf[size - 1] == '\n') {
246 			tmpbuf[size - 1] = '\0';
247 			goto wrfinish;
248 		}
249 		tmpbuf += size;
250 		len_out -= size;
251 	}
252 	return NULL;
253 
254 wrfinish:
255 	if (g_ascii_strcasecmp (buf, "PW") == 0) {
256 		/* Samba/winbind installed but not configured */
257 		return g_strdup ("PW");
258 	}
259 	if (conn_state == SOUP_NTLM_NEW &&
260 	    g_ascii_strncasecmp (buf, "YR ", 3) != 0) {
261 		/* invalid response for type 1 message */
262 		return NULL;
263 	}
264 	if (conn_state == SOUP_NTLM_RECEIVED_CHALLENGE &&
265 	    g_ascii_strncasecmp (buf, "KK ", 3) != 0 &&
266 	    g_ascii_strncasecmp (buf, "AF ", 3) != 0) {
267 		/* invalid response for type 3 message */
268 		return NULL;
269 	}
270 
271 	return g_strdup_printf ("NTLM %.*s", (int)(size - 4), buf + 3);
272 }
273 #endif /* USE_NTLM_AUTH */
274 
275 static gpointer
soup_auth_ntlm_create_connection_state(SoupConnectionAuth * auth)276 soup_auth_ntlm_create_connection_state (SoupConnectionAuth *auth)
277 {
278 	SoupNTLMConnectionState *conn;
279 
280 	conn = g_slice_new0 (SoupNTLMConnectionState);
281 	conn->state = SOUP_NTLM_NEW;
282 
283 	return conn;
284 }
285 
286 static void
soup_auth_ntlm_free_connection_state(SoupConnectionAuth * auth,gpointer state)287 soup_auth_ntlm_free_connection_state (SoupConnectionAuth *auth,
288 				      gpointer state)
289 {
290 	SoupNTLMConnectionState *conn = state;
291 
292 	g_free (conn->nonce);
293 	g_free (conn->response_header);
294 	g_free (conn->target_info);
295 	g_slice_free (SoupNTLMConnectionState, conn);
296 }
297 
298 static gboolean
soup_auth_ntlm_update_connection(SoupConnectionAuth * auth,SoupMessage * msg,const char * auth_header,gpointer state)299 soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg,
300 				  const char *auth_header, gpointer state)
301 {
302 	SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth);
303 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm);
304 	SoupNTLMConnectionState *conn = state;
305 	gboolean success = TRUE;
306 
307 	/* Note that we only return FALSE if some sort of parsing error
308 	 * occurs. Otherwise, the SoupAuth is still reusable (though it may
309 	 * no longer be _ready or _authenticated).
310 	 */
311 
312 	if (!g_str_has_prefix (auth_header, "NTLM"))
313 		return FALSE;
314 
315 	if (conn->state > SOUP_NTLM_SENT_REQUEST) {
316 		if (priv->password_state == SOUP_NTLM_PASSWORD_ACCEPTED) {
317 			/* We know our password is correct, so a 401
318 			 * means "permission denied". The code can't deal
319 			 * with re-authenticating correctly, so make sure
320 			 * we don't try.
321 			 */
322 			conn->state = SOUP_NTLM_FAILED;
323 			if (soup_message_is_keepalive (msg)) {
324 				soup_message_headers_append (msg->response_headers,
325 							     "Connection", "close");
326 			}
327 			return TRUE;
328 		}
329 
330 #ifdef USE_NTLM_AUTH
331 		if (priv->sso_available) {
332 			conn->state = SOUP_NTLM_SSO_FAILED;
333 			priv->password_state = SOUP_NTLM_PASSWORD_NONE;
334 		} else {
335 #endif
336 			conn->state = SOUP_NTLM_FAILED;
337 			priv->password_state = SOUP_NTLM_PASSWORD_REJECTED;
338 #ifdef USE_NTLM_AUTH
339 		}
340 #endif
341 		return TRUE;
342 	}
343 
344 	if (conn->state == SOUP_NTLM_NEW && !auth_header[4])
345 		return TRUE;
346 
347 	if (!auth_header[4] || !auth_header[5]) {
348 		conn->state = SOUP_NTLM_FAILED;
349 		return FALSE;
350 	}
351 
352 	if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce,
353 					priv->domain ? NULL : &priv->domain,
354 					&conn->ntlmv2_session, &conn->negotiate_target,
355 					&conn->target_info, &conn->target_info_sz)) {
356 		conn->state = SOUP_NTLM_FAILED;
357 		return FALSE;
358 	}
359 
360 #ifdef USE_NTLM_AUTH
361 	if (priv->sso_available && conn->state == SOUP_NTLM_SENT_REQUEST) {
362 		char *input, *response;
363 
364 		/* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */
365 		if (!sso_ntlm_initiate (priv)) {
366 			conn->state = SOUP_NTLM_SSO_FAILED;
367 			success = FALSE;
368 			goto out;
369 		}
370 
371 		input = g_strdup_printf ("TT %s\n", auth_header + 5);
372 		response = sso_ntlm_response (priv, input, conn->state);
373 		sso_ntlm_close (priv);
374 		g_free (input);
375 
376 		if (!response) {
377 			conn->state = SOUP_NTLM_SSO_FAILED;
378 			success = FALSE;
379 		} else if (!g_ascii_strcasecmp (response, "PW")) {
380 			conn->state = SOUP_NTLM_SSO_FAILED;
381 			priv->sso_available = FALSE;
382 			g_free (response);
383 		} else {
384 			conn->response_header = response;
385 			if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED)
386 				priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED;
387 		}
388 	}
389  out:
390 #endif
391 
392 	if (conn->state == SOUP_NTLM_SENT_REQUEST)
393 		conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
394 
395 	g_object_set (G_OBJECT (auth),
396 		      SOUP_AUTH_REALM, priv->domain,
397 		      SOUP_AUTH_HOST, soup_message_get_uri (msg)->host,
398 		      NULL);
399 	return success;
400 }
401 
402 static GSList *
soup_auth_ntlm_get_protection_space(SoupAuth * auth,SoupURI * source_uri)403 soup_auth_ntlm_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
404 {
405 	char *space, *p;
406 
407 	space = g_strdup (source_uri->path);
408 
409 	/* Strip filename component */
410 	p = strrchr (space, '/');
411 	if (p && p != space && p[1])
412 		*p = '\0';
413 
414 	return g_slist_prepend (NULL, space);
415 }
416 
417 static void
soup_auth_ntlm_authenticate(SoupAuth * auth,const char * username,const char * password)418 soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username,
419 			     const char *password)
420 {
421 	SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth);
422 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm);
423 	const char *slash;
424 
425 	g_return_if_fail (username != NULL);
426 	g_return_if_fail (password != NULL);
427 
428 	if (priv->username)
429 		g_free (priv->username);
430 	if (priv->domain)
431 		g_free (priv->domain);
432 
433 	slash = strpbrk (username, "\\/");
434 	if (slash) {
435 		priv->domain = g_strndup (username, slash - username);
436 		priv->username = g_strdup (slash + 1);
437 	} else {
438 		priv->domain = g_strdup ("");
439 		priv->username = g_strdup (username);
440 	}
441 
442 	soup_ntlm_nt_hash (password, priv->nt_hash);
443 	soup_ntlm_lanmanager_hash (password, priv->lm_hash);
444 
445 	priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED;
446 }
447 
448 static gboolean
soup_auth_ntlm_is_authenticated(SoupAuth * auth)449 soup_auth_ntlm_is_authenticated (SoupAuth *auth)
450 {
451 	SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth);
452 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm);
453 
454 	return (priv->password_state != SOUP_NTLM_PASSWORD_NONE &&
455 		priv->password_state != SOUP_NTLM_PASSWORD_REJECTED);
456 }
457 
458 static gboolean
soup_auth_ntlm_is_connection_ready(SoupConnectionAuth * auth,SoupMessage * msg,gpointer state)459 soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth,
460 				    SoupMessage        *msg,
461 				    gpointer            state)
462 {
463 	SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth);
464 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm);
465 	SoupNTLMConnectionState *conn = state;
466 
467 	if (priv->password_state == SOUP_NTLM_PASSWORD_REJECTED)
468 		return FALSE;
469 
470 	if (priv->password_state == SOUP_NTLM_PASSWORD_PROVIDED)
471 		return TRUE;
472 
473 	return conn->state != SOUP_NTLM_FAILED;
474 }
475 
476 static void
got_final_auth_result(SoupMessage * msg,gpointer data)477 got_final_auth_result (SoupMessage *msg, gpointer data)
478 {
479 	SoupAuth *auth = data;
480 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (SOUP_AUTH_NTLM (auth));
481 
482 	g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (got_final_auth_result), auth);
483 
484 	if (auth != soup_message_get_auth (msg))
485 		return;
486 
487 	if (msg->status_code != SOUP_STATUS_UNAUTHORIZED)
488 		priv->password_state = SOUP_NTLM_PASSWORD_ACCEPTED;
489 }
490 
491 static char *
soup_auth_ntlm_get_connection_authorization(SoupConnectionAuth * auth,SoupMessage * msg,gpointer state)492 soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth,
493 					     SoupMessage        *msg,
494 					     gpointer            state)
495 {
496 	SoupAuthNTLM *auth_ntlm = SOUP_AUTH_NTLM (auth);
497 	SoupAuthNTLMPrivate *priv = soup_auth_ntlm_get_instance_private (auth_ntlm);
498 	SoupNTLMConnectionState *conn = state;
499 	char *header = NULL;
500 
501 	switch (conn->state) {
502 	case SOUP_NTLM_NEW:
503 #ifdef USE_NTLM_AUTH
504 		if (sso_ntlm_initiate (priv)) {
505 			header = sso_ntlm_response (priv, "YR\n", conn->state);
506 			if (header) {
507 				if (g_ascii_strcasecmp (header, "PW") != 0) {
508 					conn->state = SOUP_NTLM_SENT_REQUEST;
509 					break;
510 				} else {
511 					g_free (header);
512 					header = NULL;
513 					priv->sso_available = FALSE;
514 				}
515 			} else {
516 				g_debug ("NTLM single-sign-on using %s failed", NTLM_AUTH);
517 			}
518 		}
519 		/* If NTLM single-sign-on fails, go back to original
520 		 * request handling process.
521 		 */
522 #endif
523 		header = soup_ntlm_request ();
524 		conn->state = SOUP_NTLM_SENT_REQUEST;
525 		break;
526 	case SOUP_NTLM_RECEIVED_CHALLENGE:
527 		if (conn->response_header) {
528 			header = conn->response_header;
529 			conn->response_header = NULL;
530 		} else {
531 			header = soup_ntlm_response (conn->nonce,
532 						     priv->username,
533 						     priv->nt_hash,
534 						     priv->lm_hash,
535 						     NULL,
536 						     priv->domain,
537 						     conn->ntlmv2_session,
538 							 conn->negotiate_target,
539 							 conn->target_info,
540 							 conn->target_info_sz);
541 		}
542 		g_clear_pointer (&conn->nonce, g_free);
543 		conn->state = SOUP_NTLM_SENT_RESPONSE;
544 
545 		if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED) {
546 			/* We need to know if this worked */
547 			g_signal_connect (msg, "got-headers",
548 					  G_CALLBACK (got_final_auth_result),
549 					  auth);
550 		}
551 		break;
552 #ifdef USE_NTLM_AUTH
553 	case SOUP_NTLM_SSO_FAILED:
554 		/* Restart request without SSO */
555 		g_debug ("NTLM single-sign-on by using %s failed", NTLM_AUTH);
556 		priv->sso_available = FALSE;
557 		header = soup_ntlm_request ();
558 		conn->state = SOUP_NTLM_SENT_REQUEST;
559 		break;
560 #endif
561 	default:
562 		break;
563 	}
564 
565 	return header;
566 }
567 
568 static void
soup_auth_ntlm_class_init(SoupAuthNTLMClass * auth_ntlm_class)569 soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class)
570 {
571 	SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_ntlm_class);
572 	SoupConnectionAuthClass *connauth_class = SOUP_CONNECTION_AUTH_CLASS (auth_ntlm_class);
573 	GObjectClass *object_class = G_OBJECT_CLASS (auth_ntlm_class);
574 
575 	auth_class->scheme_name = "NTLM";
576 	auth_class->strength = 3;
577 
578 	auth_class->get_protection_space = soup_auth_ntlm_get_protection_space;
579 	auth_class->authenticate = soup_auth_ntlm_authenticate;
580 	auth_class->is_authenticated = soup_auth_ntlm_is_authenticated;
581 
582 	connauth_class->create_connection_state = soup_auth_ntlm_create_connection_state;
583 	connauth_class->free_connection_state = soup_auth_ntlm_free_connection_state;
584 	connauth_class->update_connection = soup_auth_ntlm_update_connection;
585 	connauth_class->get_connection_authorization = soup_auth_ntlm_get_connection_authorization;
586 	connauth_class->is_connection_ready = soup_auth_ntlm_is_connection_ready;
587 
588 	object_class->finalize = soup_auth_ntlm_finalize;
589 
590 #ifdef USE_NTLM_AUTH
591 	ntlm_auth_available = g_file_test (NTLM_AUTH, G_FILE_TEST_IS_EXECUTABLE);
592 	ntlm_auth_debug = (g_getenv ("SOUP_NTLM_AUTH_DEBUG") != NULL);
593 #endif
594 }
595 
596 static void md4sum                (const unsigned char *in,
597 				   int                  nbytes,
598 				   unsigned char        digest[16]);
599 
600 typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */
601 
602 static void deskey                (DES_KS, unsigned char *, int);
603 
604 static void des                   (DES_KS, unsigned char *);
605 
606 static void setup_schedule        (const guchar *key_56, DES_KS ks);
607 
608 static void calc_response         (const guchar        *key,
609 				   const guchar        *plaintext,
610 				   guchar              *results);
611 
612 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
613                           "\x4B\x47\x53\x21\x40\x23\x24\x25" \
614 			  "\x00\x00\x00\x00\x00"
615 
616 static void
soup_ntlm_lanmanager_hash(const char * password,guchar hash[21])617 soup_ntlm_lanmanager_hash (const char *password, guchar hash[21])
618 {
619 	guchar lm_password [15];
620 	DES_KS ks;
621 	int i;
622 
623 	for (i = 0; i < 14 && password [i]; i++)
624 		lm_password [i] = g_ascii_toupper ((unsigned char) password [i]);
625 
626 	for (; i < 15; i++)
627 		lm_password [i] = '\0';
628 
629 	memcpy (hash, LM_PASSWORD_MAGIC, 21);
630 
631 	setup_schedule (lm_password, ks);
632 	des (ks, hash);
633 
634 	setup_schedule (lm_password + 7, ks);
635 	des (ks, hash + 8);
636 }
637 
638 static void
soup_ntlm_nt_hash(const char * password,guchar hash[21])639 soup_ntlm_nt_hash (const char *password, guchar hash[21])
640 {
641 	unsigned char *buf, *p;
642 
643 	p = buf = g_malloc (strlen (password) * 2);
644 
645 	while (*password) {
646 		*p++ = *password++;
647 		*p++ = '\0';
648 	}
649 
650 	md4sum (buf, p - buf, hash);
651 	memset (hash + 16, 0, 5);
652 
653 	g_free (buf);
654 }
655 
656 typedef struct {
657 	guint16 length;
658 	guint16 length2;
659 	guint16 offset;
660 	guchar  zero_pad[2];
661 } NTLMString;
662 
663 #define NTLM_CHALLENGE_NONCE_OFFSET         24
664 #define NTLM_CHALLENGE_NONCE_LENGTH          8
665 #define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
666 #define NTLM_CHALLENGE_TARGET_INFORMATION_OFFSET      40
667 
668 #define NTLM_CHALLENGE_FLAGS_OFFSET         20
669 #define NTLM_FLAGS_NEGOTIATE_NTLMV2 0x00080000
670 #define NTLM_FLAGS_NEGOTIATE_TARGET_INFORMATION 0x00800000
671 #define NTLM_FLAGS_REQUEST_TARGET 0x00000004
672 
673 #define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
674 #define NTLM_RESPONSE_FLAGS 0x8201
675 #define NTLM_RESPONSE_TARGET_INFORMATION_OFFSET 44
676 #define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000
677 
678 #define HMAC_MD5_LENGTH                     16
679 
680 typedef struct {
681         guchar     header[12];
682 
683 	NTLMString lm_resp;
684 	NTLMString nt_resp;
685 	NTLMString domain;
686 	NTLMString user;
687 	NTLMString host;
688 	NTLMString session_key;
689 
690         guint32    flags;
691 } NTLMResponse;
692 
693 static void
ntlm_set_string(NTLMString * string,int * offset,int len)694 ntlm_set_string (NTLMString *string, int *offset, int len)
695 {
696 	string->offset = GUINT16_TO_LE (*offset);
697 	string->length = string->length2 = GUINT16_TO_LE (len);
698 	*offset += len;
699 }
700 
701 static char *
soup_ntlm_request(void)702 soup_ntlm_request (void)
703 {
704 	return g_strdup ("NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
705 }
706 
707 static gboolean
soup_ntlm_parse_challenge(const char * challenge,char ** nonce,char ** default_domain,gboolean * ntlmv2_session,gboolean * negotiate_target,char ** target_info,size_t * target_info_sz)708 soup_ntlm_parse_challenge (const char *challenge,
709 			   char      **nonce,
710 			   char      **default_domain,
711 			   gboolean   *ntlmv2_session,
712 			   gboolean   *negotiate_target,
713 			   char		**target_info,
714 			   size_t	*target_info_sz)
715 {
716 	gsize clen;
717 	NTLMString domain;
718 	NTLMString target;
719 	guchar *chall;
720 	guint32 flags;
721 
722 	chall = g_base64_decode (challenge, &clen);
723 	if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET ||
724 	    clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) {
725 		g_free (chall);
726 		return FALSE;
727 	}
728 
729 	memcpy (&flags, chall + NTLM_CHALLENGE_FLAGS_OFFSET, sizeof(flags));
730 	flags = GUINT_FROM_LE (flags);
731 	*ntlmv2_session = (flags & NTLM_FLAGS_NEGOTIATE_NTLMV2) ? TRUE : FALSE;
732 	/* To know if NTLMv2 responses should be calculated */
733 	*negotiate_target = (flags & NTLM_FLAGS_NEGOTIATE_TARGET_INFORMATION ) ? TRUE : FALSE;
734         if (*negotiate_target) {
735             if (clen < NTLM_CHALLENGE_TARGET_INFORMATION_OFFSET + sizeof (target)) {
736                 g_free (chall);
737                 return FALSE;
738             }
739         }
740 
741 	if (default_domain) {
742 		memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain));
743 		domain.length = GUINT16_FROM_LE (domain.length);
744 		domain.offset = GUINT16_FROM_LE (domain.offset);
745 
746 		if (clen < domain.length + domain.offset) {
747 			g_free (chall);
748 			return FALSE;
749 		}
750 
751 		*default_domain = g_convert ((char *)chall + domain.offset,
752 					     domain.length, "UTF-8", "UCS-2LE",
753 					     NULL, NULL, NULL);
754 	}
755 
756 	if (nonce) {
757 		*nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET,
758 				   NTLM_CHALLENGE_NONCE_LENGTH);
759 	}
760 	/* For NTLMv2 response */
761 	if (*negotiate_target && target_info) {
762 		memcpy (&target, chall + NTLM_CHALLENGE_TARGET_INFORMATION_OFFSET, sizeof (target));
763 		target.length = GUINT16_FROM_LE (target.length);
764 		target.offset = GUINT16_FROM_LE (target.offset);
765 
766 		if (clen < target.length + target.offset) {
767 			g_free (chall);
768 			return FALSE;
769 		}
770 		*target_info = g_memdup (chall + target.offset, target.length);
771 		*target_info_sz = target.length;
772 	}
773 
774 	g_free (chall);
775 	return TRUE;
776 }
777 
778 static void
calc_ntlm2_session_response(const char * nonce,guchar nt_hash[21],guchar lm_hash[21],guchar * lm_resp,gsize lm_resp_sz,guchar * nt_resp)779 calc_ntlm2_session_response (const char *nonce,
780 			     guchar      nt_hash[21],
781 			     guchar      lm_hash[21],
782 			     guchar     *lm_resp,
783 			     gsize       lm_resp_sz,
784 			     guchar     *nt_resp)
785 {
786 	guint32 client_nonce[2];
787 	guchar ntlmv2_hash[16];
788 	GChecksum *ntlmv2_cksum;
789 	gsize ntlmv2_hash_sz = sizeof (ntlmv2_hash);
790 
791 	/* FIXME: if GLib ever gets a more secure random number
792 	 * generator, use it here
793 	 */
794 	client_nonce[0] = g_random_int();
795 	client_nonce[1] = g_random_int();
796 
797 	ntlmv2_cksum = g_checksum_new (G_CHECKSUM_MD5);
798 	g_checksum_update (ntlmv2_cksum, (const guchar *) nonce, 8);
799 	g_checksum_update (ntlmv2_cksum, (const guchar *) client_nonce, sizeof (client_nonce));
800 	g_checksum_get_digest (ntlmv2_cksum, ntlmv2_hash, &ntlmv2_hash_sz);
801 	g_checksum_free (ntlmv2_cksum);
802 
803 	/* Send the padded client nonce as a fake lm_resp */
804 	memset (lm_resp, 0, lm_resp_sz);
805 	memcpy (lm_resp, client_nonce, sizeof (client_nonce));
806 
807 	/* Compute nt_hash as usual but with a new nonce */
808 	calc_response (nt_hash, ntlmv2_hash, nt_resp);
809 }
810 
811 /* Compute HMAC-MD5 with Glib function*/
812 static void
calc_hmac_md5(unsigned char * hmac,const guchar * key,gsize key_sz,const guchar * data,gsize data_sz)813 calc_hmac_md5 (unsigned char *hmac, const guchar *key, gsize key_sz, const guchar *data, gsize data_sz)
814 {
815 	char *hmac_hex, *hex_pos;
816 	size_t count;
817 
818 	hmac_hex = g_compute_hmac_for_data(G_CHECKSUM_MD5, key, key_sz, data, data_sz);
819 	hex_pos = hmac_hex;
820 	for (count = 0; count < HMAC_MD5_LENGTH; count++)
821 	{
822 		/* The 'hh' sscanf format modifier is C99, so we enable it on
823 		 * non-Windows or if __USE_MINGW_ANSI_STDIO is enabled or`
824 		 * if we are building on Visual Studio 2015 or later
825 		 */
826 #if !defined (G_OS_WIN32) || (__USE_MINGW_ANSI_STDIO == 1) || (_MSC_VER >= 1900)
827 		sscanf(hex_pos, "%2hhx", &hmac[count]);
828 #else
829 		unsigned int tmp_hmac;
830 		sscanf(hex_pos, "%2x", &tmp_hmac);
831 		hmac[count] = (guint8)tmp_hmac;
832 #endif
833 
834 		hex_pos += 2;
835 	}
836 	g_free(hmac_hex);
837 }
838 
839 static void
calc_ntlmv2_response(const char * user,const char * domain,const guchar * nt_hash,const gsize nt_hash_sz,const guchar * nonce,const char * target_info,size_t target_info_sz,guchar * lm_resp,size_t lm_resp_sz,guchar * nt_resp,size_t nt_resp_sz)840 calc_ntlmv2_response (const char *user, const char *domain,
841 						const guchar *nt_hash, const gsize nt_hash_sz,
842 						const guchar *nonce,
843 						const char *target_info, size_t target_info_sz,
844 						guchar *lm_resp, size_t lm_resp_sz,
845 						guchar *nt_resp, size_t nt_resp_sz)
846 {
847 	const unsigned char blob_signature[] = {0x01,0x01,0x00,0x00};
848 	const unsigned char blob_reserved[] = {0x00,0x00,0x00,0x00};
849 	gint64 blob_timestamp;
850 	unsigned char client_nonce[8];
851 	const unsigned char blob_unknown[] = {0x00,0x00,0x00,0x00};
852 
853 	unsigned char ntv2_hash[HMAC_MD5_LENGTH];
854 	guchar *nonce_blob, *blob, *p_blob;
855 	unsigned char nonce_blob_hash[HMAC_MD5_LENGTH];
856 	unsigned char nonce_client_nonce[16], nonce_client_nonce_hash[HMAC_MD5_LENGTH];
857 	gchar *user_uppercase, *user_domain, *user_domain_conv;
858 	gsize user_domain_conv_sz;
859 	size_t blob_sz;
860 	int i;
861 
862 	/* create HMAC-MD5 hash of Unicode uppercase username and Unicode domain */
863 	user_uppercase = g_utf8_strup (user, strlen (user));
864 	user_domain = g_strconcat (user_uppercase, domain, NULL);
865 	user_domain_conv = g_convert (user_domain, -1, "UCS-2LE", "UTF-8", NULL, &user_domain_conv_sz, NULL);
866 	calc_hmac_md5 (ntv2_hash, nt_hash, nt_hash_sz, (const guchar *)user_domain_conv, user_domain_conv_sz);
867 	g_free (user_uppercase);
868 	g_free (user_domain);
869 	g_free (user_domain_conv);
870 
871 	/* create random client nonce */
872 	for (i = 0; i < sizeof (client_nonce); i++)
873 	{
874 		client_nonce[i] = g_random_int();
875 	}
876 
877 	/* create timestamp for blob
878 	 * LE, 64-bit signed value, number of tenths of a ms since January 1, 1601.*/
879 	blob_timestamp = GINT64_TO_LE(((unsigned long)time(NULL) + 11644473600) * 10000000);
880 
881 	/* create blob */
882 	blob_sz = sizeof (blob_signature) + sizeof (blob_reserved) +
883 			sizeof (blob_timestamp) + sizeof (client_nonce) +
884 			sizeof (blob_unknown) + target_info_sz;
885 	p_blob = blob = g_malloc (blob_sz);
886 	memset (blob, 0, blob_sz);
887 	memcpy (p_blob, blob_signature, sizeof (blob_signature));
888 	memcpy (p_blob += sizeof (blob_signature), blob_reserved, sizeof (blob_reserved));
889 	memcpy (p_blob += sizeof (blob_reserved), &blob_timestamp, sizeof (blob_timestamp));
890 	memcpy (p_blob += sizeof (blob_timestamp), client_nonce, sizeof (client_nonce));
891 	memcpy (p_blob += sizeof (client_nonce), blob_unknown, sizeof (blob_unknown));
892 	memcpy (p_blob += sizeof (blob_unknown), target_info, target_info_sz);
893 
894 	/* create HMAC-MD5 hash of concatenated nonce and blob */
895 	nonce_blob = g_malloc (NTLM_CHALLENGE_NONCE_LENGTH + blob_sz);
896 	memcpy (nonce_blob, nonce, NTLM_CHALLENGE_NONCE_LENGTH);
897 	memcpy (nonce_blob + NTLM_CHALLENGE_NONCE_LENGTH, blob, blob_sz);
898 	calc_hmac_md5 (nonce_blob_hash, (const guchar *)ntv2_hash, (gsize) sizeof (ntv2_hash), (const guchar *) nonce_blob, (gsize) NTLM_CHALLENGE_NONCE_LENGTH + blob_sz);
899 	g_free (nonce_blob);
900 
901 	/* create NTv2 response */
902 	memset (nt_resp, 0, nt_resp_sz);
903 	memcpy (nt_resp, nonce_blob_hash, sizeof (nonce_blob_hash));
904 	memcpy (nt_resp + sizeof (nonce_blob_hash), blob, blob_sz);
905 
906 	g_free (blob);
907 
908 	/* LMv2
909 	 * create HMAC-MD5 hash of concatenated nonce and client nonce
910 	 */
911 	memcpy (nonce_client_nonce, nonce, NTLM_CHALLENGE_NONCE_LENGTH);
912 	memcpy (nonce_client_nonce + NTLM_CHALLENGE_NONCE_LENGTH, client_nonce, sizeof (client_nonce));
913 	calc_hmac_md5 (nonce_client_nonce_hash, (const guchar *) ntv2_hash, (gsize) sizeof (ntv2_hash), (const guchar *) nonce_client_nonce, (gsize) NTLM_CHALLENGE_NONCE_LENGTH + sizeof (client_nonce));
914 
915 	/* create LMv2 response */
916 	memset (lm_resp, 0, lm_resp_sz);
917 	memcpy (lm_resp, nonce_client_nonce_hash, sizeof (nonce_client_nonce_hash));
918 	memcpy (lm_resp + sizeof (nonce_client_nonce_hash), client_nonce, sizeof (client_nonce));
919 }
920 
921 static char *
soup_ntlm_response(const char * nonce,const char * user,guchar nt_hash[21],guchar lm_hash[21],const char * host,const char * domain,gboolean ntlmv2_session,gboolean negotiate_target,const char * target_info,size_t target_info_sz)922 soup_ntlm_response (const char *nonce,
923 		    const char *user,
924 		    guchar      nt_hash[21],
925 		    guchar      lm_hash[21],
926 		    const char *host,
927 		    const char *domain,
928 		    gboolean    ntlmv2_session,
929 		    gboolean    negotiate_target,
930 		    const char	*target_info,
931 		    size_t	target_info_sz)
932 {
933 
934 	int offset;
935 	gsize hlen, dlen, ulen, nt_resp_sz;
936 	guchar lm_resp[24], *nt_resp;
937 	char *user_conv, *host_conv, *domain_conv;
938 	NTLMResponse resp;
939 	char *out, *p;
940 	int state, save;
941 
942 	if (negotiate_target)
943 	{
944 		/* nonce_blob_hash 16 + blob_signature 4 + blob_reserved 4 +
945 		 * blob_timestamp 8 + client_nonce 8 + blob_unknown 4 +
946 		 * target_info*/
947 		nt_resp_sz = NTLM_RESPONSE_TARGET_INFORMATION_OFFSET + target_info_sz;
948 	} else {
949 		nt_resp_sz = 24;
950 	}
951 	nt_resp = g_malloc (nt_resp_sz);
952 
953 	if (ntlmv2_session && !negotiate_target) {
954 		calc_ntlm2_session_response (nonce, nt_hash, lm_hash,
955 					     lm_resp, sizeof(lm_resp), nt_resp);
956 	} else if (!negotiate_target){
957 		/* Compute a regular NTLMv1 response */
958 		calc_response (nt_hash, (guchar *) nonce, nt_resp);
959 		calc_response (lm_hash, (guchar *) nonce, lm_resp);
960 	} else {
961 		calc_ntlmv2_response (user, domain,
962 					nt_hash, 21,
963 					(guchar *) nonce,
964 					target_info, target_info_sz,
965 					lm_resp, sizeof (lm_resp),
966 					nt_resp, (size_t) nt_resp_sz);
967 	}
968 
969 	memset (&resp, 0, sizeof (resp));
970 	memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header));
971 	resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS);
972 	if (ntlmv2_session)
973 		resp.flags |= GUINT32_TO_LE (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY);
974 	if (negotiate_target)
975 			resp.flags |= GUINT32_TO_LE (NTLM_FLAGS_REQUEST_TARGET);
976 	offset = sizeof (resp);
977 
978 	if (!host)
979 		host = "UNKNOWN";
980 
981 	domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL);
982 	user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL);
983 	host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL);
984 
985 	ntlm_set_string (&resp.domain, &offset, dlen);
986 	ntlm_set_string (&resp.user, &offset, ulen);
987 	ntlm_set_string (&resp.host, &offset, hlen);
988 	ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp));
989 	ntlm_set_string (&resp.nt_resp, &offset, nt_resp_sz);
990 
991 	out = g_malloc (((offset + 3) * 4) / 3 + 6);
992 	memcpy (out, "NTLM ", 5);
993 	p = out + 5;
994 
995 	state = save = 0;
996 
997 	p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp),
998 				   FALSE, p, &state, &save);
999 	p += g_base64_encode_step ((const guchar *) domain_conv, dlen,
1000 				   FALSE, p, &state, &save);
1001 	p += g_base64_encode_step ((const guchar *) user_conv, ulen,
1002 				   FALSE, p, &state, &save);
1003 	p += g_base64_encode_step ((const guchar *) host_conv, hlen,
1004 				   FALSE, p, &state, &save);
1005 	p += g_base64_encode_step (lm_resp, sizeof (lm_resp),
1006 				   FALSE, p, &state, &save);
1007 	p += g_base64_encode_step (nt_resp, nt_resp_sz,
1008 				   FALSE, p, &state, &save);
1009 	p += g_base64_encode_close (FALSE, p, &state, &save);
1010 	*p = '\0';
1011 
1012 	g_free (domain_conv);
1013 	g_free (user_conv);
1014 	g_free (host_conv);
1015 	g_free (nt_resp);
1016 
1017 	return out;
1018 }
1019 
1020 /* DES utils */
1021 /* Set up a key schedule based on a 56bit key */
1022 static void
setup_schedule(const guchar * key_56,DES_KS ks)1023 setup_schedule (const guchar *key_56, DES_KS ks)
1024 {
1025 	guchar key[8];
1026 	int i, c, bit;
1027 
1028 	key[0] = (key_56[0])                                 ;
1029 	key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF);
1030 	key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF);
1031 	key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF);
1032 	key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF);
1033 	key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF);
1034 	key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF);
1035 	key[7] =                    ((key_56[6] << 1) & 0xFF);
1036 
1037 	/* Fix parity */
1038 	for (i = 0; i < 8; i++) {
1039 		for (c = bit = 0; bit < 8; bit++)
1040 			if (key[i] & (1 << bit))
1041 				c++;
1042 		if (!(c & 1))
1043 			key[i] ^= 0x01;
1044 	}
1045 
1046         deskey (ks, key, 0);
1047 }
1048 
1049 static void
calc_response(const guchar * key,const guchar * plaintext,guchar * results)1050 calc_response (const guchar *key, const guchar *plaintext, guchar *results)
1051 {
1052         DES_KS ks;
1053 
1054 	memcpy (results, plaintext, 8);
1055 	memcpy (results + 8, plaintext, 8);
1056 	memcpy (results + 16, plaintext, 8);
1057 
1058         setup_schedule (key, ks);
1059 	des (ks, results);
1060 
1061         setup_schedule (key + 7, ks);
1062 	des (ks, results + 8);
1063 
1064         setup_schedule (key + 14, ks);
1065         des (ks, results + 16);
1066 }
1067 
1068 
1069 /*
1070  * MD4 encoder. (The one everyone else uses is not GPL-compatible;
1071  * this is a reimplementation from spec.) This doesn't need to be
1072  * efficient for our purposes, although it would be nice to fix
1073  * it to not malloc()...
1074  */
1075 
1076 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
1077 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
1078 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
1079 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
1080 
1081 static void
md4sum(const unsigned char * in,int nbytes,unsigned char digest[16])1082 md4sum (const unsigned char *in, int nbytes, unsigned char digest[16])
1083 {
1084 	unsigned char *M;
1085 	guint32 A, B, C, D, AA, BB, CC, DD, X[16];
1086 	int pbytes, nbits = nbytes * 8, i, j;
1087 
1088 	/* There is *always* padding of at least one bit. */
1089 	pbytes = ((119 - (nbytes % 64)) % 64) + 1;
1090 	M = alloca (nbytes + pbytes + 8);
1091 	memcpy (M, in, nbytes);
1092 	memset (M + nbytes, 0, pbytes + 8);
1093 	M[nbytes] = 0x80;
1094 	M[nbytes + pbytes] = nbits & 0xFF;
1095 	M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF;
1096 	M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF;
1097 	M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF;
1098 
1099 	A = 0x67452301;
1100 	B = 0xEFCDAB89;
1101 	C = 0x98BADCFE;
1102 	D = 0x10325476;
1103 
1104 	for (i = 0; i < nbytes + pbytes + 8; i += 64) {
1105 		for (j = 0; j < 16; j++) {
1106 			X[j] =  (M[i + j*4]) |
1107 				(M[i + j*4 + 1] << 8) |
1108 				(M[i + j*4 + 2] << 16) |
1109 				(M[i + j*4 + 3] << 24);
1110 		}
1111 
1112 		AA = A;
1113 		BB = B;
1114 		CC = C;
1115 		DD = D;
1116 
1117 		A = ROT (A + F(B, C, D) + X[0], 3);
1118 		D = ROT (D + F(A, B, C) + X[1], 7);
1119 		C = ROT (C + F(D, A, B) + X[2], 11);
1120 		B = ROT (B + F(C, D, A) + X[3], 19);
1121 		A = ROT (A + F(B, C, D) + X[4], 3);
1122 		D = ROT (D + F(A, B, C) + X[5], 7);
1123 		C = ROT (C + F(D, A, B) + X[6], 11);
1124 		B = ROT (B + F(C, D, A) + X[7], 19);
1125 		A = ROT (A + F(B, C, D) + X[8], 3);
1126 		D = ROT (D + F(A, B, C) + X[9], 7);
1127 		C = ROT (C + F(D, A, B) + X[10], 11);
1128 		B = ROT (B + F(C, D, A) + X[11], 19);
1129 		A = ROT (A + F(B, C, D) + X[12], 3);
1130 		D = ROT (D + F(A, B, C) + X[13], 7);
1131 		C = ROT (C + F(D, A, B) + X[14], 11);
1132 		B = ROT (B + F(C, D, A) + X[15], 19);
1133 
1134 		A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3);
1135 		D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5);
1136 		C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9);
1137 		B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
1138 		A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3);
1139 		D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5);
1140 		C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9);
1141 		B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
1142 		A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3);
1143 		D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5);
1144 		C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
1145 		B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
1146 		A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3);
1147 		D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5);
1148 		C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
1149 		B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
1150 
1151 		A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3);
1152 		D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9);
1153 		C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11);
1154 		B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
1155 		A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3);
1156 		D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
1157 		C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11);
1158 		B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
1159 		A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3);
1160 		D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9);
1161 		C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11);
1162 		B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
1163 		A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3);
1164 		D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
1165 		C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11);
1166 		B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
1167 
1168 		A += AA;
1169 		B += BB;
1170 		C += CC;
1171 		D += DD;
1172 	}
1173 
1174 	digest[0]  =  A        & 0xFF;
1175 	digest[1]  = (A >>  8) & 0xFF;
1176 	digest[2]  = (A >> 16) & 0xFF;
1177 	digest[3]  = (A >> 24) & 0xFF;
1178 	digest[4]  =  B        & 0xFF;
1179 	digest[5]  = (B >>  8) & 0xFF;
1180 	digest[6]  = (B >> 16) & 0xFF;
1181 	digest[7]  = (B >> 24) & 0xFF;
1182 	digest[8]  =  C        & 0xFF;
1183 	digest[9]  = (C >>  8) & 0xFF;
1184 	digest[10] = (C >> 16) & 0xFF;
1185 	digest[11] = (C >> 24) & 0xFF;
1186 	digest[12] =  D        & 0xFF;
1187 	digest[13] = (D >>  8) & 0xFF;
1188 	digest[14] = (D >> 16) & 0xFF;
1189 	digest[15] = (D >> 24) & 0xFF;
1190 }
1191 
1192 
1193 /* Public domain DES implementation from Phil Karn */
1194 static const guint32 Spbox[8][64] = {
1195 	{ 0x01010400,0x00000000,0x00010000,0x01010404,
1196 	  0x01010004,0x00010404,0x00000004,0x00010000,
1197 	  0x00000400,0x01010400,0x01010404,0x00000400,
1198 	  0x01000404,0x01010004,0x01000000,0x00000004,
1199 	  0x00000404,0x01000400,0x01000400,0x00010400,
1200 	  0x00010400,0x01010000,0x01010000,0x01000404,
1201 	  0x00010004,0x01000004,0x01000004,0x00010004,
1202 	  0x00000000,0x00000404,0x00010404,0x01000000,
1203 	  0x00010000,0x01010404,0x00000004,0x01010000,
1204 	  0x01010400,0x01000000,0x01000000,0x00000400,
1205 	  0x01010004,0x00010000,0x00010400,0x01000004,
1206 	  0x00000400,0x00000004,0x01000404,0x00010404,
1207 	  0x01010404,0x00010004,0x01010000,0x01000404,
1208 	  0x01000004,0x00000404,0x00010404,0x01010400,
1209 	  0x00000404,0x01000400,0x01000400,0x00000000,
1210 	  0x00010004,0x00010400,0x00000000,0x01010004 },
1211 	{ 0x80108020,0x80008000,0x00008000,0x00108020,
1212 	  0x00100000,0x00000020,0x80100020,0x80008020,
1213 	  0x80000020,0x80108020,0x80108000,0x80000000,
1214 	  0x80008000,0x00100000,0x00000020,0x80100020,
1215 	  0x00108000,0x00100020,0x80008020,0x00000000,
1216 	  0x80000000,0x00008000,0x00108020,0x80100000,
1217 	  0x00100020,0x80000020,0x00000000,0x00108000,
1218 	  0x00008020,0x80108000,0x80100000,0x00008020,
1219 	  0x00000000,0x00108020,0x80100020,0x00100000,
1220 	  0x80008020,0x80100000,0x80108000,0x00008000,
1221 	  0x80100000,0x80008000,0x00000020,0x80108020,
1222 	  0x00108020,0x00000020,0x00008000,0x80000000,
1223 	  0x00008020,0x80108000,0x00100000,0x80000020,
1224 	  0x00100020,0x80008020,0x80000020,0x00100020,
1225 	  0x00108000,0x00000000,0x80008000,0x00008020,
1226 	  0x80000000,0x80100020,0x80108020,0x00108000 },
1227 	{ 0x00000208,0x08020200,0x00000000,0x08020008,
1228 	  0x08000200,0x00000000,0x00020208,0x08000200,
1229 	  0x00020008,0x08000008,0x08000008,0x00020000,
1230 	  0x08020208,0x00020008,0x08020000,0x00000208,
1231 	  0x08000000,0x00000008,0x08020200,0x00000200,
1232 	  0x00020200,0x08020000,0x08020008,0x00020208,
1233 	  0x08000208,0x00020200,0x00020000,0x08000208,
1234 	  0x00000008,0x08020208,0x00000200,0x08000000,
1235 	  0x08020200,0x08000000,0x00020008,0x00000208,
1236 	  0x00020000,0x08020200,0x08000200,0x00000000,
1237 	  0x00000200,0x00020008,0x08020208,0x08000200,
1238 	  0x08000008,0x00000200,0x00000000,0x08020008,
1239 	  0x08000208,0x00020000,0x08000000,0x08020208,
1240 	  0x00000008,0x00020208,0x00020200,0x08000008,
1241 	  0x08020000,0x08000208,0x00000208,0x08020000,
1242 	  0x00020208,0x00000008,0x08020008,0x00020200 },
1243 	{ 0x00802001,0x00002081,0x00002081,0x00000080,
1244 	  0x00802080,0x00800081,0x00800001,0x00002001,
1245 	  0x00000000,0x00802000,0x00802000,0x00802081,
1246 	  0x00000081,0x00000000,0x00800080,0x00800001,
1247 	  0x00000001,0x00002000,0x00800000,0x00802001,
1248 	  0x00000080,0x00800000,0x00002001,0x00002080,
1249 	  0x00800081,0x00000001,0x00002080,0x00800080,
1250 	  0x00002000,0x00802080,0x00802081,0x00000081,
1251 	  0x00800080,0x00800001,0x00802000,0x00802081,
1252 	  0x00000081,0x00000000,0x00000000,0x00802000,
1253 	  0x00002080,0x00800080,0x00800081,0x00000001,
1254 	  0x00802001,0x00002081,0x00002081,0x00000080,
1255 	  0x00802081,0x00000081,0x00000001,0x00002000,
1256 	  0x00800001,0x00002001,0x00802080,0x00800081,
1257 	  0x00002001,0x00002080,0x00800000,0x00802001,
1258 	  0x00000080,0x00800000,0x00002000,0x00802080 },
1259 	{ 0x00000100,0x02080100,0x02080000,0x42000100,
1260 	  0x00080000,0x00000100,0x40000000,0x02080000,
1261 	  0x40080100,0x00080000,0x02000100,0x40080100,
1262 	  0x42000100,0x42080000,0x00080100,0x40000000,
1263 	  0x02000000,0x40080000,0x40080000,0x00000000,
1264 	  0x40000100,0x42080100,0x42080100,0x02000100,
1265 	  0x42080000,0x40000100,0x00000000,0x42000000,
1266 	  0x02080100,0x02000000,0x42000000,0x00080100,
1267 	  0x00080000,0x42000100,0x00000100,0x02000000,
1268 	  0x40000000,0x02080000,0x42000100,0x40080100,
1269 	  0x02000100,0x40000000,0x42080000,0x02080100,
1270 	  0x40080100,0x00000100,0x02000000,0x42080000,
1271 	  0x42080100,0x00080100,0x42000000,0x42080100,
1272 	  0x02080000,0x00000000,0x40080000,0x42000000,
1273 	  0x00080100,0x02000100,0x40000100,0x00080000,
1274 	  0x00000000,0x40080000,0x02080100,0x40000100 },
1275 	{ 0x20000010,0x20400000,0x00004000,0x20404010,
1276 	  0x20400000,0x00000010,0x20404010,0x00400000,
1277 	  0x20004000,0x00404010,0x00400000,0x20000010,
1278 	  0x00400010,0x20004000,0x20000000,0x00004010,
1279 	  0x00000000,0x00400010,0x20004010,0x00004000,
1280 	  0x00404000,0x20004010,0x00000010,0x20400010,
1281 	  0x20400010,0x00000000,0x00404010,0x20404000,
1282 	  0x00004010,0x00404000,0x20404000,0x20000000,
1283 	  0x20004000,0x00000010,0x20400010,0x00404000,
1284 	  0x20404010,0x00400000,0x00004010,0x20000010,
1285 	  0x00400000,0x20004000,0x20000000,0x00004010,
1286 	  0x20000010,0x20404010,0x00404000,0x20400000,
1287 	  0x00404010,0x20404000,0x00000000,0x20400010,
1288 	  0x00000010,0x00004000,0x20400000,0x00404010,
1289 	  0x00004000,0x00400010,0x20004010,0x00000000,
1290 	  0x20404000,0x20000000,0x00400010,0x20004010 },
1291 	{ 0x00200000,0x04200002,0x04000802,0x00000000,
1292 	  0x00000800,0x04000802,0x00200802,0x04200800,
1293 	  0x04200802,0x00200000,0x00000000,0x04000002,
1294 	  0x00000002,0x04000000,0x04200002,0x00000802,
1295 	  0x04000800,0x00200802,0x00200002,0x04000800,
1296 	  0x04000002,0x04200000,0x04200800,0x00200002,
1297 	  0x04200000,0x00000800,0x00000802,0x04200802,
1298 	  0x00200800,0x00000002,0x04000000,0x00200800,
1299 	  0x04000000,0x00200800,0x00200000,0x04000802,
1300 	  0x04000802,0x04200002,0x04200002,0x00000002,
1301 	  0x00200002,0x04000000,0x04000800,0x00200000,
1302 	  0x04200800,0x00000802,0x00200802,0x04200800,
1303 	  0x00000802,0x04000002,0x04200802,0x04200000,
1304 	  0x00200800,0x00000000,0x00000002,0x04200802,
1305 	  0x00000000,0x00200802,0x04200000,0x00000800,
1306 	  0x04000002,0x04000800,0x00000800,0x00200002 },
1307 	{ 0x10001040,0x00001000,0x00040000,0x10041040,
1308 	  0x10000000,0x10001040,0x00000040,0x10000000,
1309 	  0x00040040,0x10040000,0x10041040,0x00041000,
1310 	  0x10041000,0x00041040,0x00001000,0x00000040,
1311 	  0x10040000,0x10000040,0x10001000,0x00001040,
1312 	  0x00041000,0x00040040,0x10040040,0x10041000,
1313 	  0x00001040,0x00000000,0x00000000,0x10040040,
1314 	  0x10000040,0x10001000,0x00041040,0x00040000,
1315 	  0x00041040,0x00040000,0x10041000,0x00001000,
1316 	  0x00000040,0x10040040,0x00001000,0x00041040,
1317 	  0x10001000,0x00000040,0x10000040,0x10040000,
1318 	  0x10040040,0x10000000,0x00040000,0x10001040,
1319 	  0x00000000,0x10041040,0x00040040,0x10000040,
1320 	  0x10040000,0x10001000,0x10001040,0x00000000,
1321 	  0x10041040,0x00041000,0x00041000,0x00001040,
1322 	  0x00001040,0x00040040,0x10000000,0x10041000 }
1323 };
1324 
1325 #undef F
1326 #define	F(l,r,key){\
1327 	work = ((r >> 4) | (r << 28)) ^ key[0];\
1328 	l ^= Spbox[6][work & 0x3f];\
1329 	l ^= Spbox[4][(work >> 8) & 0x3f];\
1330 	l ^= Spbox[2][(work >> 16) & 0x3f];\
1331 	l ^= Spbox[0][(work >> 24) & 0x3f];\
1332 	work = r ^ key[1];\
1333 	l ^= Spbox[7][work & 0x3f];\
1334 	l ^= Spbox[5][(work >> 8) & 0x3f];\
1335 	l ^= Spbox[3][(work >> 16) & 0x3f];\
1336 	l ^= Spbox[1][(work >> 24) & 0x3f];\
1337 }
1338 /* Encrypt or decrypt a block of data in ECB mode */
1339 static void
des(guint32 ks[16][2],unsigned char block[8])1340 des (guint32 ks[16][2], unsigned char block[8])
1341 {
1342 	guint32 left,right,work;
1343 
1344 	/* Read input block and place in left/right in big-endian order */
1345 	left = ((guint32)block[0] << 24)
1346 	 | ((guint32)block[1] << 16)
1347 	 | ((guint32)block[2] << 8)
1348 	 | (guint32)block[3];
1349 	right = ((guint32)block[4] << 24)
1350 	 | ((guint32)block[5] << 16)
1351 	 | ((guint32)block[6] << 8)
1352 	 | (guint32)block[7];
1353 
1354 	/* Hoey's clever initial permutation algorithm, from Outerbridge
1355 	 * (see Schneier p 478)
1356 	 *
1357 	 * The convention here is the same as Outerbridge: rotate each
1358 	 * register left by 1 bit, i.e., so that "left" contains permuted
1359 	 * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
1360 	 * (using origin-1 numbering as in the FIPS). This allows us to avoid
1361 	 * one of the two rotates that would otherwise be required in each of
1362 	 * the 16 rounds.
1363 	 */
1364 	work = ((left >> 4) ^ right) & 0x0f0f0f0f;
1365 	right ^= work;
1366 	left ^= work << 4;
1367 	work = ((left >> 16) ^ right) & 0xffff;
1368 	right ^= work;
1369 	left ^= work << 16;
1370 	work = ((right >> 2) ^ left) & 0x33333333;
1371 	left ^= work;
1372 	right ^= (work << 2);
1373 	work = ((right >> 8) ^ left) & 0xff00ff;
1374 	left ^= work;
1375 	right ^= (work << 8);
1376 	right = (right << 1) | (right >> 31);
1377 	work = (left ^ right) & 0xaaaaaaaa;
1378 	left ^= work;
1379 	right ^= work;
1380 	left = (left << 1) | (left >> 31);
1381 
1382 	/* Now do the 16 rounds */
1383 	F(left,right,ks[0]);
1384 	F(right,left,ks[1]);
1385 	F(left,right,ks[2]);
1386 	F(right,left,ks[3]);
1387 	F(left,right,ks[4]);
1388 	F(right,left,ks[5]);
1389 	F(left,right,ks[6]);
1390 	F(right,left,ks[7]);
1391 	F(left,right,ks[8]);
1392 	F(right,left,ks[9]);
1393 	F(left,right,ks[10]);
1394 	F(right,left,ks[11]);
1395 	F(left,right,ks[12]);
1396 	F(right,left,ks[13]);
1397 	F(left,right,ks[14]);
1398 	F(right,left,ks[15]);
1399 
1400 	/* Inverse permutation, also from Hoey via Outerbridge and Schneier */
1401 	right = (right << 31) | (right >> 1);
1402 	work = (left ^ right) & 0xaaaaaaaa;
1403 	left ^= work;
1404 	right ^= work;
1405 	left = (left >> 1) | (left  << 31);
1406 	work = ((left >> 8) ^ right) & 0xff00ff;
1407 	right ^= work;
1408 	left ^= work << 8;
1409 	work = ((left >> 2) ^ right) & 0x33333333;
1410 	right ^= work;
1411 	left ^= work << 2;
1412 	work = ((right >> 16) ^ left) & 0xffff;
1413 	left ^= work;
1414 	right ^= work << 16;
1415 	work = ((right >> 4) ^ left) & 0x0f0f0f0f;
1416 	left ^= work;
1417 	right ^= work << 4;
1418 
1419 	/* Put the block back into the user's buffer with final swap */
1420 	block[0] = right >> 24;
1421 	block[1] = right >> 16;
1422 	block[2] = right >> 8;
1423 	block[3] = right;
1424 	block[4] = left >> 24;
1425 	block[5] = left >> 16;
1426 	block[6] = left >> 8;
1427 	block[7] = left;
1428 }
1429 
1430 /* Key schedule-related tables from FIPS-46 */
1431 
1432 /* permuted choice table (key) */
1433 static const unsigned char pc1[] = {
1434 	57, 49, 41, 33, 25, 17,  9,
1435 	 1, 58, 50, 42, 34, 26, 18,
1436 	10,  2, 59, 51, 43, 35, 27,
1437 	19, 11,  3, 60, 52, 44, 36,
1438 
1439 	63, 55, 47, 39, 31, 23, 15,
1440 	 7, 62, 54, 46, 38, 30, 22,
1441 	14,  6, 61, 53, 45, 37, 29,
1442 	21, 13,  5, 28, 20, 12,  4
1443 };
1444 
1445 /* number left rotations of pc1 */
1446 static const unsigned char totrot[] = {
1447 	1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
1448 };
1449 
1450 /* permuted choice key (table) */
1451 static const unsigned char pc2[] = {
1452 	14, 17, 11, 24,  1,  5,
1453 	 3, 28, 15,  6, 21, 10,
1454 	23, 19, 12,  4, 26,  8,
1455 	16,  7, 27, 20, 13,  2,
1456 	41, 52, 31, 37, 47, 55,
1457 	30, 40, 51, 45, 33, 48,
1458 	44, 49, 39, 56, 34, 53,
1459 	46, 42, 50, 36, 29, 32
1460 };
1461 
1462 /* End of DES-defined tables */
1463 
1464 
1465 /* bit 0 is left-most in byte */
1466 static const int bytebit[] = {
1467 	0200,0100,040,020,010,04,02,01
1468 };
1469 
1470 
1471 /* Generate key schedule for encryption or decryption
1472  * depending on the value of "decrypt"
1473  */
1474 static void
deskey(DES_KS k,unsigned char * key,int decrypt)1475 deskey (DES_KS k, unsigned char *key, int decrypt)
1476 {
1477 	unsigned char pc1m[56];		/* place to modify pc1 into */
1478 	unsigned char pcr[56];		/* place to rotate pc1 into */
1479 	register int i,j,l;
1480 	int m;
1481 	unsigned char ks[8];
1482 
1483 	for (j=0; j<56; j++) {		/* convert pc1 to bits of key */
1484 		l=pc1[j]-1;		/* integer bit location	 */
1485 		m = l & 07;		/* find bit		 */
1486 		pc1m[j]=(key[l>>3] &	/* find which key byte l is in */
1487 			bytebit[m])	/* and which bit of that byte */
1488 			? 1 : 0;	/* and store 1-bit result */
1489 	}
1490 	for (i=0; i<16; i++) {		/* key chunk for each iteration */
1491 		memset(ks,0,sizeof(ks));	/* Clear key schedule */
1492 		for (j=0; j<56; j++)	/* rotate pc1 the right amount */
1493 			pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28];
1494 			/* rotate left and right halves independently */
1495 		for (j=0; j<48; j++){	/* select bits individually */
1496 			/* check bit that goes to ks[j] */
1497 			if (pcr[pc2[j]-1]){
1498 				/* mask it in if it's there */
1499 				l= j % 6;
1500 				ks[j/6] |= bytebit[l] >> 2;
1501 			}
1502 		}
1503 		/* Now convert to packed odd/even interleaved form */
1504 		k[i][0] = ((guint32)ks[0] << 24)
1505 		 | ((guint32)ks[2] << 16)
1506 		 | ((guint32)ks[4] << 8)
1507 		 | ((guint32)ks[6]);
1508 		k[i][1] = ((guint32)ks[1] << 24)
1509 		 | ((guint32)ks[3] << 16)
1510 		 | ((guint32)ks[5] << 8)
1511 		 | ((guint32)ks[7]);
1512 	}
1513 }
1514