gsasl  1.8.0
cram-md5/server.c
Go to the documentation of this file.
00001 /* server.c --- SASL CRAM-MD5 server side functions.
00002  * Copyright (C) 2002-2012 Simon Josefsson
00003  *
00004  * This file is part of GNU SASL Library.
00005  *
00006  * GNU SASL Library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation; either version 2.1 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * GNU SASL Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with GNU SASL Library; if not, write to the Free
00018  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 /* Get specification. */
00028 #include "cram-md5.h"
00029 
00030 /* Get malloc, free. */
00031 #include <stdlib.h>
00032 
00033 /* Get memcpy, strdup, strlen. */
00034 #include <string.h>
00035 
00036 /* Get cram_md5_challenge. */
00037 #include "challenge.h"
00038 
00039 /* Get cram_md5_digest. */
00040 #include "digest.h"
00041 
00042 #define MD5LEN 16
00043 
00044 int
00045 _gsasl_cram_md5_server_start (Gsasl_session * sctx, void **mech_data)
00046 {
00047   char *challenge;
00048   int rc;
00049 
00050   challenge = malloc (CRAM_MD5_CHALLENGE_LEN);
00051   if (challenge == NULL)
00052     return GSASL_MALLOC_ERROR;
00053 
00054   rc = cram_md5_challenge (challenge);
00055   if (rc)
00056     return GSASL_CRYPTO_ERROR;
00057 
00058   *mech_data = challenge;
00059 
00060   return GSASL_OK;
00061 }
00062 
00063 int
00064 _gsasl_cram_md5_server_step (Gsasl_session * sctx,
00065                              void *mech_data,
00066                              const char *input, size_t input_len,
00067                              char **output, size_t * output_len)
00068 {
00069   char *challenge = mech_data;
00070   char hash[CRAM_MD5_DIGEST_LEN];
00071   const char *password;
00072   char *username = NULL;
00073   int res = GSASL_OK;
00074   char *normkey;
00075 
00076   if (input_len == 0)
00077     {
00078       *output_len = strlen (challenge);
00079       *output = strdup (challenge);
00080 
00081       return GSASL_NEEDS_MORE;
00082     }
00083 
00084   if (input_len <= MD5LEN * 2)
00085     return GSASL_MECHANISM_PARSE_ERROR;
00086 
00087   if (input[input_len - MD5LEN * 2 - 1] != ' ')
00088     return GSASL_MECHANISM_PARSE_ERROR;
00089 
00090   username = calloc (1, input_len - MD5LEN * 2);
00091   if (username == NULL)
00092     return GSASL_MALLOC_ERROR;
00093 
00094   memcpy (username, input, input_len - MD5LEN * 2 - 1);
00095 
00096   gsasl_property_set (sctx, GSASL_AUTHID, username);
00097 
00098   free (username);
00099 
00100   password = gsasl_property_get (sctx, GSASL_PASSWORD);
00101   if (!password)
00102     return GSASL_NO_PASSWORD;
00103 
00104   /* FIXME: Use SASLprep here?  Treat string as storage string?
00105      Specification is unclear. */
00106   res = gsasl_saslprep (password, 0, &normkey, NULL);
00107   if (res != GSASL_OK)
00108     return res;
00109 
00110   cram_md5_digest (challenge, strlen (challenge),
00111                    normkey, strlen (normkey), hash);
00112 
00113   free (normkey);
00114 
00115   if (memcmp (&input[input_len - MD5LEN * 2], hash, 2 * MD5LEN) == 0)
00116     res = GSASL_OK;
00117   else
00118     res = GSASL_AUTHENTICATION_ERROR;
00119 
00120   *output_len = 0;
00121   *output = NULL;
00122 
00123   return res;
00124 }
00125 
00126 void
00127 _gsasl_cram_md5_server_finish (Gsasl_session * sctx, void *mech_data)
00128 {
00129   char *challenge = mech_data;
00130 
00131   free (challenge);
00132 }