gsasl  1.8.0
login/server.c
Go to the documentation of this file.
00001 /* server.c --- Non-standard SASL mechanism LOGIN, 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 malloc, free. */
00028 #include <stdlib.h>
00029 
00030 /* Get strdup, strlen. */
00031 #include <string.h>
00032 
00033 /* Get specification. */
00034 #include "login.h"
00035 
00036 struct _Gsasl_login_server_state
00037 {
00038   int step;
00039   char *username;
00040   char *password;
00041 };
00042 
00043 #define CHALLENGE_USERNAME "User Name"
00044 #define CHALLENGE_PASSWORD "Password"
00045 
00046 int
00047 _gsasl_login_server_start (Gsasl_session * sctx, void **mech_data)
00048 {
00049   struct _Gsasl_login_server_state *state;
00050 
00051   state = calloc (1, sizeof (*state));
00052   if (state == NULL)
00053     return GSASL_MALLOC_ERROR;
00054 
00055   *mech_data = state;
00056 
00057   return GSASL_OK;
00058 }
00059 
00060 int
00061 _gsasl_login_server_step (Gsasl_session * sctx,
00062                           void *mech_data,
00063                           const char *input, size_t input_len,
00064                           char **output, size_t * output_len)
00065 {
00066   struct _Gsasl_login_server_state *state = mech_data;
00067   int res;
00068 
00069   switch (state->step)
00070     {
00071     case 0:
00072       *output = strdup (CHALLENGE_USERNAME);
00073       if (!*output)
00074         return GSASL_MALLOC_ERROR;
00075       *output_len = strlen (CHALLENGE_USERNAME);
00076 
00077       state->step++;
00078       res = GSASL_NEEDS_MORE;
00079       break;
00080 
00081     case 1:
00082       if (input_len == 0)
00083         return GSASL_MECHANISM_PARSE_ERROR;
00084 
00085       state->username = malloc (input_len + 1);
00086       if (state->username == NULL)
00087         return GSASL_MALLOC_ERROR;
00088 
00089       memcpy (state->username, input, input_len);
00090       state->username[input_len] = '\0';
00091 
00092       *output = strdup (CHALLENGE_PASSWORD);
00093       if (!*output)
00094         return GSASL_MALLOC_ERROR;
00095       *output_len = strlen (CHALLENGE_PASSWORD);
00096 
00097       state->step++;
00098       res = GSASL_NEEDS_MORE;
00099       break;
00100 
00101     case 2:
00102       if (input_len == 0)
00103         return GSASL_MECHANISM_PARSE_ERROR;
00104 
00105       state->password = malloc (input_len + 1);
00106       if (state->password == NULL)
00107         return GSASL_MALLOC_ERROR;
00108 
00109       memcpy (state->password, input, input_len);
00110       state->password[input_len] = '\0';
00111 
00112       if (input_len != strlen (state->password))
00113         return GSASL_MECHANISM_PARSE_ERROR;
00114 
00115       gsasl_property_set (sctx, GSASL_AUTHID, state->username);
00116       gsasl_property_set (sctx, GSASL_PASSWORD, state->password);
00117 
00118       res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE);
00119       if (res == GSASL_NO_CALLBACK)
00120         {
00121           const char *key;
00122 
00123           gsasl_property_set (sctx, GSASL_AUTHZID, NULL);
00124           gsasl_property_set (sctx, GSASL_PASSWORD, NULL);
00125 
00126           key = gsasl_property_get (sctx, GSASL_PASSWORD);
00127 
00128           if (key && strlen (state->password) == strlen (key) &&
00129               strcmp (state->password, key) == 0)
00130             res = GSASL_OK;
00131           else
00132             res = GSASL_AUTHENTICATION_ERROR;
00133         }
00134 
00135       *output_len = 0;
00136       *output = NULL;
00137       state->step++;
00138       break;
00139 
00140     default:
00141       res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00142       break;
00143     }
00144 
00145   return res;
00146 }
00147 
00148 void
00149 _gsasl_login_server_finish (Gsasl_session * sctx, void *mech_data)
00150 {
00151   struct _Gsasl_login_server_state *state = mech_data;
00152 
00153   if (!state)
00154     return;
00155 
00156   free (state->username);
00157   free (state->password);
00158   free (state);
00159 }