2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free Software
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,
26 /* Functions for operating in an SRP passwd file are included here */
28 #include <gnutls_int.h>
33 #include "gnutls_errors.h"
34 #include <auth_srp_passwd.h>
36 #include "gnutls_auth.h"
37 #include "gnutls_srp.h"
38 #include "gnutls_dh.h"
40 #include <gnutls_str.h>
41 #include <gnutls_datum.h>
42 #include <gnutls_num.h>
45 static int _randomize_pwd_entry (SRP_PWD_ENTRY
* entry
);
47 /* this function parses tpasswd.conf file. Format is:
48 * string(username):base64(v):base64(salt):int(index)
51 pwd_put_values (SRP_PWD_ENTRY
* entry
, char *str
)
59 p
= strrchr (str
, ':'); /* we have index */
63 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
)
214 snprintf (indexstr
, sizeof(indexstr
), "%u", (unsigned int)idx
);
216 fd
= fopen (pconf_file
, "r");
220 return GNUTLS_E_FILE_ERROR
;
223 len
= strlen (indexstr
);
224 while (fgets (line
, sizeof (line
), fd
) != NULL
)
226 /* move to first ':' */
228 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
232 if (strncmp (indexstr
, line
, MAX (i
, len
)) == 0)
234 if ((idx
= pwd_put_values2 (entry
, line
)) >= 0)
241 ret
= GNUTLS_E_SRP_PWD_ERROR
;
246 ret
= GNUTLS_E_SRP_PWD_ERROR
;
255 _gnutls_srp_pwd_read_entry (gnutls_session_t state
, char *username
,
256 SRP_PWD_ENTRY
** _entry
)
258 gnutls_srp_server_credentials_t cred
;
264 SRP_PWD_ENTRY
*entry
= NULL
;
266 *_entry
= gnutls_calloc (1, sizeof (SRP_PWD_ENTRY
));
270 return GNUTLS_E_MEMORY_ERROR
;
274 cred
= (gnutls_srp_server_credentials_t
)
275 _gnutls_get_cred (state
->key
, GNUTLS_CRD_SRP
, NULL
);
279 ret
= GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
283 /* if the callback which sends the parameters is
286 if (cred
->pwd_callback
!= NULL
)
288 ret
= cred
->pwd_callback (state
, username
, &entry
->salt
,
289 &entry
->v
, &entry
->g
, &entry
->n
);
292 { /* the user does not exist */
293 if (entry
->g
.size
!= 0 && entry
->n
.size
!= 0)
295 ret
= _randomize_pwd_entry (entry
);
306 ret
= -1; /* error in the callback */
313 ret
= GNUTLS_E_SRP_PWD_ERROR
;
320 /* The callback was not set. Proceed.
323 if (cred
->password_file
== NULL
)
326 ret
= GNUTLS_E_SRP_PWD_ERROR
;
330 /* Open the selected password file.
332 fd
= fopen (cred
->password_file
, "r");
336 ret
= GNUTLS_E_SRP_PWD_ERROR
;
340 last_idx
= 1; /* a default value */
342 len
= strlen (username
);
343 while (fgets (line
, sizeof (line
), fd
) != NULL
)
345 /* move to first ':' */
347 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
352 if (strncmp (username
, line
, MAX (i
, len
)) == 0)
354 if ((idx
= pwd_put_values (entry
, line
)) >= 0)
356 /* Keep the last index in memory, so we can retrieve fake parameters (g,n)
357 * when the user does not exist.
359 /* XXX: last_idx will not be read as both if block branches return. */
361 if (pwd_read_conf (cred
->password_conf_file
, entry
, idx
) == 0)
368 ret
= GNUTLS_E_SRP_PWD_ERROR
;
375 ret
= GNUTLS_E_SRP_PWD_ERROR
;
381 /* user was not found. Fake him. Actually read the g,n values from
382 * the last index found and randomize the entry.
384 if (pwd_read_conf (cred
->password_conf_file
, entry
, last_idx
) == 0)
386 ret
= _randomize_pwd_entry (entry
);
399 _gnutls_srp_entry_free (entry
);
400 return GNUTLS_E_SRP_PWD_ERROR
;
407 /* Randomizes the given password entry. It actually sets the verifier
408 * and the salt. Returns 0 on success.
411 _randomize_pwd_entry (SRP_PWD_ENTRY
* entry
)
416 if (entry
->g
.size
== 0 || entry
->n
.size
== 0)
419 return GNUTLS_E_INTERNAL_ERROR
;
422 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, &rnd
, 1);
429 entry
->salt
.size
= (rnd
% 10) + 9;
431 entry
->v
.data
= gnutls_malloc (20);
433 if (entry
->v
.data
== NULL
)
436 return GNUTLS_E_MEMORY_ERROR
;
439 ret
= _gnutls_rnd (GNUTLS_RND_RANDOM
, entry
->v
.data
, 20);
446 entry
->salt
.data
= gnutls_malloc (entry
->salt
.size
);
447 if (entry
->salt
.data
== NULL
)
450 return GNUTLS_E_MEMORY_ERROR
;
453 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, entry
->salt
.data
, entry
->salt
.size
);
463 /* Free all the entry parameters, except if g and n are
464 * the static ones defined in extra.h
467 _gnutls_srp_entry_free (SRP_PWD_ENTRY
* entry
)
469 _gnutls_free_datum (&entry
->v
);
470 _gnutls_free_datum (&entry
->salt
);
472 if (entry
->g
.data
!= gnutls_srp_1024_group_generator
.data
)
473 _gnutls_free_datum (&entry
->g
);
475 if (entry
->n
.data
!= gnutls_srp_1024_group_prime
.data
&&
476 entry
->n
.data
!= gnutls_srp_1536_group_prime
.data
&&
477 entry
->n
.data
!= gnutls_srp_2048_group_prime
.data
)
478 _gnutls_free_datum (&entry
->n
);
480 gnutls_free (entry
->username
);
485 #endif /* ENABLE SRP */