1/* server.c --- SASL mechanism SECURID from RFC 2808, server side.
2 * Copyright (C) 2002-2012 Simon Josefsson
3 *
4 * This file is part of GNU SASL Library.
5 *
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.
10 *
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.
15 *
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.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27/* Get specification. */
28#include "securid.h"
29
30/* Get malloc, free. */
31#include <stdlib.h>
32
33/* Get memchr, strdup, strlen. */
34#include <string.h>
35
36#define PASSCODE "passcode"
37#define PIN "pin"
38
39int
40_gsasl_securid_server_step (Gsasl_session * sctx,
41 void *mech_data,
42 const char *input, size_t input_len,
43 char **output, size_t * output_len)
44{
45 const char *authorization_id = NULL;
46 const char *authentication_id = NULL;
47 const char *passcode = NULL;
48 const char *suggestedpin;
49 char *pin = NULL;
50 int res;
51 size_t len;
52
53 if (input_len == 0)
54 {
55 *output_len = 0;
56 *output = NULL;
57 return GSASL_NEEDS_MORE;
58 }
59
60 authorization_id = input;
61 authentication_id = memchr (input, '\0', input_len - 1);
62 if (authentication_id)
63 {
64 authentication_id++;
65 passcode = memchr (authentication_id, '\0',
66 input_len - strlen (authorization_id) - 1 - 1);
67 if (passcode)
68 {
69 passcode++;
70 pin = memchr (passcode, '\0', input_len -
71 strlen (authorization_id) - 1 -
72 strlen (authentication_id) - 1 - 1);
73 if (pin)
74 {
75 pin++;
76 if (pin && !*pin)
77 pin = NULL;
78 }
79 }
80 }
81
82 if (passcode == NULL)
83 return GSASL_MECHANISM_PARSE_ERROR;
84
85 gsasl_property_set (sctx, GSASL_AUTHID, authentication_id);
86 gsasl_property_set (sctx, GSASL_AUTHZID, authorization_id);
87 gsasl_property_set (sctx, GSASL_PASSCODE, passcode);
88 if (pin)
89 gsasl_property_set (sctx, GSASL_PIN, pin);
90 else
91 gsasl_property_set (sctx, GSASL_PIN, NULL);
92
93 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SECURID);
94 switch (res)
95 {
96 case GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE:
97 *output = strdup (PASSCODE);
98 if (!*output)
99 return GSASL_MALLOC_ERROR;
100 *output_len = strlen (PASSCODE);
101 res = GSASL_NEEDS_MORE;
102 break;
103
104 case GSASL_SECURID_SERVER_NEED_NEW_PIN:
105 suggestedpin = gsasl_property_get (sctx, GSASL_SUGGESTED_PIN);
106 if (suggestedpin)
107 len = strlen (suggestedpin);
108 else
109 len = 0;
110 *output_len = strlen (PIN) + len;
111 *output = malloc (*output_len);
112 if (!*output)
113 return GSASL_MALLOC_ERROR;
114 memcpy (*output, PIN, strlen (PIN));
115 if (suggestedpin)
116 memcpy (*output + strlen (PIN), suggestedpin, len);
117 res = GSASL_NEEDS_MORE;
118 break;
119
120 default:
121 *output_len = 0;
122 *output = NULL;
123 break;
124 }
125
126 return res;
127}
128