source: rtems-libbsd/freebsd/crypto/openssl/apps/srp.c @ 0a699e7

5-freebsd-126-freebsd-12
Last change on this file since 0a699e7 was 0a699e7, checked in by Christian Mauderer <christian.mauderer@…>, on 03/28/19 at 06:13:59

bin/openssl: Import from FreeBSD.

  • Property mode set to 100644
File size: 20.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
5 * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
6 *
7 * Licensed under the OpenSSL license (the "License").  You may not use
8 * this file except in compliance with the License.  You can obtain a copy
9 * in the file LICENSE in the source distribution or at
10 * https://www.openssl.org/source/license.html
11 *
12 * Originally written by Christophe Renou and Peter Sylvester,
13 * for the EdelKey project.
14 */
15
16#include <openssl/opensslconf.h>
17#ifdef OPENSSL_NO_SRP
18NON_EMPTY_TRANSLATION_UNIT
19#else
20
21# include <stdio.h>
22# include <stdlib.h>
23# include <string.h>
24# include <openssl/conf.h>
25# include <openssl/bio.h>
26# include <openssl/err.h>
27# include <openssl/txt_db.h>
28# include <openssl/buffer.h>
29# include <openssl/srp.h>
30# include "apps.h"
31# include "progs.h"
32
33# define BASE_SECTION    "srp"
34# define CONFIG_FILE "openssl.cnf"
35
36
37# define ENV_DATABASE            "srpvfile"
38# define ENV_DEFAULT_SRP         "default_srp"
39
40static int get_index(CA_DB *db, char *id, char type)
41{
42    char **pp;
43    int i;
44    if (id == NULL)
45        return -1;
46    if (type == DB_SRP_INDEX) {
47        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
48            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
49            if (pp[DB_srptype][0] == DB_SRP_INDEX
50                && strcmp(id, pp[DB_srpid]) == 0)
51                return i;
52        }
53    } else {
54        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
55            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
56
57            if (pp[DB_srptype][0] != DB_SRP_INDEX
58                && strcmp(id, pp[DB_srpid]) == 0)
59                return i;
60        }
61    }
62
63    return -1;
64}
65
66static void print_entry(CA_DB *db, int indx, int verbose, char *s)
67{
68    if (indx >= 0 && verbose) {
69        int j;
70        char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx);
71        BIO_printf(bio_err, "%s \"%s\"\n", s, pp[DB_srpid]);
72        for (j = 0; j < DB_NUMBER; j++) {
73            BIO_printf(bio_err, "  %d = \"%s\"\n", j, pp[j]);
74        }
75    }
76}
77
78static void print_index(CA_DB *db, int indexindex, int verbose)
79{
80    print_entry(db, indexindex, verbose, "g N entry");
81}
82
83static void print_user(CA_DB *db, int userindex, int verbose)
84{
85    if (verbose > 0) {
86        char **pp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
87
88        if (pp[DB_srptype][0] != 'I') {
89            print_entry(db, userindex, verbose, "User entry");
90            print_entry(db, get_index(db, pp[DB_srpgN], 'I'), verbose,
91                        "g N entry");
92        }
93
94    }
95}
96
97static int update_index(CA_DB *db, char **row)
98{
99    char **irow;
100    int i;
101
102    irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row pointers");
103    for (i = 0; i < DB_NUMBER; i++)
104        irow[i] = row[i];
105    irow[DB_NUMBER] = NULL;
106
107    if (!TXT_DB_insert(db->db, irow)) {
108        BIO_printf(bio_err, "failed to update srpvfile\n");
109        BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
110        OPENSSL_free(irow);
111        return 0;
112    }
113    return 1;
114}
115
116static char *lookup_conf(const CONF *conf, const char *section, const char *tag)
117{
118    char *entry = NCONF_get_string(conf, section, tag);
119    if (entry == NULL)
120        BIO_printf(bio_err, "variable lookup failed for %s::%s\n", section, tag);
121    return entry;
122}
123
124static char *srp_verify_user(const char *user, const char *srp_verifier,
125                             char *srp_usersalt, const char *g, const char *N,
126                             const char *passin, int verbose)
127{
128    char password[1025];
129    PW_CB_DATA cb_tmp;
130    char *verifier = NULL;
131    char *gNid = NULL;
132    int len;
133
134    cb_tmp.prompt_info = user;
135    cb_tmp.password = passin;
136
137    len = password_callback(password, sizeof(password)-1, 0, &cb_tmp);
138    if (len > 0) {
139        password[len] = 0;
140        if (verbose)
141            BIO_printf(bio_err,
142                       "Validating\n   user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",
143                       user, srp_verifier, srp_usersalt, g, N);
144        if (verbose > 1)
145            BIO_printf(bio_err, "Pass %s\n", password);
146
147        OPENSSL_assert(srp_usersalt != NULL);
148        if ((gNid = SRP_create_verifier(user, password, &srp_usersalt,
149                                        &verifier, N, g)) == NULL) {
150            BIO_printf(bio_err, "Internal error validating SRP verifier\n");
151        } else {
152            if (strcmp(verifier, srp_verifier))
153                gNid = NULL;
154            OPENSSL_free(verifier);
155        }
156        OPENSSL_cleanse(password, len);
157    }
158    return gNid;
159}
160
161static char *srp_create_user(char *user, char **srp_verifier,
162                             char **srp_usersalt, char *g, char *N,
163                             char *passout, int verbose)
164{
165    char password[1025];
166    PW_CB_DATA cb_tmp;
167    char *gNid = NULL;
168    char *salt = NULL;
169    int len;
170    cb_tmp.prompt_info = user;
171    cb_tmp.password = passout;
172
173    len = password_callback(password, sizeof(password)-1, 1, &cb_tmp);
174    if (len > 0) {
175        password[len] = 0;
176        if (verbose)
177            BIO_printf(bio_err, "Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",
178                       user, g, N);
179        if ((gNid = SRP_create_verifier(user, password, &salt,
180                                        srp_verifier, N, g)) == NULL) {
181            BIO_printf(bio_err, "Internal error creating SRP verifier\n");
182        } else {
183            *srp_usersalt = salt;
184        }
185        OPENSSL_cleanse(password, len);
186        if (verbose > 1)
187            BIO_printf(bio_err, "gNid=%s salt =\"%s\"\n verifier =\"%s\"\n",
188                       gNid, salt, *srp_verifier);
189
190    }
191    return gNid;
192}
193
194typedef enum OPTION_choice {
195    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
196    OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD,
197    OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO,
198    OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM
199} OPTION_CHOICE;
200
201const OPTIONS srp_options[] = {
202    {"help", OPT_HELP, '-', "Display this summary"},
203    {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"},
204    {"config", OPT_CONFIG, '<', "A config file"},
205    {"name", OPT_NAME, 's', "The particular srp definition to use"},
206    {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"},
207    {"add", OPT_ADD, '-', "Add a user and srp verifier"},
208    {"modify", OPT_MODIFY, '-',
209     "Modify the srp verifier of an existing user"},
210    {"delete", OPT_DELETE, '-', "Delete user from verifier file"},
211    {"list", OPT_LIST, '-', "List users"},
212    {"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"},
213    {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"},
214    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
215    {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
216    OPT_R_OPTIONS,
217# ifndef OPENSSL_NO_ENGINE
218    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
219# endif
220    {NULL}
221};
222
223int srp_main(int argc, char **argv)
224{
225    ENGINE *e = NULL;
226    CA_DB *db = NULL;
227    CONF *conf = NULL;
228    int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i;
229    int doupdatedb = 0, mode = OPT_ERR;
230    char *user = NULL, *passinarg = NULL, *passoutarg = NULL;
231    char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;
232    char *section = NULL;
233    char **gNrow = NULL, *configfile = NULL;
234    char *srpvfile = NULL, **pp, *prog;
235    OPTION_CHOICE o;
236
237    prog = opt_init(argc, argv, srp_options);
238    while ((o = opt_next()) != OPT_EOF) {
239        switch (o) {
240        case OPT_EOF:
241        case OPT_ERR:
242 opthelp:
243            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
244            goto end;
245        case OPT_HELP:
246            opt_help(srp_options);
247            ret = 0;
248            goto end;
249        case OPT_VERBOSE:
250            verbose++;
251            break;
252        case OPT_CONFIG:
253            configfile = opt_arg();
254            break;
255        case OPT_NAME:
256            section = opt_arg();
257            break;
258        case OPT_SRPVFILE:
259            srpvfile = opt_arg();
260            break;
261        case OPT_ADD:
262        case OPT_DELETE:
263        case OPT_MODIFY:
264        case OPT_LIST:
265            if (mode != OPT_ERR) {
266                BIO_printf(bio_err,
267                           "%s: Only one of -add/-delete/-modify/-list\n",
268                           prog);
269                goto opthelp;
270            }
271            mode = o;
272            break;
273        case OPT_GN:
274            gN = opt_arg();
275            break;
276        case OPT_USERINFO:
277            userinfo = opt_arg();
278            break;
279        case OPT_PASSIN:
280            passinarg = opt_arg();
281            break;
282        case OPT_PASSOUT:
283            passoutarg = opt_arg();
284            break;
285        case OPT_ENGINE:
286            e = setup_engine(opt_arg(), 0);
287            break;
288        case OPT_R_CASES:
289            if (!opt_rand(o))
290                goto end;
291            break;
292        }
293    }
294    argc = opt_num_rest();
295    argv = opt_rest();
296
297    if (srpvfile != NULL && configfile != NULL) {
298        BIO_printf(bio_err,
299                   "-srpvfile and -configfile cannot be specified together.\n");
300        goto end;
301    }
302    if (mode == OPT_ERR) {
303        BIO_printf(bio_err,
304                   "Exactly one of the options -add, -delete, -modify -list must be specified.\n");
305        goto opthelp;
306    }
307    if (mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD) {
308        if (argc == 0) {
309            BIO_printf(bio_err, "Need at least one user.\n");
310            goto opthelp;
311        }
312        user = *argv++;
313    }
314    if ((passinarg != NULL || passoutarg != NULL) && argc != 1) {
315        BIO_printf(bio_err,
316                   "-passin, -passout arguments only valid with one user.\n");
317        goto opthelp;
318    }
319
320    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
321        BIO_printf(bio_err, "Error getting passwords\n");
322        goto end;
323    }
324
325    if (srpvfile == NULL) {
326        if (configfile == NULL)
327            configfile = default_config_file;
328
329        if (verbose)
330            BIO_printf(bio_err, "Using configuration from %s\n",
331                       configfile);
332        conf = app_load_config(configfile);
333        if (conf == NULL)
334            goto end;
335        if (configfile != default_config_file && !app_load_modules(conf))
336            goto end;
337
338        /* Lets get the config section we are using */
339        if (section == NULL) {
340            if (verbose)
341                BIO_printf(bio_err,
342                           "trying to read " ENV_DEFAULT_SRP
343                           " in " BASE_SECTION "\n");
344
345            section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP);
346            if (section == NULL)
347                goto end;
348        }
349
350        app_RAND_load_conf(conf, BASE_SECTION);
351
352        if (verbose)
353            BIO_printf(bio_err,
354                       "trying to read " ENV_DATABASE " in section \"%s\"\n",
355                       section);
356
357        srpvfile = lookup_conf(conf, section, ENV_DATABASE);
358        if (srpvfile == NULL)
359            goto end;
360    }
361
362    if (verbose)
363        BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
364                   srpvfile);
365
366    db = load_index(srpvfile, NULL);
367    if (db == NULL)
368        goto end;
369
370    /* Lets check some fields */
371    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
372        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
373
374        if (pp[DB_srptype][0] == DB_SRP_INDEX) {
375            maxgN = i;
376            if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0)
377                gNindex = i;
378
379            print_index(db, i, verbose > 1);
380        }
381    }
382
383    if (verbose)
384        BIO_printf(bio_err, "Database initialised\n");
385
386    if (gNindex >= 0) {
387        gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
388        print_entry(db, gNindex, verbose > 1, "Default g and N");
389    } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {
390        BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
391        goto end;
392    } else {
393        if (verbose)
394            BIO_printf(bio_err, "Database has no g N information.\n");
395        gNrow = NULL;
396    }
397
398    if (verbose > 1)
399        BIO_printf(bio_err, "Starting user processing\n");
400
401    while (mode == OPT_LIST || user != NULL) {
402        int userindex = -1;
403
404        if (user != NULL && verbose > 1)
405            BIO_printf(bio_err, "Processing user \"%s\"\n", user);
406        if ((userindex = get_index(db, user, 'U')) >= 0)
407            print_user(db, userindex, (verbose > 0) || mode == OPT_LIST);
408
409        if (mode == OPT_LIST) {
410            if (user == NULL) {
411                BIO_printf(bio_err, "List all users\n");
412
413                for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
414                    print_user(db, i, 1);
415            } else if (userindex < 0) {
416                BIO_printf(bio_err,
417                           "user \"%s\" does not exist, ignored. t\n", user);
418                errors++;
419            }
420        } else if (mode == OPT_ADD) {
421            if (userindex >= 0) {
422                /* reactivation of a new user */
423                char **row =
424                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);
425                BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
426                row[DB_srptype][0] = 'V';
427
428                doupdatedb = 1;
429            } else {
430                char *row[DB_NUMBER];
431                char *gNid;
432                row[DB_srpverifier] = NULL;
433                row[DB_srpsalt] = NULL;
434                row[DB_srpinfo] = NULL;
435                if (!
436                    (gNid =
437                     srp_create_user(user, &(row[DB_srpverifier]),
438                                     &(row[DB_srpsalt]),
439                                     gNrow ? gNrow[DB_srpsalt] : gN,
440                                     gNrow ? gNrow[DB_srpverifier] : NULL,
441                                     passout, verbose))) {
442                    BIO_printf(bio_err,
443                               "Cannot create srp verifier for user \"%s\", operation abandoned .\n",
444                               user);
445                    errors++;
446                    goto end;
447                }
448                row[DB_srpid] = OPENSSL_strdup(user);
449                row[DB_srptype] = OPENSSL_strdup("v");
450                row[DB_srpgN] = OPENSSL_strdup(gNid);
451
452                if ((row[DB_srpid] == NULL)
453                    || (row[DB_srpgN] == NULL)
454                    || (row[DB_srptype] == NULL)
455                    || (row[DB_srpverifier] == NULL)
456                    || (row[DB_srpsalt] == NULL)
457                    || (userinfo
458                        && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL))
459                    || !update_index(db, row)) {
460                    OPENSSL_free(row[DB_srpid]);
461                    OPENSSL_free(row[DB_srpgN]);
462                    OPENSSL_free(row[DB_srpinfo]);
463                    OPENSSL_free(row[DB_srptype]);
464                    OPENSSL_free(row[DB_srpverifier]);
465                    OPENSSL_free(row[DB_srpsalt]);
466                    goto end;
467                }
468                doupdatedb = 1;
469            }
470        } else if (mode == OPT_MODIFY) {
471            if (userindex < 0) {
472                BIO_printf(bio_err,
473                           "user \"%s\" does not exist, operation ignored.\n",
474                           user);
475                errors++;
476            } else {
477
478                char **row =
479                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);
480                char type = row[DB_srptype][0];
481                if (type == 'v') {
482                    BIO_printf(bio_err,
483                               "user \"%s\" already updated, operation ignored.\n",
484                               user);
485                    errors++;
486                } else {
487                    char *gNid;
488
489                    if (row[DB_srptype][0] == 'V') {
490                        int user_gN;
491                        char **irow = NULL;
492                        if (verbose)
493                            BIO_printf(bio_err,
494                                       "Verifying password for user \"%s\"\n",
495                                       user);
496                        if ((user_gN =
497                             get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
498                            irow =
499                                sk_OPENSSL_PSTRING_value(db->db->data,
500                                                         userindex);
501
502                        if (!srp_verify_user
503                            (user, row[DB_srpverifier], row[DB_srpsalt],
504                             irow ? irow[DB_srpsalt] : row[DB_srpgN],
505                             irow ? irow[DB_srpverifier] : NULL, passin,
506                             verbose)) {
507                            BIO_printf(bio_err,
508                                       "Invalid password for user \"%s\", operation abandoned.\n",
509                                       user);
510                            errors++;
511                            goto end;
512                        }
513                    }
514                    if (verbose)
515                        BIO_printf(bio_err, "Password for user \"%s\" ok.\n",
516                                   user);
517
518                    if (!
519                        (gNid =
520                         srp_create_user(user, &(row[DB_srpverifier]),
521                                         &(row[DB_srpsalt]),
522                                         gNrow ? gNrow[DB_srpsalt] : NULL,
523                                         gNrow ? gNrow[DB_srpverifier] : NULL,
524                                         passout, verbose))) {
525                        BIO_printf(bio_err,
526                                   "Cannot create srp verifier for user \"%s\", operation abandoned.\n",
527                                   user);
528                        errors++;
529                        goto end;
530                    }
531
532                    row[DB_srptype][0] = 'v';
533                    row[DB_srpgN] = OPENSSL_strdup(gNid);
534
535                    if (row[DB_srpid] == NULL
536                        || row[DB_srpgN] == NULL
537                        || row[DB_srptype] == NULL
538                        || row[DB_srpverifier] == NULL
539                        || row[DB_srpsalt] == NULL
540                        || (userinfo
541                            && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo))
542                                == NULL)))
543                        goto end;
544
545                    doupdatedb = 1;
546                }
547            }
548        } else if (mode == OPT_DELETE) {
549            if (userindex < 0) {
550                BIO_printf(bio_err,
551                           "user \"%s\" does not exist, operation ignored. t\n",
552                           user);
553                errors++;
554            } else {
555                char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
556
557                BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
558                xpp[DB_srptype][0] = 'R';
559                doupdatedb = 1;
560            }
561        }
562        user = *argv++;
563        if (user == NULL) {
564            /* no more processing in any mode if no users left */
565            break;
566        }
567    }
568
569    if (verbose)
570        BIO_printf(bio_err, "User procession done.\n");
571
572    if (doupdatedb) {
573        /* Lets check some fields */
574        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
575            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
576
577            if (pp[DB_srptype][0] == 'v') {
578                pp[DB_srptype][0] = 'V';
579                print_user(db, i, verbose);
580            }
581        }
582
583        if (verbose)
584            BIO_printf(bio_err, "Trying to update srpvfile.\n");
585        if (!save_index(srpvfile, "new", db))
586            goto end;
587
588        if (verbose)
589            BIO_printf(bio_err, "Temporary srpvfile created.\n");
590        if (!rotate_index(srpvfile, "new", "old"))
591            goto end;
592
593        if (verbose)
594            BIO_printf(bio_err, "srpvfile updated.\n");
595    }
596
597    ret = (errors != 0);
598 end:
599    if (errors != 0)
600        if (verbose)
601            BIO_printf(bio_err, "User errors %d.\n", errors);
602
603    if (verbose)
604        BIO_printf(bio_err, "SRP terminating with code %d.\n", ret);
605
606    OPENSSL_free(passin);
607    OPENSSL_free(passout);
608    if (ret)
609        ERR_print_errors(bio_err);
610    NCONF_free(conf);
611    free_index(db);
612    release_engine(e);
613    return ret;
614}
615#endif
Note: See TracBrowser for help on using the repository browser.