Add mem_clr.c explicity for no-asm builds.
[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, const 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,
213                                                          const char * N, const char *passin, BIO *bio,
214                                                          int verbose)
215         {
216         char password[1024];
217         PW_CB_DATA cb_tmp;
218         char *verifier = NULL;
219         char *gNid = NULL;
220
221         cb_tmp.prompt_info = user;
222         cb_tmp.password = passin;
223
224         if (password_callback(password, 1024, 0, &cb_tmp) >0)
225                 {
226                 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);
227                 BIO_printf(bio,"Pass %s\n",password);
228
229                 OPENSSL_assert(srp_usersalt != NULL);
230                 if (!(gNid=SRP_create_verifier(user, password, &srp_usersalt, &verifier,
231                                                                            N, g)))
232                         {
233                         BIO_printf(bio,"Internal error validating SRP verifier\n");
234                         }
235                 else
236                         {
237                         if (strcmp(verifier, srp_verifier))
238                                 gNid = NULL;
239                         OPENSSL_free(verifier);
240                         }
241                 }
242         return gNid;
243         }
244
245 static char *srp_create_user(char * user, char **srp_verifier,
246                                                          char **srp_usersalt,char *g, char *N,
247                                                          char *passout, BIO *bio, int verbose)
248         {
249         char password[1024];
250         PW_CB_DATA cb_tmp;
251         char *gNid = NULL;
252         char *salt = NULL;
253         cb_tmp.prompt_info = user;
254         cb_tmp.password = passout;
255
256         if (password_callback(password,1024,1,&cb_tmp) >0)
257                 {
258                 VERBOSE BIO_printf(bio,"Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,g,N);
259                 if (!(gNid =SRP_create_verifier(user, password, &salt, srp_verifier, N, g)))
260                         {
261                         BIO_printf(bio,"Internal error creating SRP verifier\n");
262                         }
263                 else 
264                         *srp_usersalt = salt;
265                 VVERBOSE BIO_printf(bio,"gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", gNid,salt, *srp_verifier);
266
267                 }
268         return gNid;
269         }
270
271 int MAIN(int argc, char **argv)
272         {
273         int add_user = 0;
274         int list_user= 0;
275         int delete_user= 0;
276         int modify_user= 0;
277         char * user = NULL;
278
279         char *passargin = NULL, *passargout = NULL;
280         char *passin = NULL, *passout = NULL;
281         char * gN = NULL;
282         int gNindex = -1;
283         char ** gNrow = NULL;
284         int maxgN = -1;
285
286         char * userinfo = NULL;
287
288         int badops=0;
289         int ret=1;
290         int errors=0;
291         int verbose=0;
292         int doupdatedb=0;
293         char *configfile=NULL;
294         char *dbfile=NULL;
295         CA_DB *db=NULL;
296         char **pp ;
297         int i;
298         long errorline = -1;
299         char *randfile=NULL;
300 #ifndef OPENSSL_NO_ENGINE
301         char *engine = NULL;
302 #endif
303         char *tofree=NULL;
304         DB_ATTR db_attr;
305
306 #ifdef EFENCE
307 EF_PROTECT_FREE=1;
308 EF_PROTECT_BELOW=1;
309 EF_ALIGNMENT=0;
310 #endif
311
312         apps_startup();
313
314         conf = NULL;
315         section = NULL;
316
317         if (bio_err == NULL)
318                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
319                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
320
321         argc--;
322         argv++;
323         while (argc >= 1 && badops == 0)
324                 {
325                 if      (strcmp(*argv,"-verbose") == 0)
326                         verbose++;
327                 else if (strcmp(*argv,"-config") == 0)
328                         {
329                         if (--argc < 1) goto bad;
330                         configfile= *(++argv);
331                         }
332                 else if (strcmp(*argv,"-name") == 0)
333                         {
334                         if (--argc < 1) goto bad;
335                         section= *(++argv);
336                         }
337                 else if (strcmp(*argv,"-srpvfile") == 0)
338                         {
339                         if (--argc < 1) goto bad;
340                         dbfile= *(++argv);
341                         }
342                 else if (strcmp(*argv,"-add") == 0)
343                         add_user=1;
344                 else if (strcmp(*argv,"-delete") == 0)
345                         delete_user=1;
346                 else if (strcmp(*argv,"-modify") == 0)
347                         modify_user=1;
348                 else if (strcmp(*argv,"-list") == 0)
349                         list_user=1;
350                 else if (strcmp(*argv,"-gn") == 0)
351                         {
352                         if (--argc < 1) goto bad;
353                         gN= *(++argv);
354                         }
355                 else if (strcmp(*argv,"-userinfo") == 0)
356                         {
357                         if (--argc < 1) goto bad;
358                         userinfo= *(++argv);
359                         }
360                 else if (strcmp(*argv,"-passin") == 0)
361                         {
362                         if (--argc < 1) goto bad;
363                         passargin= *(++argv);
364                         }
365                 else if (strcmp(*argv,"-passout") == 0)
366                         {
367                         if (--argc < 1) goto bad;
368                         passargout= *(++argv);
369                         }
370 #ifndef OPENSSL_NO_ENGINE
371                 else if (strcmp(*argv,"-engine") == 0)
372                         {
373                         if (--argc < 1) goto bad;
374                         engine= *(++argv);
375                         }
376 #endif
377
378                 else if (**argv == '-')
379                         {
380 bad:
381                         BIO_printf(bio_err,"unknown option %s\n",*argv);
382                         badops=1;
383                         break;
384                         }
385                 else 
386                         break;
387         
388                 argc--;
389                 argv++;
390                 }
391
392         if (dbfile && configfile)
393                 {
394                 BIO_printf(bio_err,"-dbfile and -configfile cannot be specified together.\n");
395                 badops = 1;
396                 }
397         if (add_user+delete_user+modify_user+list_user != 1)
398                 {
399                 BIO_printf(bio_err,"Exactly one of the options -add, -delete, -modify -list must be specified.\n");
400                 badops = 1;
401                 }
402         if (delete_user+modify_user+delete_user== 1 && argc <= 0)
403                 {
404                 BIO_printf(bio_err,"Need at least one user for options -add, -delete, -modify. \n");
405                 badops = 1;
406                 }
407         if ((passin || passout) && argc != 1 )
408                 {
409                 BIO_printf(bio_err,"-passin, -passout arguments only valid with one user.\n");
410                 badops = 1;
411                 }
412
413         if (badops)
414                 {
415                 for (pp=srp_usage; (*pp != NULL); pp++)
416                         BIO_printf(bio_err,"%s",*pp);
417
418                 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
419                 BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
420                 BIO_printf(bio_err,"                 the random number generator\n");
421                 goto err;
422                 }
423
424         ERR_load_crypto_strings();
425
426 #ifndef OPENSSL_NO_ENGINE
427         setup_engine(bio_err, engine, 0);
428 #endif
429
430         if(!app_passwd(bio_err, passargin, passargout, &passin, &passout))
431                 {
432                 BIO_printf(bio_err, "Error getting passwords\n");
433                 goto err;
434                 }
435
436         if (!dbfile)
437                 {
438
439
440         /*****************************************************************/
441                 tofree=NULL;
442                 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
443                 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
444                 if (configfile == NULL)
445                         {
446                         const char *s=X509_get_default_cert_area();
447                         size_t len;
448
449 #ifdef OPENSSL_SYS_VMS
450                         len = strlen(s)+sizeof(CONFIG_FILE);
451                         tofree=OPENSSL_malloc(len);
452                         strcpy(tofree,s);
453 #else
454                         len = strlen(s)+sizeof(CONFIG_FILE)+1;
455                         tofree=OPENSSL_malloc(len);
456                         BUF_strlcpy(tofree,s,len);
457                         BUF_strlcat(tofree,"/",len);
458 #endif
459                         BUF_strlcat(tofree,CONFIG_FILE,len);
460                         configfile=tofree;
461                         }
462
463                 VERBOSE BIO_printf(bio_err,"Using configuration from %s\n",configfile);
464                 conf = NCONF_new(NULL);
465                 if (NCONF_load(conf,configfile,&errorline) <= 0)
466                         {
467                         if (errorline <= 0)
468                                 BIO_printf(bio_err,"error loading the config file '%s'\n",
469                                         configfile);
470                         else
471                                 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
472                                         ,errorline,configfile);
473                         goto err;
474                         }
475                 if(tofree)
476                         {
477                         OPENSSL_free(tofree);
478                         tofree = NULL;
479                         }
480
481                 if (!load_config(bio_err, conf))
482                         goto err;
483
484         /* Lets get the config section we are using */
485                 if (section == NULL)
486                         {
487                         VERBOSE BIO_printf(bio_err,"trying to read " ENV_DEFAULT_SRP " in \" BASE_SECTION \"\n");
488
489                         section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_SRP);
490                         if (section == NULL)
491                                 {
492                                 lookup_fail(BASE_SECTION,ENV_DEFAULT_SRP);
493                                 goto err;
494                                 }
495                         }
496          
497                 if (randfile == NULL && conf)
498                         randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
499
500         
501                 VERBOSE BIO_printf(bio_err,"trying to read " ENV_DATABASE " in section \"%s\"\n",section);
502
503                 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
504                         {
505                         lookup_fail(section,ENV_DATABASE);
506                         goto err;
507                         }
508
509                 }
510         if (randfile == NULL)
511                 ERR_clear_error();
512         else 
513                 app_RAND_load_file(randfile, bio_err, 0);
514
515         VERBOSE BIO_printf(bio_err,"Trying to read SRP verifier file \"%s\"\n",dbfile);
516
517         db = load_index(dbfile, &db_attr);
518         if (db == NULL) goto err;
519
520         /* Lets check some fields */
521         for (i=0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
522                 {
523                 pp=sk_OPENSSL_PSTRING_value(db->db->data, i);
524         
525                 if (pp[DB_srptype][0] == DB_SRP_INDEX)
526                         {
527                         maxgN = i;
528                         if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid]))
529                                 gNindex = i;
530
531                         print_index(db, bio_err, i, verbose > 1) ;
532                         }
533                 }
534         
535         VERBOSE BIO_printf(bio_err,"Database initialised\n");
536
537         if (gNindex >= 0)
538                 {
539                 gNrow=sk_OPENSSL_PSTRING_value(db->db->data,gNindex);
540                 print_entry(db,bio_err,gNindex,verbose>1,"Default g and N") ;
541                 }
542         else if (maxgN > 0 && !SRP_get_default_gN(gN))
543                 {
544                 BIO_printf(bio_err,"No g and N value for index \"%s\"\n",gN);
545                 goto err;
546                 }
547         else
548                 {
549                 VERBOSE BIO_printf(bio_err,"Database has no g N information.\n");
550                 gNrow = NULL;
551                 }
552         
553
554         VVERBOSE BIO_printf(bio_err,"Starting user processing\n");
555
556         if (argc > 0)
557                 user = *(argv++) ;
558
559         while (list_user || user)
560                 {
561                 int userindex = -1;
562                 if (user) 
563                         VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n",user);
564                 if ((userindex = get_index(db, user, 'U')) >= 0)
565                         {
566                         print_user(db,bio_err,userindex,(verbose > 0) || list_user) ;
567                         }
568                 
569                 if (list_user)
570                         {
571                         if (user == NULL)
572                                 {
573                                 BIO_printf(bio_err,"List all users\n");
574
575                                 for (i=0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
576                                         {
577                                         print_user(db,bio_err,i,1) ;
578                                         }
579                                 list_user = 0;
580                                 }
581                         else if (userindex < 0)
582                                 {
583                                 BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n",
584                                                    user);
585                                 errors++;
586                                 }
587                         }
588                 else if (add_user)
589                         {
590                         if (userindex >= 0)
591                                 {
592                                 /* reactivation of a new user */
593                                 char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
594                                 BIO_printf(bio_err,"user \"%s\" reactivated.\n", user);
595                                 row[DB_srptype][0] = 'V' ;
596
597                                 doupdatedb = 1;
598                                 }
599                         else
600                                 {
601                                 char *row[DB_NUMBER] ; char * gNid;
602                                 row[DB_srpverifier] = NULL;
603                                 row[DB_srpsalt] = NULL;
604                                 row[DB_srpinfo] = NULL;
605                                 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)))
606                                         {
607                                                 BIO_printf(bio_err,"Cannot create srp verifier for user \"%s\", operation abandoned .\n",user);
608                                                 errors++ ;
609                                                 goto err;
610                                         }
611                                 row[DB_srpid] = BUF_strdup(user);
612                                 row[DB_srptype] = BUF_strdup("v");
613                                 row[DB_srpgN] = BUF_strdup(gNid);
614
615                                 if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
616                                         (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))) || 
617                                         !update_index(db, bio_err, row))
618                                         {
619                                         if (row[DB_srpid]) OPENSSL_free(row[DB_srpid]);
620                                         if (row[DB_srpgN]) OPENSSL_free(row[DB_srpgN]);
621                                         if (row[DB_srpinfo]) OPENSSL_free(row[DB_srpinfo]);
622                                         if (row[DB_srptype]) OPENSSL_free(row[DB_srptype]);
623                                         if (row[DB_srpverifier]) OPENSSL_free(row[DB_srpverifier]);
624                                         if (row[DB_srpsalt]) OPENSSL_free(row[DB_srpsalt]);
625                                         goto err;
626                                         }
627                                 doupdatedb = 1;
628                                 }
629                         }
630                 else if (modify_user)
631                         {
632                         if (userindex<0)
633                                 {
634                                 BIO_printf(bio_err,"user \"%s\" does not exist, operation ignored.\n",user);
635                                 errors++ ;
636                                 }
637                         else
638                                 {
639
640                                 char **row=sk_OPENSSL_PSTRING_value(db->db->data, userindex);
641                                 char type = row[DB_srptype][0] ;
642                                 if (type == 'v')
643                                         {
644                                         BIO_printf(bio_err,"user \"%s\" already updated, operation ignored.\n",user);
645                                         errors++ ;
646                                         }
647                                 else
648                                         {
649                                         char * gNid ;
650
651                                         if (row[DB_srptype][0] == 'V')
652                                                 {
653                                                 int user_gN ;
654                                                 char ** irow = NULL;
655                                                 VERBOSE BIO_printf(bio_err,"Verifying password for user \"%s\"\n",user);
656                                                 if ( (user_gN = get_index(db, row[DB_srpgN],DB_SRP_INDEX)) >= 0)
657                                                         irow = sk_OPENSSL_PSTRING_value(db->db->data,
658                                                                                                                         userindex);
659
660                                                 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))
661                                                         {
662                                                         BIO_printf(bio_err,"Invalid password for user \"%s\", operation abandoned.\n",user);
663                                                         errors++ ;
664                                                         goto err;
665                                                         }
666                                                 } 
667                                         VERBOSE BIO_printf(bio_err,"Password for user \"%s\" ok.\n",user);
668
669                                         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)))
670                                                 {
671                                                         BIO_printf(bio_err,
672                                                                            "Cannot create srp verifier for user "
673                                                                            "\"%s\", operation abandonned .\n",
674                                                                            user);
675                                                         errors++;
676                                                         goto err;
677                                                 }
678
679                                         row[DB_srptype][0] = 'v';
680                                         row[DB_srpgN] = BUF_strdup(gNid);
681  
682                                         if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
683                                                 (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))))  
684                                                 goto err;
685
686                                         doupdatedb = 1;
687                                         }
688                                 }
689                         }
690                 else if (delete_user)
691                         {
692                         if (userindex < 0)
693                                 {
694                                 BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user);
695                                 errors++;
696                                 }
697                         else
698                                 {
699                                 char ** xpp = sk_OPENSSL_PSTRING_value(db->db->data,userindex);
700                                 BIO_printf(bio_err,"user \"%s\" revoked. t\n",user);
701
702                                 xpp[DB_srptype][0] = 'R' ;
703                                 
704                                 doupdatedb = 1;
705                                 }
706                         }
707                 if (--argc > 0)
708                         user = *(argv++) ;
709                 else
710                         {
711                         user = NULL;
712                         list_user = 0;
713                         }
714                 }
715
716         VERBOSE BIO_printf(bio_err,"User procession done.\n");
717
718
719         if (doupdatedb)
720                 {
721                 /* Lets check some fields */
722                 for (i=0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
723                         {
724                         pp=sk_OPENSSL_PSTRING_value(db->db->data,i);
725         
726                         if (pp[DB_srptype][0] == 'v')
727                                 {
728                                 pp[DB_srptype][0] = 'V';
729                                 print_user(db,bio_err,i,verbose) ;
730                                 }
731                         }
732
733                 VERBOSE BIO_printf(bio_err,"Trying to update srpvfile.\n");
734                 if (!save_index(dbfile,"new",db)) goto err;
735                                 
736                 VERBOSE BIO_printf(bio_err,"Temporary srpvfile created.\n");
737                 if (!rotate_index(dbfile,"new","old")) goto err;
738
739                 VERBOSE BIO_printf(bio_err,"srpvfile updated.\n");
740                 }
741
742         ret = (errors != 0);
743 err:
744         if (errors != 0)
745         VERBOSE BIO_printf(bio_err,"User errors %d.\n",errors);
746
747         VERBOSE BIO_printf(bio_err,"SRP terminating with code %d.\n",ret);
748         if(tofree)
749                 OPENSSL_free(tofree);
750         if (ret) ERR_print_errors(bio_err);
751         if (randfile) app_RAND_write_file(randfile, bio_err);
752         if (conf) NCONF_free(conf);
753         if (db) free_index(db);
754
755         OBJ_cleanup();
756         apps_shutdown();
757         OPENSSL_EXIT(ret);
758         }
759
760
761
762 #endif
763