2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 /* Functions for operating in an SRP passwd file are included here */
23 #include "gnutls_int.h"
28 #include "gnutls_errors.h"
29 #include "auth_srp_passwd.h"
31 #include "gnutls_auth_int.h"
32 #include "gnutls_srp.h"
33 #include "gnutls_random.h"
34 #include "gnutls_dh.h"
36 #include <gnutls_str.h>
38 /* this function parses tpasswd.conf file. Format is:
39 * string(username):base64(v):base64(salt):int(index)
41 static int pwd_put_values( GNUTLS_SRP_PWD_ENTRY
*entry
, char *str
, int str_size
) {
48 p
= rindex( str
, ':'); /* we have index */
51 return GNUTLS_E_PARSING_ERROR
;
61 return GNUTLS_E_PARSING_ERROR
;
65 p
= rindex( str
, ':'); /* we have salt */
68 return GNUTLS_E_PARSING_ERROR
;
76 entry
->salt_size
= _gnutls_sbase64_decode( p
, len
, &entry
->salt
);
78 if (entry
->salt_size
<= 0) {
80 return GNUTLS_E_PARSING_ERROR
;
83 /* now go for verifier */
84 p
= rindex( str
, ':'); /* we have verifier */
86 gnutls_free(entry
->salt
);
87 return GNUTLS_E_PARSING_ERROR
;
93 if ( (p2
= index(p
, '$')) == NULL
) {
94 entry
->algorithm
= SRPSHA1_CRYPT
;
97 entry
->algorithm
= atoi(p
);
98 p2
= index(p
, '$'); /* find the last $ */
101 gnutls_free(entry
->salt
);
102 return GNUTLS_E_PARSING_ERROR
;
108 verifier_size
= _gnutls_sbase64_decode( p
, len
, &verifier
);
109 if (verifier_size
<= 0) {
111 gnutls_free(entry
->salt
);
112 return GNUTLS_E_PARSING_ERROR
;
115 if (_gnutls_mpi_scan(&entry
->v
, verifier
, &verifier_size
) || entry
->v
== NULL
) {
117 gnutls_free( entry
->salt
);
118 return GNUTLS_E_MPI_SCAN_FAILED
;
121 gnutls_free( verifier
);
123 /* now go for username */
126 entry
->username
= gnutls_strdup(str
);
127 if (entry
->username
==NULL
) {
128 gnutls_free( entry
->salt
);
130 return GNUTLS_E_MEMORY_ERROR
;
137 /* this function parses tpasswd.conf file. Format is:
138 * int(index):base64(n):int(g)
140 static int pwd_put_values2( GNUTLS_SRP_PWD_ENTRY
*entry
, char *str
, int str_size
) {
146 p
= rindex( str
, ':'); /* we have g */
149 return GNUTLS_E_PARSING_ERROR
;
155 /* read the generator */
157 if (p
[len
-1]=='\n' || p
[len
-1]==' ') len
--;
158 tmp_size
= _gnutls_sbase64_decode( p
, len
, &tmp
);
162 return GNUTLS_E_PARSING_ERROR
;
164 if (_gnutls_mpi_scan(&entry
->g
, tmp
, &tmp_size
) || entry
->g
==NULL
) {
167 return GNUTLS_E_MPI_SCAN_FAILED
;
173 /* now go for n - modulo */
174 p
= rindex( str
, ':'); /* we have n */
176 _gnutls_mpi_release(&entry
->g
);
178 return GNUTLS_E_PARSING_ERROR
;
185 tmp_size
= _gnutls_sbase64_decode( p
, len
, &tmp
);
189 _gnutls_mpi_release(&entry
->g
);
190 return GNUTLS_E_PARSING_ERROR
;
192 if (_gnutls_mpi_scan(&entry
->n
, tmp
, &tmp_size
) || entry
->n
==NULL
) {
195 _gnutls_mpi_release(&entry
->g
);
196 return GNUTLS_E_MPI_SCAN_FAILED
;
205 /* this function opens the tpasswd.conf file
207 static int pwd_read_conf( const char* pconf_file
, GNUTLS_SRP_PWD_ENTRY
* entry
, int index
) {
213 sprintf( indexstr
, "%d", index
); /* Flawfinder: ignore */
215 fd
= fopen( pconf_file
, "r");
218 return GNUTLS_E_FILE_ERROR
;
221 while( fgets( line
, sizeof(line
), fd
) != NULL
) {
222 /* move to first ':' */
224 while( (line
[i
]!=':') && (line
[i
]!='\0') && (i
< sizeof(line
)) ) {
227 if (strncmp( indexstr
, line
, strlen(indexstr
)) == 0) {
228 if ((index
= pwd_put_values2( entry
, line
, strlen(line
))) >= 0)
231 return GNUTLS_E_PWD_ERROR
;
235 return GNUTLS_E_PWD_ERROR
;
240 GNUTLS_SRP_PWD_ENTRY
*_gnutls_srp_pwd_read_entry( GNUTLS_STATE state
, char* username
, int *err
) {
241 const GNUTLS_SRP_SERVER_CREDENTIALS cred
;
245 GNUTLS_SRP_PWD_ENTRY
* entry
= gnutls_malloc(sizeof(GNUTLS_SRP_PWD_ENTRY
));
255 *err
= 0; /* normal exit */
257 cred
= _gnutls_get_cred( state
->gnutls_key
, GNUTLS_CRD_SRP
, NULL
);
265 if (cred
->password_files
<=0) {
270 /* use the callback to select a password file */
271 if (state
->gnutls_internals
.server_srp_callback
!=NULL
) {
272 pwd_index
= state
->gnutls_internals
.server_srp_callback(
273 state
, cred
->password_file
, cred
->password_conf_file
,
274 cred
->password_files
);
282 fd
= fopen( cred
->password_file
[pwd_index
], "r");
284 *err
= 1; /* failed due to critical error */
290 while( fgets( line
, sizeof(line
), fd
) != NULL
) {
291 /* move to first ':' */
293 while( (line
[i
]!=':') && (line
[i
]!='\0') && (i
< sizeof(line
)) ) {
296 len
= strlen(username
);
297 if (strncmp( username
, line
, (i
>len
)?i
:len
) == 0) {
298 if ((index
= pwd_put_values( entry
, line
, strlen(line
))) >= 0)
299 if (pwd_read_conf( cred
->password_conf_file
[pwd_index
], entry
, index
)==0) {
314 #define RNDUSER "rnd"
315 #define RND_SALT_SIZE 17
316 GNUTLS_SRP_PWD_ENTRY
* _gnutls_randomize_pwd_entry() {
317 GNUTLS_SRP_PWD_ENTRY
* pwd_entry
= gnutls_calloc(1, sizeof(GNUTLS_SRP_PWD_ENTRY
));
319 if (pwd_entry
== NULL
) {
324 pwd_entry
->g
= _gnutls_get_rnd_srp_params( &pwd_entry
->n
, 1024);
325 if (pwd_entry
->g
==NULL
|| pwd_entry
->n
==NULL
) {
327 _gnutls_srp_clear_pwd_entry( pwd_entry
);
331 pwd_entry
->username
= gnutls_malloc(strlen(RNDUSER
)+1);
332 if (pwd_entry
->username
== NULL
) {
334 _gnutls_srp_clear_pwd_entry( pwd_entry
);
337 _gnutls_str_cpy( pwd_entry
->username
, MAX_SRP_USERNAME
, RNDUSER
); /* Flawfinder: ignore */
339 pwd_entry
->v
= _gnutls_mpi_new(160);
340 if (pwd_entry
->v
==NULL
) {
342 _gnutls_srp_clear_pwd_entry( pwd_entry
);
346 gcry_mpi_randomize( pwd_entry
->v
, 160, GCRY_WEAK_RANDOM
);
348 pwd_entry
->salt_size
= RND_SALT_SIZE
;
350 pwd_entry
->salt
= gnutls_malloc(RND_SALT_SIZE
);
351 if (pwd_entry
->salt
==NULL
) {
353 _gnutls_srp_clear_pwd_entry( pwd_entry
);
357 if (_gnutls_get_random(pwd_entry
->salt
, RND_SALT_SIZE
, GNUTLS_WEAK_RANDOM
) < 0) {
359 _gnutls_srp_clear_pwd_entry( pwd_entry
);
363 pwd_entry
->algorithm
= 0;
369 void _gnutls_srp_clear_pwd_entry( GNUTLS_SRP_PWD_ENTRY
* entry
) {
370 _gnutls_mpi_release(&entry
->v
);
371 _gnutls_mpi_release(&entry
->g
);
372 _gnutls_mpi_release(&entry
->n
);
374 gnutls_free(entry
->salt
);
375 gnutls_free(entry
->username
);
382 /* Generates a prime and a generator, and returns the srpbase64 encoded value.
384 int _gnutls_srp_generate_prime(opaque
** ret_g
, opaque
** ret_n
, int bits
)
391 if ( _gnutls_dh_generate_prime(&g
, &prime
, bits
) < 0) {
393 return GNUTLS_E_MEMORY_ERROR
;
397 _gnutls_mpi_print( NULL
, &siz
, g
);
399 tmp
= gnutls_malloc(siz
);
400 if (tmp
==NULL
) return GNUTLS_E_MEMORY_ERROR
;
402 _gnutls_mpi_print( tmp
, &siz
, g
);
404 if (_gnutls_sbase64_encode(tmp
, siz
, ret_g
) < 0) {
406 return GNUTLS_E_UNKNOWN_ERROR
;
412 _gnutls_mpi_print( NULL
, &siz
, prime
);
414 tmp
= gnutls_malloc(siz
);
415 if (tmp
==NULL
) return GNUTLS_E_MEMORY_ERROR
;
417 _gnutls_mpi_print( tmp
, &siz
, prime
);
418 if (_gnutls_sbase64_encode(tmp
, siz
, ret_n
) < 0) {
420 return GNUTLS_E_UNKNOWN_ERROR
;
426 _gnutls_mpi_release(&g
);
427 _gnutls_mpi_release(&prime
);
433 #endif /* ENABLE SRP */