gsasl  1.8.0
securid/client.c
Go to the documentation of this file.
00001 /* client.c --- SASL mechanism SECURID from RFC 2808, client 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 "securid.h"
00029 
00030 /* Get malloc, free. */
00031 #include <stdlib.h>
00032 
00033 /* Get strdup, strlen. */
00034 #include <string.h>
00035 
00036 #define PASSCODE "passcode"
00037 #define PIN "pin"
00038 
00039 int
00040 _gsasl_securid_client_start (Gsasl_session * sctx, void **mech_data)
00041 {
00042   int *step;
00043 
00044   step = (int *) malloc (sizeof (*step));
00045   if (step == NULL)
00046     return GSASL_MALLOC_ERROR;
00047 
00048   *step = 0;
00049 
00050   *mech_data = step;
00051 
00052   return GSASL_OK;
00053 }
00054 
00055 int
00056 _gsasl_securid_client_step (Gsasl_session * sctx,
00057                             void *mech_data,
00058                             const char *input,
00059                             size_t input_len,
00060                             char **output, size_t * output_len)
00061 {
00062   int *step = mech_data;
00063   const char *authzid = NULL, *authid = NULL, *passcode = NULL, *pin = NULL;
00064   size_t authzidlen, authidlen, passcodelen, pinlen = 0;
00065   int do_pin = 0;
00066   int res;
00067 
00068   switch (*step)
00069     {
00070     case 1:
00071       if (input_len == strlen (PASSCODE) &&
00072           memcmp (input, PASSCODE, strlen (PASSCODE)) == 0)
00073         {
00074           *step = 0;
00075         }
00076       else if (input_len >= strlen (PIN) &&
00077                memcmp (input, PIN, strlen (PIN)) == 0)
00078         {
00079           do_pin = 1;
00080           *step = 0;
00081         }
00082       else
00083         {
00084           *output_len = 0;
00085           res = GSASL_OK;
00086           break;
00087         }
00088       /* fall through */
00089 
00090     case 0:
00091       authzid = gsasl_property_get (sctx, GSASL_AUTHZID);
00092       if (authzid)
00093         authzidlen = strlen (authzid);
00094       else
00095         authzidlen = 0;
00096 
00097       authid = gsasl_property_get (sctx, GSASL_AUTHID);
00098       if (!authid)
00099         return GSASL_NO_AUTHID;
00100       authidlen = strlen (authid);
00101 
00102       passcode = gsasl_property_get (sctx, GSASL_PASSCODE);
00103       if (!passcode)
00104         return GSASL_NO_PASSCODE;
00105       passcodelen = strlen (passcode);
00106 
00107       if (do_pin)
00108         {
00109           if (input_len > strlen (PIN))
00110             gsasl_property_set_raw (sctx, GSASL_SUGGESTED_PIN,
00111                                     &input[strlen (PIN)],
00112                                     input_len - strlen (PIN));
00113 
00114           pin = gsasl_property_get (sctx, GSASL_PIN);
00115           if (!pin)
00116             return GSASL_NO_PIN;
00117           pinlen = strlen (pin);
00118         }
00119 
00120       *output_len = authzidlen + 1 + authidlen + 1 + passcodelen + 1;
00121       if (do_pin)
00122         *output_len += pinlen + 1;
00123       *output = malloc (*output_len);
00124       if (*output == NULL)
00125         return GSASL_MALLOC_ERROR;
00126 
00127       if (authzid)
00128         memcpy (*output, authzid, authzidlen);
00129       (*output)[authzidlen] = '\0';
00130       memcpy (*output + authzidlen + 1, authid, authidlen);
00131       (*output)[authzidlen + 1 + authidlen] = '\0';
00132       memcpy (*output + authzidlen + 1 + authidlen + 1, passcode,
00133               passcodelen);
00134       (*output)[authzidlen + 1 + authidlen + 1 + passcodelen] = '\0';
00135       if (do_pin)
00136         {
00137           memcpy (*output + authzidlen + 1 + authidlen + 1 + passcodelen + 1,
00138                   pin, pinlen);
00139           (*output)[authzidlen + 1 + authidlen + 1 + passcodelen + 1 +
00140                     pinlen] = '\0';
00141         }
00142 
00143       (*step)++;
00144       res = GSASL_OK;
00145       break;
00146 
00147     case 2:
00148       *output_len = 0;
00149       *output = NULL;
00150       (*step)++;
00151       res = GSASL_OK;
00152       break;
00153 
00154     default:
00155       res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
00156       break;
00157     }
00158 
00159   return res;
00160 }
00161 
00162 void
00163 _gsasl_securid_client_finish (Gsasl_session * sctx, void *mech_data)
00164 {
00165   int *step = mech_data;
00166 
00167   free (step);
00168 }