"Fossies" - the Fresh Open Source Software Archive

Member "openssl-1.1.1g/apps/srp.c" (21 Apr 2020, 20569 Bytes) of package /linux/misc/openssl-1.1.1g.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "srp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.1.1f_vs_1.1.1g.

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