yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame] | 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 | } |