1/* server.c --- SASL mechanism PLAIN as defined in RFC 2595, 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 "plain.h"
29
30/* Get memcpy, memchr, strlen. */
31#include <string.h>
32
33/* Get malloc, free. */
34#include <stdlib.h>
35
36int
37_gsasl_plain_server_step (Gsasl_session * sctx,
38 void *mech_data,
39 const char *input, size_t input_len,
40 char **output, size_t * output_len)
41{
42 const char *authzidptr = input;
43 char *authidptr = NULL;
44 char *passwordptr = NULL;
45 char *passwdz = NULL, *passprep = NULL, *authidprep = NULL;
46 int res;
47
48 *output_len = 0;
49 *output = NULL;
50
51 if (input_len == 0)
52 return GSASL_NEEDS_MORE;
53
54 /* Parse input. */
55 {
56 size_t tmplen;
57
58 authidptr = memchr (input, 0, input_len - 1);
59 if (authidptr)
60 {
61 authidptr++;
62 passwordptr = memchr (authidptr, 0, input_len - strlen (input) - 1);
63 if (passwordptr)
64 passwordptr++;
65 else
66 return GSASL_MECHANISM_PARSE_ERROR;
67 }
68 else
69 return GSASL_MECHANISM_PARSE_ERROR;
70
71 /* As the NUL (U+0000) character is used as a deliminator, the NUL
72 (U+0000) character MUST NOT appear in authzid, authcid, or passwd
73 productions. */
74 tmplen = input_len - (size_t) (passwordptr - input);
75 if (memchr (passwordptr, 0, tmplen))
76 return GSASL_MECHANISM_PARSE_ERROR;
77 }
78
79 /* Store authid, after preparing it... */
80 {
81 res = gsasl_saslprep (authidptr, GSASL_ALLOW_UNASSIGNED,
82 &authidprep, NULL);
83 if (res != GSASL_OK)
84 return res;
85
86 gsasl_property_set (sctx, GSASL_AUTHID, authidprep);
87
88 /* Store authzid, if absent, use SASLprep(authcid). */
89 if (*authzidptr == '\0')
90 gsasl_property_set (sctx, GSASL_AUTHZID, authidprep);
91 else
92 gsasl_property_set (sctx, GSASL_AUTHZID, authzidptr);
93
94 free (authidprep);
95 }
96
97 /* Store passwd, after preparing it... */
98 {
99 size_t passwdzlen = input_len - (size_t) (passwordptr - input);
100
101 /* Need to zero terminate password... */
102 passwdz = malloc (passwdzlen + 1);
103 if (passwdz == NULL)
104 return GSASL_MALLOC_ERROR;
105 memcpy (passwdz, passwordptr, passwdzlen);
106 passwdz[passwdzlen] = '\0';
107
108 res = gsasl_saslprep (passwdz, GSASL_ALLOW_UNASSIGNED, &passprep, NULL);
109 free (passwdz);
110 if (res != GSASL_OK)
111 return res;
112
113 gsasl_property_set (sctx, GSASL_PASSWORD, passprep);
114 }
115
116 /* Authorization. Let application verify credentials internally,
117 but fall back to deal with it locally... */
118 res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE);
119 if (res == GSASL_NO_CALLBACK)
120 {
121 const char *key;
122 char *normkey;
123
124 gsasl_property_set (sctx, GSASL_PASSWORD, NULL);
125 key = gsasl_property_get (sctx, GSASL_PASSWORD);
126 if (!key)
127 {
128 free (passprep);
129 return GSASL_NO_PASSWORD;
130 }
131
132 /* Unassigned code points are not permitted. */
133 res = gsasl_saslprep (key, 0, &normkey, NULL);
134 if (res != GSASL_OK)
135 {
136 free (passprep);
137 return res;
138 }
139
140 if (strcmp (normkey, passprep) == 0)
141 res = GSASL_OK;
142 else
143 res = GSASL_AUTHENTICATION_ERROR;
144 free (normkey);
145 }
146 free (passprep);
147
148 return res;
149}
150