Tizen 2.0 Release
[external/libgnutls26.git] / lib / ext_srp.c
1 /*
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25
26 #include <gnutls_int.h>
27 #include <ext_srp.h>
28
29 #ifdef ENABLE_SRP
30
31 #include "gnutls_auth.h"
32 #include "auth_srp.h"
33 #include "gnutls_errors.h"
34 #include "gnutls_algorithms.h"
35 #include <gnutls_num.h>
36 #include <gnutls_extensions.h>
37
38 static int _gnutls_srp_unpack (gnutls_buffer_st * ps,
39                                extension_priv_data_t * _priv);
40 static int _gnutls_srp_pack (extension_priv_data_t epriv,
41                              gnutls_buffer_st * ps);
42 static void _gnutls_srp_deinit_data (extension_priv_data_t epriv);
43 static int _gnutls_srp_recv_params (gnutls_session_t state,
44                                     const opaque * data, size_t data_size);
45 static int _gnutls_srp_send_params (gnutls_session_t state, opaque * data,
46                                     size_t);
47
48 extension_entry_st ext_mod_srp = {
49   .name = "SRP",
50   .type = GNUTLS_EXTENSION_SRP,
51   .parse_type = GNUTLS_EXT_TLS,
52
53   .recv_func = _gnutls_srp_recv_params,
54   .send_func = _gnutls_srp_send_params,
55   .pack_func = _gnutls_srp_pack,
56   .unpack_func = _gnutls_srp_unpack,
57   .deinit_func = _gnutls_srp_deinit_data
58 };
59
60
61 static int
62 _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data,
63                          size_t _data_size)
64 {
65   uint8_t len;
66   ssize_t data_size = _data_size;
67   extension_priv_data_t epriv;
68   srp_ext_st *priv;
69
70   if (session->security_parameters.entity == GNUTLS_SERVER)
71     {
72       if (data_size > 0)
73         {
74           len = data[0];
75           DECR_LEN (data_size, len);
76
77           if (MAX_USERNAME_SIZE < len)
78             {
79               gnutls_assert ();
80               return GNUTLS_E_ILLEGAL_SRP_USERNAME;
81             }
82
83           priv = gnutls_calloc (1, sizeof (*priv));
84           if (priv == NULL)
85             {
86               gnutls_assert ();
87               return GNUTLS_E_MEMORY_ERROR;
88             }
89
90           priv->username = gnutls_malloc (len + 1);
91           if (priv->username)
92             {
93               memcpy (priv->username, &data[1], len);
94               /* null terminated */
95               priv->username[len] = 0;
96             }
97
98           epriv.ptr = priv;
99           _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
100         }
101     }
102   return 0;
103 }
104
105 /* returns data_size or a negative number on failure
106  * data is allocated locally
107  */
108 static int
109 _gnutls_srp_send_params (gnutls_session_t session, opaque * data,
110                          size_t data_size)
111 {
112   unsigned len;
113   extension_priv_data_t epriv;
114   srp_ext_st *priv = NULL;
115   char *username = NULL, *password = NULL;
116   int ret;
117
118   if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 &&
119       _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 &&
120       _gnutls_kx_priority (session, GNUTLS_KX_SRP_RSA) < 0)
121     {
122       /* algorithm was not allowed in this session
123        */
124       return 0;
125     }
126
127   /* this function sends the client extension data (username) */
128   if (session->security_parameters.entity == GNUTLS_CLIENT)
129     {
130       gnutls_srp_client_credentials_t cred = (gnutls_srp_client_credentials_t)
131         _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
132
133       if (cred == NULL)
134         return 0;
135
136       priv = gnutls_malloc (sizeof (*priv));
137       if (priv == NULL)
138         {
139           gnutls_assert ();
140           return GNUTLS_E_MEMORY_ERROR;
141         }
142
143       if (cred->username != NULL)
144         {                       /* send username */
145           len = MIN (strlen (cred->username), 255);
146
147           if (data_size < len + 1)
148             {
149               gnutls_assert ();
150               return GNUTLS_E_SHORT_MEMORY_BUFFER;
151             }
152
153           priv->username = strdup(cred->username);
154           if (priv->username == NULL)
155             {
156               gnutls_assert();
157               goto cleanup;
158             }
159
160           priv->password = strdup(cred->password);
161           if (priv->password == NULL)
162             {
163               gnutls_assert();
164               goto cleanup;
165             }
166
167           epriv.ptr = priv;
168           _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
169
170           data[0] = (uint8_t) len;
171           memcpy (&data[1], cred->username, len);
172           return len + 1;
173         }
174       else if (cred->get_function != NULL)
175         {
176           /* Try the callback
177            */
178
179           if (cred->get_function (session, &username, &password) < 0
180               || username == NULL || password == NULL)
181             {
182               gnutls_assert ();
183               return GNUTLS_E_ILLEGAL_SRP_USERNAME;
184             }
185
186           len = MIN (strlen (username), 255);
187
188           if (data_size < len + 1)
189             {
190               gnutls_assert ();
191               ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
192               goto cleanup;
193             }
194
195           priv->username = username;
196           priv->password = password;
197
198           epriv.ptr = priv;
199           _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
200
201           data[0] = (uint8_t) len;
202           memcpy (&data[1], username, len);
203           return len + 1;
204         }
205     }
206   return 0;
207
208 cleanup:
209   gnutls_free(username);
210   gnutls_free(password);
211   gnutls_free(priv);
212   
213   return ret;
214 }
215
216 static void
217 _gnutls_srp_deinit_data (extension_priv_data_t epriv)
218 {
219   srp_ext_st *priv = epriv.ptr;
220
221   gnutls_free (priv->username);
222   gnutls_free (priv->password);
223   gnutls_free (priv);
224 }
225
226 static int
227 _gnutls_srp_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
228 {
229   srp_ext_st *priv = epriv.ptr;
230   int ret;
231   int password_len = 0, username_len = 0;
232
233   if (priv->username)
234     username_len = strlen (priv->username);
235
236   if (priv->password)
237     password_len = strlen (priv->password);
238
239   BUFFER_APPEND_PFX (ps, priv->username, username_len);
240   BUFFER_APPEND_PFX (ps, priv->password, password_len);
241
242   return 0;
243 }
244
245 static int
246 _gnutls_srp_unpack (gnutls_buffer_st * ps, extension_priv_data_t * _priv)
247 {
248   srp_ext_st *priv;
249   int ret;
250   extension_priv_data_t epriv;
251   gnutls_datum username = { NULL, 0 }, password =
252   {
253   NULL, 0};
254
255   priv = gnutls_calloc (1, sizeof (*priv));
256   if (priv == NULL)
257     {
258       gnutls_assert ();
259       return GNUTLS_E_MEMORY_ERROR;
260     }
261
262   BUFFER_POP_DATUM (ps, &username);
263   BUFFER_POP_DATUM (ps, &password);
264
265   priv->username = username.data;
266   priv->password = password.data;
267
268   epriv.ptr = priv;
269   *_priv = epriv;
270
271   return 0;
272
273 error:
274   _gnutls_free_datum (&username);
275   _gnutls_free_datum (&password);
276   return ret;
277 }
278
279
280 #endif /* ENABLE_SRP */