PageRenderTime 66ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/certmonger-0.59/src/getcert.c

#
C | 2728 lines | 2606 code | 62 blank | 60 comment | 670 complexity | 8706463cf75bba2820998d3de4264329 MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2009,2010,2011,2012 Red Hat, Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "config.h"
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <getopt.h>
  23. #include <limits.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <time.h>
  28. #include <unistd.h>
  29. #include <talloc.h>
  30. #include <dbus/dbus.h>
  31. #include <krb5.h>
  32. #include "cm.h"
  33. #include "oiddict.h"
  34. #include "store.h"
  35. #include "store-int.h"
  36. #include "tdbus.h"
  37. #include "tdbusm.h"
  38. #ifdef ENABLE_NLS
  39. #include <libintl.h>
  40. #define _(_text) dgettext(PACKAGE, _text)
  41. #else
  42. #define _(_text) (_text)
  43. #endif
  44. #define N_(_msg) (_msg)
  45. #ifdef FORCE_CA
  46. #define GETOPT_CA ""
  47. #define DEFAULT_CA FORCE_CA
  48. #else
  49. #define GETOPT_CA "c:"
  50. #define DEFAULT_CA NULL
  51. #endif
  52. static void help(const char *cmd, const char *category);
  53. static struct {
  54. DBusConnection *conn;
  55. void *tctx;
  56. } globals = {
  57. .conn = NULL,
  58. .tctx = NULL
  59. };
  60. static char *find_ca_by_name(void *parent, enum cm_tdbus_type bus,
  61. const char *nickname, int verbose);
  62. static char *find_request_by_name(void *parent, enum cm_tdbus_type bus,
  63. const char *path, int verbose);
  64. static char *find_ca_name(void *parent, enum cm_tdbus_type bus,
  65. const char *path, int verbose);
  66. static char *find_request_name(void *parent, enum cm_tdbus_type bus,
  67. const char *path, int verbose);
  68. /* Ensure that a pathname is an absolute pathname. */
  69. static char *
  70. ensure_path_is_absolute(void *parent, const char *path)
  71. {
  72. char buf[PATH_MAX + 1], *ret;
  73. if (path[0] == '/') {
  74. return talloc_strdup(parent, path);
  75. } else {
  76. if (getcwd(buf, sizeof(buf)) == buf) {
  77. ret = talloc_asprintf(parent, "%s/%s", buf, path);
  78. printf(_("Path \"%s\" is not absolute, "
  79. "attempting to "
  80. "use \"%s\" instead.\n"), path, ret);
  81. return ret;
  82. } else {
  83. printf(_("Path \"%s\" is not absolute, and "
  84. "there was an error determining the "
  85. "name of the current directory.\n"),
  86. path);
  87. exit(1);
  88. }
  89. }
  90. }
  91. /* Ensure that a pathname is a directory. */
  92. static int
  93. ensure_path_is_directory(char *path)
  94. {
  95. struct stat st;
  96. if (stat(path, &st) == 0) {
  97. if (S_ISDIR(st.st_mode)) {
  98. return 0;
  99. } else {
  100. printf(_("Path \"%s\" is not a directory.\n"),
  101. path);
  102. return -1;
  103. }
  104. } else {
  105. printf(_("Path \"%s\": %s.\n"), path, strerror(errno));
  106. return -1;
  107. }
  108. }
  109. /* Ensure that a pathname is at least in a directory which exists. */
  110. static int
  111. ensure_parent_is_directory(void *parent, const char *path)
  112. {
  113. char *tmp, *p;
  114. tmp = talloc_strdup(parent, path);
  115. if (tmp != NULL) {
  116. p = strrchr(tmp, '/');
  117. if (p != NULL) {
  118. if (p > tmp) {
  119. *p = '\0';
  120. } else {
  121. *(p + 1) = '\0';
  122. }
  123. return ensure_path_is_directory(tmp);
  124. }
  125. }
  126. return -1;
  127. }
  128. /* Ensure that a pathname is a regular file or missing. */
  129. static int
  130. ensure_path_is_regular(const char *path)
  131. {
  132. struct stat st;
  133. if (stat(path, &st) == 0) {
  134. if (S_ISREG(st.st_mode)) {
  135. return 0;
  136. }
  137. } else {
  138. if (errno == ENOENT) {
  139. return 0;
  140. }
  141. }
  142. printf(_("Path \"%s\" is not a regular file.\n"), path);
  143. return -1;
  144. }
  145. /* Ensure that we have a suitable NSS database location. */
  146. static char *
  147. ensure_nss(void *parent, const char *path, char **nss_scheme)
  148. {
  149. char *ret;
  150. *nss_scheme = NULL;
  151. if (strncmp(path, "sql:", 4) == 0) {
  152. *nss_scheme = talloc_strdup(parent, "sql");
  153. path += 4;
  154. } else
  155. if (strncmp(path, "dbm:", 4) == 0) {
  156. *nss_scheme = talloc_strdup(parent, "dbm");
  157. path += 4;
  158. } else
  159. if (strncmp(path, "rdb:", 4) == 0) {
  160. *nss_scheme = talloc_strdup(parent, "rdb");
  161. path += 4;
  162. } else
  163. if (strncmp(path, "extern:", 7) == 0) {
  164. *nss_scheme = talloc_strdup(parent, "extern");
  165. path += 7;
  166. }
  167. ret = ensure_path_is_absolute(parent, path);
  168. if (ret != NULL) {
  169. ret = cm_store_canonicalize_directory(parent, ret);
  170. }
  171. if (ret != NULL) {
  172. if (ensure_path_is_directory(ret) != 0) {
  173. ret = NULL;
  174. }
  175. }
  176. if (ret == NULL) {
  177. exit(1);
  178. }
  179. return ret;
  180. }
  181. /* Ensure that we have a suitable location for a PEM file. */
  182. static char *
  183. ensure_pem(void *parent, const char *path)
  184. {
  185. char *ret;
  186. ret = ensure_path_is_absolute(parent, path);
  187. if (ret != NULL) {
  188. ret = cm_store_canonicalize_directory(parent, ret);
  189. }
  190. if (ret != NULL) {
  191. if (ensure_parent_is_directory(parent, ret) != 0) {
  192. ret = NULL;
  193. }
  194. }
  195. if (ret != NULL) {
  196. if (ensure_path_is_regular(ret) != 0) {
  197. ret = NULL;
  198. }
  199. }
  200. if (ret == NULL) {
  201. exit(1);
  202. }
  203. return ret;
  204. }
  205. /* Add a string to a list. */
  206. static void
  207. add_string(void *parent, char ***dest, const char *value)
  208. {
  209. char **tmp;
  210. int i;
  211. for (i = 0; ((*dest) != NULL) && ((*dest)[i] != NULL); i++) {
  212. continue;
  213. }
  214. tmp = talloc_array_ptrtype(parent, tmp, i + 2);
  215. if (tmp == NULL) {
  216. printf(_("Out of memory.\n"));
  217. exit(1);
  218. }
  219. memcpy(tmp, *dest, sizeof(tmp[0]) * i);
  220. tmp[i] = talloc_strdup(tmp, value);
  221. i++;
  222. tmp[i] = NULL;
  223. *dest = tmp;
  224. }
  225. /* Connect to the bus and set up as much of the request as we can. */
  226. static DBusMessage *
  227. prep_req(enum cm_tdbus_type which,
  228. const char *path, const char *interface, const char *method)
  229. {
  230. DBusMessage *msg;
  231. if (globals.conn == NULL) {
  232. switch (which) {
  233. case cm_tdbus_session:
  234. globals.conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
  235. break;
  236. case cm_tdbus_system:
  237. globals.conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
  238. break;
  239. }
  240. if (globals.conn == NULL) {
  241. printf(_("Error connecting to DBus.\n"));
  242. printf(_("Please verify that the message bus (D-Bus) service is running.\n"));
  243. exit(1);
  244. }
  245. }
  246. msg = dbus_message_new_method_call(CM_DBUS_NAME,
  247. path, interface, method);
  248. if (msg == NULL) {
  249. printf(_("Error creating DBus request message.\n"));
  250. exit(1);
  251. }
  252. return msg;
  253. }
  254. /* Try to offer some advice based on the error. */
  255. static enum { hint_unknown, hint_found }
  256. print_hint(const char *error, const char *message)
  257. {
  258. char *text = NULL;
  259. void *ctx;
  260. ctx = talloc_new(NULL);
  261. text = cm_tdbusm_hint(ctx, error, message);
  262. if ((text == NULL) &&
  263. (strncmp(error, CM_DBUS_ERROR_BASE,
  264. strlen(CM_DBUS_ERROR_BASE)) == 0)) {
  265. text = talloc_asprintf(ctx, "%s\n", _(message));
  266. }
  267. if (text != NULL) {
  268. printf("%s", _(text));
  269. }
  270. talloc_free(ctx);
  271. return text ? hint_found : hint_unknown;
  272. }
  273. /* Send our request and return the response. If there's an error, exit. */
  274. static DBusMessage *
  275. send_req(DBusMessage *req, int verbose)
  276. {
  277. DBusMessage *rep;
  278. DBusError err;
  279. memset(&err, 0, sizeof(err));
  280. rep = dbus_connection_send_with_reply_and_block(globals.conn, req,
  281. 30 * 1000, &err);
  282. if (rep == NULL) {
  283. if (dbus_error_is_set(&err)) {
  284. if (err.name != NULL) {
  285. if ((print_hint(err.name,
  286. err.message) == hint_unknown) ||
  287. verbose) {
  288. if ((err.message != NULL) && verbose) {
  289. printf(_("Error %s: %s\n"),
  290. err.name,
  291. err.message);
  292. } else {
  293. printf(_("Error %s\n"),
  294. err.name);
  295. }
  296. }
  297. } else {
  298. if (err.message != NULL) {
  299. printf(_("Error: %s\n"), err.message);
  300. } else {
  301. printf(_("Received error response from "
  302. "local %s service.\n"),
  303. CM_DBUS_NAME);
  304. }
  305. }
  306. } else {
  307. printf(_("No response received from %s service.\n"),
  308. CM_DBUS_NAME);
  309. }
  310. exit(1);
  311. }
  312. dbus_message_unref(req);
  313. return rep;
  314. }
  315. /* Send the specified, argument-less method call to the named object and return
  316. * the reply message. */
  317. static DBusMessage *
  318. query_rep(enum cm_tdbus_type which,
  319. const char *path, const char *interface, const char *method,
  320. int verbose)
  321. {
  322. return send_req(prep_req(which, path, interface, method), verbose);
  323. }
  324. /* Send the specified, argument-less method call to the named object, and
  325. * return a sole boolean response. */
  326. static dbus_bool_t
  327. query_rep_b(enum cm_tdbus_type which,
  328. const char *path, const char *interface, const char *method,
  329. int verbose,
  330. void *parent)
  331. {
  332. DBusMessage *rep;
  333. dbus_bool_t b;
  334. rep = query_rep(which, path, interface, method, verbose);
  335. if (cm_tdbusm_get_b(rep, parent, &b) != 0) {
  336. printf(_("Error parsing server response.\n"));
  337. exit(1);
  338. }
  339. dbus_message_unref(rep);
  340. return b;
  341. }
  342. /* Send the specified, argument-less method call to the named object, and
  343. * return the single string from the response. */
  344. static char *
  345. query_rep_s(enum cm_tdbus_type which,
  346. const char *path, const char *interface, const char *method,
  347. int verbose,
  348. void *parent)
  349. {
  350. DBusMessage *rep;
  351. char *s;
  352. rep = query_rep(which, path, interface, method, verbose);
  353. if (cm_tdbusm_get_s(rep, parent, &s) != 0) {
  354. printf(_("Error parsing server response.\n"));
  355. exit(1);
  356. }
  357. dbus_message_unref(rep);
  358. return s;
  359. }
  360. /* Send the specified, argument-less method call to the named object, and
  361. * return the single object path from the response. */
  362. static char *
  363. query_rep_p(enum cm_tdbus_type which,
  364. const char *path, const char *interface, const char *method,
  365. int verbose,
  366. void *parent)
  367. {
  368. DBusMessage *rep;
  369. char *p;
  370. rep = query_rep(which, path, interface, method, verbose);
  371. if (cm_tdbusm_get_p(rep, parent, &p) != 0) {
  372. printf(_("Error parsing server response.\n"));
  373. exit(1);
  374. }
  375. dbus_message_unref(rep);
  376. return p;
  377. }
  378. /* Send the specified, argument-less method call to the named object, and
  379. * return the array of strings from the response. */
  380. static char **
  381. query_rep_as(enum cm_tdbus_type which,
  382. const char *path, const char *interface, const char *method,
  383. int verbose,
  384. void *parent)
  385. {
  386. DBusMessage *rep;
  387. char **as;
  388. rep = query_rep(which, path, interface, method, verbose);
  389. if (cm_tdbusm_get_as(rep, parent, &as) != 0) {
  390. printf(_("Error parsing server response.\n"));
  391. exit(1);
  392. }
  393. dbus_message_unref(rep);
  394. return as;
  395. }
  396. /* Send the specified, argument-less method call to the named object, and
  397. * return the array of paths from the response. */
  398. static char **
  399. query_rep_ap(enum cm_tdbus_type which,
  400. const char *path, const char *interface, const char *method,
  401. int verbose,
  402. void *parent)
  403. {
  404. DBusMessage *rep;
  405. char **ap;
  406. rep = query_rep(which, path, interface, method, verbose);
  407. if (cm_tdbusm_get_ap(rep, parent, &ap) != 0) {
  408. printf(_("Error parsing server response.\n"));
  409. exit(1);
  410. }
  411. dbus_message_unref(rep);
  412. return ap;
  413. }
  414. /* Send the specified, argument-less method call to the named object, and
  415. * return from two to four strings from the response. */
  416. static void
  417. query_rep_sososos(enum cm_tdbus_type which,
  418. const char *path, const char *interface, const char *method,
  419. int verbose,
  420. void *parent, char **s1, char **s2, char **s3, char **s4)
  421. {
  422. DBusMessage *rep;
  423. rep = query_rep(which, path, interface, method, verbose);
  424. if (cm_tdbusm_get_sososos(rep, parent, s1, s2, s3, s4) != 0) {
  425. printf(_("Error parsing server response.\n"));
  426. exit(1);
  427. }
  428. dbus_message_unref(rep);
  429. }
  430. /* Send a query for the value of the specified property to the named object and
  431. * return the reply message. */
  432. static DBusMessage *
  433. query_prop(enum cm_tdbus_type which,
  434. const char *path, const char *interface, const char *prop,
  435. int verbose)
  436. {
  437. DBusMessage *req;
  438. req = prep_req(which, path, DBUS_INTERFACE_PROPERTIES, "Get");
  439. cm_tdbusm_set_ss(req, interface, prop);
  440. return send_req(req, verbose);
  441. }
  442. /* Read a boolean property. */
  443. static dbus_bool_t
  444. query_prop_b(enum cm_tdbus_type which,
  445. const char *path, const char *interface, const char *prop,
  446. int verbose,
  447. void *parent)
  448. {
  449. DBusMessage *rep;
  450. dbus_bool_t b;
  451. rep = query_prop(which, path, interface, prop, verbose);
  452. if (cm_tdbusm_get_b(rep, parent, &b) != 0) {
  453. printf(_("Error parsing server response.\n"));
  454. exit(1);
  455. }
  456. dbus_message_unref(rep);
  457. return b;
  458. }
  459. /* Read a string property. */
  460. static char *
  461. query_prop_s(enum cm_tdbus_type which,
  462. const char *path, const char *interface, const char *prop,
  463. int verbose,
  464. void *parent)
  465. {
  466. DBusMessage *rep;
  467. char *s;
  468. rep = query_prop(which, path, interface, prop, verbose);
  469. if (cm_tdbusm_get_s(rep, parent, &s) != 0) {
  470. s = "";
  471. }
  472. dbus_message_unref(rep);
  473. return s;
  474. }
  475. /* Read a path property. */
  476. static char *
  477. query_prop_p(enum cm_tdbus_type which,
  478. const char *path, const char *interface, const char *prop,
  479. int verbose,
  480. void *parent)
  481. {
  482. DBusMessage *rep;
  483. char *p;
  484. rep = query_prop(which, path, interface, prop, verbose);
  485. if (cm_tdbusm_get_p(rep, parent, &p) != 0) {
  486. p = "";
  487. }
  488. dbus_message_unref(rep);
  489. return p;
  490. }
  491. /* Read an array-of-strings property. */
  492. static char **
  493. query_prop_as(enum cm_tdbus_type which,
  494. const char *path, const char *interface, const char *prop,
  495. int verbose,
  496. void *parent)
  497. {
  498. DBusMessage *rep;
  499. char **as;
  500. rep = query_prop(which, path, interface, prop, verbose);
  501. if (cm_tdbusm_get_as(rep, parent, &as) != 0) {
  502. as = NULL;
  503. }
  504. dbus_message_unref(rep);
  505. return as;
  506. }
  507. /* Add a new request. */
  508. static int
  509. request(const char *argv0, int argc, char **argv)
  510. {
  511. enum cm_tdbus_type bus = CM_DBUS_DEFAULT_BUS;
  512. char subject_default[LINE_MAX];
  513. char *nss_scheme, *dbdir = NULL, *token = NULL, *nickname = NULL;
  514. char *keyfile = NULL, *certfile = NULL, *capath;
  515. char *pin = NULL, *pinfile = NULL;
  516. int keysize = 0, auto_renew = 1, verbose = 0, c, i;
  517. char *ca = DEFAULT_CA, *subject = NULL, **eku = NULL, *oid, *id = NULL;
  518. char *profile = NULL;
  519. char **principal = NULL, **dns = NULL, **email = NULL;
  520. struct cm_tdbusm_dict param[35];
  521. const struct cm_tdbusm_dict *params[36];
  522. DBusMessage *req, *rep;
  523. dbus_bool_t b;
  524. char *p;
  525. krb5_context kctx;
  526. krb5_error_code kret;
  527. krb5_principal kprincipal;
  528. char *krealm, *kuprincipal, *precommand = NULL, *postcommand = NULL;
  529. memset(subject_default, '\0', sizeof(subject_default));
  530. strcpy(subject_default, "CN=");
  531. if (gethostname(subject_default + 3,
  532. sizeof(subject_default) - 4) != 0) {
  533. strcpy(subject_default, "CN=localhost");
  534. }
  535. subject = subject_default;
  536. kctx = NULL;
  537. if ((kret = krb5_init_context(&kctx)) != 0) {
  538. kctx = NULL;
  539. printf(_("Error initializing Kerberos library: %s.\n"),
  540. error_message(kret));
  541. return 1;
  542. }
  543. krealm = NULL;
  544. if ((kret = krb5_get_default_realm(kctx, &krealm)) != 0) {
  545. krealm = NULL;
  546. }
  547. opterr = 0;
  548. while ((c = getopt(argc, argv,
  549. ":d:n:t:k:f:I:g:rRN:U:K:D:E:sSp:P:vB:C:T:"
  550. GETOPT_CA)) != -1) {
  551. switch (c) {
  552. case 'd':
  553. nss_scheme = NULL;
  554. dbdir = ensure_nss(globals.tctx, optarg, &nss_scheme);
  555. if ((nss_scheme != NULL) && (dbdir != NULL)) {
  556. dbdir = talloc_asprintf(globals.tctx, "%s:%s",
  557. nss_scheme, dbdir);
  558. }
  559. break;
  560. case 't':
  561. token = talloc_strdup(globals.tctx, optarg);
  562. break;
  563. case 'n':
  564. nickname = talloc_strdup(globals.tctx, optarg);
  565. break;
  566. case 'k':
  567. keyfile = ensure_pem(globals.tctx, optarg);
  568. break;
  569. case 'f':
  570. certfile = ensure_pem(globals.tctx, optarg);
  571. break;
  572. case 'g':
  573. keysize = atoi(optarg);
  574. break;
  575. case 'I':
  576. id = talloc_strdup(globals.tctx, optarg);
  577. break;
  578. case 'r':
  579. auto_renew++;
  580. break;
  581. case 'R':
  582. auto_renew = 0;
  583. break;
  584. case 'c':
  585. ca = talloc_strdup(globals.tctx, optarg);
  586. break;
  587. case 'T':
  588. profile = talloc_strdup(globals.tctx, optarg);
  589. break;
  590. case 'N':
  591. subject = talloc_strdup(globals.tctx, optarg);
  592. break;
  593. case 'U':
  594. oid = cm_oid_from_name(globals.tctx, optarg);
  595. if ((oid == NULL) ||
  596. (strspn(oid, "0123456789.") != strlen(oid))) {
  597. printf(_("Could not evaluate OID \"%s\".\n"),
  598. optarg);
  599. return 1;
  600. }
  601. add_string(globals.tctx, &eku, oid);
  602. break;
  603. case 'K':
  604. kprincipal = NULL;
  605. if ((kret = krb5_parse_name(kctx, optarg,
  606. &kprincipal)) != 0) {
  607. printf(_("Error parsing Kerberos principal "
  608. "name \"%s\": %s.\n"), optarg,
  609. error_message(kret));
  610. return 1;
  611. }
  612. kuprincipal = NULL;
  613. if ((kret = krb5_unparse_name(kctx, kprincipal,
  614. &kuprincipal)) != 0) {
  615. printf(_("Error unparsing Kerberos principal "
  616. "name \"%s\": %s.\n"), optarg,
  617. error_message(kret));
  618. return 1;
  619. }
  620. add_string(globals.tctx, &principal, kuprincipal);
  621. krb5_free_principal(kctx, kprincipal);
  622. break;
  623. case 'D':
  624. add_string(globals.tctx, &dns, optarg);
  625. break;
  626. case 'E':
  627. add_string(globals.tctx, &email, optarg);
  628. break;
  629. case 's':
  630. bus = cm_tdbus_session;
  631. break;
  632. case 'S':
  633. bus = cm_tdbus_system;
  634. break;
  635. case 'p':
  636. pinfile = optarg;
  637. break;
  638. case 'P':
  639. pin = optarg;
  640. break;
  641. case 'B':
  642. precommand = optarg;
  643. break;
  644. case 'C':
  645. postcommand = optarg;
  646. break;
  647. case 'v':
  648. verbose++;
  649. break;
  650. default:
  651. if (c == ':') {
  652. fprintf(stderr,
  653. _("%s: option requires an argument -- '%c'\n"),
  654. "request", optopt);
  655. } else {
  656. fprintf(stderr,
  657. _("%s: invalid option -- '%c'\n"),
  658. "request", optopt);
  659. }
  660. help(argv0, "request");
  661. return 1;
  662. }
  663. }
  664. if (optind < argc) {
  665. for (c = optind; c < argc; c++) {
  666. printf(_("Error: unused extra argument \"%s\".\n"),
  667. argv[c]);
  668. }
  669. printf(_("Error: unused extra arguments were supplied.\n"));
  670. help(argv0, "request");
  671. return 1;
  672. }
  673. if (((dbdir != NULL) && (nickname == NULL)) ||
  674. ((dbdir == NULL) && (nickname != NULL))) {
  675. printf(_("Database location or nickname specified "
  676. "without the other.\n"));
  677. help(argv0, "request");
  678. return 1;
  679. }
  680. if ((dbdir != NULL) && (certfile != NULL)) {
  681. printf(_("Database directory and certificate file "
  682. "both specified.\n"));
  683. help(argv0, "request");
  684. return 1;
  685. }
  686. if ((dbdir == NULL) &&
  687. (nickname == NULL) &&
  688. (certfile == NULL)) {
  689. printf(_("None of database directory and nickname or "
  690. "certificate file specified.\n"));
  691. help(argv0, "request");
  692. return 1;
  693. }
  694. if ((certfile != NULL) && (keyfile != NULL) &&
  695. (strcmp(certfile, keyfile) == 0)) {
  696. printf(_("Key and certificate can not both be saved to the "
  697. "same file.\n"));
  698. help(argv0, "request");
  699. return 1;
  700. }
  701. i = 0;
  702. /* If the caller supplied _no_ naming information, substitute our own
  703. * defaults. */
  704. if ((subject == subject_default) &&
  705. (eku == NULL) &&
  706. (principal == NULL) &&
  707. (dns == NULL) &&
  708. (email == NULL)) {
  709. add_string(globals.tctx, &eku, "id-kp-serverAuth");
  710. if (krealm != NULL) {
  711. add_string(globals.tctx, &principal,
  712. talloc_asprintf(globals.tctx,
  713. "host/%s@%s",
  714. subject + 3, krealm));
  715. }
  716. add_string(globals.tctx, &dns, subject + 3);
  717. }
  718. #ifdef WITH_IPA
  719. if ((ca != NULL) && (strcmp(ca, "IPA") == 0)) {
  720. if (principal == NULL) {
  721. printf(_("The IPA backend requires the use of the "
  722. "-K option (principal name) when the "
  723. "-N option (subject name) is used.\n"));
  724. help(argv0, "request");
  725. return 1;
  726. }
  727. }
  728. #endif
  729. if ((dbdir != NULL) && (nickname != NULL)) {
  730. param[i].key = "KEY_STORAGE";
  731. param[i].value_type = cm_tdbusm_dict_s;
  732. param[i].value.s = "NSSDB";
  733. params[i] = &param[i];
  734. i++;
  735. param[i].key = "KEY_LOCATION";
  736. param[i].value_type = cm_tdbusm_dict_s;
  737. param[i].value.s = dbdir;
  738. params[i] = &param[i];
  739. i++;
  740. param[i].key = "KEY_NICKNAME";
  741. param[i].value_type = cm_tdbusm_dict_s;
  742. param[i].value.s = nickname;
  743. params[i] = &param[i];
  744. i++;
  745. if (token != NULL) {
  746. param[i].key = "KEY_TOKEN";
  747. param[i].value_type = cm_tdbusm_dict_s;
  748. param[i].value.s = token;
  749. params[i] = &param[i];
  750. i++;
  751. }
  752. param[i].key = "CERT_STORAGE";
  753. param[i].value_type = cm_tdbusm_dict_s;
  754. param[i].value.s = "NSSDB";
  755. params[i] = &param[i];
  756. i++;
  757. param[i].key = "CERT_LOCATION";
  758. param[i].value_type = cm_tdbusm_dict_s;
  759. param[i].value.s = dbdir;
  760. params[i] = &param[i];
  761. i++;
  762. param[i].key = "CERT_NICKNAME";
  763. param[i].value_type = cm_tdbusm_dict_s;
  764. param[i].value.s = nickname;
  765. params[i] = &param[i];
  766. i++;
  767. if (token != NULL) {
  768. param[i].key = "CERT_TOKEN";
  769. param[i].value_type = cm_tdbusm_dict_s;
  770. param[i].value.s = token;
  771. params[i] = &param[i];
  772. i++;
  773. }
  774. } else
  775. if (certfile != NULL) {
  776. if (keyfile != NULL) {
  777. param[i].key = "KEY_STORAGE";
  778. param[i].value_type = cm_tdbusm_dict_s;
  779. param[i].value.s = "FILE";
  780. params[i] = &param[i];
  781. i++;
  782. param[i].key = "KEY_LOCATION";
  783. param[i].value_type = cm_tdbusm_dict_s;
  784. param[i].value.s = keyfile;
  785. params[i] = &param[i];
  786. i++;
  787. } else {
  788. param[i].key = "KEY_STORAGE";
  789. param[i].value_type = cm_tdbusm_dict_s;
  790. param[i].value.s = "NONE";
  791. params[i] = &param[i];
  792. i++;
  793. }
  794. param[i].key = "CERT_STORAGE";
  795. param[i].value_type = cm_tdbusm_dict_s;
  796. param[i].value.s = "FILE";
  797. params[i] = &param[i];
  798. i++;
  799. param[i].key = "CERT_LOCATION";
  800. param[i].value_type = cm_tdbusm_dict_s;
  801. param[i].value.s = certfile;
  802. params[i] = &param[i];
  803. i++;
  804. }
  805. if (pin != NULL) {
  806. param[i].key = "KEY_PIN";
  807. param[i].value_type = cm_tdbusm_dict_s;
  808. param[i].value.s = pin;
  809. params[i] = &param[i];
  810. i++;
  811. }
  812. if (pinfile != NULL) {
  813. param[i].key = "KEY_PIN_FILE";
  814. param[i].value_type = cm_tdbusm_dict_s;
  815. param[i].value.s = pinfile;
  816. params[i] = &param[i];
  817. i++;
  818. }
  819. param[i].key = "TRACK";
  820. param[i].value_type = cm_tdbusm_dict_b;
  821. param[i].value.b = TRUE;
  822. params[i] = &param[i];
  823. i++;
  824. param[i].key = "RENEW";
  825. param[i].value_type = cm_tdbusm_dict_b;
  826. param[i].value.b = auto_renew > 0;
  827. params[i] = &param[i];
  828. i++;
  829. if (keysize > 0) {
  830. param[i].key = "KEY_TYPE";
  831. param[i].value_type = cm_tdbusm_dict_s;
  832. param[i].value.s = "RSA";
  833. params[i] = &param[i];
  834. i++;
  835. param[i].key = "KEY_SIZE";
  836. param[i].value_type = cm_tdbusm_dict_n;
  837. param[i].value.n = keysize;
  838. params[i] = &param[i];
  839. i++;
  840. }
  841. if (id != NULL) {
  842. param[i].key = "NICKNAME";
  843. param[i].value_type = cm_tdbusm_dict_s;
  844. param[i].value.s = id;
  845. params[i] = &param[i];
  846. i++;
  847. }
  848. if (ca != NULL) {
  849. capath = find_ca_by_name(globals.tctx, bus, ca, verbose);
  850. if (capath == NULL) {
  851. printf(_("No CA with name \"%s\" found.\n"), ca);
  852. return 1;
  853. }
  854. param[i].key = "CA";
  855. param[i].value_type = cm_tdbusm_dict_p;
  856. param[i].value.s = capath;
  857. params[i] = &param[i];
  858. i++;
  859. } else {
  860. capath = NULL;
  861. }
  862. param[i].key = "SUBJECT";
  863. param[i].value_type = cm_tdbusm_dict_s;
  864. param[i].value.s = subject;
  865. params[i] = &param[i];
  866. i++;
  867. if (principal != NULL) {
  868. param[i].key = "PRINCIPAL";
  869. param[i].value_type = cm_tdbusm_dict_as;
  870. param[i].value.as = principal;
  871. params[i] = &param[i];
  872. i++;
  873. }
  874. if (dns != NULL) {
  875. param[i].key = "DNS";
  876. param[i].value_type = cm_tdbusm_dict_as;
  877. param[i].value.as = dns;
  878. params[i] = &param[i];
  879. i++;
  880. }
  881. if (email != NULL) {
  882. param[i].key = "EMAIL";
  883. param[i].value_type = cm_tdbusm_dict_as;
  884. param[i].value.as = email;
  885. params[i] = &param[i];
  886. i++;
  887. }
  888. if (eku != NULL) {
  889. param[i].key = "EKU";
  890. param[i].value_type = cm_tdbusm_dict_as;
  891. param[i].value.as = eku;
  892. params[i] = &param[i];
  893. i++;
  894. }
  895. if (profile != NULL) {
  896. param[i].key = CM_DBUS_PROP_CA_PROFILE;
  897. param[i].value_type = cm_tdbusm_dict_s;
  898. param[i].value.s = profile;
  899. params[i] = &param[i];
  900. i++;
  901. }
  902. if (precommand != NULL) {
  903. param[i].key = CM_DBUS_PROP_CERT_PRESAVE_COMMAND;
  904. param[i].value_type = cm_tdbusm_dict_s;
  905. param[i].value.s = precommand;
  906. params[i] = &param[i];
  907. i++;
  908. }
  909. if (postcommand != NULL) {
  910. param[i].key = CM_DBUS_PROP_CERT_POSTSAVE_COMMAND;
  911. param[i].value_type = cm_tdbusm_dict_s;
  912. param[i].value.s = postcommand;
  913. params[i] = &param[i];
  914. i++;
  915. }
  916. params[i] = NULL;
  917. req = prep_req(bus, CM_DBUS_BASE_PATH, CM_DBUS_BASE_INTERFACE,
  918. "add_request");
  919. if (cm_tdbusm_set_d(req, params) != 0) {
  920. printf(_("Error setting request arguments.\n"));
  921. exit(1);
  922. }
  923. rep = send_req(req, verbose);
  924. if (cm_tdbusm_get_bp(rep, globals.tctx, &b, &p) != 0) {
  925. printf(_("Error parsing server response.\n"));
  926. exit(1);
  927. }
  928. dbus_message_unref(rep);
  929. if (b) {
  930. nickname = find_request_name(globals.tctx, bus, p, verbose);
  931. printf(_("New signing request \"%s\" added.\n"),
  932. nickname ? nickname : p);
  933. } else {
  934. printf(_("New signing request could not be added.\n"));
  935. exit(1);
  936. }
  937. return 0;
  938. }
  939. static char *
  940. find_request_name(void *parent, enum cm_tdbus_type bus, const char *path,
  941. int verbose)
  942. {
  943. return query_rep_s(bus, path, CM_DBUS_REQUEST_INTERFACE, "get_nickname",
  944. verbose, parent);
  945. }
  946. static char *
  947. find_ca_name(void *parent, enum cm_tdbus_type bus, const char *path,
  948. int verbose)
  949. {
  950. return query_rep_s(bus, path, CM_DBUS_CA_INTERFACE, "get_nickname",
  951. verbose, parent);
  952. }
  953. static char *
  954. find_request_by_name(void *parent, enum cm_tdbus_type bus, const char *name,
  955. int verbose)
  956. {
  957. char **requests;
  958. int i, which;
  959. char *thisname;
  960. requests = query_rep_ap(bus, CM_DBUS_BASE_PATH, CM_DBUS_BASE_INTERFACE,
  961. "get_requests", verbose, globals.tctx);
  962. which = -1;
  963. for (i = 0; (requests != NULL) && (requests[i] != NULL); i++) {
  964. thisname = find_request_name(parent, bus, requests[i], verbose);
  965. if (thisname != NULL) {
  966. if (strcasecmp(name, thisname) == 0) {
  967. which = i;
  968. }
  969. talloc_free(thisname);
  970. }
  971. }
  972. if (which != -1) {
  973. return requests[which];
  974. }
  975. return NULL;
  976. }
  977. static const char *
  978. find_request_by_storage(void *parent, enum cm_tdbus_type bus,
  979. const char *dbdir,
  980. const char *nickname,
  981. const char *token,
  982. const char *certfile,
  983. int verbose)
  984. {
  985. char **requests;
  986. int i, which;
  987. char *cert_stype, *cert_sloc, *cert_nick, *cert_tok;
  988. requests = query_rep_ap(bus, CM_DBUS_BASE_PATH, CM_DBUS_BASE_INTERFACE,
  989. "get_requests", verbose, globals.tctx);
  990. which = -1;
  991. for (i = 0; (requests != NULL) && (requests[i] != NULL); i++) {
  992. query_rep_sososos(bus, requests[i],
  993. CM_DBUS_REQUEST_INTERFACE,
  994. "get_cert_storage_info",
  995. verbose, parent,
  996. &cert_stype, &cert_sloc,
  997. &cert_nick, &cert_tok);
  998. if (strcasecmp(cert_stype, "NSSDB") == 0) {
  999. if (dbdir == NULL) {
  1000. continue;
  1001. }
  1002. if ((cert_sloc == NULL) ||
  1003. (strcmp(dbdir, cert_sloc) != 0)) {
  1004. continue;
  1005. }
  1006. if (nickname == NULL) {
  1007. continue;
  1008. }
  1009. if ((cert_nick == NULL) ||
  1010. (strcmp(nickname, cert_nick) != 0)) {
  1011. continue;
  1012. }
  1013. if ((token != NULL) &&
  1014. ((cert_tok == NULL) ||
  1015. (strcmp(token, cert_tok) != 0))) {
  1016. continue;
  1017. }
  1018. } else
  1019. if (strcasecmp(cert_stype, "FILE") == 0) {
  1020. if (certfile == NULL) {
  1021. continue;
  1022. }
  1023. if (strcmp(certfile, cert_sloc) != 0) {
  1024. continue;
  1025. }
  1026. }
  1027. if (which != -1) {
  1028. /* Multiple matches? We have to give up. */
  1029. return NULL;
  1030. }
  1031. which = i;
  1032. }
  1033. if (which != -1) {
  1034. return requests[which];
  1035. }
  1036. return NULL;
  1037. }
  1038. static char *
  1039. find_ca_by_name(void *parent, enum cm_tdbus_type bus, const char *name,
  1040. int verbose)
  1041. {
  1042. char **cas;
  1043. int i, which;
  1044. char *thisname;
  1045. cas = query_rep_ap(bus, CM_DBUS_BASE_PATH, CM_DBUS_BASE_INTERFACE,
  1046. "get_known_cas", verbose, globals.tctx);
  1047. which = -1;
  1048. for (i = 0; (cas != NULL) && (cas[i] != NULL); i++) {
  1049. thisname = find_ca_name(parent, bus, cas[i], verbose);
  1050. if (thisname != NULL) {
  1051. if (strcasecmp(name, thisname) == 0) {
  1052. which = i;
  1053. }
  1054. talloc_free(thisname);
  1055. }
  1056. }
  1057. if (which != -1) {
  1058. return cas[which];
  1059. }
  1060. return NULL;
  1061. }
  1062. static int
  1063. add_basic_request(enum cm_tdbus_type bus, char *id,
  1064. char *dbdir, char *nickname, char *token,
  1065. char *keyfile, char *certfile,
  1066. char *pin, char *pinfile,
  1067. char *ca, char *profile,
  1068. char *precommand, char *postcommand,
  1069. dbus_bool_t auto_renew_stop, int verbose)
  1070. {
  1071. DBusMessage *req, *rep;
  1072. int i;
  1073. struct cm_tdbusm_dict param[22];
  1074. const struct cm_tdbusm_dict *params[23];
  1075. dbus_bool_t b;
  1076. const char *capath;
  1077. char *p;
  1078. i = 0;
  1079. if (id != NULL) {
  1080. param[i].key = "NICKNAME";
  1081. param[i].value_type = cm_tdbusm_dict_s;
  1082. param[i].value.s = id;
  1083. params[i] = &param[i];
  1084. i++;
  1085. }
  1086. if ((dbdir != NULL) && (nickname != NULL)) {
  1087. param[i].key = "KEY_STORAGE";
  1088. param[i].value_type = cm_tdbusm_dict_s;
  1089. param[i].value.s = "NSSDB";
  1090. params[i] = &param[i];
  1091. i++;
  1092. param[i].key = "KEY_LOCATION";
  1093. param[i].value_type = cm_tdbusm_dict_s;
  1094. param[i].value.s = dbdir;
  1095. params[i] = &param[i];
  1096. i++;
  1097. param[i].key = "KEY_NICKNAME";
  1098. param[i].value_type = cm_tdbusm_dict_s;
  1099. param[i].value.s = nickname;
  1100. params[i] = &param[i];
  1101. i++;
  1102. if (token != NULL) {
  1103. param[i].key = "KEY_TOKEN";
  1104. param[i].value_type = cm_tdbusm_dict_s;
  1105. param[i].value.s = token;
  1106. params[i] = &param[i];
  1107. i++;
  1108. }
  1109. param[i].key = "CERT_STORAGE";
  1110. param[i].value_type = cm_tdbusm_dict_s;
  1111. param[i].value.s = "NSSDB";
  1112. params[i] = &param[i];
  1113. i++;
  1114. param[i].key = "CERT_LOCATION";
  1115. param[i].value_type = cm_tdbusm_dict_s;
  1116. param[i].value.s = dbdir;
  1117. params[i] = &param[i];
  1118. i++;
  1119. param[i].key = "CERT_NICKNAME";
  1120. param[i].value_type = cm_tdbusm_dict_s;
  1121. param[i].value.s = nickname;
  1122. params[i] = &param[i];
  1123. i++;
  1124. if (token != NULL) {
  1125. param[i].key = "CERT_TOKEN";
  1126. param[i].value_type = cm_tdbusm_dict_s;
  1127. param[i].value.s = token;
  1128. params[i] = &param[i];
  1129. i++;
  1130. }
  1131. } else
  1132. if (certfile != NULL) {
  1133. if (keyfile != NULL) {
  1134. param[i].key = "KEY_STORAGE";
  1135. param[i].value_type = cm_tdbusm_dict_s;
  1136. param[i].value.s = "FILE";
  1137. params[i] = &param[i];
  1138. i++;
  1139. param[i].key = "KEY_LOCATION";
  1140. param[i].value_type = cm_tdbusm_dict_s;
  1141. param[i].value.s = keyfile;
  1142. params[i] = &param[i];
  1143. i++;
  1144. }
  1145. param[i].key = "CERT_STORAGE";
  1146. param[i].value_type = cm_tdbusm_dict_s;
  1147. param[i].value.s = "FILE";
  1148. params[i] = &param[i];
  1149. i++;
  1150. param[i].key = "CERT_LOCATION";
  1151. param[i].value_type = cm_tdbusm_dict_s;
  1152. param[i].value.s = certfile;
  1153. params[i] = &param[i];
  1154. i++;
  1155. }
  1156. if (pin != NULL) {
  1157. param[i].key = "KEY_PIN";
  1158. param[i].value_type = cm_tdbusm_dict_s;
  1159. param[i].value.s = pin;
  1160. params[i] = &param[i];
  1161. i++;
  1162. }
  1163. if (pinfile != NULL) {
  1164. param[i].key = "KEY_PIN_FILE";
  1165. param[i].value_type = cm_tdbusm_dict_s;
  1166. param[i].value.s = pinfile;
  1167. params[i] = &param[i];
  1168. i++;
  1169. }
  1170. param[i].key = "TRACK";
  1171. param[i].value_type = cm_tdbusm_dict_b;
  1172. param[i].value.b = TRUE;
  1173. params[i] = &param[i];
  1174. i++;
  1175. param[i].key = "RENEW";
  1176. param[i].value_type = cm_tdbusm_dict_b;
  1177. param[i].value.b = !auto_renew_stop;
  1178. params[i] = &param[i];
  1179. i++;
  1180. if (profile != NULL) {
  1181. param[i].key = CM_DBUS_PROP_CA_PROFILE;
  1182. param[i].value_type = cm_tdbusm_dict_s;
  1183. param[i].value.s = profile;
  1184. params[i] = &param[i];
  1185. i++;
  1186. }
  1187. if (precommand != NULL) {
  1188. param[i].key = CM_DBUS_PROP_CERT_PRESAVE_COMMAND;
  1189. param[i].value_type = cm_tdbusm_dict_s;
  1190. param[i].value.s = precommand;
  1191. params[i] = &param[i];
  1192. i++;
  1193. }
  1194. if (postcommand != NULL) {
  1195. param[i].key = CM_DBUS_PROP_CERT_POSTSAVE_COMMAND;
  1196. param[i].value_type = cm_tdbusm_dict_s;
  1197. param[i].value.s = postcommand;
  1198. params[i] = &param[i];
  1199. i++;
  1200. }
  1201. if (ca != NULL) {
  1202. capath = find_ca_by_name(globals.tctx, bus, ca, verbose);
  1203. if (capath == NULL) {
  1204. printf(_("No CA with name \"%s\" found.\n"), ca);
  1205. return 1;
  1206. }
  1207. param[i].key = "CA";
  1208. param[i].value_type = cm_tdbusm_dict_p;
  1209. param[i].value.s = talloc_strdup(globals.tctx, capath);
  1210. params[i] = &param[i];
  1211. i++;
  1212. } else {
  1213. capath = NULL;
  1214. }
  1215. params[i] = NULL;
  1216. req = prep_req(bus, CM_DBUS_BASE_PATH, CM_DBUS_BASE_INTERFACE,
  1217. "add_request");
  1218. if (cm_tdbusm_set_d(req, params) != 0) {
  1219. printf(_("Error setting request arguments.\n"));
  1220. exit(1);
  1221. }
  1222. rep = send_req(req, verbose);
  1223. if (cm_tdbusm_get_bp(rep, globals.tctx, &b, &p) != 0) {
  1224. printf(_("Error parsing server response.\n"));
  1225. exit(1);
  1226. }
  1227. dbus_message_unref(rep);
  1228. if (b) {
  1229. nickname = find_request_name(globals.tctx, bus, p, verbose);
  1230. printf(_("New tracking request \"%s\" added.\n"),
  1231. nickname ? nickname : p);
  1232. return 0;
  1233. } else {
  1234. printf(_("New tracking request could not be added.\n"));
  1235. return 1;
  1236. }
  1237. }
  1238. static int
  1239. set_tracking(const char *argv0, const char *category,
  1240. int argc, char **argv, dbus_bool_t track)
  1241. {
  1242. enum cm_tdbus_type bus = CM_DBUS_DEFAULT_BUS;
  1243. DBusMessage *req, *rep;
  1244. const char *request, *capath;
  1245. struct cm_tdbusm_dict param[13];
  1246. const struct cm_tdbusm_dict *params[14];
  1247. char *nss_scheme, *dbdir = NULL, *token = NULL, *nickname = NULL;
  1248. char *id = NULL, *new_id = NULL, *new_request;
  1249. char *keyfile = NULL, *certfile = NULL, *ca = DEFAULT_CA;
  1250. char *profile = NULL;
  1251. char *pin = NULL, *pinfile = NULL;
  1252. dbus_bool_t b;
  1253. int c, auto_renew_start = 0, auto_renew_stop = 0, verbose = 0, i;
  1254. char **eku = NULL, *oid;
  1255. char **principal = NULL, **dns = NULL, **email = NULL;
  1256. krb5_context kctx;
  1257. krb5_error_code kret;
  1258. krb5_principal kprincipal;
  1259. char *krealm, *kuprincipal;
  1260. char *precommand = NULL, *postcommand = NULL;
  1261. kctx = NULL;
  1262. if ((kret = krb5_init_context(&kctx)) != 0) {
  1263. kctx = NULL;
  1264. printf(_("Error initializing Kerberos library: %s.\n"),
  1265. error_message(kret));
  1266. return 1;
  1267. }
  1268. krealm = NULL;
  1269. if ((kret = krb5_get_default_realm(kctx, &krealm)) != 0) {
  1270. krealm = NULL;
  1271. }
  1272. opterr = 0;
  1273. while ((c = getopt(argc, argv,
  1274. ":d:n:t:k:f:g:p:P:rRi:I:U:K:D:E:sSvB:C:T:"
  1275. GETOPT_CA)) != -1) {
  1276. switch (c) {
  1277. case 'd':
  1278. nss_scheme = NULL;
  1279. dbdir = ensure_nss(globals.tctx, optarg, &nss_scheme);
  1280. if ((nss_scheme != NULL) && (dbdir != NULL)) {
  1281. dbdir = talloc_asprintf(globals.tctx, "%s:%s",
  1282. nss_scheme, dbdir);
  1283. }
  1284. break;
  1285. case 't':
  1286. token = talloc_strdup(globals.tctx, optarg);
  1287. break;
  1288. case 'n':
  1289. nickname = talloc_strdup(globals.tctx, optarg);
  1290. break;
  1291. case 'k':
  1292. keyfile = ensure_pem(globals.tctx, optarg);
  1293. break;
  1294. case 'f':
  1295. certfile = ensure_pem(globals.tctx, optarg);
  1296. break;
  1297. case 'r':
  1298. if (track) {
  1299. auto_renew_start++;
  1300. } else {
  1301. help(argv0, category);
  1302. return 1;
  1303. }
  1304. break;
  1305. case 'R':
  1306. if (track) {
  1307. auto_renew_stop++;
  1308. } else {
  1309. help(argv0, category);
  1310. return 1;
  1311. }
  1312. break;
  1313. case 'c':
  1314. if (track) {
  1315. ca = talloc_strdup(globals.tctx, optarg);
  1316. } else {
  1317. help(argv0, category);
  1318. return 1;
  1319. }
  1320. break;
  1321. case 'T':
  1322. profile = talloc_strdup(globals.tctx, optarg);
  1323. break;
  1324. case 'i':
  1325. id = talloc_strdup(globals.tctx, optarg);
  1326. break;
  1327. case 'I':
  1328. new_id = talloc_strdup(globals.tctx, optarg);
  1329. break;
  1330. case 'U':
  1331. oid = cm_oid_from_name(globals.tctx, optarg);
  1332. if ((oid == NULL) ||
  1333. (strspn(oid, "0123456789.") != strlen(oid))) {
  1334. printf(_("Could not evaluate OID \"%s\".\n"),
  1335. optarg);
  1336. return 1;
  1337. }
  1338. add_string(globals.tctx, &eku, oid);
  1339. break;
  1340. case 'K':
  1341. kprincipal = NULL;
  1342. if ((kret = krb5_parse_name(kctx, optarg,
  1343. &kprincipal)) != 0) {
  1344. printf(_("Error parsing Kerberos principal "
  1345. "name \"%s\": %s.\n"), optarg,
  1346. error_message(kret));
  1347. return 1;
  1348. }
  1349. kuprincipal = NULL;
  1350. if ((kret = krb5_unparse_name(kctx, kprincipal,
  1351. &kuprincipal)) != 0) {
  1352. printf(_("Error unparsing Kerberos principal "
  1353. "name \"%s\": %s.\n"), optarg,
  1354. error_message(kret));
  1355. return 1;
  1356. }
  1357. add_string(globals.tctx, &principal, kuprincipal);
  1358. krb5_free_principal(kctx, kprincipal);
  1359. break;
  1360. case 'D':
  1361. add_string(globals.tctx, &dns, optarg);
  1362. break;
  1363. case 'E':
  1364. add_string(globals.tctx, &email, optarg);
  1365. break;
  1366. case 's':
  1367. bus = cm_tdbus_session;
  1368. break;
  1369. case 'S':
  1370. bus = cm_tdbus_system;
  1371. break;
  1372. case 'p':
  1373. pinfile = optarg;
  1374. break;
  1375. case 'P':
  1376. pin = optarg;
  1377. break;
  1378. case 'B':
  1379. precommand = optarg;
  1380. break;
  1381. case 'C':
  1382. postcommand = optarg;
  1383. break;
  1384. case 'v':
  1385. verbose++;
  1386. break;
  1387. default:
  1388. if (c == ':') {
  1389. fprintf(stderr,
  1390. _("%s: option requires an argument -- '%c'\n"),
  1391. category, optopt);
  1392. } else {
  1393. fprintf(stderr, _("%s: invalid option -- '%c'\n"),
  1394. category, optopt);
  1395. }
  1396. help(argv0, category);
  1397. return 1;
  1398. }
  1399. }
  1400. krb5_free_context(kctx);
  1401. if (optind < argc) {
  1402. printf(_("Error: unused extra arguments were supplied.\n"));
  1403. help(argv0, category);
  1404. return 1;
  1405. }
  1406. if (((dbdir != NULL) && (nickname == NULL)) ||
  1407. ((dbdir == NULL) && (nickname != NULL))) {
  1408. printf(_("Database location or nickname specified "
  1409. "without the other.\n"));
  1410. help(argv0, category);
  1411. return 1;
  1412. }
  1413. if ((dbdir != NULL) && (certfile != NULL)) {
  1414. printf(_("Database directory and certificate file "
  1415. "both specified.\n"));
  1416. help(argv0, category);
  1417. return 1;
  1418. }
  1419. if ((id == NULL) &&
  1420. (dbdir == NULL) &&
  1421. (nickname == NULL) &&
  1422. (certfile == NULL)) {
  1423. printf(_("None of ID or database directory and nickname or "
  1424. "certificate file specified.\n"));
  1425. help(argv0, category);
  1426. return 1;
  1427. }
  1428. if ((certfile != NULL) && (keyfile != NULL) &&
  1429. (strcmp(certfile, keyfile) == 0)) {
  1430. printf(_("Key and certificate can not both be saved to the "
  1431. "same file.\n"));
  1432. help(argv0, category);
  1433. return 1;
  1434. }
  1435. if (id != NULL) {
  1436. request = find_request_by_name(globals.tctx, bus, id, verbose);
  1437. } else {
  1438. request = find_request_by_storage(globals.tctx, bus,
  1439. dbdir, nickname, token,
  1440. certfile, verbose);
  1441. }
  1442. if (track) {
  1443. if (request != NULL) {
  1444. /* Modify settings for an existing request. */
  1445. i = 0;
  1446. param[i].key = "TRACK";
  1447. param[i].value_type = cm_tdbusm_dict_b;
  1448. param[i].value.b = TRUE;
  1449. params[i] = &param[i];
  1450. i++;
  1451. if (auto_renew_start || auto_renew_stop) {
  1452. param[i].key = "RENEW";
  1453. param[i].value_type = cm_tdbusm_dict_b;
  1454. param[i].value.b = auto_renew_start > 0;
  1455. params[i] = &param[i];
  1456. i++;
  1457. }
  1458. if (principal != NULL) {
  1459. param[i].key = "PRINCIPAL";
  1460. param[i].value_type = cm_tdbusm_dict_as;
  1461. param[i].value.as = principal;
  1462. params[i] = &param[i];
  1463. i++;
  1464. }
  1465. if (dns != NULL) {
  1466. param[i].key = "DNS";
  1467. param[i].value_type = cm_tdbusm_dict_as;
  1468. param[i].value.as = dns;
  1469. params[i] = &param[i];
  1470. i++;
  1471. }
  1472. if (email != NULL) {
  1473. param[i].key = "EMAIL";
  1474. param[i].value_type = cm_tdbusm_dict_as;
  1475. param[i].value.as = email;
  1476. params[i] = &param[i];
  1477. i++;
  1478. }
  1479. if (eku != NULL) {
  1480. param[i].key = "EKU";
  1481. param[i].value_type = cm_tdbusm_dict_as;
  1482. param[i].value.as = eku;
  1483. params[i] = &param[i];
  1484. i++;
  1485. }
  1486. if (new_id != NULL) {
  1487. param[i].key = "NICKNAME";
  1488. param[i].value_type = cm_tdbusm_dict_s;
  1489. param[i].value.s = new_id;
  1490. params[i] = &param[i];
  1491. i++;
  1492. }
  1493. if (pin != NULL) {
  1494. param[i].key = "KEY_PIN";
  1495. param[i].value_type = cm_tdbusm_dict_s;
  1496. param[i].value.s = pin;
  1497. params[i] = &param[i];
  1498. i++;
  1499. }
  1500. if (pinfile != NULL) {
  1501. param[i].key = "KEY_PIN_FILE";
  1502. param[i].value_type = cm_tdbusm_dict_s;
  1503. param[i].value.s = pinfile;
  1504. params[i] = &param[i];
  1505. i++;
  1506. }
  1507. if (ca != NULL) {
  1508. capath = find_ca_by_name(globals.tctx, bus, ca,
  1509. verbose);
  1510. if (capath == NULL) {
  1511. printf(_("No CA with name \"%s\" "
  1512. "found.\n"), ca);
  1513. return 1;
  1514. }
  1515. param[i].key = "CA";
  1516. param[i].value_type = cm_tdbusm_dict_p;
  1517. param[i].value.s = talloc_strdup(globals.tctx,
  1518. capath);
  1519. params[i] = &param[i];
  1520. i++;
  1521. } else {
  1522. capath = NULL;
  1523. }
  1524. if (profile != NULL) {
  1525. param[i].key = CM_DBUS_PROP_CA_PROFILE;
  1526. param[i].value_type = cm_tdbusm_dict_s;
  1527. param[i].value.s = profile;
  1528. params[i] = &param[i];
  1529. i++;
  1530. }
  1531. if (precommand != NULL) {
  1532. param[i].key = CM_DBUS_PROP_CERT_PRESAVE_COMMAND;
  1533. param[i].value_type = cm_tdbusm_dict_s;
  1534. param[i].value.s = precommand;
  1535. params[i] = &param[i];
  1536. i++;
  1537. }
  1538. if (postcommand != NULL) {
  1539. param[i].key = CM_DBUS_PROP_CERT_POSTSAVE_COMMAND;
  1540. param[i].value_type = cm_tdbusm_dict_s;
  1541. param[i].value.s = postcommand;
  1542. params[i] = &param[i];
  1543. i++;
  1544. }
  1545. params[i] = NULL;
  1546. req = prep_req(bus, request, CM_DBUS_REQUEST_INTERFACE,
  1547. "modify");
  1548. if (cm_tdbusm_set_d(req, params) != 0) {
  1549. printf(_("Error setting request arguments.\n"));
  1550. exit(1);
  1551. }
  1552. rep = send_req(req, verbose);
  1553. if (cm_tdbusm_get_bp(rep, globals.tctx, &b,
  1554. &new_request) != 0) {
  1555. printf(_("Error parsing server response.\n"));
  1556. exit(1);
  1557. }
  1558. request = new_request;
  1559. dbus_message_unref(rep);
  1560. nickname = find_request_name(globals.tctx, bus,
  1561. request, verbose);
  1562. if (b) {
  1563. printf(_("Request \"%s\" modified.\n"),
  1564. nickname ? nickname : request);
  1565. return 0;
  1566. } else {
  1567. printf(_("Request \"%s\" could not be "
  1568. "modified.\n"),
  1569. nickname ? nickname : request);
  1570. return 1;
  1571. }
  1572. } else {
  1573. /* Add a new request. */
  1574. if (id != NULL) {
  1575. printf(_("No request found with specified "
  1576. "nickname.\n"));
  1577. help(argv0, category);
  1578. return 1;
  1579. }
  1580. if (((dbdir != NULL) && (nickname == NULL)) ||
  1581. ((dbdir == NULL) && (nickname != NULL))) {
  1582. printf(_("Database location or nickname "
  1583. "specified without the other.\n"));
  1584. help(argv0, category);
  1585. return 1;
  1586. }
  1587. if ((dbdir != NULL) && (certfile != NULL)) {
  1588. printf(_("Database directory and certificate "
  1589. "file both specified.\n"));
  1590. help(argv0, category);
  1591. return 1;
  1592. }
  1593. if ((dbdir == NULL) &&
  1594. (nickname == NULL) &&
  1595. (certfile == NULL)) {
  1596. printf(_("None of database directory and "
  1597. "nickname or certificate file "
  1598. "specified.\n"));
  1599. help(argv0, category);
  1600. return 1;
  1601. }
  1602. return add_basic_request(bus, new_id,
  1603. dbdir, nickname, token,
  1604. keyfile, certfile,
  1605. pin, pinfile,
  1606. ca, profile,
  1607. precommand, postcommand,
  1608. (auto_renew_stop > 0),
  1609. verbose);
  1610. }
  1611. } else {
  1612. /* Drop a request. */
  1613. if ((request == NULL) &&
  1614. (id == NULL) &&
  1615. (dbdir == NULL) &&
  1616. (nickname == NULL) &&
  1617. (certfile == NULL)) {
  1618. help(argv0, category);
  1619. return 1;
  1620. }
  1621. if (request == NULL) {
  1622. printf(_("No request found that matched arguments.\n"));
  1623. return 1;
  1624. }
  1625. nickname = find_request_name(globals.tctx, bus, request,
  1626. verbose);
  1627. req = prep_req(bus, CM_DBUS_BASE_PATH,
  1628. CM_DBUS_BASE_INTERFACE,
  1629. "remove_request");
  1630. if (cm_tdbusm_set_p(req, request) != 0) {
  1631. printf(_("Error setting request arguments.\n"));
  1632. exit(1);
  1633. }
  1634. rep = send_req(req, verbose);
  1635. if (cm_tdbusm_get_b(rep, globals.tctx, &b) != 0) {
  1636. printf(_("Error parsing server response.\n"));
  1637. exit(1);
  1638. }
  1639. dbus_message_unref(rep);
  1640. if (b) {
  1641. printf(_("Request \"%s\" removed.\n"),
  1642. nickname ? nickname : request);
  1643. return 0;
  1644. } else {
  1645. printf(_("Request \"%s\" could not be removed.\n"),
  1646. nickname ? nickname : request);
  1647. return 1;
  1648. }
  1649. }
  1650. }
  1651. static int
  1652. start_tracking(const char *argv0, int argc, char **argv)
  1653. {
  1654. return set_tracking(argv0, "start-tracking", argc, argv, TRUE);
  1655. }
  1656. static int
  1657. stop_tracking(const char *argv0, int argc, char **argv)
  1658. {
  1659. return set_tracking(argv0, "stop-tracking", argc, argv, FALSE);
  1660. }
  1661. static int
  1662. resubmit(const char *argv0, int argc, char **argv)
  1663. {
  1664. enum cm_tdbus_type bus = CM_DBUS_DEFAULT_BUS;
  1665. DBusMessage *req, *rep;
  1666. const char *request;
  1667. char *capath;
  1668. struct cm_tdbusm_dict param[18];
  1669. const struct cm_tdbusm_dict *params[19];
  1670. char *dbdir = NULL, *token = NULL, *nickname = NULL, *certfile = NULL;
  1671. char *pin = NULL, *pinfile = NULL;
  1672. char *id = NULL, *new_id = NULL, *ca = NULL, *new_request, *nss_scheme;
  1673. char *subject = NULL, **eku = NULL, *oid = NULL;
  1674. char **principal = NULL, **dns = NULL, **email = NULL;
  1675. char *profile = NULL;
  1676. dbus_bool_t b;
  1677. int verbose = 0, c, i;
  1678. krb5_context kctx;
  1679. krb5_error_code kret;
  1680. krb5_principal kprincipal;
  1681. char *kuprincipal, *precommand = NULL, *postcommand = NULL;
  1682. kctx = NULL;
  1683. if ((kret = krb5_init_context(&kctx)) != 0) {
  1684. kctx = NULL;
  1685. printf(_("Error initializing Kerberos library: %s.\n"),
  1686. error_message(kret));
  1687. return 1;
  1688. }
  1689. opterr = 0;
  1690. while ((c = getopt(argc, argv,
  1691. ":d:n:N:t:U:K:E:D:f:i:I:sSp:P:vB:C:T:"
  1692. GETOPT_CA)) != -1) {
  1693. switch (c) {
  1694. case 'd':
  1695. nss_scheme = NULL;
  1696. dbdir = ensure_nss(globals.tctx, optarg, &nss_scheme);
  1697. if ((nss_scheme != NULL) && (dbdir != NULL)) {
  1698. dbdir = talloc_asprintf(globals.tctx, "%s:%s",
  1699. nss_scheme, dbdir);
  1700. }
  1701. break;
  1702. case 't':
  1703. token = talloc_strdup(globals.tctx, optarg);
  1704. break;
  1705. case 'n':
  1706. nickname = talloc_strdup(globals.tctx, optarg);
  1707. break;
  1708. case 'f':
  1709. certfile = ensure_pem(globals.tctx, optarg);
  1710. break;
  1711. case 'c':
  1712. ca = talloc_strdup(globals.tctx, optarg);
  1713. break;
  1714. case 'T':
  1715. profile = talloc_strdup(globals.tctx, optarg);
  1716. break;
  1717. case 'i':
  1718. id = talloc_strdup(globals.tctx, optarg);
  1719. break;
  1720. case 'I':
  1721. new_id = talloc_strdup(globals.tctx, optarg);
  1722. break;
  1723. case 'N':
  1724. subject = talloc_strdup(globals.tctx, optarg);
  1725. break;
  1726. case 'U':
  1727. oid = cm_oid_from_name(globals.tctx, optarg);
  1728. if ((oid == NULL) ||
  1729. (strspn(oid, "0123456789.") != strlen(oid))) {
  1730. printf(_("Could not evaluate OID \"%s\".\n"),
  1731. optarg);
  1732. return 1;
  1733. }
  1734. add_string(globals.tctx, &eku, oid);
  1735. break;
  1736. case 'K':
  1737. kprincipal = NULL;
  1738. if ((kret = krb5_parse_name(kctx, optarg,
  1739. &kprincipal)) != 0) {
  1740. printf(_("Error parsing Kerberos principal "
  1741. "name \"%s\": %s.\n"), optarg,
  1742. error_message(kret));
  1743. return 1;
  1744. }
  1745. kuprincipal = NULL;
  1746. if ((kret = krb5_unparse_name(kctx, kprincipal,
  1747. &kuprincipal)) != 0) {
  1748. printf(_("Error unparsing Kerberos principal "
  1749. "name \"%s\": %s.\n"), optarg,
  1750. error_message(kret));
  1751. return 1;
  1752. }
  1753. add_string(globals.tctx, &principal, kuprincipal);
  1754. krb5_free_principal(kctx, kprincipal);
  1755. break;
  1756. case 'D':
  1757. add_string(globals.tctx, &dns, optarg);
  1758. break;
  1759. case 'E':
  1760. add_string(globals.tctx, &email, optarg);
  1761. break;
  1762. case 's':
  1763. bus = cm_tdbus_session;
  1764. break;
  1765. case 'S':
  1766. bus = cm_tdbus_system;
  1767. break;
  1768. case 'p':
  1769. pinfile = optarg;
  1770. break;
  1771. case 'P':
  1772. pin = optarg;
  1773. break;
  1774. case 'B':
  1775. precommand = optarg;
  1776. break;
  1777. case 'C':
  1778. postcommand = optarg;
  1779. break;
  1780. case 'v':
  1781. verbose++;
  1782. break;
  1783. default:
  1784. if (c == ':') {
  1785. fprintf(stderr,
  1786. _("%s: option requires an argument -- '%c'\n"),
  1787. "resubmit", optopt);
  1788. } else {
  1789. fprintf(stderr, _("%s: invalid option -- '%c'\n"),
  1790. "resubmit", optopt);
  1791. }
  1792. help(argv0, "resubmit");
  1793. return 1;
  1794. }
  1795. }
  1796. if (optind < argc) {
  1797. printf(_("Error: unused extra arguments were supplied.\n"));
  1798. help(argv0, "resubmit");
  1799. return 1;
  1800. }
  1801. krb5_free_context(kctx);
  1802. if (id != NULL) {
  1803. request = find_request_by_name(globals.tctx, bus, id, verbose);
  1804. } else {
  1805. request = find_request_by_storage(globals.tctx, bus,
  1806. dbdir, nickname, token,
  1807. certfile, verbose);
  1808. }
  1809. if (request == NULL) {
  1810. if (id != NULL) {
  1811. printf(_("No request found with specified "
  1812. "nickname.\n"));
  1813. help(argv0, "resubmit");
  1814. return 1;
  1815. }
  1816. if (((dbdir != NULL) && (nickname == NULL)) ||
  1817. ((dbdir == NULL) && (nickname != NULL))) {
  1818. printf(_("Database location or nickname "
  1819. "specified without the other.\n"));
  1820. help(argv0, "resubmit");
  1821. return 1;
  1822. }
  1823. if ((dbdir != NULL) && (certfile != NULL)) {
  1824. printf(_("Database directory and certificate "
  1825. "file both specified.\n"));
  1826. help(argv0, "resubmit");
  1827. return 1;
  1828. }
  1829. if ((dbdir == NULL) &&
  1830. (nickname == NULL) &&
  1831. (certfile == NULL)) {
  1832. printf(_("None of database directory and "
  1833. "nickname or certificate file "
  1834. "specified.\n"));
  1835. help(argv0, "resubmit");
  1836. return 1;
  1837. }
  1838. printf(_("No request found that matched arguments.\n"));
  1839. return 1;
  1840. }
  1841. i = 0;
  1842. if (new_id != NULL) {
  1843. param[i].key = "NICKNAME";
  1844. param[i].value_type = cm_tdbusm_dict_s;
  1845. param[i].value.s = new_id;
  1846. params[i] = &param[i];
  1847. i++;
  1848. }
  1849. if (ca != NULL) {
  1850. capath = find_ca_by_name(globals.tctx, bus, ca, verbose);
  1851. if (capath == NULL) {
  1852. printf(_("No CA with name \"%s\" found.\n"), ca);
  1853. exit(1);
  1854. }
  1855. param[i].key = "CA";
  1856. param[i].value_type = cm_tdbusm_dict_p;
  1857. param[i].value.s = talloc_strdup(globals.tctx, capath);
  1858. params[i] = &param[i];
  1859. i++;
  1860. }
  1861. if (subject != NULL) {
  1862. param[i].key = "SUBJECT";
  1863. param[i].value_type = cm_tdbusm_dict_s;
  1864. param[i].value.s = subject;
  1865. params[i] = &param[i];
  1866. i++;
  1867. }
  1868. if (principal != NULL) {
  1869. param[i].key = "PRINCIPAL";
  1870. param[i].value_type = cm_tdbusm_dict_as;
  1871. param[i].value.as = principal;
  1872. params[i] = &param[i];
  1873. i++;
  1874. }
  1875. if (dns != NULL) {
  1876. param[i].key = "DNS";
  1877. param[i].value_type = cm_tdbusm_dict_as;
  1878. param[i].value.as = dns;
  1879. params[i] = &param[i];
  1880. i++;
  1881. }
  1882. if (email != NULL) {
  1883. param[i].key = "EMAIL";
  1884. param[i].value_type = cm_tdbusm_dict_as;
  1885. param[i].value.as = email;
  1886. params[i] = &param[i];
  1887. i++;
  1888. }
  1889. if (eku != NULL) {
  1890. param[i].key = "EKU";
  1891. param[i].value_type = cm_tdbusm_dict_as;
  1892. param[i].value.as = eku;
  1893. params[i] = &param[i];
  1894. i++;
  1895. }
  1896. if (pin != NULL) {
  1897. param[i].key = "KEY_PIN";
  1898. param[i].value_type = cm_tdbusm_dict_s;
  1899. param[i].value.s = pin;
  1900. params[i] = &param[i];
  1901. i++;
  1902. }
  1903. if (pinfile != NULL) {
  1904. param[i].key = "KEY_PIN_FILE";
  1905. param[i].value_type = cm_tdbusm_dict_s;
  1906. param[i].value.s = pinfile;
  1907. params[i] = &param[i];
  1908. i++;
  1909. }
  1910. if (profile != NULL) {
  1911. param[i].key = CM_DBUS_PROP_CA_PROFILE;
  1912. param[i].value_type = cm_tdbusm_dict_s;
  1913. param[i].value.s = profile;
  1914. params[i] = &param[i];
  1915. i++;
  1916. }
  1917. if (precommand != NULL) {
  1918. param[i].key = CM_DBUS_PROP_CERT_PRESAVE_COMMAND;
  1919. param[i].value_type = cm_tdbusm_dict_s;
  1920. param[i].value.s = precommand;
  1921. params[i] = &param[i];
  1922. i++;
  1923. }
  1924. if (postcommand != NULL) {
  1925. param[i].key = CM_DBUS_PROP_CERT_POSTSAVE_COMMAND;
  1926. param[i].value_type = cm_tdbusm_dict_s;
  1927. param[i].value.s = postcommand;
  1928. params[i] = &param[i];
  1929. i++;
  1930. }
  1931. params[i] = NULL;
  1932. if (i > 0) {
  1933. req = prep_req(bus, request, CM_DBUS_REQUEST_INTERFACE,
  1934. "modify");
  1935. if (cm_tdbusm_set_d(req, params) != 0) {
  1936. printf(_("…

Large files files are truncated, but you can click here to view the full file