Fix.
[gnutls.git] / lib / auth_srp_passwd.c
blob6a1e986761703bb4ca304efa91d39d6395462dc9
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 /* Functions for operating in an SRP passwd file are included here */
27 #include <gnutls_int.h>
29 #ifdef ENABLE_SRP
31 #include "x509_b64.h"
32 #include "gnutls_errors.h"
33 #include <auth_srp_passwd.h>
34 #include "auth_srp.h"
35 #include "gnutls_auth.h"
36 #include "gnutls_srp.h"
37 #include "gnutls_dh.h"
38 #include "debug.h"
39 #include <gnutls_str.h>
40 #include <gnutls_datum.h>
41 #include <gnutls_num.h>
42 #include <random.h>
44 static int _randomize_pwd_entry (SRP_PWD_ENTRY * entry);
46 /* this function parses tpasswd.conf file. Format is:
47 * string(username):base64(v):base64(salt):int(index)
49 static int
50 pwd_put_values (SRP_PWD_ENTRY * entry, char *str)
52 char *p;
53 int len, ret;
54 opaque *verifier;
55 size_t verifier_size;
56 int indx;
58 p = strrchr (str, ':'); /* we have index */
59 if (p == NULL)
61 gnutls_assert ();
62 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
65 *p = '\0';
66 p++;
68 indx = atoi (p);
69 if (indx == 0)
71 gnutls_assert ();
72 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
75 /* now go for salt */
76 p = strrchr (str, ':'); /* we have salt */
77 if (p == NULL)
79 gnutls_assert ();
80 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
83 *p = '\0';
84 p++;
86 len = strlen (p);
88 entry->salt.size = _gnutls_sbase64_decode (p, len, &entry->salt.data);
90 if (entry->salt.size <= 0)
92 gnutls_assert ();
93 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
96 /* now go for verifier */
97 p = strrchr (str, ':'); /* we have verifier */
98 if (p == NULL)
100 _gnutls_free_datum (&entry->salt);
101 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
104 *p = '\0';
105 p++;
107 len = strlen (p);
108 ret = _gnutls_sbase64_decode (p, len, &verifier);
109 if (ret <= 0)
111 gnutls_assert ();
112 _gnutls_free_datum (&entry->salt);
113 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
116 verifier_size = ret;
117 entry->v.data = verifier;
118 entry->v.size = verifier_size;
120 /* now go for username */
121 *p = '\0';
123 entry->username = gnutls_strdup (str);
124 if (entry->username == NULL)
126 _gnutls_free_datum (&entry->salt);
127 _gnutls_free_datum (&entry->v);
128 gnutls_assert ();
129 return GNUTLS_E_MEMORY_ERROR;
132 return indx;
136 /* this function parses tpasswd.conf file. Format is:
137 * int(index):base64(n):int(g)
139 static int
140 pwd_put_values2 (SRP_PWD_ENTRY * entry, char *str)
142 char *p;
143 int len;
144 opaque *tmp;
145 int ret;
147 p = strrchr (str, ':'); /* we have g */
148 if (p == NULL)
150 gnutls_assert ();
151 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
154 *p = '\0';
155 p++;
157 /* read the generator */
158 len = strlen (p);
159 if (p[len - 1] == '\n' || p[len - 1] == ' ')
160 len--;
161 ret = _gnutls_sbase64_decode (p, len, &tmp);
163 if (ret < 0)
165 gnutls_assert ();
166 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
169 entry->g.data = tmp;
170 entry->g.size = ret;
172 /* now go for n - modulo */
173 p = strrchr (str, ':'); /* we have n */
174 if (p == NULL)
176 _gnutls_free_datum (&entry->g);
177 gnutls_assert ();
178 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
181 *p = '\0';
182 p++;
184 len = strlen (p);
185 ret = _gnutls_sbase64_decode (p, len, &tmp);
187 if (ret < 0)
189 gnutls_assert ();
190 _gnutls_free_datum (&entry->g);
191 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
194 entry->n.data = tmp;
195 entry->n.size = ret;
197 return 0;
201 /* this function opens the tpasswd.conf file and reads the g and n
202 * values. They are put in the entry.
204 static int
205 pwd_read_conf (const char *pconf_file, SRP_PWD_ENTRY * entry, int idx)
207 FILE *fd;
208 char line[2 * 1024];
209 unsigned i, len;
210 char indexstr[10];
212 sprintf (indexstr, "%d", idx); /* Flawfinder: ignore */
214 fd = fopen (pconf_file, "r");
215 if (fd == NULL)
217 gnutls_assert ();
218 return GNUTLS_E_FILE_ERROR;
221 len = strlen (indexstr);
222 while (fgets (line, sizeof (line), fd) != NULL)
224 /* move to first ':' */
225 i = 0;
226 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
228 i++;
230 if (strncmp (indexstr, line, MAX (i, len)) == 0)
232 if ((idx = pwd_put_values2 (entry, line)) >= 0)
233 return 0;
234 else
236 return GNUTLS_E_SRP_PWD_ERROR;
240 return GNUTLS_E_SRP_PWD_ERROR;
245 _gnutls_srp_pwd_read_entry (gnutls_session_t state, char *username,
246 SRP_PWD_ENTRY ** _entry)
248 gnutls_srp_server_credentials_t cred;
249 FILE *fd;
250 char line[2 * 1024];
251 unsigned i, len;
252 int ret;
253 int idx, last_idx;
254 SRP_PWD_ENTRY *entry;
256 *_entry = gnutls_calloc (1, sizeof (SRP_PWD_ENTRY));
257 if (*_entry == NULL)
259 gnutls_assert ();
260 return GNUTLS_E_MEMORY_ERROR;
262 entry = *_entry;
264 cred = (gnutls_srp_server_credentials_t)
265 _gnutls_get_cred (state->key, GNUTLS_CRD_SRP, NULL);
266 if (cred == NULL)
268 gnutls_assert ();
269 _gnutls_srp_entry_free (entry);
270 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
273 /* if the callback which sends the parameters is
274 * set, use it.
276 if (cred->pwd_callback != NULL)
278 ret = cred->pwd_callback (state, username, &entry->salt,
279 &entry->v, &entry->g, &entry->n);
281 if (ret == 1)
282 { /* the user does not exist */
283 if (entry->g.size != 0 && entry->n.size != 0)
285 ret = _randomize_pwd_entry (entry);
286 if (ret < 0)
288 gnutls_assert ();
289 _gnutls_srp_entry_free (entry);
290 return ret;
292 return 0;
294 else
296 gnutls_assert ();
297 ret = -1; /* error in the callback */
301 if (ret < 0)
303 gnutls_assert ();
304 _gnutls_srp_entry_free (entry);
305 return GNUTLS_E_SRP_PWD_ERROR;
308 return 0;
311 /* The callback was not set. Proceed.
314 if (cred->password_file == NULL)
316 gnutls_assert ();
317 return GNUTLS_E_SRP_PWD_ERROR;
320 /* Open the selected password file.
322 fd = fopen (cred->password_file, "r");
323 if (fd == NULL)
325 gnutls_assert ();
326 _gnutls_srp_entry_free (entry);
327 return GNUTLS_E_SRP_PWD_ERROR;
330 last_idx = 1; /* a default value */
332 len = strlen (username);
333 while (fgets (line, sizeof (line), fd) != NULL)
335 /* move to first ':' */
336 i = 0;
337 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
339 i++;
342 if (strncmp (username, line, MAX (i, len)) == 0)
344 if ((idx = pwd_put_values (entry, line)) >= 0)
346 /* Keep the last index in memory, so we can retrieve fake parameters (g,n)
347 * when the user does not exist.
349 /* XXX: last_idx will not be read as both if block branches return. */
350 last_idx = idx;
351 if (pwd_read_conf (cred->password_conf_file, entry, idx) == 0)
353 return 0;
355 else
357 gnutls_assert ();
358 _gnutls_srp_entry_free (entry);
359 return GNUTLS_E_SRP_PWD_ERROR;
362 else
364 gnutls_assert ();
365 _gnutls_srp_entry_free (entry);
366 return GNUTLS_E_SRP_PWD_ERROR;
371 /* user was not found. Fake him. Actually read the g,n values from
372 * the last index found and randomize the entry.
374 if (pwd_read_conf (cred->password_conf_file, entry, last_idx) == 0)
376 ret = _randomize_pwd_entry (entry);
377 if (ret < 0)
379 gnutls_assert ();
380 _gnutls_srp_entry_free (entry);
381 return ret;
384 return 0;
387 gnutls_assert ();
388 _gnutls_srp_entry_free (entry);
389 return GNUTLS_E_SRP_PWD_ERROR;
393 /* Randomizes the given password entry. It actually sets the verifier
394 * and the salt. Returns 0 on success.
396 static int
397 _randomize_pwd_entry (SRP_PWD_ENTRY * entry)
399 unsigned char rnd;
400 int ret;
402 if (entry->g.size == 0 || entry->n.size == 0)
404 gnutls_assert ();
405 return GNUTLS_E_INTERNAL_ERROR;
408 ret = _gnutls_rnd (GNUTLS_RND_NONCE, &rnd, 1);
409 if (ret < 0)
411 gnutls_assert ();
412 return ret;
415 entry->salt.size = (rnd % 10) + 9;
417 entry->v.data = gnutls_malloc (20);
418 entry->v.size = 20;
419 if (entry->v.data == NULL)
421 gnutls_assert ();
422 return GNUTLS_E_MEMORY_ERROR;
425 ret = _gnutls_rnd (GNUTLS_RND_RANDOM, entry->v.data, 20);
426 if (ret < 0)
428 gnutls_assert ();
429 return ret;
432 entry->salt.data = gnutls_malloc (entry->salt.size);
433 if (entry->salt.data == NULL)
435 gnutls_assert ();
436 return GNUTLS_E_MEMORY_ERROR;
439 ret = _gnutls_rnd (GNUTLS_RND_NONCE, entry->salt.data, entry->salt.size);
440 if (ret < 0)
442 gnutls_assert ();
443 return ret;
446 return 0;
449 /* Free all the entry parameters, except if g and n are
450 * the static ones defined in extra.h
452 void
453 _gnutls_srp_entry_free (SRP_PWD_ENTRY * entry)
455 _gnutls_free_datum (&entry->v);
456 _gnutls_free_datum (&entry->salt);
458 if (entry->g.data != gnutls_srp_1024_group_generator.data)
459 _gnutls_free_datum (&entry->g);
461 if (entry->n.data != gnutls_srp_1024_group_prime.data &&
462 entry->n.data != gnutls_srp_1536_group_prime.data &&
463 entry->n.data != gnutls_srp_2048_group_prime.data)
464 _gnutls_free_datum (&entry->n);
466 gnutls_free (entry->username);
467 gnutls_free (entry);
471 #endif /* ENABLE SRP */