Packaging: clean spec file
[platform/upstream/libgsasl.git] / plain / server.c
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
36 int
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 }