Add psktool to @direntry. Alphasort @direntry.
[gnutls.git] / lib / auth_srp_passwd.c
blob8f098315d354afde92e2fa87b2ea4d0facab8f37
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 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_int.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 len = strlen (p);
69 indx = atoi (p);
70 if (indx == 0)
72 gnutls_assert ();
73 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
76 /* now go for salt */
77 p = strrchr (str, ':'); /* we have salt */
78 if (p == NULL)
80 gnutls_assert ();
81 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
84 *p = '\0';
85 p++;
87 len = strlen (p);
89 entry->salt.size = _gnutls_sbase64_decode (p, len, &entry->salt.data);
91 if (entry->salt.size <= 0)
93 gnutls_assert ();
94 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
97 /* now go for verifier */
98 p = strrchr (str, ':'); /* we have verifier */
99 if (p == NULL)
101 _gnutls_free_datum (&entry->salt);
102 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
105 *p = '\0';
106 p++;
108 len = strlen (p);
109 ret = _gnutls_sbase64_decode (p, len, &verifier);
110 if (ret <= 0)
112 gnutls_assert ();
113 _gnutls_free_datum (&entry->salt);
114 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
117 verifier_size = ret;
118 entry->v.data = verifier;
119 entry->v.size = verifier_size;
121 /* now go for username */
122 *p = '\0';
124 entry->username = gnutls_strdup (str);
125 if (entry->username == NULL)
127 _gnutls_free_datum (&entry->salt);
128 _gnutls_free_datum (&entry->v);
129 gnutls_assert ();
130 return GNUTLS_E_MEMORY_ERROR;
133 return indx;
137 /* this function parses tpasswd.conf file. Format is:
138 * int(index):base64(n):int(g)
140 static int
141 pwd_put_values2 (SRP_PWD_ENTRY * entry, char *str)
143 char *p;
144 int len;
145 opaque *tmp;
146 int ret;
148 p = strrchr (str, ':'); /* we have g */
149 if (p == NULL)
151 gnutls_assert ();
152 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
155 *p = '\0';
156 p++;
158 /* read the generator */
159 len = strlen (p);
160 if (p[len - 1] == '\n' || p[len - 1] == ' ')
161 len--;
162 ret = _gnutls_sbase64_decode (p, len, &tmp);
164 if (ret < 0)
166 gnutls_assert ();
167 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
170 entry->g.data = tmp;
171 entry->g.size = ret;
173 /* now go for n - modulo */
174 p = strrchr (str, ':'); /* we have n */
175 if (p == NULL)
177 _gnutls_free_datum (&entry->g);
178 gnutls_assert ();
179 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
182 *p = '\0';
183 p++;
185 len = strlen (p);
186 ret = _gnutls_sbase64_decode (p, len, &tmp);
188 if (ret < 0)
190 gnutls_assert ();
191 _gnutls_free_datum (&entry->g);
192 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
195 entry->n.data = tmp;
196 entry->n.size = ret;
198 return 0;
202 /* this function opens the tpasswd.conf file and reads the g and n
203 * values. They are put in the entry.
205 static int
206 pwd_read_conf (const char *pconf_file, SRP_PWD_ENTRY * entry, int idx)
208 FILE *fd;
209 char line[2 * 1024];
210 unsigned i, len;
211 char indexstr[10];
213 sprintf (indexstr, "%d", idx); /* Flawfinder: ignore */
215 fd = fopen (pconf_file, "r");
216 if (fd == NULL)
218 gnutls_assert ();
219 return GNUTLS_E_FILE_ERROR;
222 len = strlen (indexstr);
223 while (fgets (line, sizeof (line), fd) != NULL)
225 /* move to first ':' */
226 i = 0;
227 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
229 i++;
231 if (strncmp (indexstr, line, MAX (i, len)) == 0)
233 if ((idx = pwd_put_values2 (entry, line)) >= 0)
234 return 0;
235 else
237 return GNUTLS_E_SRP_PWD_ERROR;
241 return GNUTLS_E_SRP_PWD_ERROR;
246 _gnutls_srp_pwd_read_entry (gnutls_session_t state, char *username,
247 SRP_PWD_ENTRY ** _entry)
249 gnutls_srp_server_credentials_t cred;
250 FILE *fd;
251 char line[2 * 1024];
252 unsigned i, len;
253 int ret;
254 int idx, last_idx;
255 SRP_PWD_ENTRY *entry;
257 *_entry = gnutls_calloc (1, sizeof (SRP_PWD_ENTRY));
258 if (*_entry == NULL)
260 gnutls_assert ();
261 return GNUTLS_E_MEMORY_ERROR;
263 entry = *_entry;
265 cred = (gnutls_srp_server_credentials_t)
266 _gnutls_get_cred (state->key, GNUTLS_CRD_SRP, NULL);
267 if (cred == NULL)
269 gnutls_assert ();
270 _gnutls_srp_entry_free (entry);
271 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
274 /* if the callback which sends the parameters is
275 * set, use it.
277 if (cred->pwd_callback != NULL)
279 ret = cred->pwd_callback (state, username, &entry->salt,
280 &entry->v, &entry->g, &entry->n);
282 if (ret == 1)
283 { /* the user does not exist */
284 if (entry->g.size != 0 && entry->n.size != 0)
286 ret = _randomize_pwd_entry (entry);
287 if (ret < 0)
289 gnutls_assert();
290 _gnutls_srp_entry_free (entry);
291 return ret;
293 return 0;
295 else
297 gnutls_assert ();
298 ret = -1; /* error in the callback */
302 if (ret < 0)
304 gnutls_assert ();
305 _gnutls_srp_entry_free (entry);
306 return GNUTLS_E_SRP_PWD_ERROR;
309 return 0;
312 /* The callback was not set. Proceed.
315 if (cred->password_file == NULL)
317 gnutls_assert ();
318 return GNUTLS_E_SRP_PWD_ERROR;
321 /* Open the selected password file.
323 fd = fopen (cred->password_file, "r");
324 if (fd == NULL)
326 gnutls_assert ();
327 _gnutls_srp_entry_free (entry);
328 return GNUTLS_E_SRP_PWD_ERROR;
331 last_idx = 1; /* a default value */
333 len = strlen (username);
334 while (fgets (line, sizeof (line), fd) != NULL)
336 /* move to first ':' */
337 i = 0;
338 while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
340 i++;
343 if (strncmp (username, line, MAX (i, len)) == 0)
345 if ((idx = pwd_put_values (entry, line)) >= 0)
347 /* Keep the last index in memory, so we can retrieve fake parameters (g,n)
348 * when the user does not exist.
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 (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 (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 (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 */