remove unused cipher functionality from s_client
[openssl.git] / apps / srp.c
1 /* apps/srp.c */
2 /* Written by Peter Sylvester (peter.sylvester@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@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@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@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