*** empty log message ***
[gnutls.git] / lib / auth_srp_passwd.c
blob58f6d98770411a56bc58e4eb1a85084a9db43752
1 /*
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"
25 #ifdef ENABLE_SRP
27 #include "x509_b64.h"
28 #include "gnutls_errors.h"
29 #include "auth_srp_passwd.h"
30 #include "auth_srp.h"
31 #include "gnutls_auth_int.h"
32 #include "gnutls_srp.h"
33 #include "gnutls_random.h"
34 #include "gnutls_dh.h"
35 #include "debug.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) {
42 char * p, *p2;
43 int len;
44 opaque *verifier;
45 int verifier_size;
46 int indx;
48 p = rindex( str, ':'); /* we have index */
49 if (p==NULL) {
50 gnutls_assert();
51 return GNUTLS_E_PARSING_ERROR;
54 *p='\0';
55 p++;
57 len = strlen(p);
58 indx = atoi(p);
59 if (indx==0) {
60 gnutls_assert();
61 return GNUTLS_E_PARSING_ERROR;
64 /* now go for salt */
65 p = rindex( str, ':'); /* we have salt */
66 if (p==NULL) {
67 gnutls_assert();
68 return GNUTLS_E_PARSING_ERROR;
71 *p='\0';
72 p++;
74 len = strlen(p);
76 entry->salt_size = _gnutls_sbase64_decode( p, len, &entry->salt);
78 if (entry->salt_size <= 0) {
79 gnutls_assert();
80 return GNUTLS_E_PARSING_ERROR;
83 /* now go for verifier */
84 p = rindex( str, ':'); /* we have verifier */
85 if (p==NULL) {
86 gnutls_free(entry->salt);
87 return GNUTLS_E_PARSING_ERROR;
90 *p='\0';
91 p++;
93 if ( (p2 = index(p, '$')) == NULL) {
94 entry->algorithm = SRPSHA1_CRYPT;
95 } else {
96 p++;
97 entry->algorithm = atoi(p);
98 p2 = index(p, '$'); /* find the last $ */
99 if (p2==NULL) {
100 gnutls_assert();
101 gnutls_free(entry->salt);
102 return GNUTLS_E_PARSING_ERROR;
104 p = p2+1;
107 len = strlen(p);
108 verifier_size = _gnutls_sbase64_decode( p, len, &verifier);
109 if (verifier_size <= 0) {
110 gnutls_assert();
111 gnutls_free(entry->salt);
112 return GNUTLS_E_PARSING_ERROR;
115 if (_gnutls_mpi_scan(&entry->v, verifier, &verifier_size) || entry->v == NULL) {
116 gnutls_assert();
117 gnutls_free( entry->salt);
118 return GNUTLS_E_MPI_SCAN_FAILED;
121 gnutls_free( verifier);
123 /* now go for username */
124 *p='\0';
126 entry->username = gnutls_strdup(str);
127 if (entry->username==NULL) {
128 gnutls_free( entry->salt);
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 pwd_put_values2( GNUTLS_SRP_PWD_ENTRY *entry, char *str, int str_size) {
141 char * p;
142 int len;
143 opaque * tmp;
144 int tmp_size;
146 p = rindex( str, ':'); /* we have g */
147 if (p==NULL) {
148 gnutls_assert();
149 return GNUTLS_E_PARSING_ERROR;
152 *p='\0';
153 p++;
155 /* read the generator */
156 len = strlen(p);
157 if (p[len-1]=='\n' || p[len-1]==' ') len--;
158 tmp_size = _gnutls_sbase64_decode( p, len, &tmp);
160 if (tmp_size < 0) {
161 gnutls_assert();
162 return GNUTLS_E_PARSING_ERROR;
164 if (_gnutls_mpi_scan(&entry->g, tmp, &tmp_size) || entry->g==NULL) {
165 gnutls_assert();
166 gnutls_free(tmp);
167 return GNUTLS_E_MPI_SCAN_FAILED;
170 gnutls_free(tmp);
173 /* now go for n - modulo */
174 p = rindex( str, ':'); /* we have n */
175 if (p==NULL) {
176 _gnutls_mpi_release(&entry->g);
177 gnutls_assert();
178 return GNUTLS_E_PARSING_ERROR;
181 *p='\0';
182 p++;
184 len = strlen(p);
185 tmp_size = _gnutls_sbase64_decode( p, len, &tmp);
187 if (tmp_size < 0) {
188 gnutls_assert();
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) {
193 gnutls_assert();
194 gnutls_free(tmp);
195 _gnutls_mpi_release(&entry->g);
196 return GNUTLS_E_MPI_SCAN_FAILED;
199 gnutls_free(tmp);
201 return 0;
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) {
208 FILE * fd;
209 char line[2*1024];
210 int i;
211 char indexstr[10];
213 sprintf( indexstr, "%d", index); /* Flawfinder: ignore */
215 fd = fopen( pconf_file, "r");
216 if (fd==NULL) {
217 gnutls_assert();
218 return GNUTLS_E_FILE_ERROR;
221 while( fgets( line, sizeof(line), fd) != NULL) {
222 /* move to first ':' */
223 i=0;
224 while( (line[i]!=':') && (line[i]!='\0') && (i < sizeof(line)) ) {
225 i++;
227 if (strncmp( indexstr, line, strlen(indexstr)) == 0) {
228 if ((index = pwd_put_values2( entry, line, strlen(line))) >= 0)
229 return 0;
230 else {
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;
242 FILE * fd;
243 char line[2*1024];
244 int i, len;
245 GNUTLS_SRP_PWD_ENTRY * entry = gnutls_malloc(sizeof(GNUTLS_SRP_PWD_ENTRY));
246 int index;
247 int pwd_index = 0;
249 if (entry==NULL) {
250 gnutls_assert();
251 *err = 1;
252 return NULL;
255 *err = 0; /* normal exit */
257 cred = _gnutls_get_cred( state->gnutls_key, GNUTLS_CRD_SRP, NULL);
258 if (cred==NULL) {
259 *err = 1;
260 gnutls_assert();
261 gnutls_free(entry);
262 return NULL;
265 if (cred->password_files<=0) {
266 gnutls_assert();
267 return NULL;
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);
276 if (pwd_index < 0) {
277 gnutls_assert();
278 return NULL;
282 fd = fopen( cred->password_file[pwd_index], "r");
283 if (fd==NULL) {
284 *err = 1; /* failed due to critical error */
285 gnutls_assert();
286 gnutls_free(entry);
287 return NULL;
290 while( fgets( line, sizeof(line), fd) != NULL) {
291 /* move to first ':' */
292 i=0;
293 while( (line[i]!=':') && (line[i]!='\0') && (i < sizeof(line)) ) {
294 i++;
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) {
300 return entry;
301 } else {
302 gnutls_free(entry);
303 return NULL;
305 else {
306 gnutls_free(entry);
307 return NULL;
311 return NULL;
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) {
320 gnutls_assert();
321 return NULL;
324 pwd_entry->g = _gnutls_get_rnd_srp_params( &pwd_entry->n, 1024);
325 if (pwd_entry->g==NULL || pwd_entry->n==NULL) {
326 gnutls_assert();
327 _gnutls_srp_clear_pwd_entry( pwd_entry);
328 return NULL;
331 pwd_entry->username = gnutls_malloc(strlen(RNDUSER)+1);
332 if (pwd_entry->username == NULL) {
333 gnutls_assert();
334 _gnutls_srp_clear_pwd_entry( pwd_entry);
335 return NULL;
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) {
341 gnutls_assert();
342 _gnutls_srp_clear_pwd_entry( pwd_entry);
343 return NULL;
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) {
352 gnutls_assert();
353 _gnutls_srp_clear_pwd_entry( pwd_entry);
354 return NULL;
357 if (_gnutls_get_random(pwd_entry->salt, RND_SALT_SIZE, GNUTLS_WEAK_RANDOM) < 0) {
358 gnutls_assert();
359 _gnutls_srp_clear_pwd_entry( pwd_entry);
360 return NULL;
363 pwd_entry->algorithm = 0;
365 return pwd_entry;
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);
377 gnutls_free(entry);
379 return;
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)
387 MPI prime, g;
388 int siz;
389 char *tmp;
391 if ( _gnutls_dh_generate_prime(&g, &prime, bits) < 0) {
392 gnutls_assert();
393 return GNUTLS_E_MEMORY_ERROR;
396 siz = 0;
397 _gnutls_mpi_print( NULL, &siz, g);
398 if (ret_g != NULL) {
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) {
405 gnutls_free(tmp);
406 return GNUTLS_E_UNKNOWN_ERROR;
408 gnutls_free(tmp);
411 siz = 0;
412 _gnutls_mpi_print( NULL, &siz, prime);
413 if (ret_n != NULL) {
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) {
419 gnutls_free(tmp);
420 return GNUTLS_E_UNKNOWN_ERROR;
423 gnutls_free(tmp);
426 _gnutls_mpi_release(&g);
427 _gnutls_mpi_release(&prime);
429 return 0;
433 #endif /* ENABLE SRP */