Guile: Fix `x509-certificate-dn-oid' and related functions.
[gnutls.git] / lib / auth_srp_passwd.c
blob0f8fc552ac7310a819127cee7dc04a86c8ece53e
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
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 <gc.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_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 last_idx = idx;
350 if (pwd_read_conf (cred->password_conf_file, entry, idx) == 0)
352 return 0;
354 else
356 gnutls_assert ();
357 _gnutls_srp_entry_free (entry);
358 return GNUTLS_E_SRP_PWD_ERROR;
361 else
363 gnutls_assert ();
364 _gnutls_srp_entry_free (entry);
365 return GNUTLS_E_SRP_PWD_ERROR;
370 /* user was not found. Fake him. Actually read the g,n values from
371 * the last index found and randomize the entry.
373 if (pwd_read_conf (cred->password_conf_file, entry, last_idx) == 0)
375 ret = _randomize_pwd_entry (entry);
376 if (ret < 0)
378 gnutls_assert ();
379 _gnutls_srp_entry_free (entry);
380 return ret;
383 return 0;
386 gnutls_assert ();
387 _gnutls_srp_entry_free (entry);
388 return GNUTLS_E_SRP_PWD_ERROR;
392 /* Randomizes the given password entry. It actually sets the verifier
393 * and the salt. Returns 0 on success.
395 static int
396 _randomize_pwd_entry (SRP_PWD_ENTRY * entry)
398 unsigned char rnd;
400 if (entry->g.size == 0 || entry->n.size == 0)
402 gnutls_assert ();
403 return GNUTLS_E_INTERNAL_ERROR;
406 if (gc_nonce (&rnd, 1) != GC_OK)
408 gnutls_assert ();
409 return GNUTLS_E_RANDOM_FAILED;
411 entry->salt.size = (rnd % 10) + 9;
413 entry->v.data = gnutls_malloc (20);
414 entry->v.size = 20;
415 if (entry->v.data == NULL)
417 gnutls_assert ();
418 return GNUTLS_E_MEMORY_ERROR;
421 if (gc_nonce (entry->v.data, 20) != GC_OK)
423 gnutls_assert ();
424 return GNUTLS_E_RANDOM_FAILED;
427 entry->salt.data = gnutls_malloc (entry->salt.size);
428 if (entry->salt.data == NULL)
430 gnutls_assert ();
431 return GNUTLS_E_MEMORY_ERROR;
434 if (gc_nonce (entry->salt.data, entry->salt.size) != GC_OK)
436 gnutls_assert ();
437 return GNUTLS_E_RANDOM_FAILED;
440 return 0;
443 /* Free all the entry parameters, except if g and n are
444 * the static ones defined in extra.h
446 void
447 _gnutls_srp_entry_free (SRP_PWD_ENTRY * entry)
449 _gnutls_free_datum (&entry->v);
450 _gnutls_free_datum (&entry->salt);
452 if (entry->g.data != gnutls_srp_1024_group_generator.data)
453 _gnutls_free_datum (&entry->g);
455 if (entry->n.data != gnutls_srp_1024_group_prime.data &&
456 entry->n.data != gnutls_srp_1536_group_prime.data &&
457 entry->n.data != gnutls_srp_2048_group_prime.data)
458 _gnutls_free_datum (&entry->n);
460 gnutls_free (entry->username);
461 gnutls_free (entry);
465 #endif /* ENABLE SRP */