+int srp_main(int argc, char **argv)
+{
+ CA_DB *db = NULL;
+ DB_ATTR db_attr;
+ CONF *conf = NULL;
+ int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i;
+ int doupdatedb = 0, mode = OPT_ERR;
+ char *user = NULL, *passinarg = NULL, *passoutarg = NULL;
+ char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;
+ char *randfile = NULL, *tofree = NULL, *section = NULL;
+ char **gNrow = NULL, *configfile = default_config_file;
+ char *dbfile = NULL, **pp, *prog;
+ OPTION_CHOICE o;
+
+ prog = opt_init(argc, argv, srp_options);
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_EOF:
+ case OPT_ERR:
+ opthelp:
+ BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+ goto end;
+ case OPT_HELP:
+ opt_help(srp_options);
+ ret = 0;
+ goto end;
+ case OPT_VERBOSE:
+ verbose++;
+ break;
+ case OPT_CONFIG:
+ configfile = opt_arg();
+ break;
+ case OPT_NAME:
+ section = opt_arg();
+ break;
+ case OPT_SRPVFILE:
+ dbfile = opt_arg();
+ break;
+ case OPT_ADD:
+ case OPT_DELETE:
+ case OPT_MODIFY:
+ case OPT_LIST:
+ if (mode != OPT_ERR) {
+ BIO_printf(bio_err,
+ "%s: Only one of -add/delete-modify/-list\n",
+ prog);
+ goto opthelp;
+ }
+ mode = o;
+ break;
+ case OPT_GN:
+ gN = opt_arg();
+ break;
+ case OPT_USERINFO:
+ userinfo = opt_arg();
+ break;
+ case OPT_PASSIN:
+ passinarg = opt_arg();
+ break;
+ case OPT_PASSOUT:
+ passoutarg = opt_arg();
+ break;
+ case OPT_ENGINE:
+ (void)setup_engine(opt_arg(), 0);
+ break;
+ }
+ }
+ argc = opt_num_rest();
+ argv = opt_rest();
+
+ if (dbfile && configfile) {
+ BIO_printf(bio_err,
+ "-dbfile and -configfile cannot be specified together.\n");
+ goto end;
+ }
+ if (mode == OPT_ERR) {
+ BIO_printf(bio_err,
+ "Exactly one of the options -add, -delete, -modify -list must be specified.\n");
+ goto opthelp;
+ }
+ if ((mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD)
+ && argc < 1) {
+ BIO_printf(bio_err,
+ "Need at least one user for options -add, -delete, -modify. \n");
+ goto opthelp;
+ }
+ if ((passin || passout) && argc != 1) {
+ BIO_printf(bio_err,
+ "-passin, -passout arguments only valid with one user.\n");
+ goto opthelp;
+ }
+
+ if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
+ BIO_printf(bio_err, "Error getting passwords\n");
+ goto end;
+ }
+
+ if (!dbfile) {
+ if (verbose)
+ BIO_printf(bio_err, "Using configuration from %s\n",
+ configfile);
+ conf = app_load_config(configfile);
+ if (conf == NULL)
+ goto end;
+ if (!app_load_modules(conf))
+ goto end;
+
+ /* Lets get the config section we are using */
+ if (section == NULL) {
+ if (verbose)
+ BIO_printf(bio_err,
+ "trying to read " ENV_DEFAULT_SRP
+ " in \" BASE_SECTION \"\n");
+
+ section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_SRP);
+ if (section == NULL) {
+ lookup_fail(BASE_SECTION, ENV_DEFAULT_SRP);
+ goto end;
+ }
+ }
+
+ if (randfile == NULL && conf)
+ randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
+
+ if (verbose)
+ BIO_printf(bio_err,
+ "trying to read " ENV_DATABASE " in section \"%s\"\n",
+ section);
+
+ if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
+ lookup_fail(section, ENV_DATABASE);
+ goto end;
+ }
+
+ }
+ if (randfile == NULL)
+ ERR_clear_error();
+ else
+ app_RAND_load_file(randfile, 0);
+
+ if (verbose)
+ BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
+ dbfile);
+
+ db = load_index(dbfile, &db_attr);
+ if (db == NULL)
+ goto end;
+
+ /* Lets check some fields */
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] == DB_SRP_INDEX) {
+ maxgN = i;
+ if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0)
+ gNindex = i;
+
+ print_index(db, i, verbose > 1);
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Database initialised\n");
+
+ if (gNindex >= 0) {
+ gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
+ print_entry(db, gNindex, verbose > 1, "Default g and N");
+ } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {
+ BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
+ goto end;
+ } else {
+ if (verbose)
+ BIO_printf(bio_err, "Database has no g N information.\n");
+ gNrow = NULL;
+ }
+
+ if (verbose > 1)
+ BIO_printf(bio_err, "Starting user processing\n");
+
+ if (argc > 0)
+ user = *(argv++);
+
+ while (mode == OPT_LIST || user) {
+ int userindex = -1;
+ if (user)
+ if (verbose > 1)
+ BIO_printf(bio_err, "Processing user \"%s\"\n", user);
+ if ((userindex = get_index(db, user, 'U')) >= 0) {
+ print_user(db, userindex, (verbose > 0)
+ || mode == OPT_LIST);
+ }
+
+ if (mode == OPT_LIST) {
+ if (user == NULL) {
+ BIO_printf(bio_err, "List all users\n");
+
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ print_user(db, i, 1);
+ }
+ } else if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, ignored. t\n", user);
+ errors++;
+ }
+ } else if (mode == OPT_ADD) {
+ if (userindex >= 0) {
+ /* reactivation of a new user */
+ char **row =
+ sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+ BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
+ row[DB_srptype][0] = 'V';
+
+ doupdatedb = 1;
+ } else {
+ char *row[DB_NUMBER];
+ char *gNid;
+ row[DB_srpverifier] = NULL;
+ row[DB_srpsalt] = NULL;
+ row[DB_srpinfo] = NULL;
+ if (!
+ (gNid =
+ srp_create_user(user, &(row[DB_srpverifier]),
+ &(row[DB_srpsalt]),
+ gNrow ? gNrow[DB_srpsalt] : gN,
+ gNrow ? gNrow[DB_srpverifier] : NULL,
+ passout, verbose))) {
+ BIO_printf(bio_err,
+ "Cannot create srp verifier for user \"%s\", operation abandoned .\n",
+ user);
+ errors++;
+ goto end;
+ }
+ row[DB_srpid] = BUF_strdup(user);
+ row[DB_srptype] = BUF_strdup("v");
+ row[DB_srpgN] = BUF_strdup(gNid);
+
+ if ((row[DB_srpid] == NULL)
+ || (row[DB_srpgN] == NULL)
+ || (row[DB_srptype] == NULL)
+ || (row[DB_srpverifier] == NULL)
+ || (row[DB_srpsalt] == NULL)
+ || (userinfo
+ && ((row[DB_srpinfo] = BUF_strdup(userinfo)) == NULL))
+ || !update_index(db, row)) {
+ OPENSSL_free(row[DB_srpid]);
+ OPENSSL_free(row[DB_srpgN]);
+ OPENSSL_free(row[DB_srpinfo]);
+ OPENSSL_free(row[DB_srptype]);
+ OPENSSL_free(row[DB_srpverifier]);
+ OPENSSL_free(row[DB_srpsalt]);
+ goto end;
+ }
+ doupdatedb = 1;
+ }
+ } else if (mode == OPT_MODIFY) {
+ if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, operation ignored.\n",
+ user);
+ errors++;
+ } else {
+
+ char **row =
+ sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+ char type = row[DB_srptype][0];
+ if (type == 'v') {
+ BIO_printf(bio_err,
+ "user \"%s\" already updated, operation ignored.\n",
+ user);
+ errors++;
+ } else {
+ char *gNid;
+
+ if (row[DB_srptype][0] == 'V') {
+ int user_gN;
+ char **irow = NULL;
+ if (verbose)
+ BIO_printf(bio_err,
+ "Verifying password for user \"%s\"\n",
+ user);
+ if ((user_gN =
+ get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
+ irow =
+ sk_OPENSSL_PSTRING_value(db->db->data,
+ userindex);
+
+ if (!srp_verify_user
+ (user, row[DB_srpverifier], row[DB_srpsalt],
+ irow ? irow[DB_srpsalt] : row[DB_srpgN],
+ irow ? irow[DB_srpverifier] : NULL, passin,
+ verbose)) {
+ BIO_printf(bio_err,
+ "Invalid password for user \"%s\", operation abandoned.\n",
+ user);
+ errors++;
+ goto end;
+ }
+ }
+ if (verbose)
+ BIO_printf(bio_err, "Password for user \"%s\" ok.\n",
+ user);
+
+ if (!
+ (gNid =
+ srp_create_user(user, &(row[DB_srpverifier]),
+ &(row[DB_srpsalt]),
+ gNrow ? gNrow[DB_srpsalt] : NULL,
+ gNrow ? gNrow[DB_srpverifier] : NULL,
+ passout, verbose))) {
+ BIO_printf(bio_err,
+ "Cannot create srp verifier for user \"%s\", operation abandoned.\n",
+ user);
+ errors++;
+ goto end;
+ }
+
+ row[DB_srptype][0] = 'v';
+ row[DB_srpgN] = BUF_strdup(gNid);
+
+ if (row[DB_srpid] == NULL
+ || row[DB_srpgN] == NULL
+ || row[DB_srptype] == NULL
+ || row[DB_srpverifier] == NULL
+ || row[DB_srpsalt] == NULL
+ || (userinfo
+ && ((row[DB_srpinfo] = BUF_strdup(userinfo))
+ == NULL)))
+ goto end;
+
+ doupdatedb = 1;
+ }
+ }
+ } else if (mode == OPT_DELETE) {
+ if (userindex < 0) {
+ BIO_printf(bio_err,
+ "user \"%s\" does not exist, operation ignored. t\n",
+ user);
+ errors++;
+ } else {
+ char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+ BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
+ xpp[DB_srptype][0] = 'R';
+ doupdatedb = 1;
+ }
+ }
+ if (--argc > 0)
+ user = *(argv++);
+ else {
+ user = NULL;
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "User procession done.\n");
+
+ if (doupdatedb) {
+ /* Lets check some fields */
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
+ pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] == 'v') {
+ pp[DB_srptype][0] = 'V';
+ print_user(db, i, verbose);
+ }
+ }
+
+ if (verbose)
+ BIO_printf(bio_err, "Trying to update srpvfile.\n");
+ if (!save_index(dbfile, "new", db))
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "Temporary srpvfile created.\n");
+ if (!rotate_index(dbfile, "new", "old"))
+ goto end;
+
+ if (verbose)
+ BIO_printf(bio_err, "srpvfile updated.\n");
+ }
+
+ ret = (errors != 0);
+ end:
+ if (errors != 0)
+ if (verbose)
+ BIO_printf(bio_err, "User errors %d.\n", errors);
+
+ if (verbose)
+ BIO_printf(bio_err, "SRP terminating with code %d.\n", ret);
+ OPENSSL_free(tofree);
+ if (ret)
+ ERR_print_errors(bio_err);
+ if (randfile)
+ app_RAND_write_file(randfile);
+ NCONF_free(conf);
+ free_index(db);
+ OBJ_cleanup();
+ return (ret);
+}