Bump versions.
[gsasl.git] / lib / cram-md5 / server.c
blob58a0ba5f3f6a63be7084ee3d9baf529eb3d19711
1 /* server.c --- SASL CRAM-MD5 server side functions.
2 * Copyright (C) 2002, 2003, 2004, 2006 Simon Josefsson
4 * This file is part of GNU SASL Library.
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.
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.
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.
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 /* Get specification. */
28 #include "cram-md5.h"
30 /* Get malloc, free. */
31 #include <stdlib.h>
33 /* Get memcpy, strdup, strlen. */
34 #include <string.h>
36 /* Get cram_md5_challenge. */
37 #include "challenge.h"
39 /* Get cram_md5_digest. */
40 #include "digest.h"
42 #define MD5LEN 16
44 int
45 _gsasl_cram_md5_server_start (Gsasl_session * sctx, void **mech_data)
47 char *challenge;
49 challenge = malloc (CRAM_MD5_CHALLENGE_LEN);
50 if (challenge == NULL)
51 return GSASL_MALLOC_ERROR;
53 cram_md5_challenge (challenge);
55 *mech_data = challenge;
57 return GSASL_OK;
60 int
61 _gsasl_cram_md5_server_step (Gsasl_session * sctx,
62 void *mech_data,
63 const char *input, size_t input_len,
64 char **output, size_t * output_len)
66 char *challenge = mech_data;
67 char hash[CRAM_MD5_DIGEST_LEN];
68 const char *password;
69 char *username = NULL;
70 int res = GSASL_OK;
71 char *normkey;
73 if (input_len == 0)
75 *output_len = strlen (challenge);
76 *output = strdup (challenge);
78 return GSASL_NEEDS_MORE;
81 if (input_len <= MD5LEN * 2)
82 return GSASL_MECHANISM_PARSE_ERROR;
84 if (input[input_len - MD5LEN * 2 - 1] != ' ')
85 return GSASL_MECHANISM_PARSE_ERROR;
87 username = calloc (1, input_len - MD5LEN * 2);
88 if (username == NULL)
89 return GSASL_MALLOC_ERROR;
91 memcpy (username, input, input_len - MD5LEN * 2 - 1);
93 gsasl_property_set (sctx, GSASL_AUTHID, username);
95 free (username);
97 password = gsasl_property_get (sctx, GSASL_PASSWORD);
98 if (!password)
99 return GSASL_NO_PASSWORD;
101 /* FIXME: Use SASLprep here? Treat string as storage string?
102 Specification is unclear. */
103 res = gsasl_saslprep (password, 0, &normkey, NULL);
104 if (res != GSASL_OK)
105 return res;
107 cram_md5_digest (challenge, strlen (challenge),
108 normkey, strlen (normkey), hash);
110 free (normkey);
112 if (memcmp (&input[input_len - MD5LEN * 2], hash, 2 * MD5LEN) == 0)
113 res = GSASL_OK;
114 else
115 res = GSASL_AUTHENTICATION_ERROR;
117 *output_len = 0;
118 *output = NULL;
120 return res;
123 void
124 _gsasl_cram_md5_server_finish (Gsasl_session * sctx, void *mech_data)
126 char *challenge = mech_data;
128 if (challenge)
129 free (challenge);