You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cert_cmd.c 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * 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, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdio.h>
  25. #include <errno.h>
  26. #include <getopt.h>
  27. #include <ipxe/x509.h>
  28. #include <ipxe/certstore.h>
  29. #include <ipxe/image.h>
  30. #include <ipxe/command.h>
  31. #include <ipxe/parseopt.h>
  32. #include <usr/imgmgmt.h>
  33. #include <usr/certmgmt.h>
  34. /** @file
  35. *
  36. * Certificate management commands
  37. *
  38. */
  39. /** "cert<xxx>" options */
  40. struct cert_options {
  41. /** Certificate subject name */
  42. char *name;
  43. /** Keep certificate file after parsing */
  44. int keep;
  45. };
  46. /** "cert<xxx>" option list */
  47. static union {
  48. /* "certstore" takes both options */
  49. struct option_descriptor certstore[2];
  50. /* "certstat" takes only --subject */
  51. struct option_descriptor certstat[1];
  52. /* "certfree" takes only --subject */
  53. struct option_descriptor certfree[1];
  54. } opts = {
  55. .certstore = {
  56. OPTION_DESC ( "subject", 's', required_argument,
  57. struct cert_options, name, parse_string ),
  58. OPTION_DESC ( "keep", 'k', no_argument,
  59. struct cert_options, keep, parse_flag ),
  60. },
  61. };
  62. /** A "cert<xxx>" command descriptor */
  63. struct cert_command_descriptor {
  64. /** Command descriptor */
  65. struct command_descriptor cmd;
  66. /** Payload
  67. *
  68. * @v cert X.509 certificate
  69. * @ret rc Return status code
  70. */
  71. int ( * payload ) ( struct x509_certificate *cert );
  72. };
  73. /**
  74. * Construct "cert<xxx>" command descriptor
  75. *
  76. * @v _struct Options structure type
  77. * @v _options Option descriptor array
  78. * @v _min_args Minimum number of non-option arguments
  79. * @v _max_args Maximum number of non-option arguments
  80. * @v _usage Command usage
  81. * @v _payload Payload method
  82. * @ret _command Command descriptor
  83. */
  84. #define CERT_COMMAND_DESC( _struct, _options, _min_args, _max_args, \
  85. _usage, _payload ) \
  86. { \
  87. .cmd = COMMAND_DESC ( _struct, _options, _min_args, \
  88. _max_args, _usage ), \
  89. .payload = _payload, \
  90. }
  91. /**
  92. * Execute "cert<xxx>" command
  93. *
  94. * @v argc Argument count
  95. * @v argv Argument list
  96. * @v certcmd Command descriptor
  97. * @ret rc Return status code
  98. */
  99. static int cert_exec ( int argc, char **argv,
  100. struct cert_command_descriptor *certcmd ) {
  101. struct command_descriptor *cmd = &certcmd->cmd;
  102. struct cert_options opts;
  103. struct image *image = NULL;
  104. struct x509_certificate *cert;
  105. struct x509_certificate *tmp;
  106. unsigned int count = 0;
  107. size_t offset = 0;
  108. int next;
  109. int rc;
  110. /* Parse options */
  111. if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
  112. goto err_parse;
  113. /* Acquire image, if applicable */
  114. if ( ( optind < argc ) &&
  115. ( ( rc = imgacquire ( argv[optind], 0, &image ) ) != 0 ) )
  116. goto err_acquire;
  117. /* Get first entry in certificate store */
  118. tmp = list_first_entry ( &certstore.links, struct x509_certificate,
  119. store.list );
  120. /* Iterate over certificates */
  121. while ( 1 ) {
  122. /* Get next certificate from image or store as applicable */
  123. if ( image ) {
  124. /* Get next certificate from image */
  125. if ( offset >= image->len )
  126. break;
  127. next = image_x509 ( image, offset, &cert );
  128. if ( next < 0 ) {
  129. rc = next;
  130. printf ( "Could not parse certificate: %s\n",
  131. strerror ( rc ) );
  132. goto err_x509;
  133. }
  134. offset = next;
  135. } else {
  136. /* Get next certificate from store */
  137. cert = tmp;
  138. if ( ! cert )
  139. break;
  140. tmp = list_next_entry ( tmp, &certstore.links,
  141. store.list );
  142. x509_get ( cert );
  143. }
  144. /* Skip non-matching names, if a name was specified */
  145. if ( opts.name && ( x509_check_name ( cert, opts.name ) != 0 )){
  146. x509_put ( cert );
  147. continue;
  148. }
  149. /* Execute payload */
  150. if ( ( rc = certcmd->payload ( cert ) ) != 0 ) {
  151. x509_put ( cert );
  152. goto err_payload;
  153. }
  154. /* Count number of certificates processed */
  155. count++;
  156. /* Drop reference to certificate */
  157. x509_put ( cert );
  158. }
  159. /* Fail if a name was specified and no matching certificates
  160. * were found.
  161. */
  162. if ( opts.name && ( count == 0 ) ) {
  163. printf ( "\"%s\" : no such certificate\n", opts.name );
  164. rc = -ENOENT;
  165. goto err_none;
  166. }
  167. err_none:
  168. err_payload:
  169. err_x509:
  170. if ( image && ( ! opts.keep ) )
  171. unregister_image ( image );
  172. err_acquire:
  173. err_parse:
  174. return rc;
  175. }
  176. /**
  177. * "certstat" payload
  178. *
  179. * @v cert X.509 certificate
  180. * @ret rc Return status code
  181. */
  182. static int certstat_payload ( struct x509_certificate *cert ) {
  183. certstat ( cert );
  184. return 0;
  185. }
  186. /** "certstat" command descriptor */
  187. static struct cert_command_descriptor certstat_cmd =
  188. CERT_COMMAND_DESC ( struct cert_options, opts.certstat, 0, 0, NULL,
  189. certstat_payload );
  190. /**
  191. * The "certstat" command
  192. *
  193. * @v argc Argument count
  194. * @v argv Argument list
  195. * @ret rc Return status code
  196. */
  197. static int certstat_exec ( int argc, char **argv ) {
  198. return cert_exec ( argc, argv, &certstat_cmd );
  199. }
  200. /**
  201. * "certstore" payload
  202. *
  203. * @v cert X.509 certificate
  204. * @ret rc Return status code
  205. */
  206. static int certstore_payload ( struct x509_certificate *cert ) {
  207. /* Mark certificate as having been added explicitly */
  208. cert->flags |= X509_FL_EXPLICIT;
  209. return 0;
  210. }
  211. /** "certstore" command descriptor */
  212. static struct cert_command_descriptor certstore_cmd =
  213. CERT_COMMAND_DESC ( struct cert_options, opts.certstore, 0, 1,
  214. "[<uri|image>]", certstore_payload );
  215. /**
  216. * The "certstore" command
  217. *
  218. * @v argc Argument count
  219. * @v argv Argument list
  220. * @ret rc Return status code
  221. */
  222. static int certstore_exec ( int argc, char **argv ) {
  223. return cert_exec ( argc, argv, &certstore_cmd );
  224. }
  225. /**
  226. * "certfree" payload
  227. *
  228. * @v cert X.509 certificate
  229. * @ret rc Return status code
  230. */
  231. static int certfree_payload ( struct x509_certificate *cert ) {
  232. /* Remove from certificate store */
  233. certstore_del ( cert );
  234. return 0;
  235. }
  236. /** "certfree" command descriptor */
  237. static struct cert_command_descriptor certfree_cmd =
  238. CERT_COMMAND_DESC ( struct cert_options, opts.certfree, 0, 0, NULL,
  239. certfree_payload );
  240. /**
  241. * The "certfree" command
  242. *
  243. * @v argc Argument count
  244. * @v argv Argument list
  245. * @ret rc Return status code
  246. */
  247. static int certfree_exec ( int argc, char **argv ) {
  248. return cert_exec ( argc, argv, &certfree_cmd );
  249. }
  250. /** Certificate management commands */
  251. struct command certmgmt_commands[] __command = {
  252. {
  253. .name = "certstat",
  254. .exec = certstat_exec,
  255. },
  256. {
  257. .name = "certstore",
  258. .exec = certstore_exec,
  259. },
  260. {
  261. .name = "certfree",
  262. .exec = certfree_exec,
  263. },
  264. };