1 | /* printer.h --- Convert DIGEST-MD5 token structures into strings. |
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 "printer.h" |
29 | |
30 | /* Get free. */ |
31 | #include <stdlib.h> |
32 | |
33 | /* Get asprintf. */ |
34 | #include <stdio.h> |
35 | |
36 | /* Get token validator. */ |
37 | #include "validate.h" |
38 | |
39 | /* Append a key/value pair to a comma'd string list. Additionally enclose |
40 | the value in quotes if requested. */ |
41 | static int |
42 | comma_append (char **dst, const char *key, const char *value, int quotes) |
43 | { |
44 | char *tmp; |
45 | int result; |
46 | |
47 | if (*dst) |
48 | if (value) |
49 | if (quotes) |
50 | result = asprintf (&tmp, "%s, %s=\"%s\"" , *dst, key, value); |
51 | else |
52 | result = asprintf (&tmp, "%s, %s=%s" , *dst, key, value); |
53 | else |
54 | result = asprintf (&tmp, "%s, %s" , *dst, key); |
55 | else if (value) |
56 | if (quotes) |
57 | result = asprintf (&tmp, "%s=\"%s\"" , key, value); |
58 | else |
59 | result = asprintf (&tmp, "%s=%s" , key, value); |
60 | else |
61 | result = asprintf (&tmp, "%s" , key); |
62 | |
63 | if (result < 0) |
64 | return result; |
65 | |
66 | free (*dst); |
67 | |
68 | *dst = tmp; |
69 | |
70 | return result; |
71 | } |
72 | |
73 | char * |
74 | digest_md5_print_challenge (digest_md5_challenge * c) |
75 | { |
76 | char *out = NULL; |
77 | size_t i; |
78 | |
79 | /* Below we assume the mandatory fields are present, verify that |
80 | first to avoid crashes. */ |
81 | if (digest_md5_validate_challenge (c) != 0) |
82 | return NULL; |
83 | |
84 | for (i = 0; i < c->nrealms; i++) |
85 | { |
86 | if (comma_append (&out, "realm" , c->realms[i], 1) < 0) |
87 | { |
88 | free (out); |
89 | return NULL; |
90 | } |
91 | } |
92 | |
93 | if (c->nonce) |
94 | if (comma_append (&out, "nonce" , c->nonce, 1) < 0) |
95 | { |
96 | free (out); |
97 | return NULL; |
98 | } |
99 | |
100 | if (c->qops) |
101 | { |
102 | char *tmp = NULL; |
103 | |
104 | if (c->qops & DIGEST_MD5_QOP_AUTH) |
105 | if (comma_append (&tmp, "auth" , NULL, 0) < 0) |
106 | { |
107 | free (tmp); |
108 | free (out); |
109 | return NULL; |
110 | } |
111 | |
112 | if (c->qops & DIGEST_MD5_QOP_AUTH_INT) |
113 | if (comma_append (&tmp, "auth-int" , NULL, 0) < 0) |
114 | { |
115 | free (tmp); |
116 | free (out); |
117 | return NULL; |
118 | } |
119 | |
120 | if (c->qops & DIGEST_MD5_QOP_AUTH_CONF) |
121 | if (comma_append (&tmp, "auth-conf" , NULL, 0) < 0) |
122 | { |
123 | free (tmp); |
124 | free (out); |
125 | return NULL; |
126 | } |
127 | |
128 | if (comma_append (&out, "qop" , tmp, 1) < 0) |
129 | { |
130 | free (tmp); |
131 | free (out); |
132 | return NULL; |
133 | } |
134 | |
135 | free (tmp); |
136 | } |
137 | |
138 | if (c->stale) |
139 | if (comma_append (&out, "stale" , "true" , 0) < 0) |
140 | { |
141 | free (out); |
142 | return NULL; |
143 | } |
144 | |
145 | if (c->servermaxbuf) |
146 | { |
147 | char *tmp; |
148 | |
149 | if (asprintf (&tmp, "%lu" , c->servermaxbuf) < 0) |
150 | { |
151 | free (out); |
152 | return NULL; |
153 | } |
154 | |
155 | if (comma_append (&out, "maxbuf" , tmp, 0) < 0) |
156 | { |
157 | free (out); |
158 | return NULL; |
159 | } |
160 | |
161 | free (tmp); |
162 | } |
163 | |
164 | if (c->utf8) |
165 | if (comma_append (&out, "charset" , "utf-8" , 0) < 0) |
166 | { |
167 | free (out); |
168 | return NULL; |
169 | } |
170 | |
171 | if (comma_append (&out, "algorithm" , "md5-sess" , 0) < 0) |
172 | { |
173 | free (out); |
174 | return NULL; |
175 | } |
176 | |
177 | if (c->ciphers) |
178 | { |
179 | char *tmp = NULL; |
180 | |
181 | if (c->ciphers & DIGEST_MD5_CIPHER_3DES) |
182 | if (comma_append (&tmp, "3des" , NULL, 0) < 0) |
183 | { |
184 | free (tmp); |
185 | free (out); |
186 | return NULL; |
187 | } |
188 | |
189 | if (c->ciphers & DIGEST_MD5_CIPHER_DES) |
190 | if (comma_append (&tmp, "des" , NULL, 0) < 0) |
191 | { |
192 | free (tmp); |
193 | free (out); |
194 | return NULL; |
195 | } |
196 | |
197 | if (c->ciphers & DIGEST_MD5_CIPHER_RC4_40) |
198 | if (comma_append (&tmp, "rc4-40" , NULL, 0) < 0) |
199 | { |
200 | free (tmp); |
201 | free (out); |
202 | return NULL; |
203 | } |
204 | |
205 | if (c->ciphers & DIGEST_MD5_CIPHER_RC4) |
206 | if (comma_append (&tmp, "rc4" , NULL, 0) < 0) |
207 | { |
208 | free (tmp); |
209 | free (out); |
210 | return NULL; |
211 | } |
212 | |
213 | if (c->ciphers & DIGEST_MD5_CIPHER_RC4_56) |
214 | if (comma_append (&tmp, "rc4-56" , NULL, 0) < 0) |
215 | { |
216 | free (tmp); |
217 | free (out); |
218 | return NULL; |
219 | } |
220 | |
221 | if (c->ciphers & DIGEST_MD5_CIPHER_AES_CBC) |
222 | if (comma_append (&tmp, "aes-cbc" , NULL, 0) < 0) |
223 | { |
224 | free (tmp); |
225 | free (out); |
226 | return NULL; |
227 | } |
228 | |
229 | if (comma_append (&out, "cipher" , tmp, 1) < 0) |
230 | { |
231 | free (tmp); |
232 | free (out); |
233 | return NULL; |
234 | } |
235 | |
236 | free (tmp); |
237 | } |
238 | |
239 | return out; |
240 | } |
241 | |
242 | char * |
243 | digest_md5_print_response (digest_md5_response * r) |
244 | { |
245 | char *out = NULL; |
246 | const char *qop = NULL; |
247 | const char *cipher = NULL; |
248 | |
249 | /* Below we assume the mandatory fields are present, verify that |
250 | first to avoid crashes. */ |
251 | if (digest_md5_validate_response (r) != 0) |
252 | return NULL; |
253 | |
254 | if (r->qop & DIGEST_MD5_QOP_AUTH_CONF) |
255 | qop = "qop=auth-conf" ; |
256 | else if (r->qop & DIGEST_MD5_QOP_AUTH_INT) |
257 | qop = "qop=auth-int" ; |
258 | else if (r->qop & DIGEST_MD5_QOP_AUTH) |
259 | qop = "qop=auth" ; |
260 | |
261 | if (r->cipher & DIGEST_MD5_CIPHER_3DES) |
262 | cipher = "cipher=3des" ; |
263 | else if (r->cipher & DIGEST_MD5_CIPHER_DES) |
264 | cipher = "cipher=des" ; |
265 | else if (r->cipher & DIGEST_MD5_CIPHER_RC4_40) |
266 | cipher = "cipher=rc4-40" ; |
267 | else if (r->cipher & DIGEST_MD5_CIPHER_RC4) |
268 | cipher = "cipher=rc4" ; |
269 | else if (r->cipher & DIGEST_MD5_CIPHER_RC4_56) |
270 | cipher = "cipher=rc4-56" ; |
271 | else if (r->cipher & DIGEST_MD5_CIPHER_AES_CBC) |
272 | cipher = "cipher=aes-cbc" ; |
273 | else if (r->cipher & DIGEST_MD5_CIPHER_3DES) |
274 | cipher = "cipher=3des" ; |
275 | |
276 | if (r->username) |
277 | if (comma_append (&out, "username" , r->username, 1) < 0) |
278 | { |
279 | free (out); |
280 | return NULL; |
281 | } |
282 | |
283 | if (r->realm) |
284 | if (comma_append (&out, "realm" , r->realm, 1) < 0) |
285 | { |
286 | free (out); |
287 | return NULL; |
288 | } |
289 | |
290 | if (r->nonce) |
291 | if (comma_append (&out, "nonce" , r->nonce, 1) < 0) |
292 | { |
293 | free (out); |
294 | return NULL; |
295 | } |
296 | |
297 | if (r->cnonce) |
298 | if (comma_append (&out, "cnonce" , r->cnonce, 1) < 0) |
299 | { |
300 | free (out); |
301 | return NULL; |
302 | } |
303 | |
304 | if (r->nc) |
305 | { |
306 | char *tmp; |
307 | |
308 | if (asprintf (&tmp, "%08lx" , r->nc) < 0) |
309 | { |
310 | free (out); |
311 | return NULL; |
312 | } |
313 | |
314 | if (comma_append (&out, "nc" , tmp, 0) < 0) |
315 | { |
316 | free (tmp); |
317 | free (out); |
318 | return NULL; |
319 | } |
320 | |
321 | free (tmp); |
322 | } |
323 | |
324 | if (qop) |
325 | if (comma_append (&out, qop, NULL, 0) < 0) |
326 | { |
327 | free (out); |
328 | return NULL; |
329 | } |
330 | |
331 | if (r->digesturi) |
332 | if (comma_append (&out, "digest-uri" , r->digesturi, 1) < 0) |
333 | { |
334 | free (out); |
335 | return NULL; |
336 | } |
337 | |
338 | if (r->response) |
339 | if (comma_append (&out, "response" , r->response, 0) < 0) |
340 | { |
341 | free (out); |
342 | return NULL; |
343 | } |
344 | |
345 | if (r->clientmaxbuf) |
346 | { |
347 | char *tmp; |
348 | |
349 | if (asprintf (&tmp, "%lu" , r->clientmaxbuf) < 0) |
350 | { |
351 | free (out); |
352 | return NULL; |
353 | } |
354 | |
355 | if (comma_append (&out, "maxbuf" , tmp, 0) < 0) |
356 | { |
357 | free (tmp); |
358 | free (out); |
359 | return NULL; |
360 | } |
361 | |
362 | free (tmp); |
363 | } |
364 | |
365 | if (r->utf8) |
366 | if (comma_append (&out, "charset" , "utf-8" , 0) < 0) |
367 | { |
368 | free (out); |
369 | return NULL; |
370 | } |
371 | |
372 | if (cipher) |
373 | if (comma_append (&out, cipher, NULL, 0) < 0) |
374 | { |
375 | free (out); |
376 | return NULL; |
377 | } |
378 | |
379 | if (r->authzid) |
380 | if (comma_append (&out, "authzid" , r->authzid, 1) < 0) |
381 | { |
382 | free (out); |
383 | return NULL; |
384 | } |
385 | |
386 | return out; |
387 | } |
388 | |
389 | char * |
390 | digest_md5_print_finish (digest_md5_finish * finish) |
391 | { |
392 | char *out; |
393 | |
394 | /* Below we assume the mandatory fields are present, verify that |
395 | first to avoid crashes. */ |
396 | if (digest_md5_validate_finish (finish) != 0) |
397 | return NULL; |
398 | |
399 | if (asprintf (&out, "rspauth=%s" , finish->rspauth) < 0) |
400 | return NULL; |
401 | |
402 | return out; |
403 | } |
404 | |