1/* client.c --- SASL CRAM-MD5 client side functions.
2 * Copyright (C) 2002-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 specification. */
28#include "cram-md5.h"
29
30/* Get malloc, free. */
31#include <stdlib.h>
32
33/* Get memcpy, strlen. */
34#include <string.h>
35
36/* Get cram_md5_digest. */
37#include "digest.h"
38
39int
40_gsasl_cram_md5_client_step (Gsasl_session * sctx,
41 void *mech_data,
42 const char *input, size_t input_len,
43 char **output, size_t * output_len)
44{
45 char response[CRAM_MD5_DIGEST_LEN];
46 const char *p;
47 size_t len;
48 char *tmp;
49 char *authid;
50 int rc;
51
52 if (input_len == 0)
53 {
54 *output_len = 0;
55 *output = NULL;
56 return GSASL_NEEDS_MORE;
57 }
58
59 p = gsasl_property_get (sctx, GSASL_AUTHID);
60 if (!p)
61 return GSASL_NO_AUTHID;
62
63 /* XXX Use query strings here? Specification is unclear. */
64 rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED, &authid, NULL);
65 if (rc != GSASL_OK)
66 return rc;
67
68 p = gsasl_property_get (sctx, GSASL_PASSWORD);
69 if (!p)
70 {
71 free (authid);
72 return GSASL_NO_PASSWORD;
73 }
74
75 /* XXX Use query strings here? Specification is unclear. */
76 rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED, &tmp, NULL);
77 if (rc != GSASL_OK)
78 {
79 free (authid);
80 return rc;
81 }
82
83 cram_md5_digest (input, input_len, tmp, strlen (tmp), response);
84
85 free (tmp);
86
87 len = strlen (authid);
88
89 *output_len = len + strlen (" ") + CRAM_MD5_DIGEST_LEN;
90 *output = malloc (*output_len);
91 if (!*output)
92 {
93 free (authid);
94 return GSASL_MALLOC_ERROR;
95 }
96
97 memcpy (*output, authid, len);
98 (*output)[len++] = ' ';
99 memcpy (*output + len, response, CRAM_MD5_DIGEST_LEN);
100
101 free (authid);
102
103 return GSASL_OK;
104}
105