Home | History | Annotate | Download | only in apps
      1 /* apps/srp.c */
      2 /* Written by Peter Sylvester (peter.sylvester (at) edelweb.fr)
      3  * for the EdelKey project and contributed to the OpenSSL project 2004.
      4  */
      5 /* ====================================================================
      6  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. All advertising materials mentioning features or use of this
     21  *    software must display the following acknowledgment:
     22  *    "This product includes software developed by the OpenSSL Project
     23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     24  *
     25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     26  *    endorse or promote products derived from this software without
     27  *    prior written permission. For written permission, please contact
     28  *    licensing (at) OpenSSL.org.
     29  *
     30  * 5. Products derived from this software may not be called "OpenSSL"
     31  *    nor may "OpenSSL" appear in their names without prior written
     32  *    permission of the OpenSSL Project.
     33  *
     34  * 6. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by the OpenSSL Project
     37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     38  *
     39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     50  * OF THE POSSIBILITY OF SUCH DAMAGE.
     51  * ====================================================================
     52  *
     53  * This product includes cryptographic software written by Eric Young
     54  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 #include <openssl/opensslconf.h>
     59 
     60 #ifndef OPENSSL_NO_SRP
     61 #include <stdio.h>
     62 #include <stdlib.h>
     63 #include <string.h>
     64 #include <openssl/conf.h>
     65 #include <openssl/bio.h>
     66 #include <openssl/err.h>
     67 #include <openssl/txt_db.h>
     68 #include <openssl/buffer.h>
     69 #include <openssl/srp.h>
     70 
     71 #include "apps.h"
     72 
     73 #undef PROG
     74 #define PROG srp_main
     75 
     76 #define BASE_SECTION	"srp"
     77 #define CONFIG_FILE "openssl.cnf"
     78 
     79 #define ENV_RANDFILE		"RANDFILE"
     80 
     81 #define ENV_DATABASE		"srpvfile"
     82 #define ENV_DEFAULT_SRP		"default_srp"
     83 
     84 static char *srp_usage[]={
     85 "usage: srp [args] [user] \n",
     86 "\n",
     87 " -verbose        Talk alot while doing things\n",
     88 " -config file    A config file\n",
     89 " -name arg       The particular srp definition to use\n",
     90 " -srpvfile arg   The srp verifier file name\n",
     91 " -add            add an user and srp verifier\n",
     92 " -modify         modify the srp verifier of an existing user\n",
     93 " -delete         delete user from verifier file\n",
     94 " -list           list user\n",
     95 " -gn arg         g and N values to be used for new verifier\n",
     96 " -userinfo arg   additional info to be set for user\n",
     97 " -passin arg     input file pass phrase source\n",
     98 " -passout arg    output file pass phrase source\n",
     99 #ifndef OPENSSL_NO_ENGINE
    100 " -engine e         - use engine e, possibly a hardware device.\n",
    101 #endif
    102 NULL
    103 };
    104 
    105 #ifdef EFENCE
    106 extern int EF_PROTECT_FREE;
    107 extern int EF_PROTECT_BELOW;
    108 extern int EF_ALIGNMENT;
    109 #endif
    110 
    111 static CONF *conf=NULL;
    112 static char *section=NULL;
    113 
    114 #define VERBOSE if (verbose)
    115 #define VVERBOSE if (verbose>1)
    116 
    117 
    118 int MAIN(int, char **);
    119 
    120 static int get_index(CA_DB *db, char* id, char type)
    121 	{
    122 	char ** pp;
    123 	int i;
    124 	if (id == NULL) return -1;
    125 	if (type == DB_SRP_INDEX)
    126 	for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    127 		{
    128 		pp = sk_OPENSSL_PSTRING_value(db->db->data,i);
    129 		if (pp[DB_srptype][0] == DB_SRP_INDEX  && !strcmp(id,pp[DB_srpid]))
    130 			return i;
    131 		}
    132 	else for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    133 		{
    134 		pp = sk_OPENSSL_PSTRING_value(db->db->data,i);
    135 
    136 		if (pp[DB_srptype][0] != DB_SRP_INDEX && !strcmp(id,pp[DB_srpid]))
    137 			return i;
    138 		}
    139 
    140 	return -1 ;
    141 	}
    142 
    143 static void print_entry(CA_DB *db, BIO *bio, int indx, int verbose, char *s)
    144 	{
    145 	if (indx >= 0 && verbose)
    146 		{
    147 		int j;
    148 		char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx);
    149 		BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]);
    150 		for (j = 0; j < DB_NUMBER; j++)
    151 			{
    152 			BIO_printf(bio_err,"  %d = \"%s\"\n", j, pp[j]);
    153 			}
    154 		}
    155 	}
    156 
    157 static void print_index(CA_DB *db, BIO *bio, int indexindex, int verbose)
    158 	{
    159 	print_entry(db, bio, indexindex, verbose, "g N entry") ;
    160 	}
    161 
    162 static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose)
    163 	{
    164 	if (verbose > 0)
    165 		{
    166 		char **pp = sk_OPENSSL_PSTRING_value(db->db->data,userindex);
    167 
    168 		if (pp[DB_srptype][0] != 'I')
    169 			{
    170 			print_entry(db, bio, userindex, verbose, "User entry");
    171 			print_entry(db, bio, get_index(db, pp[DB_srpgN], 'I'), verbose, "g N entry");
    172 			}
    173 
    174 		}
    175 	}
    176 
    177 static int update_index(CA_DB *db, BIO *bio, char **row)
    178 	{
    179 	char ** irow;
    180 	int i;
    181 
    182 	if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
    183 		{
    184 		BIO_printf(bio_err,"Memory allocation failure\n");
    185 		return 0;
    186 		}
    187 
    188 	for (i=0; i<DB_NUMBER; i++)
    189 		{
    190 		irow[i]=row[i];
    191 		row[i]=NULL;
    192 		}
    193 	irow[DB_NUMBER]=NULL;
    194 
    195 	if (!TXT_DB_insert(db->db,irow))
    196 		{
    197 		BIO_printf(bio,"failed to update srpvfile\n");
    198 		BIO_printf(bio,"TXT_DB error number %ld\n",db->db->error);
    199 		OPENSSL_free(irow);
    200 		return 0;
    201 		}
    202 	return 1;
    203 	}
    204 
    205 static void lookup_fail(const char *name, char *tag)
    206 	{
    207 	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
    208 	}
    209 
    210 
    211 static char *srp_verify_user(const char *user, const char *srp_verifier,
    212 			     char *srp_usersalt, const char *g, const char *N,
    213 			     const char *passin, BIO *bio, int verbose)
    214 	{
    215 	char password[1024];
    216 	PW_CB_DATA cb_tmp;
    217 	char *verifier = NULL;
    218 	char *gNid = NULL;
    219 
    220 	cb_tmp.prompt_info = user;
    221 	cb_tmp.password = passin;
    222 
    223  	if (password_callback(password, 1024, 0, &cb_tmp) >0)
    224 		{
    225 		VERBOSE BIO_printf(bio,"Validating\n   user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,srp_verifier,srp_usersalt, g, N);
    226 		BIO_printf(bio, "Pass %s\n", password);
    227 
    228 		if (!(gNid=SRP_create_verifier(user, password, &srp_usersalt, &verifier, N, g)))
    229 			{
    230 			BIO_printf(bio, "Internal error validating SRP verifier\n");
    231 			}
    232 		else
    233 			{
    234 			if (strcmp(verifier, srp_verifier))
    235 				gNid = NULL;
    236 			OPENSSL_free(verifier);
    237 			}
    238 		}
    239 	return gNid;
    240 	}
    241 
    242 static char *srp_create_user(char *user, char **srp_verifier,
    243 			     char **srp_usersalt, char *g, char *N,
    244 			     char *passout, BIO *bio, int verbose)
    245 	{
    246  	char password[1024];
    247         PW_CB_DATA cb_tmp;
    248 	char *gNid = NULL;
    249 	char *salt = NULL;
    250         cb_tmp.prompt_info = user;
    251         cb_tmp.password = passout;
    252 
    253 	if (password_callback(password,1024,1,&cb_tmp) >0)
    254 		{
    255 		VERBOSE BIO_printf(bio,"Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,g,N);
    256 		if (!(gNid =SRP_create_verifier(user, password, &salt, srp_verifier, N, g)))
    257 			{
    258 			BIO_printf(bio,"Internal error creating SRP verifier\n");
    259 			}
    260 		else
    261 			*srp_usersalt = salt;
    262 		VVERBOSE BIO_printf(bio,"gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", gNid,salt, *srp_verifier);
    263 
    264 		}
    265 	return gNid;
    266 	}
    267 
    268 int MAIN(int argc, char **argv)
    269 	{
    270 	int add_user = 0;
    271 	int list_user= 0;
    272 	int delete_user= 0;
    273 	int modify_user= 0;
    274 	char * user = NULL;
    275 
    276 	char *passargin = NULL, *passargout = NULL;
    277 	char *passin = NULL, *passout = NULL;
    278         char * gN = NULL;
    279 	int gNindex = -1;
    280 	char ** gNrow = NULL;
    281 	int maxgN = -1;
    282 
    283 	char * userinfo = NULL;
    284 
    285 	int badops=0;
    286 	int ret=1;
    287 	int errors=0;
    288 	int verbose=0;
    289 	int doupdatedb=0;
    290 	char *configfile=NULL;
    291 	char *dbfile=NULL;
    292 	CA_DB *db=NULL;
    293 	char **pp ;
    294 	int i;
    295 	long errorline = -1;
    296 	char *randfile=NULL;
    297 #ifndef OPENSSL_NO_ENGINE
    298 	char *engine = NULL;
    299 #endif
    300 	char *tofree=NULL;
    301 	DB_ATTR db_attr;
    302 
    303 #ifdef EFENCE
    304 EF_PROTECT_FREE=1;
    305 EF_PROTECT_BELOW=1;
    306 EF_ALIGNMENT=0;
    307 #endif
    308 
    309 	apps_startup();
    310 
    311 	conf = NULL;
    312 	section = NULL;
    313 
    314 	if (bio_err == NULL)
    315 		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
    316 			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
    317 
    318 	argc--;
    319 	argv++;
    320 	while (argc >= 1 && badops == 0)
    321 		{
    322 		if	(strcmp(*argv,"-verbose") == 0)
    323 			verbose++;
    324 		else if	(strcmp(*argv,"-config") == 0)
    325 			{
    326 			if (--argc < 1) goto bad;
    327 			configfile= *(++argv);
    328 			}
    329 		else if (strcmp(*argv,"-name") == 0)
    330 			{
    331 			if (--argc < 1) goto bad;
    332 			section= *(++argv);
    333 			}
    334 		else if	(strcmp(*argv,"-srpvfile") == 0)
    335 			{
    336 			if (--argc < 1) goto bad;
    337 			dbfile= *(++argv);
    338 			}
    339 		else if (strcmp(*argv,"-add") == 0)
    340 			add_user=1;
    341 		else if (strcmp(*argv,"-delete") == 0)
    342 			delete_user=1;
    343 		else if (strcmp(*argv,"-modify") == 0)
    344 			modify_user=1;
    345 		else if (strcmp(*argv,"-list") == 0)
    346 			list_user=1;
    347 		else if (strcmp(*argv,"-gn") == 0)
    348 			{
    349 			if (--argc < 1) goto bad;
    350 			gN= *(++argv);
    351 			}
    352 		else if (strcmp(*argv,"-userinfo") == 0)
    353 			{
    354 			if (--argc < 1) goto bad;
    355 			userinfo= *(++argv);
    356 			}
    357 		else if (strcmp(*argv,"-passin") == 0)
    358 			{
    359 			if (--argc < 1) goto bad;
    360 			passargin= *(++argv);
    361 			}
    362 		else if (strcmp(*argv,"-passout") == 0)
    363 			{
    364 			if (--argc < 1) goto bad;
    365 			passargout= *(++argv);
    366 			}
    367 #ifndef OPENSSL_NO_ENGINE
    368 		else if (strcmp(*argv,"-engine") == 0)
    369 			{
    370 			if (--argc < 1) goto bad;
    371 			engine= *(++argv);
    372 			}
    373 #endif
    374 
    375 		else if (**argv == '-')
    376 			{
    377 bad:
    378 			BIO_printf(bio_err,"unknown option %s\n",*argv);
    379 			badops=1;
    380 			break;
    381 			}
    382 		else
    383 			break;
    384 
    385 		argc--;
    386 		argv++;
    387 		}
    388 
    389 	if (dbfile && configfile)
    390 		{
    391 		BIO_printf(bio_err,"-dbfile and -configfile cannot be specified together.\n");
    392 		badops = 1;
    393 		}
    394 	if (add_user+delete_user+modify_user+list_user != 1)
    395 		{
    396 		BIO_printf(bio_err,"Exactly one of the options -add, -delete, -modify -list must be specified.\n");
    397 		badops = 1;
    398 		}
    399 	if (delete_user+modify_user+delete_user== 1 && argc <= 0)
    400 		{
    401 		BIO_printf(bio_err,"Need at least one user for options -add, -delete, -modify. \n");
    402 		badops = 1;
    403 		}
    404 	if ((passin || passout) && argc != 1 )
    405 		{
    406 		BIO_printf(bio_err,"-passin, -passout arguments only valid with one user.\n");
    407 		badops = 1;
    408 		}
    409 
    410 	if (badops)
    411 		{
    412 		for (pp=srp_usage; (*pp != NULL); pp++)
    413 			BIO_printf(bio_err,"%s",*pp);
    414 
    415 		BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
    416 		BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
    417 		BIO_printf(bio_err,"                 the random number generator\n");
    418 		goto err;
    419 		}
    420 
    421 	ERR_load_crypto_strings();
    422 
    423 #ifndef OPENSSL_NO_ENGINE
    424 	setup_engine(bio_err, engine, 0);
    425 #endif
    426 
    427 	if(!app_passwd(bio_err, passargin, passargout, &passin, &passout))
    428 		{
    429 		BIO_printf(bio_err, "Error getting passwords\n");
    430 		goto err;
    431 		}
    432 
    433         if (!dbfile)
    434 		{
    435 
    436 
    437 	/*****************************************************************/
    438 		tofree=NULL;
    439 		if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
    440 		if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
    441 		if (configfile == NULL)
    442 			{
    443 			const char *s=X509_get_default_cert_area();
    444 			size_t len;
    445 
    446 #ifdef OPENSSL_SYS_VMS
    447 			len = strlen(s)+sizeof(CONFIG_FILE);
    448 			tofree=OPENSSL_malloc(len);
    449 			strcpy(tofree,s);
    450 #else
    451 			len = strlen(s)+sizeof(CONFIG_FILE)+1;
    452 			tofree=OPENSSL_malloc(len);
    453 			BUF_strlcpy(tofree,s,len);
    454 			BUF_strlcat(tofree,"/",len);
    455 #endif
    456 			BUF_strlcat(tofree,CONFIG_FILE,len);
    457 			configfile=tofree;
    458 			}
    459 
    460 		VERBOSE BIO_printf(bio_err,"Using configuration from %s\n",configfile);
    461 		conf = NCONF_new(NULL);
    462 		if (NCONF_load(conf,configfile,&errorline) <= 0)
    463 			{
    464 			if (errorline <= 0)
    465 				BIO_printf(bio_err,"error loading the config file '%s'\n",
    466 					configfile);
    467 			else
    468 				BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
    469 					,errorline,configfile);
    470 			goto err;
    471 			}
    472 		if(tofree)
    473 			{
    474 			OPENSSL_free(tofree);
    475 			tofree = NULL;
    476 			}
    477 
    478 		if (!load_config(bio_err, conf))
    479 			goto err;
    480 
    481 	/* Lets get the config section we are using */
    482 		if (section == NULL)
    483 			{
    484 			VERBOSE BIO_printf(bio_err,"trying to read " ENV_DEFAULT_SRP " in \" BASE_SECTION \"\n");
    485 
    486 			section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_SRP);
    487 			if (section == NULL)
    488 				{
    489 				lookup_fail(BASE_SECTION,ENV_DEFAULT_SRP);
    490 				goto err;
    491 				}
    492 			}
    493 
    494 		if (randfile == NULL && conf)
    495 	        	randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
    496 
    497 
    498 		VERBOSE BIO_printf(bio_err,"trying to read " ENV_DATABASE " in section \"%s\"\n",section);
    499 
    500 		if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
    501 			{
    502 			lookup_fail(section,ENV_DATABASE);
    503 			goto err;
    504 			}
    505 
    506         	}
    507 	if (randfile == NULL)
    508 		ERR_clear_error();
    509        	else
    510 		app_RAND_load_file(randfile, bio_err, 0);
    511 
    512 	VERBOSE BIO_printf(bio_err,"Trying to read SRP verifier file \"%s\"\n",dbfile);
    513 
    514 	db = load_index(dbfile, &db_attr);
    515 	if (db == NULL) goto err;
    516 
    517 	/* Lets check some fields */
    518 	for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    519 		{
    520 		pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
    521 
    522 		if (pp[DB_srptype][0] == DB_SRP_INDEX)
    523 			{
    524 			maxgN = i;
    525 			if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid]))
    526 				gNindex = i;
    527 
    528 			print_index(db, bio_err, i, verbose > 1);
    529 			}
    530 		}
    531 
    532 	VERBOSE BIO_printf(bio_err, "Database initialised\n");
    533 
    534 	if (gNindex >= 0)
    535 		{
    536 		gNrow = sk_OPENSSL_PSTRING_value(db->db->data,gNindex);
    537 		print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N");
    538 		}
    539 	else if (maxgN > 0 && !SRP_get_default_gN(gN))
    540 		{
    541 		BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
    542 		goto err;
    543 		}
    544 	else
    545 		{
    546 		VERBOSE BIO_printf(bio_err, "Database has no g N information.\n");
    547 		gNrow = NULL;
    548 		}
    549 
    550 
    551 	VVERBOSE BIO_printf(bio_err,"Starting user processing\n");
    552 
    553 	if (argc > 0)
    554 		user = *(argv++) ;
    555 
    556 	while (list_user || user)
    557 		{
    558 		int userindex = -1;
    559 		if (user)
    560 			VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user);
    561 		if ((userindex = get_index(db, user, 'U')) >= 0)
    562 			{
    563 			print_user(db, bio_err, userindex, (verbose > 0) || list_user);
    564 			}
    565 
    566 		if (list_user)
    567 			{
    568 			if (user == NULL)
    569 				{
    570 				BIO_printf(bio_err,"List all users\n");
    571 
    572 				for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    573 					{
    574 					print_user(db,bio_err, i, 1);
    575 					}
    576 				list_user = 0;
    577 				}
    578 			else if (userindex < 0)
    579 				{
    580 				BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n",
    581 					   user);
    582 				errors++;
    583 				}
    584 			}
    585 		else if (add_user)
    586 			{
    587 			if (userindex >= 0)
    588 				{
    589 				/* reactivation of a new user */
    590 				char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
    591 				BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
    592 				row[DB_srptype][0] = 'V';
    593 
    594 				doupdatedb = 1;
    595 				}
    596 			else
    597 				{
    598 				char *row[DB_NUMBER] ; char *gNid;
    599 				row[DB_srpverifier] = NULL;
    600 				row[DB_srpsalt] = NULL;
    601 				row[DB_srpinfo] = NULL;
    602 				if (!(gNid = srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:gN,gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
    603 					{
    604 						BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user);
    605 						errors++;
    606 						goto err;
    607 					}
    608 				row[DB_srpid] = BUF_strdup(user);
    609 				row[DB_srptype] = BUF_strdup("v");
    610 				row[DB_srpgN] = BUF_strdup(gNid);
    611 
    612 				if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
    613 					(userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))) ||
    614 					!update_index(db, bio_err, row))
    615 					{
    616 					if (row[DB_srpid]) OPENSSL_free(row[DB_srpid]);
    617 					if (row[DB_srpgN]) OPENSSL_free(row[DB_srpgN]);
    618 					if (row[DB_srpinfo]) OPENSSL_free(row[DB_srpinfo]);
    619 					if (row[DB_srptype]) OPENSSL_free(row[DB_srptype]);
    620 					if (row[DB_srpverifier]) OPENSSL_free(row[DB_srpverifier]);
    621 					if (row[DB_srpsalt]) OPENSSL_free(row[DB_srpsalt]);
    622 					goto err;
    623 					}
    624 				doupdatedb = 1;
    625 				}
    626 			}
    627 		else if (modify_user)
    628 			{
    629 			if (userindex < 0)
    630 				{
    631 				BIO_printf(bio_err,"user \"%s\" does not exist, operation ignored.\n",user);
    632 				errors++;
    633 				}
    634 			else
    635 				{
    636 
    637 				char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
    638 				char type = row[DB_srptype][0];
    639 				if (type == 'v')
    640 					{
    641 					BIO_printf(bio_err,"user \"%s\" already updated, operation ignored.\n",user);
    642 					errors++;
    643 					}
    644 				else
    645 					{
    646 					char *gNid;
    647 
    648 					if (row[DB_srptype][0] == 'V')
    649 						{
    650 						int user_gN;
    651 						char **irow = NULL;
    652 						VERBOSE BIO_printf(bio_err,"Verifying password for user \"%s\"\n",user);
    653 						if ( (user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
    654 							irow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
    655 
    656  						if (!srp_verify_user(user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, bio_err, verbose))
    657 							{
    658 							BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user);
    659 							errors++;
    660 							goto err;
    661 							}
    662 						}
    663 					VERBOSE BIO_printf(bio_err,"Password for user \"%s\" ok.\n",user);
    664 
    665 					if (!(gNid=srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:NULL, gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
    666 						{
    667 						BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user);
    668 						errors++;
    669 						goto err;
    670 						}
    671 
    672 					row[DB_srptype][0] = 'v';
    673 					row[DB_srpgN] = BUF_strdup(gNid);
    674 
    675 					if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
    676 						(userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))))
    677 						goto err;
    678 
    679 					doupdatedb = 1;
    680 					}
    681 				}
    682 			}
    683 		else if (delete_user)
    684 			{
    685 			if (userindex < 0)
    686 				{
    687 				BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user);
    688 				errors++;
    689 				}
    690 			else
    691 				{
    692 				char **xpp = sk_OPENSSL_PSTRING_value(db->db->data,userindex);
    693 				BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
    694 
    695 				xpp[DB_srptype][0] = 'R';
    696 
    697 				doupdatedb = 1;
    698 				}
    699 			}
    700 		if (--argc > 0)
    701 			user = *(argv++) ;
    702 		else
    703 			{
    704 			user = NULL;
    705 			list_user = 0;
    706 			}
    707 		}
    708 
    709 	VERBOSE BIO_printf(bio_err,"User procession done.\n");
    710 
    711 
    712 	if (doupdatedb)
    713 		{
    714 		/* Lets check some fields */
    715 		for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    716 			{
    717 			pp = sk_OPENSSL_PSTRING_value(db->db->data,i);
    718 
    719 			if (pp[DB_srptype][0] == 'v')
    720 				{
    721 				pp[DB_srptype][0] = 'V';
    722 				print_user(db, bio_err, i, verbose);
    723 				}
    724 			}
    725 
    726 		VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n");
    727 		if (!save_index(dbfile, "new", db)) goto err;
    728 
    729 		VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n");
    730 		if (!rotate_index(dbfile, "new", "old")) goto err;
    731 
    732 		VERBOSE BIO_printf(bio_err, "srpvfile updated.\n");
    733 		}
    734 
    735 	ret = (errors != 0);
    736 err:
    737 	if (errors != 0)
    738 	VERBOSE BIO_printf(bio_err,"User errors %d.\n",errors);
    739 
    740 	VERBOSE BIO_printf(bio_err,"SRP terminating with code %d.\n",ret);
    741 	if(tofree)
    742 		OPENSSL_free(tofree);
    743 	if (ret) ERR_print_errors(bio_err);
    744 	if (randfile) app_RAND_write_file(randfile, bio_err);
    745 	if (conf) NCONF_free(conf);
    746 	if (db) free_index(db);
    747 
    748 	OBJ_cleanup();
    749 	apps_shutdown();
    750 	OPENSSL_EXIT(ret);
    751 	}
    752 
    753 
    754 
    755 #endif
    756 
    757