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,
25 /* Functions for operating in an SRP passwd file are included here */
27 #include <gnutls_int.h>
32 #include "gnutls_errors.h"
33 #include <auth_srp_passwd.h>
35 #include "gnutls_auth_int.h"
36 #include "gnutls_srp.h"
37 #include "gnutls_dh.h"
39 #include <gnutls_str.h>
40 #include <gnutls_datum.h>
41 #include <gnutls_num.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)
50 pwd_put_values (SRP_PWD_ENTRY
* entry
, char *str
)
58 p
= strrchr (str
, ':'); /* we have index */
62 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
73 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
77 p
= strrchr (str
, ':'); /* we have salt */
81 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
89 entry
->salt
.size
= _gnutls_sbase64_decode (p
, len
, &entry
->salt
.data
);
91 if (entry
->salt
.size
<= 0)
94 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
97 /* now go for verifier */
98 p
= strrchr (str
, ':'); /* we have verifier */
101 _gnutls_free_datum (&entry
->salt
);
102 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
109 ret
= _gnutls_sbase64_decode (p
, len
, &verifier
);
113 _gnutls_free_datum (&entry
->salt
);
114 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
118 entry
->v
.data
= verifier
;
119 entry
->v
.size
= verifier_size
;
121 /* now go for username */
124 entry
->username
= gnutls_strdup (str
);
125 if (entry
->username
== NULL
)
127 _gnutls_free_datum (&entry
->salt
);
128 _gnutls_free_datum (&entry
->v
);
130 return GNUTLS_E_MEMORY_ERROR
;
137 /* this function parses tpasswd.conf file. Format is:
138 * int(index):base64(n):int(g)
141 pwd_put_values2 (SRP_PWD_ENTRY
* entry
, char *str
)
148 p
= strrchr (str
, ':'); /* we have g */
152 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
158 /* read the generator */
160 if (p
[len
- 1] == '\n' || p
[len
- 1] == ' ')
162 ret
= _gnutls_sbase64_decode (p
, len
, &tmp
);
167 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
173 /* now go for n - modulo */
174 p
= strrchr (str
, ':'); /* we have n */
177 _gnutls_free_datum (&entry
->g
);
179 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
186 ret
= _gnutls_sbase64_decode (p
, len
, &tmp
);
191 _gnutls_free_datum (&entry
->g
);
192 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
202 /* this function opens the tpasswd.conf file and reads the g and n
203 * values. They are put in the entry.
206 pwd_read_conf (const char *pconf_file
, SRP_PWD_ENTRY
* entry
, int idx
)
213 sprintf (indexstr
, "%d", idx
); /* Flawfinder: ignore */
215 fd
= fopen (pconf_file
, "r");
219 return GNUTLS_E_FILE_ERROR
;
222 len
= strlen (indexstr
);
223 while (fgets (line
, sizeof (line
), fd
) != NULL
)
225 /* move to first ':' */
227 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
231 if (strncmp (indexstr
, line
, MAX (i
, len
)) == 0)
233 if ((idx
= pwd_put_values2 (entry
, line
)) >= 0)
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
;
255 SRP_PWD_ENTRY
*entry
;
257 *_entry
= gnutls_calloc (1, sizeof (SRP_PWD_ENTRY
));
261 return GNUTLS_E_MEMORY_ERROR
;
265 cred
= (gnutls_srp_server_credentials_t
)
266 _gnutls_get_cred (state
->key
, GNUTLS_CRD_SRP
, NULL
);
270 _gnutls_srp_entry_free (entry
);
271 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
274 /* if the callback which sends the parameters is
277 if (cred
->pwd_callback
!= NULL
)
279 ret
= cred
->pwd_callback (state
, username
, &entry
->salt
,
280 &entry
->v
, &entry
->g
, &entry
->n
);
283 { /* the user does not exist */
284 if (entry
->g
.size
!= 0 && entry
->n
.size
!= 0)
286 ret
= _randomize_pwd_entry (entry
);
289 _gnutls_srp_entry_free (entry
);
297 ret
= -1; /* error in the callback */
304 _gnutls_srp_entry_free (entry
);
305 return GNUTLS_E_SRP_PWD_ERROR
;
311 /* The callback was not set. Proceed.
314 if (cred
->password_file
== NULL
)
317 return GNUTLS_E_SRP_PWD_ERROR
;
320 /* Open the selected password file.
322 fd
= fopen (cred
->password_file
, "r");
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 ':' */
337 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
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.
350 if (pwd_read_conf (cred
->password_conf_file
, entry
, idx
) == 0)
357 _gnutls_srp_entry_free (entry
);
358 return GNUTLS_E_SRP_PWD_ERROR
;
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
);
379 _gnutls_srp_entry_free (entry
);
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.
396 _randomize_pwd_entry (SRP_PWD_ENTRY
* entry
)
400 if (entry
->g
.size
== 0 || entry
->n
.size
== 0)
403 return GNUTLS_E_INTERNAL_ERROR
;
406 if (gc_nonce (&rnd
, 1) != GC_OK
)
409 return GNUTLS_E_RANDOM_FAILED
;
411 entry
->salt
.size
= (rnd
% 10) + 9;
413 entry
->v
.data
= gnutls_malloc (20);
415 if (entry
->v
.data
== NULL
)
418 return GNUTLS_E_MEMORY_ERROR
;
421 if (gc_nonce (entry
->v
.data
, 20) != GC_OK
)
424 return GNUTLS_E_RANDOM_FAILED
;
427 entry
->salt
.data
= gnutls_malloc (entry
->salt
.size
);
428 if (entry
->salt
.data
== NULL
)
431 return GNUTLS_E_MEMORY_ERROR
;
434 if (gc_nonce (entry
->salt
.data
, entry
->salt
.size
) != GC_OK
)
437 return GNUTLS_E_RANDOM_FAILED
;
443 /* Free all the entry parameters, except if g and n are
444 * the static ones defined in extra.h
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
);
465 #endif /* ENABLE SRP */