gsasl  1.8.0
plain/server.c
Go to the documentation of this file.
00001 /* server.c --- SASL mechanism PLAIN as defined in RFC 2595, server side.
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 "plain.h"
00029 
00030 /* Get memcpy, memchr, strlen. */
00031 #include <string.h>
00032 
00033 /* Get malloc, free. */
00034 #include <stdlib.h>
00035 
00036 int
00037 _gsasl_plain_server_step (Gsasl_session * sctx,
00038                           void *mech_data,
00039                           const char *input, size_t input_len,
00040                           char **output, size_t * output_len)
00041 {
00042   const char *authzidptr = input;
00043   char *authidptr = NULL;
00044   char *passwordptr = NULL;
00045   char *passwdz = NULL, *passprep = NULL, *authidprep = NULL;
00046   int res;
00047 
00048   *output_len = 0;
00049   *output = NULL;
00050 
00051   if (input_len == 0)
00052     return GSASL_NEEDS_MORE;
00053 
00054   /* Parse input. */
00055   {
00056     size_t tmplen;
00057 
00058     authidptr = memchr (input, 0, input_len - 1);
00059     if (authidptr)
00060       {
00061         authidptr++;
00062         passwordptr = memchr (authidptr, 0, input_len - strlen (input) - 1);
00063         if (passwordptr)
00064           passwordptr++;
00065         else
00066           return GSASL_MECHANISM_PARSE_ERROR;
00067       }
00068     else
00069       return GSASL_MECHANISM_PARSE_ERROR;
00070 
00071     /* As the NUL (U+0000) character is used as a deliminator, the NUL
00072        (U+0000) character MUST NOT appear in authzid, authcid, or passwd
00073        productions. */
00074     tmplen = input_len - (size_t) (passwordptr - input);
00075     if (memchr (passwordptr, 0, tmplen))
00076       return GSASL_MECHANISM_PARSE_ERROR;
00077   }
00078 
00079   /* Store authid, after preparing it... */
00080   {
00081     res = gsasl_saslprep (authidptr, GSASL_ALLOW_UNASSIGNED,
00082                           &authidprep, NULL);
00083     if (res != GSASL_OK)
00084       return res;
00085 
00086     gsasl_property_set (sctx, GSASL_AUTHID, authidprep);
00087 
00088     /* Store authzid, if absent, use SASLprep(authcid). */
00089     if (*authzidptr == '\0')
00090       gsasl_property_set (sctx, GSASL_AUTHZID, authidprep);
00091     else
00092       gsasl_property_set (sctx, GSASL_AUTHZID, authzidptr);
00093 
00094     free (authidprep);
00095   }
00096 
00097   /* Store passwd, after preparing it... */
00098   {
00099     size_t passwdzlen = input_len - (size_t) (passwordptr - input);
00100 
00101     /* Need to zero terminate password... */
00102     passwdz = malloc (passwdzlen + 1);
00103     if (passwdz == NULL)
00104       return GSASL_MALLOC_ERROR;
00105     memcpy (passwdz, passwordptr, passwdzlen);
00106     passwdz[passwdzlen] = '\0';
00107 
00108     res = gsasl_saslprep (passwdz, GSASL_ALLOW_UNASSIGNED, &passprep, NULL);
00109     free (passwdz);
00110     if (res != GSASL_OK)
00111       return res;
00112 
00113     gsasl_property_set (sctx, GSASL_PASSWORD, passprep);
00114   }
00115 
00116   /* Authorization.  Let application verify credentials internally,
00117      but fall back to deal with it locally... */
00118   res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE);
00119   if (res == GSASL_NO_CALLBACK)
00120     {
00121       const char *key;
00122       char *normkey;
00123 
00124       gsasl_property_set (sctx, GSASL_PASSWORD, NULL);
00125       key = gsasl_property_get (sctx, GSASL_PASSWORD);
00126       if (!key)
00127         {
00128           free (passprep);
00129           return GSASL_NO_PASSWORD;
00130         }
00131 
00132       /* Unassigned code points are not permitted. */
00133       res = gsasl_saslprep (key, 0, &normkey, NULL);
00134       if (res != GSASL_OK)
00135         {
00136           free (passprep);
00137           return res;
00138         }
00139 
00140       if (strcmp (normkey, passprep) == 0)
00141         res = GSASL_OK;
00142       else
00143         res = GSASL_AUTHENTICATION_ERROR;
00144       free (normkey);
00145     }
00146   free (passprep);
00147 
00148   return res;
00149 }