srp.c 20 KB

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