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, ¶ms, 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, ¶ms);
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