1 /*
2   File autogenerated by gengetopt version 2.23
3   generated with the following command:
4   gengetopt --conf-parser -i /home/aveen/yubico_workspace/yubico-piv-tool-2.2.0/yubico-piv-tool/tool/cmdline.ggo --output-dir /home/aveen/yubico_workspace/yubico-piv-tool-2.2.0/yubico-piv-tool/tool
5 
6   The developers of gengetopt consider the fixed text that goes in all
7   gengetopt output files to be in the public domain:
8   we make no copyright claims on it.
9 */
10 
11 /* If we use autoconf.  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #ifndef FIX_UNUSED
21 #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
22 #endif
23 
24 #include <getopt.h>
25 
26 #include "cmdline.h"
27 
28 const char *gengetopt_args_info_purpose = "";
29 
30 const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTION]...";
31 
32 const char *gengetopt_args_info_versiontext = "";
33 
34 const char *gengetopt_args_info_description = "";
35 
36 const char *gengetopt_args_info_full_help[] = {
37   "  -h, --help               Print help and exit",
38   "      --full-help          Print help, including hidden options, and exit",
39   "  -V, --version            Print version and exit",
40   "  -v, --verbose[=INT]      Print more information  (default=`0')",
41   "  -r, --reader=STRING      Only use a matching reader  (default=`Yubikey')",
42   "  -k, --key[=STRING]       Management key to use, if no value is specified key\n                             will be asked for\n                             (default=`010203040506070801020304050607080102030405060708')",
43   "  -a, --action=ENUM        Action to take  (possible values=\"version\",\n                             \"generate\", \"set-mgm-key\", \"reset\",\n                             \"pin-retries\", \"import-key\",\n                             \"import-certificate\", \"set-chuid\",\n                             \"request-certificate\", \"verify-pin\",\n                             \"change-pin\", \"change-puk\", \"unblock-pin\",\n                             \"selfsign-certificate\", \"delete-certificate\",\n                             \"read-certificate\", \"status\",\n                             \"test-signature\", \"test-decipher\",\n                             \"list-readers\", \"set-ccc\", \"write-object\",\n                             \"read-object\", \"attest\")",
44   "\n       Multiple actions may be given at once and will be executed in order\n       for example --action=verify-pin --action=request-certificate\n",
45   "  -s, --slot=ENUM          What key slot to operate on  (possible\n                             values=\"9a\", \"9c\", \"9d\", \"9e\", \"82\",\n                             \"83\", \"84\", \"85\", \"86\", \"87\", \"88\",\n                             \"89\", \"8a\", \"8b\", \"8c\", \"8d\", \"8e\",\n                             \"8f\", \"90\", \"91\", \"92\", \"93\", \"94\",\n                             \"95\", \"f9\")",
46   "\n       9a is for PIV Authentication\n       9c is for Digital Signature (PIN always checked)\n       9d is for Key Management\n       9e is for Card Authentication (PIN never checked)\n       82-95 is for Retired Key Management\n       f9 is for Attestation\n",
47   "  -A, --algorithm=ENUM     What algorithm to use  (possible values=\"RSA1024\",\n                             \"RSA2048\", \"ECCP256\", \"ECCP384\"\n                             default=`RSA2048')",
48   "  -H, --hash=ENUM          Hash to use for signatures  (possible\n                             values=\"SHA1\", \"SHA256\", \"SHA384\",\n                             \"SHA512\" default=`SHA256')",
49   "  -n, --new-key=STRING     New management key to use for action set-mgm-key, if\n                             omitted key will be asked for",
50   "      --pin-retries=INT    Number of retries before the pin code is blocked",
51   "      --puk-retries=INT    Number of retries before the puk code is blocked",
52   "  -i, --input=STRING       Filename to use as input, - for stdin  (default=`-')",
53   "  -o, --output=STRING      Filename to use as output, - for stdout\n                             (default=`-')",
54   "  -K, --key-format=ENUM    Format of the key being read/written  (possible\n                             values=\"PEM\", \"PKCS12\", \"GZIP\", \"DER\",\n                             \"SSH\" default=`PEM')",
55   "  -p, --password=STRING    Password for decryption of private key file, if\n                             omitted password will be asked for",
56   "  -S, --subject=STRING     The subject to use for certificate request",
57   "\n       The subject must be written as:\n       /CN=host.example.com/OU=test/O=example.com/\n",
58   "      --serial=INT         Serial number of the self-signed certificate",
59   "      --valid-days=INT     Time (in days) until the self-signed certificate\n                             expires  (default=`365')",
60   "  -P, --pin=STRING         Pin/puk code for verification, if omitted pin/puk\n                             will be asked for",
61   "  -N, --new-pin=STRING     New pin/puk code for changing, if omitted pin/puk\n                             will be asked for",
62   "      --pin-policy=ENUM    Set pin policy for action generate or import-key.\n                             Only available on YubiKey 4  (possible\n                             values=\"never\", \"once\", \"always\")",
63   "      --touch-policy=ENUM  Set touch policy for action generate, import-key or\n                             set-mgm-key. Only available on YubiKey 4\n                             (possible values=\"never\", \"always\",\n                             \"cached\")",
64   "      --id=INT             Id of object for write/read object",
65   "  -f, --format=ENUM        Format of data for write/read object  (possible\n                             values=\"hex\", \"base64\", \"binary\"\n                             default=`hex')",
66   "      --sign               Sign data  (default=off)",
67   "      --stdin-input        Read sensitive values from stdin  (default=off)",
68   "      --attestation        Add attestation cross-signature  (default=off)",
69     0
70 };
71 
72 static void
init_help_array(void)73 init_help_array(void)
74 {
75   gengetopt_args_info_help[0] = gengetopt_args_info_full_help[0];
76   gengetopt_args_info_help[1] = gengetopt_args_info_full_help[1];
77   gengetopt_args_info_help[2] = gengetopt_args_info_full_help[2];
78   gengetopt_args_info_help[3] = gengetopt_args_info_full_help[3];
79   gengetopt_args_info_help[4] = gengetopt_args_info_full_help[4];
80   gengetopt_args_info_help[5] = gengetopt_args_info_full_help[5];
81   gengetopt_args_info_help[6] = gengetopt_args_info_full_help[6];
82   gengetopt_args_info_help[7] = gengetopt_args_info_full_help[7];
83   gengetopt_args_info_help[8] = gengetopt_args_info_full_help[8];
84   gengetopt_args_info_help[9] = gengetopt_args_info_full_help[9];
85   gengetopt_args_info_help[10] = gengetopt_args_info_full_help[10];
86   gengetopt_args_info_help[11] = gengetopt_args_info_full_help[11];
87   gengetopt_args_info_help[12] = gengetopt_args_info_full_help[12];
88   gengetopt_args_info_help[13] = gengetopt_args_info_full_help[13];
89   gengetopt_args_info_help[14] = gengetopt_args_info_full_help[14];
90   gengetopt_args_info_help[15] = gengetopt_args_info_full_help[15];
91   gengetopt_args_info_help[16] = gengetopt_args_info_full_help[16];
92   gengetopt_args_info_help[17] = gengetopt_args_info_full_help[17];
93   gengetopt_args_info_help[18] = gengetopt_args_info_full_help[18];
94   gengetopt_args_info_help[19] = gengetopt_args_info_full_help[19];
95   gengetopt_args_info_help[20] = gengetopt_args_info_full_help[20];
96   gengetopt_args_info_help[21] = gengetopt_args_info_full_help[21];
97   gengetopt_args_info_help[22] = gengetopt_args_info_full_help[22];
98   gengetopt_args_info_help[23] = gengetopt_args_info_full_help[23];
99   gengetopt_args_info_help[24] = gengetopt_args_info_full_help[24];
100   gengetopt_args_info_help[25] = gengetopt_args_info_full_help[25];
101   gengetopt_args_info_help[26] = gengetopt_args_info_full_help[26];
102   gengetopt_args_info_help[27] = gengetopt_args_info_full_help[27];
103   gengetopt_args_info_help[28] = gengetopt_args_info_full_help[28];
104   gengetopt_args_info_help[29] = gengetopt_args_info_full_help[31];
105   gengetopt_args_info_help[30] = 0;
106 
107 }
108 
109 const char *gengetopt_args_info_help[31];
110 
111 typedef enum {ARG_NO
112   , ARG_FLAG
113   , ARG_STRING
114   , ARG_INT
115   , ARG_ENUM
116 } cmdline_parser_arg_type;
117 
118 static
119 void clear_given (struct gengetopt_args_info *args_info);
120 static
121 void clear_args (struct gengetopt_args_info *args_info);
122 
123 static int
124 cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
125                         struct cmdline_parser_params *params, const char *additional_error);
126 
127 static int
128 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
129 struct line_list
130 {
131   char * string_arg;
132   struct line_list * next;
133 };
134 
135 static struct line_list *cmd_line_list = 0;
136 static struct line_list *cmd_line_list_tmp = 0;
137 
138 static void
free_cmd_list(void)139 free_cmd_list(void)
140 {
141   /* free the list of a previous call */
142   if (cmd_line_list)
143     {
144       while (cmd_line_list) {
145         cmd_line_list_tmp = cmd_line_list;
146         cmd_line_list = cmd_line_list->next;
147         free (cmd_line_list_tmp->string_arg);
148         free (cmd_line_list_tmp);
149       }
150     }
151 }
152 
153 
154 const char *cmdline_parser_action_values[] = {"version", "generate", "set-mgm-key", "reset", "pin-retries", "import-key", "import-certificate", "set-chuid", "request-certificate", "verify-pin", "change-pin", "change-puk", "unblock-pin", "selfsign-certificate", "delete-certificate", "read-certificate", "status", "test-signature", "test-decipher", "list-readers", "set-ccc", "write-object", "read-object", "attest", 0}; /*< Possible values for action. */
155 const char *cmdline_parser_slot_values[] = {"9a", "9c", "9d", "9e", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "f9", 0}; /*< Possible values for slot. */
156 const char *cmdline_parser_algorithm_values[] = {"RSA1024", "RSA2048", "ECCP256", "ECCP384", 0}; /*< Possible values for algorithm. */
157 const char *cmdline_parser_hash_values[] = {"SHA1", "SHA256", "SHA384", "SHA512", 0}; /*< Possible values for hash. */
158 const char *cmdline_parser_key_format_values[] = {"PEM", "PKCS12", "GZIP", "DER", "SSH", 0}; /*< Possible values for key-format. */
159 const char *cmdline_parser_pin_policy_values[] = {"never", "once", "always", 0}; /*< Possible values for pin-policy. */
160 const char *cmdline_parser_touch_policy_values[] = {"never", "always", "cached", 0}; /*< Possible values for touch-policy. */
161 const char *cmdline_parser_format_values[] = {"hex", "base64", "binary", 0}; /*< Possible values for format. */
162 
163 static char *
164 gengetopt_strdup (const char *s);
165 
166 static
clear_given(struct gengetopt_args_info * args_info)167 void clear_given (struct gengetopt_args_info *args_info)
168 {
169   args_info->help_given = 0 ;
170   args_info->full_help_given = 0 ;
171   args_info->version_given = 0 ;
172   args_info->verbose_given = 0 ;
173   args_info->reader_given = 0 ;
174   args_info->key_given = 0 ;
175   args_info->action_given = 0 ;
176   args_info->slot_given = 0 ;
177   args_info->algorithm_given = 0 ;
178   args_info->hash_given = 0 ;
179   args_info->new_key_given = 0 ;
180   args_info->pin_retries_given = 0 ;
181   args_info->puk_retries_given = 0 ;
182   args_info->input_given = 0 ;
183   args_info->output_given = 0 ;
184   args_info->key_format_given = 0 ;
185   args_info->password_given = 0 ;
186   args_info->subject_given = 0 ;
187   args_info->serial_given = 0 ;
188   args_info->valid_days_given = 0 ;
189   args_info->pin_given = 0 ;
190   args_info->new_pin_given = 0 ;
191   args_info->pin_policy_given = 0 ;
192   args_info->touch_policy_given = 0 ;
193   args_info->id_given = 0 ;
194   args_info->format_given = 0 ;
195   args_info->sign_given = 0 ;
196   args_info->stdin_input_given = 0 ;
197   args_info->attestation_given = 0 ;
198 }
199 
200 static
clear_args(struct gengetopt_args_info * args_info)201 void clear_args (struct gengetopt_args_info *args_info)
202 {
203   FIX_UNUSED (args_info);
204   args_info->verbose_arg = 0;
205   args_info->verbose_orig = NULL;
206   args_info->reader_arg = gengetopt_strdup ("Yubikey");
207   args_info->reader_orig = NULL;
208   args_info->key_arg = gengetopt_strdup ("010203040506070801020304050607080102030405060708");
209   args_info->key_orig = NULL;
210   args_info->action_arg = NULL;
211   args_info->action_orig = NULL;
212   args_info->slot_arg = slot__NULL;
213   args_info->slot_orig = NULL;
214   args_info->algorithm_arg = algorithm_arg_RSA2048;
215   args_info->algorithm_orig = NULL;
216   args_info->hash_arg = hash_arg_SHA256;
217   args_info->hash_orig = NULL;
218   args_info->new_key_arg = NULL;
219   args_info->new_key_orig = NULL;
220   args_info->pin_retries_orig = NULL;
221   args_info->puk_retries_orig = NULL;
222   args_info->input_arg = gengetopt_strdup ("-");
223   args_info->input_orig = NULL;
224   args_info->output_arg = gengetopt_strdup ("-");
225   args_info->output_orig = NULL;
226   args_info->key_format_arg = key_format_arg_PEM;
227   args_info->key_format_orig = NULL;
228   args_info->password_arg = NULL;
229   args_info->password_orig = NULL;
230   args_info->subject_arg = NULL;
231   args_info->subject_orig = NULL;
232   args_info->serial_orig = NULL;
233   args_info->valid_days_arg = 365;
234   args_info->valid_days_orig = NULL;
235   args_info->pin_arg = NULL;
236   args_info->pin_orig = NULL;
237   args_info->new_pin_arg = NULL;
238   args_info->new_pin_orig = NULL;
239   args_info->pin_policy_arg = pin_policy__NULL;
240   args_info->pin_policy_orig = NULL;
241   args_info->touch_policy_arg = touch_policy__NULL;
242   args_info->touch_policy_orig = NULL;
243   args_info->id_orig = NULL;
244   args_info->format_arg = format_arg_hex;
245   args_info->format_orig = NULL;
246   args_info->sign_flag = 0;
247   args_info->stdin_input_flag = 0;
248   args_info->attestation_flag = 0;
249 
250 }
251 
252 static
init_args_info(struct gengetopt_args_info * args_info)253 void init_args_info(struct gengetopt_args_info *args_info)
254 {
255 
256   init_help_array();
257   args_info->help_help = gengetopt_args_info_full_help[0] ;
258   args_info->full_help_help = gengetopt_args_info_full_help[1] ;
259   args_info->version_help = gengetopt_args_info_full_help[2] ;
260   args_info->verbose_help = gengetopt_args_info_full_help[3] ;
261   args_info->reader_help = gengetopt_args_info_full_help[4] ;
262   args_info->key_help = gengetopt_args_info_full_help[5] ;
263   args_info->action_help = gengetopt_args_info_full_help[6] ;
264   args_info->action_min = 0;
265   args_info->action_max = 0;
266   args_info->slot_help = gengetopt_args_info_full_help[8] ;
267   args_info->algorithm_help = gengetopt_args_info_full_help[10] ;
268   args_info->hash_help = gengetopt_args_info_full_help[11] ;
269   args_info->new_key_help = gengetopt_args_info_full_help[12] ;
270   args_info->pin_retries_help = gengetopt_args_info_full_help[13] ;
271   args_info->puk_retries_help = gengetopt_args_info_full_help[14] ;
272   args_info->input_help = gengetopt_args_info_full_help[15] ;
273   args_info->output_help = gengetopt_args_info_full_help[16] ;
274   args_info->key_format_help = gengetopt_args_info_full_help[17] ;
275   args_info->password_help = gengetopt_args_info_full_help[18] ;
276   args_info->subject_help = gengetopt_args_info_full_help[19] ;
277   args_info->serial_help = gengetopt_args_info_full_help[21] ;
278   args_info->valid_days_help = gengetopt_args_info_full_help[22] ;
279   args_info->pin_help = gengetopt_args_info_full_help[23] ;
280   args_info->new_pin_help = gengetopt_args_info_full_help[24] ;
281   args_info->pin_policy_help = gengetopt_args_info_full_help[25] ;
282   args_info->touch_policy_help = gengetopt_args_info_full_help[26] ;
283   args_info->id_help = gengetopt_args_info_full_help[27] ;
284   args_info->format_help = gengetopt_args_info_full_help[28] ;
285   args_info->sign_help = gengetopt_args_info_full_help[29] ;
286   args_info->stdin_input_help = gengetopt_args_info_full_help[30] ;
287   args_info->attestation_help = gengetopt_args_info_full_help[31] ;
288 
289 }
290 
291 void
cmdline_parser_print_version(void)292 cmdline_parser_print_version (void)
293 {
294   printf ("%s %s\n",
295      (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
296      CMDLINE_PARSER_VERSION);
297 
298   if (strlen(gengetopt_args_info_versiontext) > 0)
299     printf("\n%s\n", gengetopt_args_info_versiontext);
300 }
301 
print_help_common(void)302 static void print_help_common(void)
303 {
304 	size_t len_purpose = strlen(gengetopt_args_info_purpose);
305 	size_t len_usage = strlen(gengetopt_args_info_usage);
306 
307 	if (len_usage > 0) {
308 		printf("%s\n", gengetopt_args_info_usage);
309 	}
310 	if (len_purpose > 0) {
311 		printf("%s\n", gengetopt_args_info_purpose);
312 	}
313 
314 	if (len_usage || len_purpose) {
315 		printf("\n");
316 	}
317 
318 	if (strlen(gengetopt_args_info_description) > 0) {
319 		printf("%s\n\n", gengetopt_args_info_description);
320 	}
321 }
322 
323 void
cmdline_parser_print_help(void)324 cmdline_parser_print_help (void)
325 {
326   int i = 0;
327   print_help_common();
328   while (gengetopt_args_info_help[i])
329     printf("%s\n", gengetopt_args_info_help[i++]);
330 }
331 
332 void
cmdline_parser_print_full_help(void)333 cmdline_parser_print_full_help (void)
334 {
335   int i = 0;
336   print_help_common();
337   while (gengetopt_args_info_full_help[i])
338     printf("%s\n", gengetopt_args_info_full_help[i++]);
339 }
340 
341 void
cmdline_parser_init(struct gengetopt_args_info * args_info)342 cmdline_parser_init (struct gengetopt_args_info *args_info)
343 {
344   clear_given (args_info);
345   clear_args (args_info);
346   init_args_info (args_info);
347 }
348 
349 void
cmdline_parser_params_init(struct cmdline_parser_params * params)350 cmdline_parser_params_init(struct cmdline_parser_params *params)
351 {
352   if (params)
353     {
354       params->override = 0;
355       params->initialize = 1;
356       params->check_required = 1;
357       params->check_ambiguity = 0;
358       params->print_errors = 1;
359     }
360 }
361 
362 struct cmdline_parser_params *
cmdline_parser_params_create(void)363 cmdline_parser_params_create(void)
364 {
365   struct cmdline_parser_params *params =
366     (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
367   cmdline_parser_params_init(params);
368   return params;
369 }
370 
371 static void
free_string_field(char ** s)372 free_string_field (char **s)
373 {
374   if (*s)
375     {
376       free (*s);
377       *s = 0;
378     }
379 }
380 
381 /** @brief generic value variable */
382 union generic_value {
383     int int_arg;
384     char *string_arg;
385     const char *default_string_arg;
386 };
387 
388 /** @brief holds temporary values for multiple options */
389 struct generic_list
390 {
391   union generic_value arg;
392   char *orig;
393   struct generic_list *next;
394 };
395 
396 /**
397  * @brief add a node at the head of the list
398  */
add_node(struct generic_list ** list)399 static void add_node(struct generic_list **list) {
400   struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));
401   new_node->next = *list;
402   *list = new_node;
403   new_node->arg.string_arg = 0;
404   new_node->orig = 0;
405 }
406 
407 /**
408  * The passed arg parameter is NOT set to 0 from this function
409  */
410 static void
free_multiple_field(unsigned int len,void * arg,char *** orig)411 free_multiple_field(unsigned int len, void *arg, char ***orig)
412 {
413   unsigned int i;
414   if (arg) {
415     for (i = 0; i < len; ++i)
416       {
417         free_string_field(&((*orig)[i]));
418       }
419 
420     free (arg);
421     free (*orig);
422     *orig = 0;
423   }
424 }
425 
426 
427 static void
cmdline_parser_release(struct gengetopt_args_info * args_info)428 cmdline_parser_release (struct gengetopt_args_info *args_info)
429 {
430 
431   free_string_field (&(args_info->verbose_orig));
432   free_string_field (&(args_info->reader_arg));
433   free_string_field (&(args_info->reader_orig));
434   free_string_field (&(args_info->key_arg));
435   free_string_field (&(args_info->key_orig));
436   free_multiple_field (args_info->action_given, (void *)(args_info->action_arg), &(args_info->action_orig));
437   args_info->action_arg = 0;
438   free_string_field (&(args_info->slot_orig));
439   free_string_field (&(args_info->algorithm_orig));
440   free_string_field (&(args_info->hash_orig));
441   free_string_field (&(args_info->new_key_arg));
442   free_string_field (&(args_info->new_key_orig));
443   free_string_field (&(args_info->pin_retries_orig));
444   free_string_field (&(args_info->puk_retries_orig));
445   free_string_field (&(args_info->input_arg));
446   free_string_field (&(args_info->input_orig));
447   free_string_field (&(args_info->output_arg));
448   free_string_field (&(args_info->output_orig));
449   free_string_field (&(args_info->key_format_orig));
450   free_string_field (&(args_info->password_arg));
451   free_string_field (&(args_info->password_orig));
452   free_string_field (&(args_info->subject_arg));
453   free_string_field (&(args_info->subject_orig));
454   free_string_field (&(args_info->serial_orig));
455   free_string_field (&(args_info->valid_days_orig));
456   free_string_field (&(args_info->pin_arg));
457   free_string_field (&(args_info->pin_orig));
458   free_string_field (&(args_info->new_pin_arg));
459   free_string_field (&(args_info->new_pin_orig));
460   free_string_field (&(args_info->pin_policy_orig));
461   free_string_field (&(args_info->touch_policy_orig));
462   free_string_field (&(args_info->id_orig));
463   free_string_field (&(args_info->format_orig));
464 
465 
466 
467   clear_given (args_info);
468 }
469 
470 /**
471  * @param val the value to check
472  * @param values the possible values
473  * @return the index of the matched value:
474  * -1 if no value matched,
475  * -2 if more than one value has matched
476  */
477 static int
check_possible_values(const char * val,const char * values[])478 check_possible_values(const char *val, const char *values[])
479 {
480   int i, found, last;
481   size_t len;
482 
483   if (!val)   /* otherwise strlen() crashes below */
484     return -1; /* -1 means no argument for the option */
485 
486   found = last = 0;
487 
488   for (i = 0, len = strlen(val); values[i]; ++i)
489     {
490       if (strncmp(val, values[i], len) == 0)
491         {
492           ++found;
493           last = i;
494           if (strlen(values[i]) == len)
495             return i; /* exact macth no need to check more */
496         }
497     }
498 
499   if (found == 1) /* one match: OK */
500     return last;
501 
502   return (found ? -2 : -1); /* return many values or none matched */
503 }
504 
505 
506 static void
write_into_file(FILE * outfile,const char * opt,const char * arg,const char * values[])507 write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
508 {
509   int found = -1;
510   if (arg) {
511     if (values) {
512       found = check_possible_values(arg, values);
513     }
514     if (found >= 0)
515       fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]);
516     else
517       fprintf(outfile, "%s=\"%s\"\n", opt, arg);
518   } else {
519     fprintf(outfile, "%s\n", opt);
520   }
521 }
522 
523 static void
write_multiple_into_file(FILE * outfile,int len,const char * opt,char ** arg,const char * values[])524 write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[])
525 {
526   int i;
527 
528   for (i = 0; i < len; ++i)
529     write_into_file(outfile, opt, (arg ? arg[i] : 0), values);
530 }
531 
532 int
cmdline_parser_dump(FILE * outfile,struct gengetopt_args_info * args_info)533 cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
534 {
535   int i = 0;
536 
537   if (!outfile)
538     {
539       fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
540       return EXIT_FAILURE;
541     }
542 
543   if (args_info->help_given)
544     write_into_file(outfile, "help", 0, 0 );
545   if (args_info->full_help_given)
546     write_into_file(outfile, "full-help", 0, 0 );
547   if (args_info->version_given)
548     write_into_file(outfile, "version", 0, 0 );
549   if (args_info->verbose_given)
550     write_into_file(outfile, "verbose", args_info->verbose_orig, 0);
551   if (args_info->reader_given)
552     write_into_file(outfile, "reader", args_info->reader_orig, 0);
553   if (args_info->key_given)
554     write_into_file(outfile, "key", args_info->key_orig, 0);
555   write_multiple_into_file(outfile, args_info->action_given, "action", args_info->action_orig, cmdline_parser_action_values);
556   if (args_info->slot_given)
557     write_into_file(outfile, "slot", args_info->slot_orig, cmdline_parser_slot_values);
558   if (args_info->algorithm_given)
559     write_into_file(outfile, "algorithm", args_info->algorithm_orig, cmdline_parser_algorithm_values);
560   if (args_info->hash_given)
561     write_into_file(outfile, "hash", args_info->hash_orig, cmdline_parser_hash_values);
562   if (args_info->new_key_given)
563     write_into_file(outfile, "new-key", args_info->new_key_orig, 0);
564   if (args_info->pin_retries_given)
565     write_into_file(outfile, "pin-retries", args_info->pin_retries_orig, 0);
566   if (args_info->puk_retries_given)
567     write_into_file(outfile, "puk-retries", args_info->puk_retries_orig, 0);
568   if (args_info->input_given)
569     write_into_file(outfile, "input", args_info->input_orig, 0);
570   if (args_info->output_given)
571     write_into_file(outfile, "output", args_info->output_orig, 0);
572   if (args_info->key_format_given)
573     write_into_file(outfile, "key-format", args_info->key_format_orig, cmdline_parser_key_format_values);
574   if (args_info->password_given)
575     write_into_file(outfile, "password", args_info->password_orig, 0);
576   if (args_info->subject_given)
577     write_into_file(outfile, "subject", args_info->subject_orig, 0);
578   if (args_info->serial_given)
579     write_into_file(outfile, "serial", args_info->serial_orig, 0);
580   if (args_info->valid_days_given)
581     write_into_file(outfile, "valid-days", args_info->valid_days_orig, 0);
582   if (args_info->pin_given)
583     write_into_file(outfile, "pin", args_info->pin_orig, 0);
584   if (args_info->new_pin_given)
585     write_into_file(outfile, "new-pin", args_info->new_pin_orig, 0);
586   if (args_info->pin_policy_given)
587     write_into_file(outfile, "pin-policy", args_info->pin_policy_orig, cmdline_parser_pin_policy_values);
588   if (args_info->touch_policy_given)
589     write_into_file(outfile, "touch-policy", args_info->touch_policy_orig, cmdline_parser_touch_policy_values);
590   if (args_info->id_given)
591     write_into_file(outfile, "id", args_info->id_orig, 0);
592   if (args_info->format_given)
593     write_into_file(outfile, "format", args_info->format_orig, cmdline_parser_format_values);
594   if (args_info->sign_given)
595     write_into_file(outfile, "sign", 0, 0 );
596   if (args_info->stdin_input_given)
597     write_into_file(outfile, "stdin-input", 0, 0 );
598   if (args_info->attestation_given)
599     write_into_file(outfile, "attestation", 0, 0 );
600 
601 
602   i = EXIT_SUCCESS;
603   return i;
604 }
605 
606 int
cmdline_parser_file_save(const char * filename,struct gengetopt_args_info * args_info)607 cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
608 {
609   FILE *outfile;
610   int i = 0;
611 
612   outfile = fopen(filename, "w");
613 
614   if (!outfile)
615     {
616       fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
617       return EXIT_FAILURE;
618     }
619 
620   i = cmdline_parser_dump(outfile, args_info);
621   fclose (outfile);
622 
623   return i;
624 }
625 
626 void
cmdline_parser_free(struct gengetopt_args_info * args_info)627 cmdline_parser_free (struct gengetopt_args_info *args_info)
628 {
629   cmdline_parser_release (args_info);
630 }
631 
632 /** @brief replacement of strdup, which is not standard */
633 char *
gengetopt_strdup(const char * s)634 gengetopt_strdup (const char *s)
635 {
636   char *result = 0;
637   if (!s)
638     return result;
639 
640   result = (char*)malloc(strlen(s) + 1);
641   if (result == (char*)0)
642     return (char*)0;
643   strcpy(result, s);
644   return result;
645 }
646 
647 static char *
get_multiple_arg_token(const char * arg)648 get_multiple_arg_token(const char *arg)
649 {
650   const char *tok;
651   char *ret;
652   size_t len, num_of_escape, i, j;
653 
654   if (!arg)
655     return 0;
656 
657   tok = strchr (arg, ',');
658   num_of_escape = 0;
659 
660   /* make sure it is not escaped */
661   while (tok)
662     {
663       if (*(tok-1) == '\\')
664         {
665           /* find the next one */
666           tok = strchr (tok+1, ',');
667           ++num_of_escape;
668         }
669       else
670         break;
671     }
672 
673   if (tok)
674     len = (size_t)(tok - arg + 1);
675   else
676     len = strlen (arg) + 1;
677 
678   len -= num_of_escape;
679 
680   ret = (char *) malloc (len);
681 
682   i = 0;
683   j = 0;
684   while (arg[i] && (j < len-1))
685     {
686       if (arg[i] == '\\' &&
687 	  arg[ i + 1 ] &&
688 	  arg[ i + 1 ] == ',')
689         ++i;
690 
691       ret[j++] = arg[i++];
692     }
693 
694   ret[len-1] = '\0';
695 
696   return ret;
697 }
698 
699 static const char *
get_multiple_arg_token_next(const char * arg)700 get_multiple_arg_token_next(const char *arg)
701 {
702   const char *tok;
703 
704   if (!arg)
705     return 0;
706 
707   tok = strchr (arg, ',');
708 
709   /* make sure it is not escaped */
710   while (tok)
711     {
712       if (*(tok-1) == '\\')
713         {
714           /* find the next one */
715           tok = strchr (tok+1, ',');
716         }
717       else
718         break;
719     }
720 
721   if (! tok || strlen(tok) == 1)
722     return 0;
723 
724   return tok+1;
725 }
726 
727 static int
728 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc);
729 
730 int
check_multiple_option_occurrences(const char * prog_name,unsigned int option_given,unsigned int min,unsigned int max,const char * option_desc)731 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc)
732 {
733   int error_occurred = 0;
734 
735   if (option_given && (min > 0 || max > 0))
736     {
737       if (min > 0 && max > 0)
738         {
739           if (min == max)
740             {
741               /* specific occurrences */
742               if (option_given != (unsigned int) min)
743                 {
744                   fprintf (stderr, "%s: %s option occurrences must be %d\n",
745                     prog_name, option_desc, min);
746                   error_occurred = 1;
747                 }
748             }
749           else if (option_given < (unsigned int) min
750                 || option_given > (unsigned int) max)
751             {
752               /* range occurrences */
753               fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n",
754                 prog_name, option_desc, min, max);
755               error_occurred = 1;
756             }
757         }
758       else if (min > 0)
759         {
760           /* at least check */
761           if (option_given < min)
762             {
763               fprintf (stderr, "%s: %s option occurrences must be at least %d\n",
764                 prog_name, option_desc, min);
765               error_occurred = 1;
766             }
767         }
768       else if (max > 0)
769         {
770           /* at most check */
771           if (option_given > max)
772             {
773               fprintf (stderr, "%s: %s option occurrences must be at most %d\n",
774                 prog_name, option_desc, max);
775               error_occurred = 1;
776             }
777         }
778     }
779 
780   return error_occurred;
781 }
782 int
cmdline_parser(int argc,char ** argv,struct gengetopt_args_info * args_info)783 cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
784 {
785   return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
786 }
787 
788 int
cmdline_parser_ext(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params)789 cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
790                    struct cmdline_parser_params *params)
791 {
792   int result;
793   result = cmdline_parser_internal (argc, argv, args_info, params, 0);
794 
795   if (result == EXIT_FAILURE)
796     {
797       cmdline_parser_free (args_info);
798       exit (EXIT_FAILURE);
799     }
800 
801   return result;
802 }
803 
804 int
cmdline_parser2(int argc,char ** argv,struct gengetopt_args_info * args_info,int override,int initialize,int check_required)805 cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
806 {
807   int result;
808   struct cmdline_parser_params params;
809 
810   params.override = override;
811   params.initialize = initialize;
812   params.check_required = check_required;
813   params.check_ambiguity = 0;
814   params.print_errors = 1;
815 
816   result = cmdline_parser_internal (argc, argv, args_info, &params, 0);
817 
818   if (result == EXIT_FAILURE)
819     {
820       cmdline_parser_free (args_info);
821       exit (EXIT_FAILURE);
822     }
823 
824   return result;
825 }
826 
827 int
cmdline_parser_required(struct gengetopt_args_info * args_info,const char * prog_name)828 cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
829 {
830   int result = EXIT_SUCCESS;
831 
832   if (cmdline_parser_required2(args_info, prog_name, 0) > 0)
833     result = EXIT_FAILURE;
834 
835   if (result == EXIT_FAILURE)
836     {
837       cmdline_parser_free (args_info);
838       exit (EXIT_FAILURE);
839     }
840 
841   return result;
842 }
843 
844 int
cmdline_parser_required2(struct gengetopt_args_info * args_info,const char * prog_name,const char * additional_error)845 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
846 {
847   int error_occurred = 0;
848   FIX_UNUSED (additional_error);
849 
850   /* checks for required options */
851   if (! args_info->action_given)
852     {
853       fprintf (stderr, "%s: '--action' ('-a') option required%s\n", prog_name, (additional_error ? additional_error : ""));
854       error_occurred = 1;
855     }
856 
857   if (check_multiple_option_occurrences(prog_name, args_info->action_given, args_info->action_min, args_info->action_max, "'--action' ('-a')"))
858      error_occurred = 1;
859 
860 
861   /* checks for dependences among options */
862   if (args_info->pin_retries_given && ! args_info->puk_retries_given)
863     {
864       fprintf (stderr, "%s: '--pin-retries' option depends on option 'puk-retries'%s\n", prog_name, (additional_error ? additional_error : ""));
865       error_occurred = 1;
866     }
867   if (args_info->puk_retries_given && ! args_info->pin_retries_given)
868     {
869       fprintf (stderr, "%s: '--puk-retries' option depends on option 'pin-retries'%s\n", prog_name, (additional_error ? additional_error : ""));
870       error_occurred = 1;
871     }
872   if (args_info->new_pin_given && ! args_info->pin_given)
873     {
874       fprintf (stderr, "%s: '--new-pin' ('-N') option depends on option 'pin'%s\n", prog_name, (additional_error ? additional_error : ""));
875       error_occurred = 1;
876     }
877 
878   return error_occurred;
879 }
880 
881 
882 static char *package_name = 0;
883 
884 /**
885  * @brief updates an option
886  * @param field the generic pointer to the field to update
887  * @param orig_field the pointer to the orig field
888  * @param field_given the pointer to the number of occurrence of this option
889  * @param prev_given the pointer to the number of occurrence already seen
890  * @param value the argument for this option (if null no arg was specified)
891  * @param possible_values the possible values for this option (if specified)
892  * @param default_value the default value (in case the option only accepts fixed values)
893  * @param arg_type the type of this option
894  * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
895  * @param override @see cmdline_parser_params.override
896  * @param no_free whether to free a possible previous value
897  * @param multiple_option whether this is a multiple option
898  * @param long_opt the corresponding long option
899  * @param short_opt the corresponding short option (or '-' if none)
900  * @param additional_error possible further error specification
901  */
902 static
update_arg(void * field,char ** orig_field,unsigned int * field_given,unsigned int * prev_given,char * value,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,int check_ambiguity,int override,int no_free,int multiple_option,const char * long_opt,char short_opt,const char * additional_error)903 int update_arg(void *field, char **orig_field,
904                unsigned int *field_given, unsigned int *prev_given,
905                char *value, const char *possible_values[],
906                const char *default_value,
907                cmdline_parser_arg_type arg_type,
908                int check_ambiguity, int override,
909                int no_free, int multiple_option,
910                const char *long_opt, char short_opt,
911                const char *additional_error)
912 {
913   char *stop_char = 0;
914   const char *val = value;
915   int found;
916   char **string_field;
917   FIX_UNUSED (field);
918 
919   stop_char = 0;
920   found = 0;
921 
922   if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
923     {
924       if (short_opt != '-')
925         fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
926                package_name, long_opt, short_opt,
927                (additional_error ? additional_error : ""));
928       else
929         fprintf (stderr, "%s: `--%s' option given more than once%s\n",
930                package_name, long_opt,
931                (additional_error ? additional_error : ""));
932       return 1; /* failure */
933     }
934 
935   if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0)
936     {
937       if (short_opt != '-')
938         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n",
939           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt,
940           (additional_error ? additional_error : ""));
941       else
942         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n",
943           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt,
944           (additional_error ? additional_error : ""));
945       return 1; /* failure */
946     }
947 
948   if (field_given && *field_given && ! override)
949     return 0;
950   if (prev_given)
951     (*prev_given)++;
952   if (field_given)
953     (*field_given)++;
954   if (possible_values)
955     val = possible_values[found];
956 
957   switch(arg_type) {
958   case ARG_FLAG:
959     *((int *)field) = !*((int *)field);
960     break;
961   case ARG_INT:
962     if (val) *((int *)field) = strtol (val, &stop_char, 0);
963     break;
964   case ARG_ENUM:
965     if (val) *((int *)field) = found;
966     break;
967   case ARG_STRING:
968     if (val) {
969       string_field = (char **)field;
970       if (!no_free && *string_field)
971         free (*string_field); /* free previous string */
972       *string_field = gengetopt_strdup (val);
973     }
974     break;
975   default:
976     break;
977   };
978 
979   /* check numeric conversion */
980   switch(arg_type) {
981   case ARG_INT:
982     if (val && !(stop_char && *stop_char == '\0')) {
983       fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
984       return 1; /* failure */
985     }
986     break;
987   default:
988     ;
989   };
990 
991   /* store the original value */
992   switch(arg_type) {
993   case ARG_NO:
994   case ARG_FLAG:
995     break;
996   default:
997     if (value && orig_field) {
998       if (no_free) {
999         *orig_field = value;
1000       } else {
1001         if (*orig_field)
1002           free (*orig_field); /* free previous string */
1003         *orig_field = gengetopt_strdup (value);
1004       }
1005     }
1006   };
1007 
1008   return 0; /* OK */
1009 }
1010 
1011 /**
1012  * @brief store information about a multiple option in a temporary list
1013  * @param list where to (temporarily) store multiple options
1014  */
1015 static
update_multiple_arg_temp(struct generic_list ** list,unsigned int * prev_given,const char * val,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,const char * long_opt,char short_opt,const char * additional_error)1016 int update_multiple_arg_temp(struct generic_list **list,
1017                unsigned int *prev_given, const char *val,
1018                const char *possible_values[], const char *default_value,
1019                cmdline_parser_arg_type arg_type,
1020                const char *long_opt, char short_opt,
1021                const char *additional_error)
1022 {
1023   /* store single arguments */
1024   char *multi_token;
1025   const char *multi_next;
1026 
1027   if (arg_type == ARG_NO) {
1028     (*prev_given)++;
1029     return 0; /* OK */
1030   }
1031 
1032   multi_token = get_multiple_arg_token(val);
1033   multi_next = get_multiple_arg_token_next (val);
1034 
1035   while (1)
1036     {
1037       add_node (list);
1038       if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,
1039           prev_given, multi_token, possible_values, default_value,
1040           arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {
1041         if (multi_token) free(multi_token);
1042         return 1; /* failure */
1043       }
1044 
1045       if (multi_next)
1046         {
1047           multi_token = get_multiple_arg_token(multi_next);
1048           multi_next = get_multiple_arg_token_next (multi_next);
1049         }
1050       else
1051         break;
1052     }
1053 
1054   return 0; /* OK */
1055 }
1056 
1057 /**
1058  * @brief free the passed list (including possible string argument)
1059  */
1060 static
free_list(struct generic_list * list,short string_arg)1061 void free_list(struct generic_list *list, short string_arg)
1062 {
1063   if (list) {
1064     struct generic_list *tmp;
1065     while (list)
1066       {
1067         tmp = list;
1068         if (string_arg && list->arg.string_arg)
1069           free (list->arg.string_arg);
1070         if (list->orig)
1071           free (list->orig);
1072         list = list->next;
1073         free (tmp);
1074       }
1075   }
1076 }
1077 
1078 /**
1079  * @brief updates a multiple option starting from the passed list
1080  */
1081 static
update_multiple_arg(void * field,char *** orig_field,unsigned int field_given,unsigned int prev_given,union generic_value * default_value,cmdline_parser_arg_type arg_type,struct generic_list * list)1082 void update_multiple_arg(void *field, char ***orig_field,
1083                unsigned int field_given, unsigned int prev_given, union generic_value *default_value,
1084                cmdline_parser_arg_type arg_type,
1085                struct generic_list *list)
1086 {
1087   int i;
1088   struct generic_list *tmp;
1089 
1090   if (prev_given && list) {
1091     *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));
1092 
1093     switch(arg_type) {
1094     case ARG_INT:
1095     case ARG_ENUM:
1096       *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break;
1097     case ARG_STRING:
1098       *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;
1099     default:
1100       break;
1101     };
1102 
1103     for (i = (prev_given - 1); i >= 0; --i)
1104       {
1105         tmp = list;
1106 
1107         switch(arg_type) {
1108         case ARG_INT:
1109           (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;
1110         case ARG_ENUM:
1111           (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;
1112         case ARG_STRING:
1113           (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;
1114         default:
1115           break;
1116         }
1117         (*orig_field) [i + field_given] = list->orig;
1118         list = list->next;
1119         free (tmp);
1120       }
1121   } else { /* set the default value */
1122     if (default_value && ! field_given) {
1123       switch(arg_type) {
1124       case ARG_INT:
1125       case ARG_ENUM:
1126         if (! *((int **)field)) {
1127           *((int **)field) = (int *)malloc (sizeof (int));
1128           (*((int **)field))[0] = default_value->int_arg;
1129         }
1130         break;
1131       case ARG_STRING:
1132         if (! *((char ***)field)) {
1133           *((char ***)field) = (char **)malloc (sizeof (char *));
1134           (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);
1135         }
1136         break;
1137       default: break;
1138       }
1139       if (!(*orig_field)) {
1140         *orig_field = (char **) malloc (sizeof (char *));
1141         (*orig_field)[0] = 0;
1142       }
1143     }
1144   }
1145 }
1146 
1147 int
cmdline_parser_internal(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params,const char * additional_error)1148 cmdline_parser_internal (
1149   int argc, char **argv, struct gengetopt_args_info *args_info,
1150                         struct cmdline_parser_params *params, const char *additional_error)
1151 {
1152   int c;	/* Character of the parsed option.  */
1153 
1154   struct generic_list * action_list = NULL;
1155   int error_occurred = 0;
1156   struct gengetopt_args_info local_args_info;
1157 
1158   int override;
1159   int initialize;
1160   int check_required;
1161   int check_ambiguity;
1162 
1163   package_name = argv[0];
1164 
1165   /* TODO: Why is this here? It is not used anywhere. */
1166   override = params->override;
1167   FIX_UNUSED(override);
1168 
1169   initialize = params->initialize;
1170   check_required = params->check_required;
1171 
1172   /* TODO: Why is this here? It is not used anywhere. */
1173   check_ambiguity = params->check_ambiguity;
1174   FIX_UNUSED(check_ambiguity);
1175 
1176   if (initialize)
1177     cmdline_parser_init (args_info);
1178 
1179   cmdline_parser_init (&local_args_info);
1180 
1181   optarg = 0;
1182   optind = 0;
1183   opterr = params->print_errors;
1184   optopt = '?';
1185 
1186   while (1)
1187     {
1188       int option_index = 0;
1189 
1190       static struct option long_options[] = {
1191         { "help",	0, NULL, 'h' },
1192         { "full-help",	0, NULL, 0 },
1193         { "version",	0, NULL, 'V' },
1194         { "verbose",	2, NULL, 'v' },
1195         { "reader",	1, NULL, 'r' },
1196         { "key",	2, NULL, 'k' },
1197         { "action",	1, NULL, 'a' },
1198         { "slot",	1, NULL, 's' },
1199         { "algorithm",	1, NULL, 'A' },
1200         { "hash",	1, NULL, 'H' },
1201         { "new-key",	1, NULL, 'n' },
1202         { "pin-retries",	1, NULL, 0 },
1203         { "puk-retries",	1, NULL, 0 },
1204         { "input",	1, NULL, 'i' },
1205         { "output",	1, NULL, 'o' },
1206         { "key-format",	1, NULL, 'K' },
1207         { "password",	1, NULL, 'p' },
1208         { "subject",	1, NULL, 'S' },
1209         { "serial",	1, NULL, 0 },
1210         { "valid-days",	1, NULL, 0 },
1211         { "pin",	1, NULL, 'P' },
1212         { "new-pin",	1, NULL, 'N' },
1213         { "pin-policy",	1, NULL, 0 },
1214         { "touch-policy",	1, NULL, 0 },
1215         { "id",	1, NULL, 0 },
1216         { "format",	1, NULL, 'f' },
1217         { "sign",	0, NULL, 0 },
1218         { "stdin-input",	0, NULL, 0 },
1219         { "attestation",	0, NULL, 0 },
1220         { 0,  0, 0, 0 }
1221       };
1222 
1223       c = getopt_long (argc, argv, "hVv::r:k::a:s:A:H:n:i:o:K:p:S:P:N:f:", long_options, &option_index);
1224 
1225       if (c == -1) break;	/* Exit from `while (1)' loop.  */
1226 
1227       switch (c)
1228         {
1229         case 'h':	/* Print help and exit.  */
1230           cmdline_parser_print_help ();
1231           cmdline_parser_free (&local_args_info);
1232           exit (EXIT_SUCCESS);
1233 
1234         case 'V':	/* Print version and exit.  */
1235           cmdline_parser_print_version ();
1236           cmdline_parser_free (&local_args_info);
1237           exit (EXIT_SUCCESS);
1238 
1239         case 'v':	/* Print more information.  */
1240 
1241 
1242           if (update_arg( (void *)&(args_info->verbose_arg),
1243                &(args_info->verbose_orig), &(args_info->verbose_given),
1244               &(local_args_info.verbose_given), optarg, 0, "0", ARG_INT,
1245               check_ambiguity, override, 0, 0,
1246               "verbose", 'v',
1247               additional_error))
1248             goto failure;
1249 
1250           break;
1251         case 'r':	/* Only use a matching reader.  */
1252 
1253 
1254           if (update_arg( (void *)&(args_info->reader_arg),
1255                &(args_info->reader_orig), &(args_info->reader_given),
1256               &(local_args_info.reader_given), optarg, 0, "Yubikey", ARG_STRING,
1257               check_ambiguity, override, 0, 0,
1258               "reader", 'r',
1259               additional_error))
1260             goto failure;
1261 
1262           break;
1263         case 'k':	/* Management key to use, if no value is specified key will be asked for.  */
1264 
1265 
1266           if (update_arg( (void *)&(args_info->key_arg),
1267                &(args_info->key_orig), &(args_info->key_given),
1268               &(local_args_info.key_given), optarg, 0, "010203040506070801020304050607080102030405060708", ARG_STRING,
1269               check_ambiguity, override, 0, 0,
1270               "key", 'k',
1271               additional_error))
1272             goto failure;
1273 
1274           break;
1275         case 'a':	/* Action to take.  */
1276 
1277           if (update_multiple_arg_temp(&action_list,
1278               &(local_args_info.action_given), optarg, cmdline_parser_action_values, 0, ARG_ENUM,
1279               "action", 'a',
1280               additional_error))
1281             goto failure;
1282 
1283           break;
1284         case 's':	/* What key slot to operate on.  */
1285 
1286 
1287           if (update_arg( (void *)&(args_info->slot_arg),
1288                &(args_info->slot_orig), &(args_info->slot_given),
1289               &(local_args_info.slot_given), optarg, cmdline_parser_slot_values, 0, ARG_ENUM,
1290               check_ambiguity, override, 0, 0,
1291               "slot", 's',
1292               additional_error))
1293             goto failure;
1294 
1295           break;
1296         case 'A':	/* What algorithm to use.  */
1297 
1298 
1299           if (update_arg( (void *)&(args_info->algorithm_arg),
1300                &(args_info->algorithm_orig), &(args_info->algorithm_given),
1301               &(local_args_info.algorithm_given), optarg, cmdline_parser_algorithm_values, "RSA2048", ARG_ENUM,
1302               check_ambiguity, override, 0, 0,
1303               "algorithm", 'A',
1304               additional_error))
1305             goto failure;
1306 
1307           break;
1308         case 'H':	/* Hash to use for signatures.  */
1309 
1310 
1311           if (update_arg( (void *)&(args_info->hash_arg),
1312                &(args_info->hash_orig), &(args_info->hash_given),
1313               &(local_args_info.hash_given), optarg, cmdline_parser_hash_values, "SHA256", ARG_ENUM,
1314               check_ambiguity, override, 0, 0,
1315               "hash", 'H',
1316               additional_error))
1317             goto failure;
1318 
1319           break;
1320         case 'n':	/* New management key to use for action set-mgm-key, if omitted key will be asked for.  */
1321 
1322 
1323           if (update_arg( (void *)&(args_info->new_key_arg),
1324                &(args_info->new_key_orig), &(args_info->new_key_given),
1325               &(local_args_info.new_key_given), optarg, 0, 0, ARG_STRING,
1326               check_ambiguity, override, 0, 0,
1327               "new-key", 'n',
1328               additional_error))
1329             goto failure;
1330 
1331           break;
1332         case 'i':	/* Filename to use as input, - for stdin.  */
1333 
1334 
1335           if (update_arg( (void *)&(args_info->input_arg),
1336                &(args_info->input_orig), &(args_info->input_given),
1337               &(local_args_info.input_given), optarg, 0, "-", ARG_STRING,
1338               check_ambiguity, override, 0, 0,
1339               "input", 'i',
1340               additional_error))
1341             goto failure;
1342 
1343           break;
1344         case 'o':	/* Filename to use as output, - for stdout.  */
1345 
1346 
1347           if (update_arg( (void *)&(args_info->output_arg),
1348                &(args_info->output_orig), &(args_info->output_given),
1349               &(local_args_info.output_given), optarg, 0, "-", ARG_STRING,
1350               check_ambiguity, override, 0, 0,
1351               "output", 'o',
1352               additional_error))
1353             goto failure;
1354 
1355           break;
1356         case 'K':	/* Format of the key being read/written.  */
1357 
1358 
1359           if (update_arg( (void *)&(args_info->key_format_arg),
1360                &(args_info->key_format_orig), &(args_info->key_format_given),
1361               &(local_args_info.key_format_given), optarg, cmdline_parser_key_format_values, "PEM", ARG_ENUM,
1362               check_ambiguity, override, 0, 0,
1363               "key-format", 'K',
1364               additional_error))
1365             goto failure;
1366 
1367           break;
1368         case 'p':	/* Password for decryption of private key file, if omitted password will be asked for.  */
1369 
1370 
1371           if (update_arg( (void *)&(args_info->password_arg),
1372                &(args_info->password_orig), &(args_info->password_given),
1373               &(local_args_info.password_given), optarg, 0, 0, ARG_STRING,
1374               check_ambiguity, override, 0, 0,
1375               "password", 'p',
1376               additional_error))
1377             goto failure;
1378 
1379           break;
1380         case 'S':	/* The subject to use for certificate request.  */
1381 
1382 
1383           if (update_arg( (void *)&(args_info->subject_arg),
1384                &(args_info->subject_orig), &(args_info->subject_given),
1385               &(local_args_info.subject_given), optarg, 0, 0, ARG_STRING,
1386               check_ambiguity, override, 0, 0,
1387               "subject", 'S',
1388               additional_error))
1389             goto failure;
1390 
1391           break;
1392         case 'P':	/* Pin/puk code for verification, if omitted pin/puk will be asked for.  */
1393 
1394 
1395           if (update_arg( (void *)&(args_info->pin_arg),
1396                &(args_info->pin_orig), &(args_info->pin_given),
1397               &(local_args_info.pin_given), optarg, 0, 0, ARG_STRING,
1398               check_ambiguity, override, 0, 0,
1399               "pin", 'P',
1400               additional_error))
1401             goto failure;
1402 
1403           break;
1404         case 'N':	/* New pin/puk code for changing, if omitted pin/puk will be asked for.  */
1405 
1406 
1407           if (update_arg( (void *)&(args_info->new_pin_arg),
1408                &(args_info->new_pin_orig), &(args_info->new_pin_given),
1409               &(local_args_info.new_pin_given), optarg, 0, 0, ARG_STRING,
1410               check_ambiguity, override, 0, 0,
1411               "new-pin", 'N',
1412               additional_error))
1413             goto failure;
1414 
1415           break;
1416         case 'f':	/* Format of data for write/read object.  */
1417 
1418 
1419           if (update_arg( (void *)&(args_info->format_arg),
1420                &(args_info->format_orig), &(args_info->format_given),
1421               &(local_args_info.format_given), optarg, cmdline_parser_format_values, "hex", ARG_ENUM,
1422               check_ambiguity, override, 0, 0,
1423               "format", 'f',
1424               additional_error))
1425             goto failure;
1426 
1427           break;
1428 
1429         case 0:	/* Long option with no short option */
1430           if (strcmp (long_options[option_index].name, "full-help") == 0) {
1431             cmdline_parser_print_full_help ();
1432             cmdline_parser_free (&local_args_info);
1433             exit (EXIT_SUCCESS);
1434           }
1435 
1436           /* Number of retries before the pin code is blocked.  */
1437           if (strcmp (long_options[option_index].name, "pin-retries") == 0)
1438           {
1439 
1440 
1441             if (update_arg( (void *)&(args_info->pin_retries_arg),
1442                  &(args_info->pin_retries_orig), &(args_info->pin_retries_given),
1443                 &(local_args_info.pin_retries_given), optarg, 0, 0, ARG_INT,
1444                 check_ambiguity, override, 0, 0,
1445                 "pin-retries", '-',
1446                 additional_error))
1447               goto failure;
1448 
1449           }
1450           /* Number of retries before the puk code is blocked.  */
1451           else if (strcmp (long_options[option_index].name, "puk-retries") == 0)
1452           {
1453 
1454 
1455             if (update_arg( (void *)&(args_info->puk_retries_arg),
1456                  &(args_info->puk_retries_orig), &(args_info->puk_retries_given),
1457                 &(local_args_info.puk_retries_given), optarg, 0, 0, ARG_INT,
1458                 check_ambiguity, override, 0, 0,
1459                 "puk-retries", '-',
1460                 additional_error))
1461               goto failure;
1462 
1463           }
1464           /* Serial number of the self-signed certificate.  */
1465           else if (strcmp (long_options[option_index].name, "serial") == 0)
1466           {
1467 
1468 
1469             if (update_arg( (void *)&(args_info->serial_arg),
1470                  &(args_info->serial_orig), &(args_info->serial_given),
1471                 &(local_args_info.serial_given), optarg, 0, 0, ARG_INT,
1472                 check_ambiguity, override, 0, 0,
1473                 "serial", '-',
1474                 additional_error))
1475               goto failure;
1476 
1477           }
1478           /* Time (in days) until the self-signed certificate expires.  */
1479           else if (strcmp (long_options[option_index].name, "valid-days") == 0)
1480           {
1481 
1482 
1483             if (update_arg( (void *)&(args_info->valid_days_arg),
1484                  &(args_info->valid_days_orig), &(args_info->valid_days_given),
1485                 &(local_args_info.valid_days_given), optarg, 0, "365", ARG_INT,
1486                 check_ambiguity, override, 0, 0,
1487                 "valid-days", '-',
1488                 additional_error))
1489               goto failure;
1490 
1491           }
1492           /* Set pin policy for action generate or import-key. Only available on YubiKey 4.  */
1493           else if (strcmp (long_options[option_index].name, "pin-policy") == 0)
1494           {
1495 
1496 
1497             if (update_arg( (void *)&(args_info->pin_policy_arg),
1498                  &(args_info->pin_policy_orig), &(args_info->pin_policy_given),
1499                 &(local_args_info.pin_policy_given), optarg, cmdline_parser_pin_policy_values, 0, ARG_ENUM,
1500                 check_ambiguity, override, 0, 0,
1501                 "pin-policy", '-',
1502                 additional_error))
1503               goto failure;
1504 
1505           }
1506           /* Set touch policy for action generate, import-key or set-mgm-key. Only available on YubiKey 4.  */
1507           else if (strcmp (long_options[option_index].name, "touch-policy") == 0)
1508           {
1509 
1510 
1511             if (update_arg( (void *)&(args_info->touch_policy_arg),
1512                  &(args_info->touch_policy_orig), &(args_info->touch_policy_given),
1513                 &(local_args_info.touch_policy_given), optarg, cmdline_parser_touch_policy_values, 0, ARG_ENUM,
1514                 check_ambiguity, override, 0, 0,
1515                 "touch-policy", '-',
1516                 additional_error))
1517               goto failure;
1518 
1519           }
1520           /* Id of object for write/read object.  */
1521           else if (strcmp (long_options[option_index].name, "id") == 0)
1522           {
1523 
1524 
1525             if (update_arg( (void *)&(args_info->id_arg),
1526                  &(args_info->id_orig), &(args_info->id_given),
1527                 &(local_args_info.id_given), optarg, 0, 0, ARG_INT,
1528                 check_ambiguity, override, 0, 0,
1529                 "id", '-',
1530                 additional_error))
1531               goto failure;
1532 
1533           }
1534           /* Sign data.  */
1535           else if (strcmp (long_options[option_index].name, "sign") == 0)
1536           {
1537 
1538 
1539             if (update_arg((void *)&(args_info->sign_flag), 0, &(args_info->sign_given),
1540                 &(local_args_info.sign_given), optarg, 0, 0, ARG_FLAG,
1541                 check_ambiguity, override, 1, 0, "sign", '-',
1542                 additional_error))
1543               goto failure;
1544 
1545           }
1546           /* Read sensitive values from stdin.  */
1547           else if (strcmp (long_options[option_index].name, "stdin-input") == 0)
1548           {
1549 
1550 
1551             if (update_arg((void *)&(args_info->stdin_input_flag), 0, &(args_info->stdin_input_given),
1552                 &(local_args_info.stdin_input_given), optarg, 0, 0, ARG_FLAG,
1553                 check_ambiguity, override, 1, 0, "stdin-input", '-',
1554                 additional_error))
1555               goto failure;
1556 
1557           }
1558           /* Add attestation cross-signature.  */
1559           else if (strcmp (long_options[option_index].name, "attestation") == 0)
1560           {
1561 
1562 
1563             if (update_arg((void *)&(args_info->attestation_flag), 0, &(args_info->attestation_given),
1564                 &(local_args_info.attestation_given), optarg, 0, 0, ARG_FLAG,
1565                 check_ambiguity, override, 1, 0, "attestation", '-',
1566                 additional_error))
1567               goto failure;
1568 
1569           }
1570 
1571           break;
1572         case '?':	/* Invalid option.  */
1573           /* `getopt_long' already printed an error message.  */
1574           goto failure;
1575 
1576         default:	/* bug: option not considered.  */
1577           fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
1578           abort ();
1579         } /* switch */
1580     } /* while */
1581 
1582 
1583   update_multiple_arg((void *)&(args_info->action_arg),
1584     &(args_info->action_orig), args_info->action_given,
1585     local_args_info.action_given, 0,
1586     ARG_ENUM, action_list);
1587 
1588   args_info->action_given += local_args_info.action_given;
1589   local_args_info.action_given = 0;
1590 
1591   if (check_required)
1592     {
1593       error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error);
1594     }
1595 
1596   cmdline_parser_release (&local_args_info);
1597 
1598   if ( error_occurred )
1599     return (EXIT_FAILURE);
1600 
1601   return 0;
1602 
1603 failure:
1604   free_list (action_list, 0 );
1605 
1606   cmdline_parser_release (&local_args_info);
1607   return (EXIT_FAILURE);
1608 }
1609 
1610 #ifndef CONFIG_FILE_LINE_SIZE
1611 #define CONFIG_FILE_LINE_SIZE 2048
1612 #endif
1613 #define ADDITIONAL_ERROR " in configuration file "
1614 
1615 #define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3)
1616 /* 3 is for "--" and "=" */
1617 
1618 static int
_cmdline_parser_configfile(const char * filename,int * my_argc)1619 _cmdline_parser_configfile (const char *filename, int *my_argc)
1620 {
1621   FILE* file;
1622   char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1];
1623   char linebuf[CONFIG_FILE_LINE_SIZE];
1624   int line_num = 0;
1625   int result = 0, equal;
1626   char *fopt, *farg;
1627   char *str_index;
1628   size_t len, next_token;
1629   char delimiter;
1630 
1631   if ((file = fopen(filename, "r")) == 0)
1632     {
1633       fprintf (stderr, "%s: Error opening configuration file '%s'\n",
1634                CMDLINE_PARSER_PACKAGE, filename);
1635       return EXIT_FAILURE;
1636     }
1637 
1638   while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != 0)
1639     {
1640       ++line_num;
1641       my_argv[0] = '\0';
1642       len = strlen(linebuf);
1643       if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1))
1644         {
1645           fprintf (stderr, "%s:%s:%d: Line too long in configuration file\n",
1646                    CMDLINE_PARSER_PACKAGE, filename, line_num);
1647           result = EXIT_FAILURE;
1648           break;
1649         }
1650 
1651       /* find first non-whitespace character in the line */
1652       next_token = strspn (linebuf, " \t\r\n");
1653       str_index  = linebuf + next_token;
1654 
1655       if ( str_index[0] == '\0' || str_index[0] == '#')
1656         continue; /* empty line or comment line is skipped */
1657 
1658       fopt = str_index;
1659 
1660       /* truncate fopt at the end of the first non-valid character */
1661       next_token = strcspn (fopt, " \t\r\n=");
1662 
1663       if (fopt[next_token] == '\0') /* the line is over */
1664         {
1665           farg  = 0;
1666           equal = 0;
1667           goto noarg;
1668         }
1669 
1670       /* remember if equal sign is present */
1671       equal = (fopt[next_token] == '=');
1672       fopt[next_token++] = '\0';
1673 
1674       /* advance pointers to the next token after the end of fopt */
1675       next_token += strspn (fopt + next_token, " \t\r\n");
1676 
1677       /* check for the presence of equal sign, and if so, skip it */
1678       if ( !equal )
1679         if ((equal = (fopt[next_token] == '=')))
1680           {
1681             next_token++;
1682             next_token += strspn (fopt + next_token, " \t\r\n");
1683           }
1684       str_index  += next_token;
1685 
1686       /* find argument */
1687       farg = str_index;
1688       if ( farg[0] == '\"' || farg[0] == '\'' )
1689         { /* quoted argument */
1690           str_index = strchr (++farg, str_index[0] ); /* skip opening quote */
1691           if (! str_index)
1692             {
1693               fprintf
1694                 (stderr,
1695                  "%s:%s:%d: unterminated string in configuration file\n",
1696                  CMDLINE_PARSER_PACKAGE, filename, line_num);
1697               result = EXIT_FAILURE;
1698               break;
1699             }
1700         }
1701       else
1702         { /* read up the remaining part up to a delimiter */
1703           next_token = strcspn (farg, " \t\r\n#\'\"");
1704           str_index += next_token;
1705         }
1706 
1707       /* truncate farg at the delimiter and store it for further check */
1708       delimiter = *str_index, *str_index++ = '\0';
1709 
1710       /* everything but comment is illegal at the end of line */
1711       if (delimiter != '\0' && delimiter != '#')
1712         {
1713           str_index += strspn(str_index, " \t\r\n");
1714           if (*str_index != '\0' && *str_index != '#')
1715             {
1716               fprintf
1717                 (stderr,
1718                  "%s:%s:%d: malformed string in configuration file\n",
1719                  CMDLINE_PARSER_PACKAGE, filename, line_num);
1720               result = EXIT_FAILURE;
1721               break;
1722             }
1723         }
1724 
1725     noarg:
1726       if (!strcmp(fopt,"include")) {
1727         if (farg && *farg) {
1728           result = _cmdline_parser_configfile(farg, my_argc);
1729         } else {
1730           fprintf(stderr, "%s:%s:%d: include requires a filename argument.\n",
1731                   CMDLINE_PARSER_PACKAGE, filename, line_num);
1732         }
1733         continue;
1734       }
1735       len = strlen(fopt);
1736       strcat (my_argv, len > 1 ? "--" : "-");
1737       strcat (my_argv, fopt);
1738       if (len > 1 && ((farg && *farg) || equal))
1739         strcat (my_argv, "=");
1740       if (farg && *farg)
1741         strcat (my_argv, farg);
1742       ++(*my_argc);
1743 
1744       cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
1745       cmd_line_list_tmp->next = cmd_line_list;
1746       cmd_line_list = cmd_line_list_tmp;
1747       cmd_line_list->string_arg = gengetopt_strdup(my_argv);
1748     } /* while */
1749 
1750   if (file)
1751     fclose(file);
1752   return result;
1753 }
1754 
1755 int
cmdline_parser_configfile(const char * filename,struct gengetopt_args_info * args_info,int override,int initialize,int check_required)1756 cmdline_parser_configfile (
1757   const char *filename,
1758                            struct gengetopt_args_info *args_info,
1759                            int override, int initialize, int check_required)
1760 {
1761   struct cmdline_parser_params params;
1762 
1763   params.override = override;
1764   params.initialize = initialize;
1765   params.check_required = check_required;
1766   params.check_ambiguity = 0;
1767   params.print_errors = 1;
1768 
1769   return cmdline_parser_config_file (filename, args_info, &params);
1770 }
1771 
1772 int
cmdline_parser_config_file(const char * filename,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params)1773 cmdline_parser_config_file (const char *filename,
1774                            struct gengetopt_args_info *args_info,
1775                            struct cmdline_parser_params *params)
1776 {
1777   int i, result;
1778   int my_argc = 1;
1779   char **my_argv_arg;
1780   char *additional_error;
1781 
1782   /* store the program name */
1783   cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
1784   cmd_line_list_tmp->next = cmd_line_list;
1785   cmd_line_list = cmd_line_list_tmp;
1786   cmd_line_list->string_arg = gengetopt_strdup (CMDLINE_PARSER_PACKAGE);
1787 
1788   result = _cmdline_parser_configfile(filename, &my_argc);
1789 
1790   if (result != EXIT_FAILURE) {
1791     my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *));
1792     cmd_line_list_tmp = cmd_line_list;
1793 
1794     for (i = my_argc - 1; i >= 0; --i) {
1795       my_argv_arg[i] = cmd_line_list_tmp->string_arg;
1796       cmd_line_list_tmp = cmd_line_list_tmp->next;
1797     }
1798 
1799     my_argv_arg[my_argc] = 0;
1800 
1801     additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
1802     strcpy (additional_error, ADDITIONAL_ERROR);
1803     strcat (additional_error, filename);
1804     result =
1805       cmdline_parser_internal (my_argc, my_argv_arg, args_info,
1806                               params,
1807                               additional_error);
1808 
1809     free (additional_error);
1810     free (my_argv_arg);
1811   }
1812 
1813   free_cmd_list();
1814   if (result == EXIT_FAILURE)
1815     {
1816       cmdline_parser_free (args_info);
1817       exit (EXIT_FAILURE);
1818     }
1819 
1820   return result;
1821 }
1822 /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */
1823