1/* validate.c --- Validate consistency of DIGEST-MD5 tokens.
2 * Copyright (C) 2004-2012 Simon Josefsson
3 *
4 * This file is part of GNU SASL Library.
5 *
6 * GNU SASL Library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * GNU SASL Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GNU SASL Library; if not, write to the Free
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27/* Get prototypes. */
28#include "validate.h"
29
30/* Get strcmp, strlen. */
31#include <string.h>
32
33int
34digest_md5_validate_challenge (digest_md5_challenge * c)
35{
36 /* This directive is required and MUST appear exactly once; if
37 not present, or if multiple instances are present, the
38 client should abort the authentication exchange. */
39 if (!c->nonce)
40 return -1;
41
42 /* This directive must be present exactly once if "auth-conf" is
43 offered in the "qop-options" directive */
44 if (c->ciphers && !(c->qops & DIGEST_MD5_QOP_AUTH_CONF))
45 return -1;
46 if (!c->ciphers && (c->qops & DIGEST_MD5_QOP_AUTH_CONF))
47 return -1;
48
49 return 0;
50}
51
52int
53digest_md5_validate_response (digest_md5_response * r)
54{
55 /* This directive is required and MUST be present exactly
56 once; otherwise, authentication fails. */
57 if (!r->username)
58 return -1;
59
60 /* This directive is required and MUST be present exactly
61 once; otherwise, authentication fails. */
62 if (!r->nonce)
63 return -1;
64
65 /* This directive is required and MUST be present exactly once;
66 otherwise, authentication fails. */
67 if (!r->cnonce)
68 return -1;
69
70 /* This directive is required and MUST be present exactly once;
71 otherwise, or if the value is 0, authentication fails. */
72 if (!r->nc)
73 return -1;
74
75 /* This directive is required and MUST be present exactly
76 once; if multiple instances are present, the client MUST
77 abort the authentication exchange. */
78 if (!r->digesturi)
79 return -1;
80
81 /* This directive is required and MUST be present exactly
82 once; otherwise, authentication fails. */
83 if (!*r->response)
84 return -1;
85
86 if (strlen (r->response) != DIGEST_MD5_RESPONSE_LENGTH)
87 return -1;
88
89 /* This directive MUST appear exactly once if "auth-conf" is
90 negotiated; if required and not present, authentication fails.
91 If the client recognizes no cipher and the server only advertised
92 "auth-conf" in the qop option, the client MUST abort the
93 authentication exchange. */
94 if (r->qop == DIGEST_MD5_QOP_AUTH_CONF && !r->cipher)
95 return -1;
96 if (r->qop != DIGEST_MD5_QOP_AUTH_CONF && r->cipher)
97 return -1;
98
99 return 0;
100}
101
102int
103digest_md5_validate_finish (digest_md5_finish * f)
104{
105 if (!f->rspauth)
106 return -1;
107
108 /* A string of 32 hex digits */
109 if (strlen (f->rspauth) != DIGEST_MD5_RESPONSE_LENGTH)
110 return -1;
111
112 return 0;
113}
114
115int
116digest_md5_validate (digest_md5_challenge * c, digest_md5_response * r)
117{
118 if (!c->nonce || !r->nonce)
119 return -1;
120
121 if (strcmp (c->nonce, r->nonce) != 0)
122 return -1;
123
124 if (r->nc != 1)
125 return -1;
126
127 if (!c->utf8 && r->utf8)
128 return -1;
129
130 if (!((c->qops ? c->qops : DIGEST_MD5_QOP_AUTH) &
131 (r->qop ? r->qop : DIGEST_MD5_QOP_AUTH)))
132 return -1;
133
134 if ((r->qop & DIGEST_MD5_QOP_AUTH_CONF) && !(c->ciphers & r->cipher))
135 return -1;
136
137 /* FIXME: Check more? */
138
139 return 0;
140}
141