apps/srp.c: make it indent-friendly.
[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 a lot 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 int MAIN(int, char **);
118
119 static int get_index(CA_DB *db, char *id, char type)
120 {
121     char **pp;
122     int i;
123     if (id == NULL)
124         return -1;
125     if (type == DB_SRP_INDEX)
126         for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
127             pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
128             if (pp[DB_srptype][0] == DB_SRP_INDEX
129                 && !strcmp(id, pp[DB_srpid]))
130                 return i;
131     } else
132         for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
133             pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
134
135             if (pp[DB_srptype][0] != DB_SRP_INDEX
136                 && !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         int j;
147         char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx);
148         BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]);
149         for (j = 0; j < DB_NUMBER; j++) {
150             BIO_printf(bio_err, "  %d = \"%s\"\n", j, pp[j]);
151         }
152     }
153 }
154
155 static void print_index(CA_DB *db, BIO *bio, int indexindex, int verbose)
156 {
157     print_entry(db, bio, indexindex, verbose, "g N entry");
158 }
159
160 static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose)
161 {
162     if (verbose > 0) {
163         char **pp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
164
165         if (pp[DB_srptype][0] != 'I') {
166             print_entry(db, bio, userindex, verbose, "User entry");
167             print_entry(db, bio, get_index(db, pp[DB_srpgN], 'I'), verbose,
168                         "g N entry");
169         }
170
171     }
172 }
173
174 static int update_index(CA_DB *db, BIO *bio, char **row)
175 {
176     char **irow;
177     int i;
178
179     if ((irow =
180          (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) {
181         BIO_printf(bio_err, "Memory allocation failure\n");
182         return 0;
183     }
184
185     for (i = 0; i < DB_NUMBER; i++) {
186         irow[i] = row[i];
187         row[i] = NULL;
188     }
189     irow[DB_NUMBER] = NULL;
190
191     if (!TXT_DB_insert(db->db, irow)) {
192         BIO_printf(bio, "failed to update srpvfile\n");
193         BIO_printf(bio, "TXT_DB error number %ld\n", db->db->error);
194         OPENSSL_free(irow);
195         return 0;
196     }
197     return 1;
198 }
199
200 static void lookup_fail(const char *name, const char *tag)
201 {
202     BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag);
203 }
204
205 static char *srp_verify_user(const char *user, const char *srp_verifier,
206                              char *srp_usersalt, const char *g, const char *N,
207                              const char *passin, BIO *bio, int verbose)
208 {
209     char password[1024];
210     PW_CB_DATA cb_tmp;
211     char *verifier = NULL;
212     char *gNid = NULL;
213
214     cb_tmp.prompt_info = user;
215     cb_tmp.password = passin;
216
217     if (password_callback(password, 1024, 0, &cb_tmp) > 0) {
218         VERBOSE BIO_printf(bio,
219                            "Validating\n"
220                            " user=\"%s\"\n"
221                            " srp_verifier=\"%s\"\n"
222                            " srp_usersalt=\"%s\"\n"
223                            " g=\"%s\"\n N=\"%s\"\n",
224                            user, srp_verifier, srp_usersalt, g, N);
225         BIO_printf(bio, "Pass %s\n", password);
226
227         OPENSSL_assert(srp_usersalt != NULL);
228         if (!(gNid = SRP_create_verifier(user, password, &srp_usersalt,
229                                          &verifier, N, g))) {
230             BIO_printf(bio, "Internal error validating SRP verifier\n");
231         } else {
232             if (strcmp(verifier, srp_verifier))
233                 gNid = NULL;
234             OPENSSL_free(verifier);
235         }
236     }
237     return gNid;
238 }
239
240 static char *srp_create_user(char *user, char **srp_verifier,
241                              char **srp_usersalt, char *g, char *N,
242                              char *passout, BIO *bio, int verbose)
243 {
244     char password[1024];
245     PW_CB_DATA cb_tmp;
246     char *gNid = NULL;
247     char *salt = NULL;
248     cb_tmp.prompt_info = user;
249     cb_tmp.password = passout;
250
251     if (password_callback(password, 1024, 1, &cb_tmp) > 0) {
252         VERBOSE BIO_printf(bio,
253                            "Creating\n"
254                            " user=\"%s\"\n"
255                            " g=\"%s\"\n" " N=\"%s\"\n", user, g, N);
256         if (!(gNid = SRP_create_verifier(user, password, &salt,
257                                          srp_verifier, N, g))) {
258             BIO_printf(bio, "Internal error creating SRP verifier\n");
259         } else
260             *srp_usersalt = salt;
261         VVERBOSE BIO_printf(bio, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n",
262                             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         if (strcmp(*argv, "-verbose") == 0)
322             verbose++;
323         else if (strcmp(*argv, "-config") == 0) {
324             if (--argc < 1)
325                 goto bad;
326             configfile = *(++argv);
327         } else if (strcmp(*argv, "-name") == 0) {
328             if (--argc < 1)
329                 goto bad;
330             section = *(++argv);
331         } else if (strcmp(*argv, "-srpvfile") == 0) {
332             if (--argc < 1)
333                 goto bad;
334             dbfile = *(++argv);
335         } else if (strcmp(*argv, "-add") == 0)
336             add_user = 1;
337         else if (strcmp(*argv, "-delete") == 0)
338             delete_user = 1;
339         else if (strcmp(*argv, "-modify") == 0)
340             modify_user = 1;
341         else if (strcmp(*argv, "-list") == 0)
342             list_user = 1;
343         else if (strcmp(*argv, "-gn") == 0) {
344             if (--argc < 1)
345                 goto bad;
346             gN = *(++argv);
347         } else if (strcmp(*argv, "-userinfo") == 0) {
348             if (--argc < 1)
349                 goto bad;
350             userinfo = *(++argv);
351         } else if (strcmp(*argv, "-passin") == 0) {
352             if (--argc < 1)
353                 goto bad;
354             passargin = *(++argv);
355         } else if (strcmp(*argv, "-passout") == 0) {
356             if (--argc < 1)
357                 goto bad;
358             passargout = *(++argv);
359         }
360 # ifndef OPENSSL_NO_ENGINE
361         else if (strcmp(*argv, "-engine") == 0) {
362             if (--argc < 1)
363                 goto bad;
364             engine = *(++argv);
365         }
366 # endif
367
368         else if (**argv == '-') {
369  bad:
370             BIO_printf(bio_err, "unknown option %s\n", *argv);
371             badops = 1;
372             break;
373         } else
374             break;
375
376         argc--;
377         argv++;
378     }
379
380     if (dbfile && configfile) {
381         BIO_printf(bio_err,
382                    "-dbfile and -configfile cannot be specified together.\n");
383         badops = 1;
384     }
385     if (add_user + delete_user + modify_user + list_user != 1) {
386         BIO_printf(bio_err, "Exactly one of the options "
387                    "-add, -delete, -modify -list must be specified.\n");
388         badops = 1;
389     }
390     if (delete_user + modify_user + delete_user == 1 && argc <= 0) {
391         BIO_printf(bio_err, "Need at least one user for options "
392                    "-add, -delete, -modify. \n");
393         badops = 1;
394     }
395     if ((passin || passout) && argc != 1) {
396         BIO_printf(bio_err,
397                    "-passin, -passout arguments only valid with one user.\n");
398         badops = 1;
399     }
400
401     if (badops) {
402         for (pp = srp_usage; (*pp != NULL); pp++)
403             BIO_printf(bio_err, "%s", *pp);
404
405         BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
406                    LIST_SEPARATOR_CHAR);
407         BIO_printf(bio_err,
408                    "                 load the file (or the files in the directory) into\n");
409         BIO_printf(bio_err, "                 the random number generator\n");
410         goto err;
411     }
412
413     ERR_load_crypto_strings();
414
415 # ifndef OPENSSL_NO_ENGINE
416     setup_engine(bio_err, engine, 0);
417 # endif
418
419     if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
420         BIO_printf(bio_err, "Error getting passwords\n");
421         goto err;
422     }
423
424     if (!dbfile) {
425
426         /*****************************************************************/
427         tofree = NULL;
428         if (configfile == NULL)
429             configfile = getenv("OPENSSL_CONF");
430         if (configfile == NULL)
431             configfile = getenv("SSLEAY_CONF");
432         if (configfile == NULL) {
433             const char *s = X509_get_default_cert_area();
434             size_t len;
435
436 # ifdef OPENSSL_SYS_VMS
437             len = strlen(s) + sizeof(CONFIG_FILE);
438             tofree = OPENSSL_malloc(len);
439             strcpy(tofree, s);
440 # else
441             len = strlen(s) + sizeof(CONFIG_FILE) + 1;
442             tofree = OPENSSL_malloc(len);
443             BUF_strlcpy(tofree, s, len);
444             BUF_strlcat(tofree, "/", len);
445 # endif
446             BUF_strlcat(tofree, CONFIG_FILE, len);
447             configfile = tofree;
448         }
449
450         VERBOSE BIO_printf(bio_err, "Using configuration from %s\n",
451                            configfile);
452         conf = NCONF_new(NULL);
453         if (NCONF_load(conf, configfile, &errorline) <= 0) {
454             if (errorline <= 0)
455                 BIO_printf(bio_err, "error loading the config file '%s'\n",
456                            configfile);
457             else
458                 BIO_printf(bio_err, "error on line %ld of config file '%s'\n",
459                            errorline, configfile);
460             goto err;
461         }
462         if (tofree) {
463             OPENSSL_free(tofree);
464             tofree = NULL;
465         }
466
467         if (!load_config(bio_err, conf))
468             goto err;
469
470         /* Lets get the config section we are using */
471         if (section == NULL) {
472             VERBOSE BIO_printf(bio_err,
473                                "trying to read " ENV_DEFAULT_SRP
474                                " in \" BASE_SECTION \"\n");
475
476             section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_SRP);
477             if (section == NULL) {
478                 lookup_fail(BASE_SECTION, ENV_DEFAULT_SRP);
479                 goto err;
480             }
481         }
482
483         if (randfile == NULL && conf)
484             randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
485
486         VERBOSE BIO_printf(bio_err,
487                            "trying to read " ENV_DATABASE
488                            " in section \"%s\"\n", section);
489
490         if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
491             lookup_fail(section, ENV_DATABASE);
492             goto err;
493         }
494
495     }
496     if (randfile == NULL)
497         ERR_clear_error();
498     else
499         app_RAND_load_file(randfile, bio_err, 0);
500
501     VERBOSE BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
502                        dbfile);
503
504     db = load_index(dbfile, &db_attr);
505     if (db == NULL)
506         goto err;
507
508     /* Lets check some fields */
509     for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
510         pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
511
512         if (pp[DB_srptype][0] == DB_SRP_INDEX) {
513             maxgN = i;
514             if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid]))
515                 gNindex = i;
516
517             print_index(db, bio_err, i, verbose > 1);
518         }
519     }
520
521     VERBOSE BIO_printf(bio_err, "Database initialised\n");
522
523     if (gNindex >= 0) {
524         gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
525         print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N");
526     } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {
527         BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
528         goto err;
529     } else {
530         VERBOSE BIO_printf(bio_err, "Database has no g N information.\n");
531         gNrow = NULL;
532     }
533
534     VVERBOSE BIO_printf(bio_err, "Starting user processing\n");
535
536     if (argc > 0)
537         user = *(argv++);
538
539     while (list_user || user) {
540         int userindex = -1;
541         if (user)
542             VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user);
543         if ((userindex = get_index(db, user, 'U')) >= 0) {
544             print_user(db, bio_err, userindex, (verbose > 0) || list_user);
545         }
546
547         if (list_user) {
548             if (user == NULL) {
549                 BIO_printf(bio_err, "List all users\n");
550
551                 for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
552                     print_user(db, bio_err, i, 1);
553                 }
554                 list_user = 0;
555             } else if (userindex < 0) {
556                 BIO_printf(bio_err,
557                            "user \"%s\" does not exist, ignored. t\n", user);
558                 errors++;
559             }
560         } else if (add_user) {
561             if (userindex >= 0) {
562                 /* reactivation of a new user */
563                 char **row =
564                     sk_OPENSSL_PSTRING_value(db->db->data, userindex);
565                 BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
566                 row[DB_srptype][0] = 'V';
567
568                 doupdatedb = 1;
569             } else {
570                 char *row[DB_NUMBER];
571                 char *gNid;
572                 row[DB_srpverifier] = NULL;
573                 row[DB_srpsalt] = NULL;
574                 row[DB_srpinfo] = NULL;
575                 if (!(gNid = srp_create_user(user, &(row[DB_srpverifier]),
576                                              &(row[DB_srpsalt]),
577                                              gNrow ? gNrow[DB_srpsalt] : gN,
578                                              gNrow ? gNrow[DB_srpverifier] :
579                                              NULL, passout, bio_err,
580                                              verbose))) {
581                     BIO_printf(bio_err,
582                                "Cannot create srp verifier for user \"%s\","
583                                " operation abandoned .\n", user);
584                     errors++;
585                     goto err;
586                 }
587                 row[DB_srpid] = BUF_strdup(user);
588                 row[DB_srptype] = BUF_strdup("v");
589                 row[DB_srpgN] = BUF_strdup(gNid);
590
591                 if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype]
592                     || !row[DB_srpverifier] || !row[DB_srpsalt]
593                     || (userinfo
594                         && (!(row[DB_srpinfo] = BUF_strdup(userinfo))))
595                     || !update_index(db, bio_err, row)) {
596                     if (row[DB_srpid])
597                         OPENSSL_free(row[DB_srpid]);
598                     if (row[DB_srpgN])
599                         OPENSSL_free(row[DB_srpgN]);
600                     if (row[DB_srpinfo])
601                         OPENSSL_free(row[DB_srpinfo]);
602                     if (row[DB_srptype])
603                         OPENSSL_free(row[DB_srptype]);
604                     if (row[DB_srpverifier])
605                         OPENSSL_free(row[DB_srpverifier]);
606                     if (row[DB_srpsalt])
607                         OPENSSL_free(row[DB_srpsalt]);
608                     goto err;
609                 }
610                 doupdatedb = 1;
611             }
612         } else if (modify_user) {
613             if (userindex < 0) {
614                 BIO_printf(bio_err,
615                            "user \"%s\" does not exist, operation ignored.\n",
616                            user);
617                 errors++;
618             } else {
619
620                 char **row =
621                     sk_OPENSSL_PSTRING_value(db->db->data, userindex);
622                 char type = row[DB_srptype][0];
623                 if (type == 'v') {
624                     BIO_printf(bio_err,
625                                "user \"%s\" already updated, operation ignored.\n",
626                                user);
627                     errors++;
628                 } else {
629                     char *gNid;
630
631                     if (row[DB_srptype][0] == 'V') {
632                         int user_gN;
633                         char **irow = NULL;
634                         VERBOSE BIO_printf(bio_err,
635                                            "Verifying password for user \"%s\"\n",
636                                            user);
637                         if ((user_gN =
638                              get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
639                             irow =
640                                 sk_OPENSSL_PSTRING_value(db->db->data,
641                                                          userindex);
642
643                         if (!srp_verify_user
644                             (user, row[DB_srpverifier], row[DB_srpsalt],
645                              irow ? irow[DB_srpsalt] : row[DB_srpgN],
646                              irow ? irow[DB_srpverifier] : NULL, passin,
647                              bio_err, verbose)) {
648                             BIO_printf(bio_err,
649                                        "Invalid password for user \"%s\", operation abandoned.\n",
650                                        user);
651                             errors++;
652                             goto err;
653                         }
654                     }
655                     VERBOSE BIO_printf(bio_err,
656                                        "Password for user \"%s\" ok.\n",
657                                        user);
658
659                     if (!(gNid = srp_create_user(user, &(row[DB_srpverifier]),
660                                                  &(row[DB_srpsalt]),
661                                                  gNrow ? gNrow[DB_srpsalt] :
662                                                  NULL,
663                                                  gNrow ? gNrow[DB_srpverifier]
664                                                  : NULL, passout, bio_err,
665                                                  verbose))) {
666                         BIO_printf(bio_err,
667                                    "Cannot create srp verifier for user \"%s\","
668                                    " operation abandoned.\n", user);
669                         errors++;
670                         goto err;
671                     }
672
673                     row[DB_srptype][0] = 'v';
674                     row[DB_srpgN] = BUF_strdup(gNid);
675
676                     if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype]
677                         || !row[DB_srpverifier] || !row[DB_srpsalt]
678                         || (userinfo
679                             && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))))
680                         goto err;
681
682                     doupdatedb = 1;
683                 }
684             }
685         } else if (delete_user) {
686             if (userindex < 0) {
687                 BIO_printf(bio_err,
688                            "user \"%s\" does not exist, operation ignored. t\n",
689                            user);
690                 errors++;
691             } else {
692                 char **xpp =
693                     sk_OPENSSL_PSTRING_value(db->db->data, userindex);
694                 BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
695
696                 xpp[DB_srptype][0] = 'R';
697
698                 doupdatedb = 1;
699             }
700         }
701         if (--argc > 0)
702             user = *(argv++);
703         else {
704             user = NULL;
705             list_user = 0;
706         }
707     }
708
709     VERBOSE BIO_printf(bio_err, "User procession done.\n");
710
711     if (doupdatedb) {
712         /* Lets check some fields */
713         for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
714             pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
715
716             if (pp[DB_srptype][0] == 'v') {
717                 pp[DB_srptype][0] = 'V';
718                 print_user(db, bio_err, i, verbose);
719             }
720         }
721
722         VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n");
723         if (!save_index(dbfile, "new", db))
724             goto err;
725
726         VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n");
727         if (!rotate_index(dbfile, "new", "old"))
728             goto err;
729
730         VERBOSE BIO_printf(bio_err, "srpvfile updated.\n");
731     }
732
733     ret = (errors != 0);
734  err:
735     if (errors != 0)
736         VERBOSE BIO_printf(bio_err, "User errors %d.\n", errors);
737
738     VERBOSE BIO_printf(bio_err, "SRP terminating with code %d.\n", ret);
739     if (tofree)
740         OPENSSL_free(tofree);
741     if (ret)
742         ERR_print_errors(bio_err);
743     if (randfile)
744         app_RAND_write_file(randfile, bio_err);
745     if (conf)
746         NCONF_free(conf);
747     if (db)
748         free_index(db);
749
750     OBJ_cleanup();
751     apps_shutdown();
752     OPENSSL_EXIT(ret);
753 }
754
755 #endif