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