1 /* digest-md5.c implementation of SASL mechanism DIGEST-MD5 from RFC 2831
2 * Copyright (C) 2002 Simon Josefsson
3 * Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. (getsubopt)
5 * This file is part of libgsasl.
7 * Libgsasl is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libgsasl is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with libgsasl; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 # include <inttypes.h>
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
45 #define NONCE_ENTROPY_BITS 64
46 #define CNONCE_ENTROPY_BITS 64
49 #define REALM_PRE "realm=\""
50 #define REALM_POST "\"" DELIM
51 #define NONCE_PRE "nonce=\""
52 #define NONCE_POST "\"" DELIM
53 #define QOP_LIST_PRE "qop=\""
54 #define QOP_LIST_POST "\"" DELIM
55 #ifdef DONT_WORKAROUND_CYRUS_SASL_BUG
56 #define QOP_DELIM DELIM
60 #define QOP_AUTH "auth"
61 #define QOP_AUTH_INT "auth-int"
62 #define QOP_AUTH_CONF "auth-conf"
63 #define MAXBUF_PRE "maxbuf="
64 #define MAXBUF_POST DELIM
65 #define DEFAULT_CHARSET "utf-8"
66 #define CHARSET "charset=" DEFAULT_CHARSET DELIM
67 #define DEFAULT_ALGORITHM "md5-sess"
68 #define ALGORITHM "algorithm=" DEFAULT_ALGORITHM DELIM
69 #define CIPHER_PRE "cipher=\""
70 #define CIPHER_DELIM DELIM
71 #define CIPHER_DES "des"
72 #define CIPHER_3DES "3des"
73 #define CIPHER_RC4_40 "rc4-40"
74 #define CIPHER_RC4 "rc4"
75 #define CIPHER_RC4_56 "rc4-56"
76 #define CIPHER_AES "aes"
77 #ifdef DONT_WORKAROUND_CYRUS_SASL_BUG
78 #define CIPHER_POST "\"" DELIM
80 #define CIPHER_POST "\""
83 #define USERNAME_PRE "username=\""
84 #define USERNAME_POST "\"" DELIM
85 #define CNONCE_PRE "cnonce=\""
86 #define CNONCE_POST "\"" DELIM
87 #define NONCE_COUNT_PRE "nc="
88 #define NONCE_COUNT_POST DELIM
89 #define QOP_PRE "qop="
90 #define QOP_POST DELIM
91 #define RESPONSE_PRE "response="
92 #define RESPONSE_POST "" DELIM
93 #define AUTHZID_PRE "authzid=\""
94 #define AUTHZID_POST "\"" DELIM
95 #define DIGEST_URI_PRE "digest-uri=\""
96 #define DIGEST_URI_POST "\"" DELIM
98 #define RSPAUTH_PRE "rspauth="
99 #define RSPAUTH_POST ""
101 #define A2_PRE "AUTHENTICATE:"
102 #define A2_POST ":00000000000000000000000000000000"
106 #define SASL_INTEGRITY_PREFIX_LENGTH 4
108 #define MAC_DATA_LEN 4
109 #define MAC_HMAC_LEN 10
110 #define MAC_MSG_TYPE "\x00\x01"
111 #define MAC_MSG_TYPE_LEN 2
112 #define MAC_SEQNUM_LEN 4
113 #define MAXBUF_DEFAULT 65536
114 #define RESPONSE_LENGTH 32
115 #define RSPAUTH_LENGTH RESPONSE_LENGTH
116 #define DERIVE_CLIENT_INTEGRITY_KEY_STRING "Digest session key to client-to-server signing key magic constant"
117 #define DERIVE_SERVER_INTEGRITY_KEY_STRING "Digest session key to server-to-client signing key magic constant"
118 #define DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING "Digest H(A1) to client-to-server sealing key magic constant"
119 #define DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING "Digest H(A1) to server-to-client sealing key magic constant"
122 #define CLIENT_PRINT_OUTPUT 0
123 #define SERVER_PRINT_OUTPUT 0
127 /* the order must match the following struct */
138 const char *digest_challenge_opts
[] = {
139 /* the order must match the previous enum */
153 /* the order must match the following struct */
154 RESPONSE_USERNAME
= 0,
168 const char *digest_response_opts
[] = {
169 /* the order must match the previous enum */
187 /* the order must match the following struct */
188 RESPONSEAUTH_RSPAUTH
= 0
191 const char *digest_responseauth_opts
[] = {
192 /* the order must match the previous enum */
199 /* the order must match the following struct */
205 const char *qop_opts
[] = {
206 /* the order must match the previous enum */
215 /* the order must match the following struct */
216 CIPHER_DES_OPTION
= 0,
219 CIPHER_RC4_40_OPTION
,
220 CIPHER_RC4_56_OPTION
,
224 const char *cipher_opts
[] = {
225 /* the order must match the previous enum */
235 /* Parse comma separate list into words.
236 Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
237 From the GNU C Library, under GNU LGPL version 2.1.
238 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
239 Modified for Libgsasl by Simon Josefsson <simon@josefsson.org>
240 Copyright (C) 2002 Simon Josefsson
242 Parse comma separated suboption from *OPTIONP and match against
243 strings in TOKENS. If found return index and set *VALUEP to
244 optional value introduced by an equal sign. If the suboption is
245 not part of TOKENS return in *VALUEP beginning of unknown
246 suboption. On exit *OPTIONP is set to the beginning of the next
247 token or at the terminating NUL character. */
249 _gsasl_getsubopt (optionp
, tokens
, valuep
)
256 int inside_quote
= 0;
258 if (**optionp
== '\0')
261 /* Find end of next token. */
263 while (*endp
!= '\0' && (inside_quote
|| (!inside_quote
&& *endp
!= ',')))
266 inside_quote
= !inside_quote
;
270 /* Find start of value. */
271 vstart
= memchr (*optionp
, '=', endp
- *optionp
);
275 /* Try to match the characters between *OPTIONP and VSTART against
276 one of the TOKENS. */
277 for (cnt
= 0; tokens
[cnt
] != NULL
; ++cnt
)
278 if (memcmp (*optionp
, tokens
[cnt
], vstart
- *optionp
) == 0
279 && tokens
[cnt
][vstart
- *optionp
] == '\0')
281 /* We found the current option in TOKENS. */
282 *valuep
= vstart
!= endp
? vstart
+ 1 : NULL
;
284 while (*valuep
&& (**valuep
== ' ' ||
287 **valuep
== '\n' || **valuep
== '"'))
294 while (*endp
== ' ' ||
296 *endp
== '\r' || *endp
== '\n' || *endp
== '"')
298 while (**optionp
== ' ' ||
299 **optionp
== '\t' || **optionp
== '\r' || **optionp
== '\n')
305 /* The current suboption does not match any option. */
311 while (**optionp
== ' ' ||
312 **optionp
== '\t' || **optionp
== '\r' || **optionp
== '\n')
319 _gsasl_digest (char *output
, /* must have 2*MD5LEN available bytes */
320 unsigned char secret
[MD5LEN
], unsigned char *nonce
, uint32_t nc
, char *cnonce
, int qop
, char *authzid
, char *digesturi
, char *a2string
, /* "AUTHENTICATE:" or ":" */
321 int cipher
, /* used by kcc and kcs */
322 char *kic
, /* output client integrity key, may be NULL */
323 char *kis
, /* output server integrity key, may be NULL */
324 char *kcc
, /* output client confidentiality key, may be NULL */
325 char *kcs
) /* output server confidentiality key, may be NULL */
327 char nchex
[NCLEN
+ 1];
328 char a1hexhash
[2 * MD5LEN
];
329 char a2hexhash
[2 * MD5LEN
];
336 md5h
= gcry_md_open (GCRY_MD_MD5
, 0);
338 return GSASL_GCRYPT_ERROR
;
340 gcry_md_write (md5h
, secret
, MD5LEN
);
341 gcry_md_write (md5h
, COLON
, strlen (COLON
));
342 gcry_md_write (md5h
, nonce
, strlen (nonce
));
343 gcry_md_write (md5h
, COLON
, strlen (COLON
));
344 gcry_md_write (md5h
, cnonce
, strlen (cnonce
));
345 if (authzid
&& strlen (authzid
) > 0)
347 gcry_md_write (md5h
, COLON
, strlen (COLON
));
348 gcry_md_write (md5h
, authzid
, strlen (authzid
));
351 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
353 return GSASL_GCRYPT_ERROR
;
360 md5h2
= gcry_md_open (GCRY_MD_MD5
, 0);
362 return GSASL_GCRYPT_ERROR
;
364 gcry_md_write (md5h2
, hash
, MD5LEN
);
365 gcry_md_write (md5h2
, DERIVE_CLIENT_INTEGRITY_KEY_STRING
,
366 strlen (DERIVE_CLIENT_INTEGRITY_KEY_STRING
));
368 hash2
= gcry_md_read (md5h2
, GCRY_MD_MD5
);
370 return GSASL_GCRYPT_ERROR
;
372 memcpy (kic
, hash2
, MD5LEN
);
374 gcry_md_close (md5h2
);
383 md5h2
= gcry_md_open (GCRY_MD_MD5
, 0);
385 return GSASL_GCRYPT_ERROR
;
387 if (cipher
== GSASL_CIPHER_RC4_40
)
389 else if (cipher
== GSASL_CIPHER_RC4_56
)
393 gcry_md_write (md5h2
, hash
, n
);
394 gcry_md_write (md5h2
, DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING
,
395 strlen (DERIVE_CLIENT_CONFIDENTIALITY_KEY_STRING
));
397 hash2
= gcry_md_read (md5h2
, GCRY_MD_MD5
);
399 return GSASL_GCRYPT_ERROR
;
401 memcpy (kcc
, hash2
, MD5LEN
);
403 gcry_md_close (md5h2
);
411 md5h2
= gcry_md_open (GCRY_MD_MD5
, 0);
413 return GSASL_GCRYPT_ERROR
;
415 gcry_md_write (md5h2
, hash
, MD5LEN
);
416 gcry_md_write (md5h2
, DERIVE_SERVER_INTEGRITY_KEY_STRING
,
417 strlen (DERIVE_SERVER_INTEGRITY_KEY_STRING
));
419 hash2
= gcry_md_read (md5h2
, GCRY_MD_MD5
);
421 return GSASL_GCRYPT_ERROR
;
423 memcpy (kis
, hash2
, MD5LEN
);
425 gcry_md_close (md5h2
);
434 md5h2
= gcry_md_open (GCRY_MD_MD5
, 0);
436 return GSASL_GCRYPT_ERROR
;
438 if (cipher
== GSASL_CIPHER_RC4_40
)
440 else if (cipher
== GSASL_CIPHER_RC4_56
)
444 gcry_md_write (md5h2
, hash
, n
);
445 gcry_md_write (md5h2
, DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING
,
446 strlen (DERIVE_SERVER_CONFIDENTIALITY_KEY_STRING
));
448 hash2
= gcry_md_read (md5h2
, GCRY_MD_MD5
);
450 return GSASL_GCRYPT_ERROR
;
452 memcpy (kcs
, hash2
, MD5LEN
);
454 gcry_md_close (md5h2
);
457 for (i
= 0; i
< MD5LEN
; i
++)
459 a1hexhash
[2 * i
+ 1] = HEXCHAR (hash
[i
]);
460 a1hexhash
[2 * i
+ 0] = HEXCHAR (hash
[i
] >> 4);
462 gcry_md_close (md5h
);
466 md5h
= gcry_md_open (GCRY_MD_MD5
, 0);
468 return GSASL_GCRYPT_ERROR
;
470 gcry_md_write (md5h
, a2string
, strlen (a2string
));
471 gcry_md_write (md5h
, digesturi
, strlen (digesturi
));
472 if (qop
& GSASL_QOP_AUTH_INT
|| qop
& GSASL_QOP_AUTH_CONF
)
474 gcry_md_write (md5h
, A2_POST
, strlen (A2_POST
));
477 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
479 return GSASL_GCRYPT_ERROR
;
481 for (i
= 0; i
< MD5LEN
; i
++)
483 a2hexhash
[2 * i
+ 1] = HEXCHAR (hash
[i
]);
484 a2hexhash
[2 * i
+ 0] = HEXCHAR (hash
[i
] >> 4);
486 gcry_md_close (md5h
);
490 md5h
= gcry_md_open (GCRY_MD_MD5
, 0);
492 return GSASL_GCRYPT_ERROR
;
494 gcry_md_write (md5h
, a1hexhash
, 2 * MD5LEN
);
495 gcry_md_write (md5h
, COLON
, strlen (COLON
));
496 gcry_md_write (md5h
, nonce
, strlen (nonce
));
497 gcry_md_write (md5h
, COLON
, strlen (COLON
));
498 sprintf (nchex
, "%0*x", NCLEN
, nc
);
499 gcry_md_write (md5h
, nchex
, strlen (nchex
));
500 gcry_md_write (md5h
, COLON
, strlen (COLON
));
501 gcry_md_write (md5h
, cnonce
, strlen (cnonce
));
502 gcry_md_write (md5h
, COLON
, strlen (COLON
));
503 if (qop
& GSASL_QOP_AUTH_CONF
)
504 gcry_md_write (md5h
, QOP_AUTH_CONF
, strlen (QOP_AUTH_CONF
));
505 else if (qop
& GSASL_QOP_AUTH_INT
)
506 gcry_md_write (md5h
, QOP_AUTH_INT
, strlen (QOP_AUTH_INT
));
507 else if (qop
& GSASL_QOP_AUTH
)
508 gcry_md_write (md5h
, QOP_AUTH
, strlen (QOP_AUTH
));
509 gcry_md_write (md5h
, COLON
, strlen (COLON
));
510 gcry_md_write (md5h
, a2hexhash
, 2 * MD5LEN
);
512 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
514 return GSASL_GCRYPT_ERROR
;
516 for (i
= 0; i
< MD5LEN
; i
++)
518 output
[2 * i
+ 1] = HEXCHAR (hash
[i
]);
519 output
[2 * i
+ 0] = HEXCHAR (hash
[i
] >> 4);
521 gcry_md_close (md5h
);
528 struct _Gsasl_digest_md5_client_state
531 unsigned char secret
[MD5LEN
];
532 unsigned char *nonce
;
534 unsigned char cnonce
[2 * CNONCE_ENTROPY_BITS
/ 8 + 1];
537 unsigned char *authzid
;
538 unsigned char *digesturi
;
539 unsigned char response
[RESPONSE_LENGTH
+ 1];
540 uint32_t readseqnum
, sendseqnum
;
541 unsigned char kic
[MD5LEN
];
542 unsigned char kcc
[MD5LEN
];
543 unsigned char kis
[MD5LEN
];
544 unsigned char kcs
[MD5LEN
];
546 typedef struct _Gsasl_digest_md5_client_state _Gsasl_digest_md5_client_state
;
549 _gsasl_digest_md5_client_init (Gsasl_ctx
* ctx
)
553 if (gcry_check_version (GCRYPT_VERSION
) == NULL
)
554 return GSASL_GCRYPT_ERROR
;
556 res
= gcry_control (GCRYCTL_INIT_SECMEM
, 512, 0);
557 if (res
!= GCRYERR_SUCCESS
)
558 return GSASL_GCRYPT_ERROR
;
564 _gsasl_digest_md5_client_done (Gsasl_ctx
* ctx
)
570 _gsasl_digest_md5_client_start (Gsasl_session_ctx
* cctx
, void **mech_data
)
572 _Gsasl_digest_md5_client_state
*state
;
575 ctx
= gsasl_client_ctx_get (cctx
);
577 return GSASL_CANNOT_GET_CTX
;
579 if (gsasl_client_callback_authentication_id_get (ctx
) == NULL
)
580 return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK
;
582 if (gsasl_client_callback_password_get (ctx
) == NULL
)
583 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK
;
585 state
= (_Gsasl_digest_md5_client_state
*) malloc (sizeof (*state
));
587 return GSASL_MALLOC_ERROR
;
593 state
->qop
= GSASL_QOP_AUTH
;
594 state
->authzid
= NULL
;
595 state
->digesturi
= NULL
;
596 state
->readseqnum
= 0;
597 state
->sendseqnum
= 0;
605 _gsasl_digest_md5_client_step (Gsasl_session_ctx
* cctx
,
609 char *output
, size_t * output_len
)
611 _Gsasl_digest_md5_client_state
*state
= mech_data
;
612 Gsasl_client_callback_authorization_id cb_authorization_id
;
613 Gsasl_client_callback_authentication_id cb_authentication_id
;
614 Gsasl_client_callback_password cb_password
;
615 Gsasl_client_callback_service cb_service
;
616 Gsasl_client_callback_qop cb_qop
;
617 Gsasl_client_callback_maxbuf cb_maxbuf
;
624 ctx
= gsasl_client_ctx_get (cctx
);
626 return GSASL_CANNOT_GET_CTX
;
628 cb_qop
= gsasl_client_callback_qop_get (ctx
);
629 cb_authorization_id
= gsasl_client_callback_authorization_id_get (ctx
);
630 cb_maxbuf
= gsasl_client_callback_maxbuf_get (ctx
);
632 cb_authentication_id
= gsasl_client_callback_authentication_id_get (ctx
);
633 if (cb_authentication_id
== NULL
)
634 return GSASL_NEED_CLIENT_AUTHENTICATION_ID_CALLBACK
;
636 cb_password
= gsasl_client_callback_password_get (ctx
);
637 if (cb_password
== NULL
)
638 return GSASL_NEED_CLIENT_PASSWORD_CALLBACK
;
640 cb_service
= gsasl_client_callback_service_get (ctx
);
641 if (cb_service
== NULL
)
642 return GSASL_NEED_CLIENT_SERVICE_CALLBACK
;
645 return GSASL_TOO_SMALL_BUFFER
;
650 #if CLIENT_PRINT_OUTPUT
651 if (input
&& input_len
> 0)
652 fprintf (stderr
, "%s\n", input
);
662 return GSASL_NEEDS_MORE
;
670 int maxbuf
= MAXBUF_DEFAULT
;
673 if (input
== NULL
|| input_len
== 0)
674 return GSASL_MECHANISM_PARSE_ERROR
;
676 zinput
= malloc (input_len
+ 1);
678 return GSASL_MALLOC_ERROR
;
679 memcpy (zinput
, input
, input_len
);
680 zinput
[input_len
] = '\0';
682 gcry_randomize (state
->cnonce
, CNONCE_ENTROPY_BITS
/ 8,
684 for (i
= 0; i
< CNONCE_ENTROPY_BITS
/ 8; i
++)
686 state
->cnonce
[CNONCE_ENTROPY_BITS
/ 8 + i
] =
687 HEXCHAR (state
->cnonce
[i
]);
688 state
->cnonce
[i
] = HEXCHAR (state
->cnonce
[i
] >> 4);
690 state
->cnonce
[2 * CNONCE_ENTROPY_BITS
/ 8] = '\0';
693 while (*subopts
!= '\0')
694 switch (_gsasl_getsubopt (&subopts
, digest_challenge_opts
, &value
))
696 case CHALLENGE_REALM
:
698 realm
= (char **) malloc (sizeof (*realm
));
700 realm
= realloc (realm
, (nrealm
+ 1) * sizeof (*realm
));
703 res
= GSASL_MALLOC_ERROR
;
706 realm
[nrealm
] = strdup (value
);
710 case CHALLENGE_NONCE
:
711 if (state
->nonce
!= NULL
)
713 res
= GSASL_MECHANISM_PARSE_ERROR
;
716 state
->nonce
= strdup (value
);
726 while (*subsubopts
!= '\0')
727 switch (_gsasl_getsubopt (&subsubopts
, qop_opts
, &val
))
729 case QOP_AUTH_OPTION
:
730 state
->qop
|= GSASL_QOP_AUTH
;
733 case QOP_AUTH_INT_OPTION
:
734 state
->qop
|= GSASL_QOP_AUTH_INT
;
737 case QOP_AUTH_CONF_OPTION
:
738 state
->qop
|= GSASL_QOP_AUTH_CONF
;
742 /* Ignore unknown qop */
748 case CHALLENGE_STALE
:
749 printf ("XXX stale: %s\n", value
);
752 case CHALLENGE_MAXBUF
:
753 maxbuf
= strtol (value
, NULL
, 10);
756 case CHALLENGE_CHARSET
:
757 if (strcmp (DEFAULT_CHARSET
, value
) != 0)
759 res
= GSASL_MECHANISM_PARSE_ERROR
;
764 case CHALLENGE_ALGORITHM
:
765 if (strcmp (DEFAULT_ALGORITHM
, value
) != 0)
767 res
= GSASL_MECHANISM_PARSE_ERROR
;
772 case CHALLENGE_CIPHER
:
779 res
= GSASL_MECHANISM_PARSE_ERROR
;
784 while (*subsubopts
!= '\0')
785 switch (_gsasl_getsubopt (&subsubopts
, cipher_opts
, &val
))
787 case CIPHER_DES_OPTION
:
788 state
->cipher
|= GSASL_CIPHER_DES
;
791 case CIPHER_3DES_OPTION
:
792 state
->cipher
|= GSASL_CIPHER_3DES
;
795 case CIPHER_RC4_OPTION
:
796 state
->cipher
|= GSASL_CIPHER_RC4
;
799 case CIPHER_RC4_40_OPTION
:
800 state
->cipher
|= GSASL_CIPHER_RC4_40
;
803 case CIPHER_RC4_56_OPTION
:
804 state
->cipher
|= GSASL_CIPHER_RC4_56
;
807 case CIPHER_AES_OPTION
:
808 state
->cipher
|= GSASL_CIPHER_AES
;
812 /* Ignoring unknown cipher. */
819 /* Ignoring unknown parameter. */
822 if (state
->qop
== 0 || state
->nonce
== NULL
||
823 (state
->qop
& GSASL_QOP_AUTH_CONF
&&
824 !(state
->cipher
& GSASL_CIPHER_3DES
)))
826 res
= GSASL_MECHANISM_PARSE_ERROR
;
830 state
->qop
= cb_qop (cctx
, state
->qop
);
832 state
->qop
= state
->qop
;
833 if (cb_authorization_id
)
837 res
= cb_authorization_id (cctx
, NULL
, &authzidlen
);
840 state
->authzid
= (char *) malloc (authzidlen
+ 1);
841 if (state
->authzid
== NULL
)
843 res
= GSASL_MALLOC_ERROR
;
846 res
= cb_authorization_id (cctx
, state
->authzid
, &authzidlen
);
849 state
->authzid
[authzidlen
] = '\0';
855 res
= cb_authentication_id (cctx
, NULL
, &usernamelen
);
860 strlen (USERNAME_PRE
) +
861 usernamelen
+ strlen (USERNAME_POST
) >= *output_len
)
863 res
= GSASL_TOO_SMALL_BUFFER
;
867 strcat (output
, USERNAME_PRE
);
868 outlen
+= strlen (USERNAME_PRE
);
870 res
= cb_authentication_id (cctx
, &output
[outlen
], &usernamelen
);
873 outlen
+= usernamelen
;
875 strcat (output
, USERNAME_POST
);
876 outlen
+= strlen (USERNAME_POST
);
883 strlen (realm
[0]) + strlen (REALM_POST
) >= *output_len
)
885 res
= GSASL_TOO_SMALL_BUFFER
;
889 strcat (output
, REALM_PRE
);
890 outlen
+= strlen (REALM_PRE
);
892 strcat (output
, realm
[0]);
893 outlen
+= strlen (realm
[0]);
895 strcat (output
, REALM_POST
);
896 outlen
+= strlen (REALM_POST
);
902 strlen (state
->nonce
) + strlen (NONCE_POST
) >= *output_len
)
904 res
= GSASL_TOO_SMALL_BUFFER
;
908 strcat (output
, NONCE_PRE
);
909 outlen
+= strlen (NONCE_PRE
);
911 strcat (output
, state
->nonce
);
912 outlen
+= strlen (state
->nonce
);
914 strcat (output
, NONCE_POST
);
915 outlen
+= strlen (NONCE_POST
);
920 strlen (CNONCE_PRE
) +
921 strlen (state
->cnonce
) + strlen (CNONCE_POST
) >= *output_len
)
923 res
= GSASL_TOO_SMALL_BUFFER
;
927 strcat (output
, CNONCE_PRE
);
928 outlen
+= strlen (CNONCE_PRE
);
930 strcat (output
, state
->cnonce
);
931 outlen
+= strlen (state
->cnonce
);
933 strcat (output
, CNONCE_POST
);
934 outlen
+= strlen (CNONCE_POST
);
939 strlen (NONCE_COUNT_PRE
) +
940 NCLEN
+ strlen (NONCE_COUNT_POST
) >= *output_len
)
942 res
= GSASL_TOO_SMALL_BUFFER
;
946 strcat (output
, NONCE_COUNT_PRE
);
947 outlen
+= strlen (NONCE_COUNT_PRE
);
949 sprintf (output
+ outlen
, "%0*x", NCLEN
, state
->nc
);
952 strcat (output
, NONCE_COUNT_POST
);
953 outlen
+= strlen (NONCE_COUNT_POST
);
959 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
960 qopstr
= QOP_AUTH_CONF
;
961 else if (state
->qop
& GSASL_QOP_AUTH_INT
)
962 qopstr
= QOP_AUTH_INT
;
963 else if (state
->qop
& GSASL_QOP_AUTH
)
968 strlen (qopstr
) + strlen (QOP_POST
) >= *output_len
)
970 res
= GSASL_TOO_SMALL_BUFFER
;
974 strcat (output
, QOP_PRE
);
975 outlen
+= strlen (QOP_PRE
);
977 strcat (output
, qopstr
);
978 outlen
+= strlen (qopstr
);
980 strcat (output
, QOP_POST
);
981 outlen
+= strlen (QOP_POST
);
985 size_t servicelen
= 0;
986 size_t hostnamelen
= 0;
987 size_t servicenamelen
= 0;
990 res
= cb_service (cctx
, NULL
, &servicelen
,
991 NULL
, &hostnamelen
, NULL
, &servicenamelen
);
994 len
= servicelen
+ strlen ("/") + hostnamelen
+
995 (servicenamelen
> 0 ? strlen ("/") + servicenamelen
: 0) + 1;
996 state
->digesturi
= malloc (len
);
997 if (state
->digesturi
== NULL
)
999 res
= GSASL_MALLOC_ERROR
;
1002 res
= cb_service (cctx
, state
->digesturi
, &servicelen
,
1003 state
->digesturi
+ 1 + servicelen
, &hostnamelen
,
1004 (servicenamelen
> 0 ?
1005 state
->digesturi
+ 1 + servicelen
+ 1 +
1006 hostnamelen
: NULL
), &servicenamelen
);
1007 if (res
!= GSASL_OK
)
1009 state
->digesturi
[servicelen
] = '/';
1010 state
->digesturi
[servicelen
+ 1 + hostnamelen
] = '/';
1011 state
->digesturi
[len
- 1] = '\0';
1014 strlen (DIGEST_URI_PRE
) +
1015 len
+ strlen (DIGEST_URI_POST
) >= *output_len
)
1017 res
= GSASL_TOO_SMALL_BUFFER
;
1021 strcat (output
, DIGEST_URI_PRE
);
1022 outlen
+= strlen (DIGEST_URI_PRE
);
1024 strcat (output
, state
->digesturi
);
1025 outlen
+= strlen (state
->digesturi
);
1027 strcat (output
, DIGEST_URI_POST
);
1028 outlen
+= strlen (DIGEST_URI_POST
);
1037 strlen (RESPONSE_PRE
) +
1038 RESPONSE_LENGTH
+ strlen (RESPONSE_POST
) >= *output_len
)
1040 res
= GSASL_TOO_SMALL_BUFFER
;
1044 strcat (output
, RESPONSE_PRE
);
1045 outlen
+= strlen (RESPONSE_PRE
);
1047 md5h
= gcry_md_open (GCRY_MD_MD5
, 0);
1050 res
= GSASL_GCRYPT_ERROR
;
1053 len
= *output_len
- outlen
;
1054 res
= cb_authentication_id (cctx
, output
+ outlen
, &len
);
1055 if (res
!= GSASL_OK
)
1058 gcry_md_write (md5h
, output
+ outlen
, len
);
1059 gcry_md_write (md5h
, COLON
, strlen (COLON
));
1061 gcry_md_write (md5h
, realm
[0], strlen (realm
[0]));
1062 gcry_md_write (md5h
, COLON
, strlen (COLON
));
1064 len
= *output_len
- outlen
;
1065 /* XXX? password stored in callee's output buffer */
1066 res
= cb_password (cctx
, output
+ outlen
, &len
);
1067 if (res
!= GSASL_OK
)
1069 tmp
= stringprep_utf8_nfkc_normalize (output
+ outlen
, len
);
1072 res
= GSASL_UNICODE_NORMALIZATION_ERROR
;
1075 gcry_md_write (md5h
, tmp
, strlen (tmp
));
1077 if (res
!= GCRYERR_SUCCESS
)
1079 res
= GSASL_GCRYPT_ERROR
;
1083 tmp
= gcry_md_read (md5h
, GCRY_MD_MD5
);
1086 res
= GSASL_GCRYPT_ERROR
;
1089 memcpy (state
->secret
, tmp
, MD5LEN
);
1090 gcry_md_close (md5h
);
1092 res
= _gsasl_digest (state
->response
, state
->secret
,
1093 state
->nonce
, state
->nc
, state
->cnonce
,
1094 state
->qop
, state
->authzid
,
1095 state
->digesturi
, A2_PRE
,
1097 state
->kic
, state
->kis
,
1098 state
->kcc
, state
->kcs
);
1099 if (res
!= GSASL_OK
)
1101 state
->response
[RESPONSE_LENGTH
] = '\0';
1102 memcpy (output
+ outlen
, state
->response
, RESPONSE_LENGTH
+ 1);
1103 outlen
+= RESPONSE_LENGTH
;
1105 strcat (output
, RESPONSE_POST
);
1106 outlen
+= strlen (RESPONSE_POST
);
1109 && (maxbuf
= cb_maxbuf (cctx
, maxbuf
)) != MAXBUF_DEFAULT
)
1111 if (outlen
+ strlen (MAXBUF_PRE
) +
1112 /* XXX don't require -lm, how? */
1113 1 + floor (log10 (INT_MAX
)) +
1114 strlen (MAXBUF_POST
) >= *output_len
)
1116 res
= GSASL_TOO_SMALL_BUFFER
;
1120 strcat (output
, MAXBUF_PRE
);
1121 outlen
+= strlen (MAXBUF_PRE
);
1123 sprintf (&output
[outlen
], "%d", maxbuf
);
1124 outlen
+= strlen (&output
[outlen
]);
1126 strcat (output
, MAXBUF_POST
);
1127 outlen
+= strlen (MAXBUF_POST
);
1130 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
1134 if (state
->cipher
& GSASL_CIPHER_AES
)
1135 cipherstr
= CIPHER_AES
;
1136 else if (state
->cipher
& GSASL_CIPHER_3DES
)
1137 cipherstr
= CIPHER_3DES
;
1138 else if (state
->cipher
& GSASL_CIPHER_DES
)
1139 cipherstr
= CIPHER_DES
;
1140 else if (state
->cipher
& GSASL_CIPHER_RC4
)
1141 cipherstr
= CIPHER_RC4
;
1142 else if (state
->cipher
& GSASL_CIPHER_RC4_56
)
1143 cipherstr
= CIPHER_RC4_56
;
1144 else if (state
->cipher
& GSASL_CIPHER_RC4_40
)
1145 cipherstr
= CIPHER_RC4_40
;
1148 strlen (CIPHER_PRE
) +
1149 strlen (cipherstr
) + strlen (CIPHER_POST
) >= *output_len
)
1151 res
= GSASL_TOO_SMALL_BUFFER
;
1155 strcat (output
, CIPHER_PRE
);
1156 outlen
+= strlen (CIPHER_PRE
);
1158 strcat (output
, cipherstr
);
1159 outlen
+= strlen (cipherstr
);
1161 strcat (output
, CIPHER_POST
);
1162 outlen
+= strlen (CIPHER_POST
);
1165 if (state
->authzid
&& strlen (state
->authzid
) > 0)
1168 strlen (AUTHZID_PRE
) +
1169 strlen (state
->authzid
) +
1170 strlen (AUTHZID_POST
) >= *output_len
)
1172 res
= GSASL_TOO_SMALL_BUFFER
;
1176 strcat (output
, AUTHZID_PRE
);
1177 outlen
+= strlen (AUTHZID_PRE
);
1179 strcat (output
, state
->authzid
);
1180 outlen
+= strlen (state
->authzid
);
1182 strcat (output
, AUTHZID_POST
);
1183 outlen
+= strlen (AUTHZID_POST
);
1186 res
= GSASL_NEEDS_MORE
;
1193 *output_len
= outlen
;
1199 char *zinput
= NULL
;
1204 res
= GSASL_MECHANISM_PARSE_ERROR
;
1208 if (input
&& input_len
> 0)
1210 zinput
= malloc (input_len
+ 1);
1212 return GSASL_MALLOC_ERROR
;
1213 memcpy (zinput
, input
, input_len
);
1214 zinput
[input_len
] = '\0';
1217 res
= GSASL_AUTHENTICATION_ERROR
;
1219 while (*subopts
!= '\0')
1220 switch (_gsasl_getsubopt (&subopts
,
1221 digest_responseauth_opts
, &value
))
1223 case RESPONSEAUTH_RSPAUTH
:
1224 res
= _gsasl_digest (output
+ outlen
, state
->secret
,
1225 state
->nonce
, state
->nc
,
1226 state
->cnonce
, state
->qop
,
1227 state
->authzid
, state
->digesturi
, COLON
,
1228 state
->cipher
, NULL
, NULL
, NULL
, NULL
);
1229 if (res
!= GSASL_OK
)
1232 if (memcmp (value
, output
+ outlen
, RESPONSE_LENGTH
) == 0)
1235 res
= GSASL_AUTHENTICATION_ERROR
;
1239 /* Unknown suboption. */
1249 res
= GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
;
1253 #if CLIENT_PRINT_OUTPUT
1254 if (output
&& *output_len
> 0)
1255 fprintf (stderr
, "%s\n", output
);
1262 _gsasl_digest_md5_client_finish (Gsasl_session_ctx
* cctx
, void *mech_data
)
1264 _Gsasl_digest_md5_client_state
*state
= mech_data
;
1267 free (state
->authzid
);
1269 free (state
->nonce
);
1270 if (state
->digesturi
)
1271 free (state
->digesturi
);
1278 _gsasl_digest_md5_client_encode (Gsasl_session_ctx
* xctx
,
1282 char *output
, size_t * output_len
)
1284 _Gsasl_digest_md5_client_state
*state
= mech_data
;
1287 if (state
== NULL
|| state
->step
!= 3)
1289 *output_len
= input_len
;
1291 memcpy (output
, input
, input_len
);
1295 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
1299 else if (state
->qop
& GSASL_QOP_AUTH_INT
)
1305 if (MAC_DATA_LEN
+ input_len
+ MAC_HMAC_LEN
+
1306 MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
> *output_len
)
1307 return GSASL_TOO_SMALL_BUFFER
;
1309 md5h
= gcry_md_open (GCRY_MD_MD5
, GCRY_MD_FLAG_HMAC
);
1311 return GSASL_GCRYPT_ERROR
;
1313 res
= gcry_md_setkey (md5h
, state
->kic
, MD5LEN
);
1314 if (res
!= GCRYERR_SUCCESS
)
1315 return GSASL_GCRYPT_ERROR
;
1317 tmp
= htonl (state
->sendseqnum
);
1318 gcry_md_write (md5h
, (unsigned char*) &tmp
, MAC_SEQNUM_LEN
);
1319 gcry_md_write (md5h
, input
, input_len
);
1321 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
1323 return GSASL_GCRYPT_ERROR
;
1327 *output_len
= MAC_DATA_LEN
;
1328 memcpy (output
+ *output_len
, input
, input_len
);
1329 *output_len
+= input_len
;
1330 memcpy (output
+ *output_len
, hash
, MAC_HMAC_LEN
);
1331 *output_len
+= MAC_HMAC_LEN
;
1332 memcpy (output
+ *output_len
, MAC_MSG_TYPE
, MAC_MSG_TYPE_LEN
);
1333 *output_len
+= MAC_MSG_TYPE_LEN
;
1334 tmp
= htonl (state
->sendseqnum
);
1335 memcpy (output
+ *output_len
, &tmp
, MAC_SEQNUM_LEN
);
1336 *output_len
+= MAC_SEQNUM_LEN
;
1337 tmp
= htonl (*output_len
- MAC_DATA_LEN
);
1338 memcpy (output
, &tmp
, MAC_DATA_LEN
);
1339 state
->sendseqnum
++;
1342 *output_len
= MAC_DATA_LEN
+ input_len
+ MAC_HMAC_LEN
1343 + MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
1345 gcry_md_close (md5h
);
1352 _gsasl_digest_md5_client_decode (Gsasl_session_ctx
* xctx
,
1356 char *output
, size_t * output_len
)
1358 _Gsasl_digest_md5_client_state
*state
= mech_data
;
1360 if (state
== NULL
|| state
->step
!= 3)
1362 *output_len
= input_len
;
1364 memcpy (output
, input
, input_len
);
1368 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
1372 else if (state
->qop
& GSASL_QOP_AUTH_INT
)
1379 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
)
1380 return GSASL_NEEDS_MORE
;
1382 len
= ntohl (*(uint32_t *) input
);
1384 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
+ len
)
1385 return GSASL_NEEDS_MORE
;
1387 len
-= MAC_HMAC_LEN
+ MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
1389 md5h
= gcry_md_open (GCRY_MD_MD5
, GCRY_MD_FLAG_HMAC
);
1391 return GSASL_GCRYPT_ERROR
;
1393 res
= gcry_md_setkey (md5h
, state
->kis
, MD5LEN
);
1394 if (res
!= GCRYERR_SUCCESS
)
1395 return GSASL_GCRYPT_ERROR
;
1397 tmp
= htonl (state
->readseqnum
);
1399 gcry_md_write (md5h
, (unsigned char*)&tmp
, SASL_INTEGRITY_PREFIX_LENGTH
);
1400 gcry_md_write (md5h
, input
+ MAC_DATA_LEN
, len
);
1402 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
1404 return GSASL_GCRYPT_ERROR
;
1408 input
+ input_len
- MAC_SEQNUM_LEN
- MAC_MSG_TYPE_LEN
-
1409 MAC_HMAC_LEN
, MAC_HMAC_LEN
) == 0
1410 && memcmp (MAC_MSG_TYPE
,
1411 input
+ input_len
- MAC_SEQNUM_LEN
- MAC_MSG_TYPE_LEN
,
1412 MAC_MSG_TYPE_LEN
) == 0
1413 && memcmp (&tmp
, input
+ input_len
- MAC_SEQNUM_LEN
,
1414 MAC_SEQNUM_LEN
) == 0)
1419 memcpy (output
, input
+ MAC_DATA_LEN
, len
);
1420 state
->readseqnum
++;
1424 return GSASL_INTEGRITY_ERROR
;
1426 gcry_md_close (md5h
);
1434 struct _Gsasl_digest_md5_server_state
1437 char nonce
[NONCE_ENTROPY_BITS
/ 8];
1439 Gsasl_cipher cipher
;
1440 uint32_t readseqnum
, sendseqnum
;
1441 unsigned char kic
[MD5LEN
];
1442 unsigned char kcc
[MD5LEN
];
1443 unsigned char kis
[MD5LEN
];
1444 unsigned char kcs
[MD5LEN
];
1446 typedef struct _Gsasl_digest_md5_server_state _Gsasl_digest_md5_server_state
;
1449 _gsasl_digest_md5_server_init (Gsasl_ctx
* ctx
)
1451 if (gcry_check_version (GCRYPT_VERSION
) == NULL
)
1452 return GSASL_GCRYPT_ERROR
;
1458 _gsasl_digest_md5_server_done (Gsasl_ctx
* ctx
)
1464 _gsasl_digest_md5_server_start (Gsasl_session_ctx
* sctx
, void **mech_data
)
1466 _Gsasl_digest_md5_server_state
*state
;
1467 Gsasl_server_callback_retrieve cb_retrieve
;
1468 Gsasl_server_callback_digest_md5 cb_digest_md5
;
1471 ctx
= gsasl_server_ctx_get (sctx
);
1473 return GSASL_CANNOT_GET_CTX
;
1475 cb_retrieve
= gsasl_server_callback_retrieve_get (ctx
);
1476 cb_digest_md5
= gsasl_server_callback_digest_md5_get (ctx
);
1478 if (gsasl_server_callback_digest_md5_get (ctx
) == NULL
&&
1479 gsasl_server_callback_retrieve_get (ctx
) == NULL
)
1480 return GSASL_NEED_SERVER_DIGEST_MD5_CALLBACK
;
1482 state
= (_Gsasl_digest_md5_server_state
*) malloc (sizeof (*state
));
1484 return GSASL_MALLOC_ERROR
;
1487 state
->qop
= GSASL_QOP_AUTH
| GSASL_QOP_AUTH_INT
| GSASL_QOP_AUTH_CONF
;
1488 state
->cipher
= GSASL_CIPHER_DES
| GSASL_CIPHER_3DES
| GSASL_CIPHER_RC4
|
1489 GSASL_CIPHER_RC4_40
| GSASL_CIPHER_RC4_56
| GSASL_CIPHER_AES
;
1490 gcry_randomize (state
->nonce
, NONCE_ENTROPY_BITS
/ 8, GCRY_WEAK_RANDOM
);
1491 state
->readseqnum
= 0;
1492 state
->sendseqnum
= 0;
1500 _gsasl_digest_md5_server_step (Gsasl_session_ctx
* sctx
,
1504 char *output
, size_t * output_len
)
1506 _Gsasl_digest_md5_server_state
*state
= mech_data
;
1507 Gsasl_server_callback_realm cb_realm
;
1508 Gsasl_server_callback_qop cb_qop
;
1509 Gsasl_server_callback_maxbuf cb_maxbuf
;
1510 Gsasl_server_callback_cipher cb_cipher
;
1511 Gsasl_server_callback_retrieve cb_retrieve
;
1512 Gsasl_server_callback_digest_md5 cb_digest_md5
;
1518 ctx
= gsasl_server_ctx_get (sctx
);
1520 return GSASL_CANNOT_GET_CTX
;
1522 cb_realm
= gsasl_server_callback_realm_get (ctx
);
1523 cb_qop
= gsasl_server_callback_qop_get (ctx
);
1524 cb_maxbuf
= gsasl_server_callback_maxbuf_get (ctx
);
1525 cb_cipher
= gsasl_server_callback_cipher_get (ctx
);
1526 cb_retrieve
= gsasl_server_callback_retrieve_get (ctx
);
1527 cb_digest_md5
= gsasl_server_callback_digest_md5_get (ctx
);
1529 if (gsasl_server_callback_digest_md5_get (ctx
) == NULL
&&
1530 gsasl_server_callback_retrieve_get (ctx
) == NULL
)
1531 return GSASL_NEED_SERVER_DIGEST_MD5_CALLBACK
;
1533 if (*output_len
< 1)
1534 return GSASL_TOO_SMALL_BUFFER
;
1536 strcpy (output
, "");
1539 #if SERVER_PRINT_OUTPUT
1540 if (input
&& input_len
> 0)
1541 fprintf (stderr
, "%s\n", input
);
1544 switch (state
->step
)
1552 realmlen
= *output_len
;
1553 for (i
= 0; cb_realm (sctx
, NULL
, &realmlen
, i
) == GSASL_OK
; i
++)
1555 if (outlen
+ strlen (REALM_PRE
) +
1556 realmlen
+ strlen (REALM_POST
) >= *output_len
)
1557 return GSASL_TOO_SMALL_BUFFER
;
1559 strcat (output
, REALM_PRE
);
1560 outlen
+= strlen (REALM_PRE
);
1562 cb_realm (sctx
, &output
[outlen
], &realmlen
, i
);
1564 output
[outlen
] = '\0';
1566 strcat (output
, REALM_POST
);
1567 outlen
+= strlen (REALM_POST
);
1569 realmlen
= *output_len
- outlen
;
1576 if (outlen
+ strlen (NONCE_PRE
) +
1577 2 * NONCE_ENTROPY_BITS
/ 8 + strlen (NONCE_POST
) >= *output_len
)
1578 return GSASL_TOO_SMALL_BUFFER
;
1580 strcat (output
, NONCE_PRE
);
1581 outlen
+= strlen (NONCE_PRE
);
1583 for (i
= 0; i
< NONCE_ENTROPY_BITS
/ 8; i
++)
1585 output
[outlen
+ 2 * i
+ 1] = HEXCHAR (state
->nonce
[i
]);
1586 output
[outlen
+ 2 * i
+ 0] = HEXCHAR (state
->nonce
[i
] >> 4);
1588 output
[outlen
+ 2 * NONCE_ENTROPY_BITS
/ 8] = '\0';
1589 outlen
+= 2 * NONCE_ENTROPY_BITS
/ 8;
1591 strcat (output
, NONCE_POST
);
1592 outlen
+= strlen (NONCE_POST
);
1597 strlen (QOP_LIST_PRE
) +
1599 strlen (QOP_AUTH_INT
) +
1600 strlen (QOP_AUTH_CONF
) + strlen (QOP_LIST_POST
) >= *output_len
)
1601 return GSASL_TOO_SMALL_BUFFER
;
1604 state
->qop
= cb_qop (sctx
);
1607 (GSASL_QOP_AUTH
| GSASL_QOP_AUTH_INT
| GSASL_QOP_AUTH_CONF
))
1609 strcat (output
, QOP_LIST_PRE
);
1610 outlen
+= strlen (QOP_LIST_PRE
);
1613 if (state
->qop
& GSASL_QOP_AUTH
)
1615 strcat (output
, QOP_AUTH
);
1616 outlen
+= strlen (QOP_AUTH
);
1618 strcat (output
, QOP_DELIM
);
1619 outlen
+= strlen (QOP_DELIM
);
1622 if (state
->qop
& GSASL_QOP_AUTH_INT
)
1624 strcat (output
, QOP_AUTH_INT
);
1625 outlen
+= strlen (QOP_AUTH_INT
);
1627 strcat (output
, QOP_DELIM
);
1628 outlen
+= strlen (QOP_DELIM
);
1631 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
1633 strcat (output
, QOP_AUTH_CONF
);
1634 outlen
+= strlen (QOP_AUTH_CONF
);
1638 (GSASL_QOP_AUTH
| GSASL_QOP_AUTH_INT
| GSASL_QOP_AUTH_CONF
))
1640 strcat (output
, QOP_LIST_POST
);
1641 outlen
+= strlen (QOP_LIST_POST
);
1645 if (cb_maxbuf
&& (maxbuf
= cb_maxbuf (sctx
)) != MAXBUF_DEFAULT
)
1647 if (outlen
+ strlen (MAXBUF_PRE
) +
1648 /* XXX don't require -lm, how? */
1649 1 + floor (log10 (INT_MAX
)) +
1650 strlen (MAXBUF_POST
) >= *output_len
)
1651 return GSASL_TOO_SMALL_BUFFER
;
1653 strcat (output
, MAXBUF_PRE
);
1654 outlen
+= strlen (MAXBUF_PRE
);
1656 sprintf (&output
[outlen
], "%d", maxbuf
);
1657 outlen
+= strlen (&output
[outlen
]);
1659 strcat (output
, MAXBUF_POST
);
1660 outlen
+= strlen (MAXBUF_POST
);
1664 if (outlen
+ strlen (CHARSET
) >= *output_len
)
1665 return GSASL_TOO_SMALL_BUFFER
;
1667 strcat (output
, CHARSET
);
1668 outlen
+= strlen (CHARSET
);
1672 if (outlen
+ strlen (ALGORITHM
) >= *output_len
)
1673 return GSASL_TOO_SMALL_BUFFER
;
1675 strcat (output
, ALGORITHM
);
1676 outlen
+= strlen (ALGORITHM
);
1681 strlen (CIPHER_PRE
) +
1682 strlen (CIPHER_DES
) +
1683 strlen (CIPHER_DELIM
) +
1684 strlen (CIPHER_3DES
) +
1685 strlen (CIPHER_DELIM
) +
1686 strlen (CIPHER_RC4
) +
1687 strlen (CIPHER_DELIM
) +
1688 strlen (CIPHER_RC4_40
) +
1689 strlen (CIPHER_DELIM
) +
1690 strlen (CIPHER_RC4_56
) +
1691 strlen (CIPHER_DELIM
) +
1692 strlen (CIPHER_AES
) +
1693 strlen (CIPHER_DELIM
) + strlen (CIPHER_POST
) >= *output_len
)
1694 return GSASL_TOO_SMALL_BUFFER
;
1697 state
->cipher
= cb_cipher (sctx
);
1699 strcat (output
, CIPHER_PRE
);
1700 outlen
+= strlen (CIPHER_PRE
);
1702 if (state
->cipher
& GSASL_CIPHER_DES
)
1704 strcat (output
, CIPHER_DES
);
1705 outlen
+= strlen (CIPHER_DES
);
1707 strcat (output
, CIPHER_DELIM
);
1708 outlen
+= strlen (CIPHER_DELIM
);
1711 if (state
->cipher
& GSASL_CIPHER_3DES
)
1713 strcat (output
, CIPHER_3DES
);
1714 outlen
+= strlen (CIPHER_3DES
);
1716 strcat (output
, CIPHER_DELIM
);
1717 outlen
+= strlen (CIPHER_DELIM
);
1720 if (state
->cipher
& GSASL_CIPHER_RC4
)
1722 strcat (output
, CIPHER_RC4
);
1723 outlen
+= strlen (CIPHER_RC4
);
1725 strcat (output
, CIPHER_DELIM
);
1726 outlen
+= strlen (CIPHER_DELIM
);
1729 if (state
->cipher
& GSASL_CIPHER_RC4_40
)
1731 strcat (output
, CIPHER_RC4_40
);
1732 outlen
+= strlen (CIPHER_RC4_40
);
1734 strcat (output
, CIPHER_DELIM
);
1735 outlen
+= strlen (CIPHER_DELIM
);
1738 if (state
->cipher
& GSASL_CIPHER_RC4_56
)
1740 strcat (output
, CIPHER_RC4_56
);
1741 outlen
+= strlen (CIPHER_RC4_56
);
1743 strcat (output
, CIPHER_DELIM
);
1744 outlen
+= strlen (CIPHER_DELIM
);
1747 if (state
->cipher
& GSASL_CIPHER_AES
)
1749 strcat (output
, CIPHER_AES
);
1750 outlen
+= strlen (CIPHER_AES
);
1752 strcat (output
, CIPHER_DELIM
);
1753 outlen
+= strlen (CIPHER_DELIM
);
1756 strcat (output
, CIPHER_POST
);
1757 outlen
+= strlen (CIPHER_POST
);
1759 *output_len
= outlen
;
1761 res
= GSASL_NEEDS_MORE
;
1766 unsigned char *nonce
= NULL
;
1767 char *cnonce
= NULL
;
1769 char *authzid
= NULL
;
1770 char *digesturi
= NULL
;
1771 const char *subopts
, *value
;
1772 unsigned char *realm
= NULL
;
1773 unsigned char *username
= NULL
;
1774 unsigned char *response
= NULL
;
1775 char *zinput
= NULL
;
1777 int maxbuf
= MAXBUF_DEFAULT
;
1780 GCRY_MD_HD md5h
= NULL
;
1781 unsigned char secret
[MD5LEN
];
1784 return GSASL_MECHANISM_PARSE_ERROR
;
1786 if (input
&& input_len
> 0)
1788 zinput
= malloc (input_len
+ 1);
1790 return GSASL_MALLOC_ERROR
;
1791 memcpy (zinput
, input
, input_len
);
1792 zinput
[input_len
] = '\0';
1796 while (*subopts
!= '\0')
1797 switch (_gsasl_getsubopt (&subopts
, digest_response_opts
, &value
))
1799 case RESPONSE_USERNAME
:
1800 if (username
!= NULL
)
1802 res
= GSASL_MECHANISM_PARSE_ERROR
;
1805 username
= strdup (value
);
1808 case RESPONSE_REALM
:
1811 res
= GSASL_MECHANISM_PARSE_ERROR
;
1814 realm
= strdup (value
);
1817 case RESPONSE_NONCE
:
1820 res
= GSASL_MECHANISM_PARSE_ERROR
;
1823 nonce
= strdup (value
);
1825 for (i
= 0; i
< MIN (strlen (nonce
), NONCE_ENTROPY_BITS
/ 8);
1827 if ((nonce
[2 * i
+ 1] != HEXCHAR (state
->nonce
[i
]))
1828 || (nonce
[2 * i
+ 0] != HEXCHAR (state
->nonce
[i
] >> 4)))
1829 res
= GSASL_MECHANISM_PARSE_ERROR
;
1830 if (res
!= GSASL_OK
)
1834 case RESPONSE_CNONCE
:
1837 res
= GSASL_MECHANISM_PARSE_ERROR
;
1840 cnonce
= strdup (value
);
1846 res
= GSASL_MECHANISM_PARSE_ERROR
;
1849 nc
= strtoul (value
, NULL
, 16);
1853 if (strcmp (value
, QOP_AUTH
) == 0)
1854 qop
= GSASL_QOP_AUTH
;
1855 else if (strcmp (value
, QOP_AUTH_INT
) == 0)
1856 qop
= GSASL_QOP_AUTH_INT
;
1857 else if (strcmp (value
, QOP_AUTH_CONF
) == 0)
1858 qop
= GSASL_QOP_AUTH_CONF
;
1861 res
= GSASL_MECHANISM_PARSE_ERROR
;
1864 if (!(state
->qop
& qop
))
1866 res
= GSASL_MECHANISM_PARSE_ERROR
;
1872 case RESPONSE_DIGEST_URI
:
1873 if (digesturi
!= NULL
)
1875 res
= GSASL_MECHANISM_PARSE_ERROR
;
1878 digesturi
= strdup (value
);
1881 case RESPONSE_RESPONSE
:
1882 if (response
!= NULL
)
1884 res
= GSASL_MECHANISM_PARSE_ERROR
;
1887 response
= strdup (value
);
1890 case RESPONSE_MAXBUF
:
1891 maxbuf
= strtol (value
, NULL
, 10);
1894 case RESPONSE_CHARSET
:
1895 if (strcmp (DEFAULT_CHARSET
, value
) != 0)
1897 res
= GSASL_MECHANISM_PARSE_ERROR
;
1902 case RESPONSE_CIPHER
:
1905 res
= GSASL_MECHANISM_PARSE_ERROR
;
1908 if (strcmp (value
, CIPHER_AES
) == 0)
1909 cipher
= GSASL_CIPHER_AES
;
1910 else if (strcmp (value
, CIPHER_3DES
) == 0)
1911 cipher
= GSASL_CIPHER_3DES
;
1912 else if (strcmp (value
, CIPHER_DES
) == 0)
1913 cipher
= GSASL_CIPHER_DES
;
1914 else if (strcmp (value
, CIPHER_RC4
) == 0)
1915 cipher
= GSASL_CIPHER_RC4
;
1916 else if (strcmp (value
, CIPHER_RC4_40
) == 0)
1917 cipher
= GSASL_CIPHER_RC4_40
;
1918 else if (strcmp (value
, CIPHER_RC4_56
) == 0)
1919 cipher
= GSASL_CIPHER_RC4_56
;
1922 res
= GSASL_MECHANISM_PARSE_ERROR
;
1925 if (!(state
->cipher
& cipher
))
1927 res
= GSASL_MECHANISM_PARSE_ERROR
;
1930 state
->cipher
= cipher
;
1933 case RESPONSE_AUTHZID
:
1934 if (authzid
!= NULL
)
1936 res
= GSASL_MECHANISM_PARSE_ERROR
;
1939 authzid
= strdup (value
);
1943 /* Ignoring unknown parameter. */
1947 if (username
== NULL
|| nonce
== NULL
||
1948 cnonce
== NULL
|| response
== NULL
||
1949 (state
->qop
& GSASL_QOP_AUTH_CONF
&& state
->cipher
== 0))
1951 res
= GSASL_MECHANISM_PARSE_ERROR
;
1956 strlen (RSPAUTH_PRE
) +
1957 RESPONSE_LENGTH
+ strlen (RSPAUTH_POST
) >= *output_len
)
1959 res
= GSASL_TOO_SMALL_BUFFER
;
1969 res
= cb_retrieve (sctx
, username
, authzid
, realm
, NULL
, &keylen
);
1970 if (res
!= GSASL_OK
)
1972 key
= malloc (keylen
);
1975 res
= GSASL_MALLOC_ERROR
;
1978 res
= cb_retrieve (sctx
, username
, authzid
, realm
, key
, &keylen
);
1979 if (res
!= GSASL_OK
)
1984 normkey
= stringprep_utf8_nfkc_normalize (key
, keylen
);
1986 if (normkey
== NULL
)
1988 res
= GSASL_UNICODE_NORMALIZATION_ERROR
;
1992 md5h
= gcry_md_open (GCRY_MD_MD5
, 0);
1995 res
= GSASL_GCRYPT_ERROR
;
1998 gcry_md_write (md5h
, username
, strlen (username
));
1999 gcry_md_write (md5h
, COLON
, strlen (COLON
));
2001 gcry_md_write (md5h
, realm
, strlen (realm
));
2002 gcry_md_write (md5h
, COLON
, strlen (COLON
));
2003 gcry_md_write (md5h
, normkey
, strlen (normkey
));
2005 tmp
= gcry_md_read (md5h
, GCRY_MD_MD5
);
2008 res
= GSASL_GCRYPT_ERROR
;
2011 memcpy (secret
, tmp
, MD5LEN
);
2013 else /* if (cb_digest_md5) */
2015 /* XXX? secret hash stored in callee's output buffer */
2016 res
= cb_digest_md5 (sctx
, username
, realm
, output
+ outlen
);
2017 if (res
!= GSASL_OK
)
2020 memcpy (secret
, output
+ outlen
, MD5LEN
);
2023 /* verify response */
2024 res
= _gsasl_digest (output
+ outlen
, secret
,
2025 nonce
, nc
, cnonce
, state
->qop
, authzid
,
2027 state
->cipher
, NULL
, NULL
, NULL
, NULL
);
2028 if (res
!= GSASL_OK
)
2031 if (memcmp (response
, output
+ outlen
, RESPONSE_LENGTH
) != 0)
2033 res
= GSASL_AUTHENTICATION_ERROR
;
2037 output
[outlen
] = '\0';
2039 /* XXX check more things here. digest-uri?,
2040 nc etc. nonce, which is the most important, is checked
2043 /* generate rspauth */
2045 strcat (output
, RSPAUTH_PRE
);
2046 outlen
+= strlen (RSPAUTH_PRE
);
2048 res
= _gsasl_digest (output
+ outlen
, secret
,
2049 nonce
, nc
, cnonce
, state
->qop
, authzid
,
2052 state
->kic
, state
->kis
, state
->kcc
, state
->kcs
);
2053 if (res
!= GSASL_OK
)
2055 outlen
+= RSPAUTH_LENGTH
;
2057 strcat (output
, RSPAUTH_POST
);
2058 outlen
+= strlen (RSPAUTH_POST
);
2061 gcry_md_close (md5h
);
2063 res
= GSASL_NEEDS_MORE
;
2082 *output_len
= outlen
;
2093 res
= GSASL_MECHANISM_CALLED_TOO_MANY_TIMES
;
2097 #if SERVER_PRINT_OUTPUT
2098 if (output
&& *output_len
> 0)
2099 fprintf (stderr
, "%s\n", output
);
2106 _gsasl_digest_md5_server_finish (Gsasl_session_ctx
* sctx
, void *mech_data
)
2108 _Gsasl_digest_md5_server_state
*state
= mech_data
;
2116 _gsasl_digest_md5_server_encode (Gsasl_session_ctx
* xctx
,
2120 char *output
, size_t * output_len
)
2122 _Gsasl_digest_md5_server_state
*state
= mech_data
;
2125 if (state
== NULL
|| state
->step
!= 3)
2127 *output_len
= input_len
;
2129 memcpy (output
, input
, input_len
);
2133 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
2137 else if (state
->qop
& GSASL_QOP_AUTH_INT
)
2143 if (MAC_DATA_LEN
+ input_len
+ MAC_HMAC_LEN
+
2144 MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
> *output_len
)
2145 return GSASL_TOO_SMALL_BUFFER
;
2147 md5h
= gcry_md_open (GCRY_MD_MD5
, GCRY_MD_FLAG_HMAC
);
2149 return GSASL_GCRYPT_ERROR
;
2151 res
= gcry_md_setkey (md5h
, state
->kis
, MD5LEN
);
2152 if (res
!= GCRYERR_SUCCESS
)
2153 return GSASL_GCRYPT_ERROR
;
2155 tmp
= htonl (state
->sendseqnum
);
2156 gcry_md_write (md5h
, (unsigned char*)&tmp
, MAC_SEQNUM_LEN
);
2157 gcry_md_write (md5h
, input
, input_len
);
2159 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
2161 return GSASL_GCRYPT_ERROR
;
2165 *output_len
= MAC_DATA_LEN
;
2166 memcpy (output
+ *output_len
, input
, input_len
);
2167 *output_len
+= input_len
;
2168 memcpy (output
+ *output_len
, hash
, MAC_HMAC_LEN
);
2169 *output_len
+= MAC_HMAC_LEN
;
2170 memcpy (output
+ *output_len
, MAC_MSG_TYPE
, MAC_MSG_TYPE_LEN
);
2171 *output_len
+= MAC_MSG_TYPE_LEN
;
2172 tmp
= htonl (state
->sendseqnum
);
2173 memcpy (output
+ *output_len
, &tmp
, MAC_SEQNUM_LEN
);
2174 *output_len
+= MAC_SEQNUM_LEN
;
2175 tmp
= htonl (*output_len
- MAC_DATA_LEN
);
2176 memcpy (output
, &tmp
, MAC_DATA_LEN
);
2177 state
->sendseqnum
++;
2180 *output_len
= MAC_DATA_LEN
+ input_len
+ MAC_HMAC_LEN
2181 + MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
2183 gcry_md_close (md5h
);
2190 _gsasl_digest_md5_server_decode (Gsasl_session_ctx
* xctx
,
2194 char *output
, size_t * output_len
)
2196 _Gsasl_digest_md5_server_state
*state
= mech_data
;
2198 if (state
== NULL
|| state
->step
!= 3)
2200 *output_len
= input_len
;
2202 memcpy (output
, input
, input_len
);
2206 if (state
->qop
& GSASL_QOP_AUTH_CONF
)
2210 else if (state
->qop
& GSASL_QOP_AUTH_INT
)
2217 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
)
2218 return GSASL_NEEDS_MORE
;
2220 len
= ntohl (*(uint32_t *) input
);
2222 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
+ len
)
2223 return GSASL_NEEDS_MORE
;
2225 len
-= MAC_HMAC_LEN
+ MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
2227 md5h
= gcry_md_open (GCRY_MD_MD5
, GCRY_MD_FLAG_HMAC
);
2229 return GSASL_GCRYPT_ERROR
;
2231 res
= gcry_md_setkey (md5h
, state
->kic
, MD5LEN
);
2232 if (res
!= GCRYERR_SUCCESS
)
2233 return GSASL_GCRYPT_ERROR
;
2235 tmp
= htonl (state
->readseqnum
);
2237 gcry_md_write (md5h
, (unsigned char*)&tmp
, SASL_INTEGRITY_PREFIX_LENGTH
);
2238 gcry_md_write (md5h
, input
+ MAC_DATA_LEN
, len
);
2240 hash
= gcry_md_read (md5h
, GCRY_MD_MD5
);
2242 return GSASL_GCRYPT_ERROR
;
2246 input
+ input_len
- MAC_SEQNUM_LEN
- MAC_MSG_TYPE_LEN
-
2247 MAC_HMAC_LEN
, MAC_HMAC_LEN
) == 0
2248 && memcmp (MAC_MSG_TYPE
,
2249 input
+ input_len
- MAC_SEQNUM_LEN
- MAC_MSG_TYPE_LEN
,
2250 MAC_MSG_TYPE_LEN
) == 0
2251 && memcmp (&tmp
, input
+ input_len
- MAC_SEQNUM_LEN
,
2252 MAC_SEQNUM_LEN
) == 0)
2257 memcpy (output
, input
+ MAC_DATA_LEN
, len
);
2258 state
->readseqnum
++;
2262 return GSASL_INTEGRITY_ERROR
;
2264 gcry_md_close (md5h
);
2270 #endif /* USE_DIGEST_MD5 */