Fixed leaks in key generation and other cleanups. Patch by Tomas Mraz.
[gnutls.git] / lib / ext_srp.c
blob2d39ba98f7f4a103c8c937eb51269b9b89833d8c
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
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.
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.
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
26 #include <gnutls_int.h>
27 #include <ext_srp.h>
29 #ifdef ENABLE_SRP
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>
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);
48 extension_entry_st ext_mod_srp = {
49 .name = "SRP",
50 .type = GNUTLS_EXTENSION_SRP,
51 .parse_type = GNUTLS_EXT_TLS,
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
61 static int
62 _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data,
63 size_t _data_size)
65 uint8_t len;
66 ssize_t data_size = _data_size;
67 extension_priv_data_t epriv;
68 srp_ext_st *priv;
70 if (session->security_parameters.entity == GNUTLS_SERVER)
72 if (data_size > 0)
74 len = data[0];
75 DECR_LEN (data_size, len);
77 if (MAX_USERNAME_SIZE < len)
79 gnutls_assert ();
80 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
83 priv = gnutls_calloc (1, sizeof (*priv));
84 if (priv == NULL)
86 gnutls_assert ();
87 return GNUTLS_E_MEMORY_ERROR;
90 priv->username = gnutls_malloc (len + 1);
91 if (priv->username)
93 memcpy (priv->username, &data[1], len);
94 /* null terminated */
95 priv->username[len] = 0;
98 epriv.ptr = priv;
99 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
102 return 0;
105 /* returns data_size or a negative number on failure
106 * data is allocated locally
108 static int
109 _gnutls_srp_send_params (gnutls_session_t session, opaque * data,
110 size_t data_size)
112 unsigned len;
113 extension_priv_data_t epriv;
114 srp_ext_st *priv = NULL;
115 char *username = NULL, *password = NULL;
116 int ret;
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)
122 /* algorithm was not allowed in this session
124 return 0;
127 /* this function sends the client extension data (username) */
128 if (session->security_parameters.entity == GNUTLS_CLIENT)
130 gnutls_srp_client_credentials_t cred = (gnutls_srp_client_credentials_t)
131 _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
133 if (cred == NULL)
134 return 0;
136 priv = gnutls_malloc (sizeof (*priv));
137 if (priv == NULL)
139 gnutls_assert ();
140 return GNUTLS_E_MEMORY_ERROR;
143 if (cred->username != NULL)
144 { /* send username */
145 len = MIN (strlen (cred->username), 255);
147 if (data_size < len + 1)
149 gnutls_assert ();
150 return GNUTLS_E_SHORT_MEMORY_BUFFER;
153 priv->username = strdup(cred->username);
154 if (priv->username == NULL)
156 gnutls_assert();
157 goto cleanup;
160 priv->password = strdup(cred->password);
161 if (priv->password == NULL)
163 gnutls_assert();
164 goto cleanup;
167 epriv.ptr = priv;
168 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
170 data[0] = (uint8_t) len;
171 memcpy (&data[1], cred->username, len);
172 return len + 1;
174 else if (cred->get_function != NULL)
176 /* Try the callback
179 if (cred->get_function (session, &username, &password) < 0
180 || username == NULL || password == NULL)
182 gnutls_assert ();
183 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
186 len = MIN (strlen (username), 255);
188 if (data_size < len + 1)
190 gnutls_assert ();
191 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
192 goto cleanup;
195 priv->username = username;
196 priv->password = password;
198 epriv.ptr = priv;
199 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SRP, epriv);
201 data[0] = (uint8_t) len;
202 memcpy (&data[1], username, len);
203 return len + 1;
206 return 0;
208 cleanup:
209 gnutls_free(username);
210 gnutls_free(password);
211 gnutls_free(priv);
213 return ret;
216 static void
217 _gnutls_srp_deinit_data (extension_priv_data_t epriv)
219 srp_ext_st *priv = epriv.ptr;
221 gnutls_free (priv->username);
222 gnutls_free (priv->password);
223 gnutls_free (priv);
226 static int
227 _gnutls_srp_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
229 srp_ext_st *priv = epriv.ptr;
230 int ret;
231 int password_len = 0, username_len = 0;
233 if (priv->username)
234 username_len = strlen (priv->username);
236 if (priv->password)
237 password_len = strlen (priv->password);
239 BUFFER_APPEND_PFX (ps, priv->username, username_len);
240 BUFFER_APPEND_PFX (ps, priv->password, password_len);
242 return 0;
245 static int
246 _gnutls_srp_unpack (gnutls_buffer_st * ps, extension_priv_data_t * _priv)
248 srp_ext_st *priv;
249 int ret;
250 extension_priv_data_t epriv;
251 gnutls_datum username = { NULL, 0 }, password =
253 NULL, 0};
255 priv = gnutls_calloc (1, sizeof (*priv));
256 if (priv == NULL)
258 gnutls_assert ();
259 return GNUTLS_E_MEMORY_ERROR;
262 BUFFER_POP_DATUM (ps, &username);
263 BUFFER_POP_DATUM (ps, &password);
265 priv->username = username.data;
266 priv->password = password.data;
268 epriv.ptr = priv;
269 *_priv = epriv;
271 return 0;
273 error:
274 _gnutls_free_datum (&username);
275 _gnutls_free_datum (&password);
276 return ret;
280 #endif /* ENABLE_SRP */