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,
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
);
290 _gnutls_srp_entry_free (entry
);
298 ret
= -1; /* error in the callback */
305 _gnutls_srp_entry_free (entry
);
306 return GNUTLS_E_SRP_PWD_ERROR
;
312 /* The callback was not set. Proceed.
315 if (cred
->password_file
== NULL
)
318 return GNUTLS_E_SRP_PWD_ERROR
;
321 /* Open the selected password file.
323 fd
= fopen (cred
->password_file
, "r");
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 ':' */
338 while ((line
[i
] != ':') && (line
[i
] != '\0') && (i
< sizeof (line
)))
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.
351 if (pwd_read_conf (cred
->password_conf_file
, entry
, idx
) == 0)
358 _gnutls_srp_entry_free (entry
);
359 return GNUTLS_E_SRP_PWD_ERROR
;
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
);
380 _gnutls_srp_entry_free (entry
);
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.
397 _randomize_pwd_entry (SRP_PWD_ENTRY
* entry
)
402 if (entry
->g
.size
== 0 || entry
->n
.size
== 0)
405 return GNUTLS_E_INTERNAL_ERROR
;
408 ret
= _gnutls_rnd (RND_NONCE
, &rnd
, 1);
415 entry
->salt
.size
= (rnd
% 10) + 9;
417 entry
->v
.data
= gnutls_malloc (20);
419 if (entry
->v
.data
== NULL
)
422 return GNUTLS_E_MEMORY_ERROR
;
425 ret
= _gnutls_rnd (RND_RANDOM
, entry
->v
.data
, 20);
432 entry
->salt
.data
= gnutls_malloc (entry
->salt
.size
);
433 if (entry
->salt
.data
== NULL
)
436 return GNUTLS_E_MEMORY_ERROR
;
439 ret
= _gnutls_rnd (RND_NONCE
, entry
->salt
.data
, entry
->salt
.size
);
449 /* Free all the entry parameters, except if g and n are
450 * the static ones defined in extra.h
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
);
471 #endif /* ENABLE SRP */