1 /*
2 * Copyright (C) 2003-2015 FreeIPMI Core Team
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #if HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #if STDC_HEADERS
26 #include <string.h>
27 #endif /* STDC_HEADERS */
28 #if HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
31 #ifdef HAVE_ERROR_H
32 #include <error.h>
33 #endif /* HAVE_ERROR_H */
34 #include <assert.h>
35 #include <errno.h>
36
37 #include <freeipmi/freeipmi.h>
38
39 #include "freeipmi-portability.h"
40 #include "parse-common.h"
41 #include "pstdout.h"
42 #include "tool-cmdline-common.h"
43 #include "tool-util-common.h"
44
45 error_t
cmdline_config_file_parse(int key,char * arg,struct argp_state * state)46 cmdline_config_file_parse (int key, char *arg, struct argp_state *state)
47 {
48 struct common_cmd_args *common_args;
49
50 assert (state);
51
52 common_args = state->input;
53
54 switch (key)
55 {
56 /* ARGP_CONFIG_KEY for backwards compatability */
57 case ARGP_CONFIG_KEY:
58 case ARGP_CONFIG_FILE_KEY:
59 free (common_args->config_file);
60 if (!(common_args->config_file = strdup (arg)))
61 {
62 perror ("strdup");
63 exit (EXIT_FAILURE);
64 }
65 break;
66 case ARGP_KEY_ARG:
67 break;
68 case ARGP_KEY_END:
69 break;
70 default:
71 /* don't parse anything else, fall to return (0) */
72 break;
73 }
74
75 return (0);
76 }
77
78 /* From David Wheeler's Secure Programming Guide */
79 static void *
__secure_memset(void * s,int c,size_t n)80 __secure_memset (void *s, int c, size_t n)
81 {
82 volatile char *p;
83
84 if (!s || !n)
85 return (NULL);
86
87 p = s;
88 while (n--)
89 *p++=c;
90
91 return (s);
92 }
93
94 error_t
common_parse_opt(int key,char * arg,struct common_cmd_args * common_args)95 common_parse_opt (int key,
96 char *arg,
97 struct common_cmd_args *common_args)
98 {
99 char *endptr;
100 int tmp;
101 unsigned int outofband_flags, outofband_2_0_flags, inband_flags, sdr_flags, section_flags;
102 int n;
103
104 assert (common_args);
105
106 switch (key)
107 {
108 /*
109 * inband options
110 */
111 case ARGP_DRIVER_TYPE_KEY:
112 if (common_args->driver_type_outofband_only)
113 {
114 if ((tmp = parse_outofband_driver_type (arg)) < 0)
115 {
116 fprintf (stderr, "invalid driver type\n");
117 exit (EXIT_FAILURE);
118 }
119 }
120 else
121 {
122 if ((tmp = parse_driver_type (arg)) < 0)
123 {
124 fprintf (stderr, "invalid driver type\n");
125 exit (EXIT_FAILURE);
126 }
127 }
128 common_args->driver_type = tmp;
129 break;
130 /* ARGP_NO_PROBING_KEY for backwards compatability */
131 case ARGP_NO_PROBING_KEY:
132 case ARGP_DISABLE_AUTO_PROBE_KEY:
133 common_args->disable_auto_probe = 1;
134 break;
135 case ARGP_DRIVER_ADDRESS_KEY:
136 errno = 0;
137 tmp = strtol (arg, &endptr, 0);
138 if (errno
139 || endptr[0] != '\0'
140 || tmp <= 0)
141 {
142 fprintf (stderr, "invalid driver address\n");
143 exit (EXIT_FAILURE);
144 }
145 common_args->driver_address = tmp;
146 break;
147 case ARGP_DRIVER_DEVICE_KEY:
148 free (common_args->driver_device);
149 if (!(common_args->driver_device = strdup (arg)))
150 {
151 perror ("strdup");
152 exit (EXIT_FAILURE);
153 }
154 break;
155 case ARGP_REGISTER_SPACING_KEY:
156 errno = 0;
157 tmp = strtol (arg, &endptr, 0);
158 if (errno
159 || endptr[0] != '\0'
160 || tmp <= 0)
161 {
162 fprintf (stderr, "invalid register spacing\n");
163 exit (EXIT_FAILURE);
164 }
165 common_args->register_spacing = tmp;
166 break;
167 case ARGP_TARGET_CHANNEL_NUMBER_KEY:
168 errno = 0;
169 tmp = strtol (arg, &endptr, 0);
170 if (errno
171 || endptr[0] != '\0'
172 || tmp < 0
173 || !IPMI_CHANNEL_NUMBER_VALID (tmp))
174 {
175 fprintf (stderr, "invalid target channel numbern");
176 exit (EXIT_FAILURE);
177 }
178 common_args->target_channel_number = tmp;
179 common_args->target_channel_number_is_set = 1;
180 break;
181 case ARGP_TARGET_SLAVE_ADDRESS_KEY:
182 errno = 0;
183 tmp = strtol (arg, &endptr, 0);
184 if (errno
185 || endptr[0] != '\0'
186 || tmp < 0)
187 {
188 fprintf (stderr, "invalid target slave addressn");
189 exit (EXIT_FAILURE);
190 }
191 common_args->target_slave_address = tmp;
192 common_args->target_slave_address_is_set = 1;
193 break;
194
195 /*
196 * outofband options
197 */
198 case ARGP_HOSTNAME_KEY:
199 free (common_args->hostname);
200 if (!(common_args->hostname = strdup (arg)))
201 {
202 perror ("strdup");
203 exit (EXIT_FAILURE);
204 }
205 break;
206 case ARGP_USERNAME_KEY:
207 if (strlen (arg) > IPMI_MAX_USER_NAME_LENGTH)
208 {
209 fprintf (stderr, "username too long\n");
210 exit (EXIT_FAILURE);
211 }
212 else
213 {
214 free (common_args->username);
215 if (!(common_args->username = strdup (arg)))
216 {
217 perror ("strdup");
218 exit (EXIT_FAILURE);
219 }
220 }
221 n = strlen (arg);
222 __secure_memset (arg, '\0', n);
223 break;
224 case ARGP_PASSWORD_KEY:
225 if (strlen (arg) > IPMI_2_0_MAX_PASSWORD_LENGTH)
226 {
227 fprintf (stderr, "password too long\n");
228 exit (EXIT_FAILURE);
229 }
230 else
231 {
232 free (common_args->password);
233 if (!(common_args->password = strdup (arg)))
234 {
235 perror ("strdup");
236 exit (EXIT_FAILURE);
237 }
238 }
239 n = strlen (arg);
240 __secure_memset (arg, '\0', n);
241 break;
242 case ARGP_PASSWORD_PROMPT_KEY:
243 free (common_args->password);
244 arg = getpass ("Password: ");
245 if (arg && strlen (arg) > IPMI_2_0_MAX_PASSWORD_LENGTH)
246 {
247 fprintf (stderr, "password too long\n");
248 exit (EXIT_FAILURE);
249 }
250 if (!(common_args->password = strdup (arg)))
251 {
252 perror ("strdup");
253 exit (EXIT_FAILURE);
254 }
255 break;
256 case ARGP_K_G_KEY:
257 {
258 int rv;
259
260 if (common_args->k_g_len)
261 {
262 memset (common_args->k_g, '\0', IPMI_MAX_K_G_LENGTH + 1);
263 common_args->k_g_len = 0;
264 }
265
266 if ((rv = check_kg_len (arg)) < 0)
267 {
268 fprintf (stderr, "k_g too long\n");
269 exit (EXIT_FAILURE);
270 }
271
272 if ((rv = parse_kg (common_args->k_g, IPMI_MAX_K_G_LENGTH, arg)) < 0)
273 {
274 fprintf (stderr, "k_g input formatted incorrectly\n");
275 exit (EXIT_FAILURE);
276 }
277 if (rv > 0)
278 common_args->k_g_len = rv;
279 n = strlen (arg);
280 __secure_memset (arg, '\0', n);
281 }
282 break;
283 case ARGP_K_G_PROMPT_KEY:
284 {
285 int rv;
286
287 if (common_args->k_g_len)
288 {
289 memset (common_args->k_g, '\0', IPMI_MAX_K_G_LENGTH + 1);
290 common_args->k_g_len = 0;
291 }
292
293 arg = getpass ("K_g: ");
294
295 if ((rv = check_kg_len (arg)) < 0)
296 {
297 fprintf (stderr, "k_g too long\n");
298 exit (EXIT_FAILURE);
299 }
300
301 if ((rv = parse_kg (common_args->k_g, IPMI_MAX_K_G_LENGTH, arg)) < 0)
302 {
303 fprintf (stderr, "k_g input formatted incorrectly\n");
304 exit (EXIT_FAILURE);
305 }
306 if (rv > 0)
307 common_args->k_g_len = rv;
308 }
309 break;
310 /* ARGP_TIMEOUT_KEY for backwards compatability */
311 case ARGP_TIMEOUT_KEY:
312 case ARGP_SESSION_TIMEOUT_KEY:
313 errno = 0;
314 tmp = strtol (arg, &endptr, 0);
315 if (errno
316 || endptr[0] != '\0'
317 || tmp <= 0)
318 {
319 fprintf (stderr, "invalid session timeout\n");
320 exit (EXIT_FAILURE);
321 }
322 common_args->session_timeout = tmp;
323 break;
324 /* ARGP_RETRY_TIMEOUT_KEY for backwards compatability */
325 case ARGP_RETRY_TIMEOUT_KEY:
326 case ARGP_RETRANSMISSION_TIMEOUT_KEY:
327 errno = 0;
328 tmp = strtol (arg, &endptr, 0);
329 if (errno
330 || endptr[0] != '\0'
331 || tmp <= 0)
332 {
333 fprintf (stderr, "invalid retransmission timeout\n");
334 exit (EXIT_FAILURE);
335 }
336 common_args->retransmission_timeout = tmp;
337 break;
338 /* ARGP_AUTH_TYPE_KEY for backwards compatability */
339 case ARGP_AUTH_TYPE_KEY:
340 case ARGP_AUTHENTICATION_TYPE_KEY:
341 if ((tmp = parse_authentication_type (arg)) < 0)
342 {
343 fprintf (stderr, "invalid authentication type\n");
344 exit (EXIT_FAILURE);
345 }
346 common_args->authentication_type = tmp;
347 break;
348 case ARGP_CIPHER_SUITE_ID_KEY:
349 errno = 0;
350 tmp = strtol (arg, &endptr, 0);
351 if (errno
352 || endptr[0] != '\0'
353 || tmp < IPMI_CIPHER_SUITE_ID_MIN
354 || tmp > IPMI_CIPHER_SUITE_ID_MAX)
355 {
356 fprintf (stderr, "invalid cipher suite id\n");
357 exit (EXIT_FAILURE);
358 }
359 if (!IPMI_CIPHER_SUITE_ID_SUPPORTED (tmp))
360 {
361 fprintf (stderr, "unsupported cipher suite id\n");
362 exit (EXIT_FAILURE);
363 }
364 common_args->cipher_suite_id = tmp;
365 break;
366 /* ARGP_PRIVILEGE_KEY for backwards compatability */
367 /* ARGP_PRIV_LEVEL_KEY for backwards compatability */ \
368 case ARGP_PRIVILEGE_KEY:
369 case ARGP_PRIV_LEVEL_KEY:
370 case ARGP_PRIVILEGE_LEVEL_KEY:
371 if ((tmp = parse_privilege_level (arg)) < 0)
372 {
373 fprintf (stderr, "invalid privilege level\n");
374 exit (EXIT_FAILURE);
375 }
376 common_args->privilege_level = tmp;
377 break;
378
379 /*
380 * misc options
381 */
382
383 /* ARGP_CONFIG_KEY for backwards compatability */
384 case ARGP_CONFIG_KEY:
385 case ARGP_CONFIG_FILE_KEY:
386 /* ignore config option - should have been parsed earlier */
387 break;
388 case ARGP_WORKAROUND_FLAGS_KEY:
389 if (parse_workaround_flags_tool (arg,
390 &outofband_flags,
391 &outofband_2_0_flags,
392 &inband_flags,
393 &sdr_flags,
394 §ion_flags) < 0)
395 {
396 fprintf (stderr, "invalid workaround flags\n");
397 exit (EXIT_FAILURE);
398 }
399 common_args->workaround_flags_outofband = outofband_flags;
400 common_args->workaround_flags_outofband_2_0 = outofband_2_0_flags;
401 common_args->workaround_flags_inband = inband_flags;
402 common_args->workaround_flags_sdr = sdr_flags;
403 common_args->section_specific_workaround_flags = section_flags;
404 break;
405 case ARGP_DEBUG_KEY:
406 common_args->debug++;
407 break;
408
409 /*
410 * sdr options
411 */
412 case ARGP_FLUSH_CACHE_KEY:
413 case ARGP_FLUSH_CACHE_LEGACY_KEY:
414 common_args->flush_cache = 1;
415 break;
416 case ARGP_QUIET_CACHE_KEY:
417 case ARGP_QUIET_CACHE_LEGACY_KEY:
418 common_args->quiet_cache = 1;
419 break;
420 case ARGP_SDR_CACHE_RECREATE_KEY:
421 common_args->sdr_cache_recreate = 1;
422 break;
423 case ARGP_SDR_CACHE_FILE_KEY:
424 free (common_args->sdr_cache_file);
425 if (!(common_args->sdr_cache_file = strdup (arg)))
426 {
427 perror ("strdup");
428 exit (EXIT_FAILURE);
429 }
430 break;
431 case ARGP_SDR_CACHE_DIRECTORY_KEY:
432 free (common_args->sdr_cache_directory);
433 if (!(common_args->sdr_cache_directory = strdup (arg)))
434 {
435 perror ("strdup");
436 exit (EXIT_FAILURE);
437 }
438 break;
439 case ARGP_IGNORE_SDR_CACHE_KEY:
440 common_args->ignore_sdr_cache = 1;
441 break;
442
443 /*
444 * time options
445 */
446 case ARGP_UTC_TO_LOCALTIME_KEY:
447 common_args->utc_to_localtime = 1;
448 break;
449 case ARGP_LOCALTIME_TO_UTC_KEY:
450 common_args->localtime_to_utc = 1;
451 break;
452 case ARGP_UTC_OFFSET_KEY:
453 errno = 0;
454 tmp = strtol (arg, &endptr, 0);
455 if (errno
456 || endptr[0] != '\0'
457 || !IPMI_UTC_OFFSET_VALID (tmp))
458 {
459 fprintf (stderr, "invalid UTC offset\n");
460 exit (EXIT_FAILURE);
461 }
462 common_args->utc_offset = tmp;
463 break;
464
465 /*
466 * hostrange options
467 */
468 case ARGP_BUFFER_OUTPUT_KEY:
469 common_args->buffer_output = 1;
470 break;
471 case ARGP_CONSOLIDATE_OUTPUT_KEY:
472 common_args->consolidate_output = 1;
473 break;
474 case ARGP_FANOUT_KEY:
475 errno = 0;
476 tmp = strtol (arg, &endptr, 10);
477 if (errno
478 || endptr[0] != '\0'
479 || (tmp < PSTDOUT_FANOUT_MIN)
480 || (tmp > PSTDOUT_FANOUT_MAX))
481 {
482 fprintf (stderr, "invalid fanout\n");
483 exit (EXIT_FAILURE);
484 break;
485 }
486 common_args->fanout = tmp;
487 break;
488 case ARGP_ELIMINATE_KEY:
489 common_args->eliminate = 1;
490 break;
491 case ARGP_ALWAYS_PREFIX_KEY:
492 common_args->always_prefix = 1;
493 break;
494 default:
495 return (ARGP_ERR_UNKNOWN);
496 }
497
498 return (0);
499 }
500
501 static void
_init_common_cmd_args(struct common_cmd_args * common_args)502 _init_common_cmd_args (struct common_cmd_args *common_args)
503 {
504 assert (common_args);
505
506 common_args->disable_auto_probe = 0;
507 common_args->driver_type = IPMI_DEVICE_UNKNOWN;
508 common_args->driver_type_outofband_only = 0;
509 common_args->driver_address = 0;
510 common_args->driver_device = NULL;
511 common_args->register_spacing = 0;
512 common_args->target_channel_number = 0;
513 common_args->target_channel_number_is_set = 0;
514 common_args->target_slave_address = 0;
515 common_args->target_slave_address_is_set = 0;
516
517 common_args->hostname = NULL;
518 common_args->username = NULL;
519 common_args->password = NULL;
520 memset (common_args->k_g, '\0', IPMI_MAX_K_G_LENGTH + 1);
521 common_args->k_g_len = 0;
522 common_args->session_timeout = 0;
523 common_args->retransmission_timeout = 0;
524 common_args->authentication_type = IPMI_AUTHENTICATION_TYPE_MD5;
525 common_args->cipher_suite_id = 3;
526 /* privilege_level set by parent function */
527
528 common_args->config_file = NULL;
529 common_args->workaround_flags_outofband = 0;
530 common_args->workaround_flags_outofband_2_0 = 0;
531 common_args->workaround_flags_inband = 0;
532 common_args->section_specific_workaround_flags = 0;
533 common_args->debug = 0;
534
535 common_args->flush_cache = 0;
536 common_args->quiet_cache = 0;
537 common_args->sdr_cache_recreate = 0;
538 common_args->sdr_cache_file = NULL;
539 common_args->sdr_cache_directory = NULL;
540 common_args->ignore_sdr_cache = 0;
541
542 common_args->utc_to_localtime = 0;
543 common_args->localtime_to_utc = 0;
544 common_args->utc_offset = 0;
545
546 common_args->buffer_output = 0;
547 common_args->consolidate_output = 0;
548 common_args->fanout = 0;
549 common_args->eliminate = 0;
550 common_args->always_prefix = 0;
551 }
552
553 void
init_common_cmd_args_user(struct common_cmd_args * common_args)554 init_common_cmd_args_user (struct common_cmd_args *common_args)
555 {
556 assert (common_args);
557
558 _init_common_cmd_args (common_args);
559 common_args->privilege_level = IPMI_PRIVILEGE_LEVEL_USER;
560 }
561
562 void
init_common_cmd_args_operator(struct common_cmd_args * common_args)563 init_common_cmd_args_operator (struct common_cmd_args *common_args)
564 {
565 assert (common_args);
566
567 _init_common_cmd_args (common_args);
568 common_args->privilege_level = IPMI_PRIVILEGE_LEVEL_OPERATOR;
569 }
570
571 void
init_common_cmd_args_admin(struct common_cmd_args * common_args)572 init_common_cmd_args_admin (struct common_cmd_args *common_args)
573 {
574 _init_common_cmd_args (common_args);
575 common_args->privilege_level = IPMI_PRIVILEGE_LEVEL_ADMIN;
576 }
577
578 void
verify_common_cmd_args_inband(struct common_cmd_args * common_args)579 verify_common_cmd_args_inband (struct common_cmd_args *common_args)
580 {
581 assert (common_args);
582
583 if (common_args->driver_device)
584 {
585 if (access (common_args->driver_device, R_OK|W_OK) < 0)
586 {
587 fprintf (stderr, "insufficient permission on driver device '%s'\n",
588 common_args->driver_device);
589 exit (EXIT_FAILURE);
590 }
591 }
592 }
593
594 void
verify_common_cmd_args_outofband(struct common_cmd_args * common_args,int check_hostname)595 verify_common_cmd_args_outofband (struct common_cmd_args *common_args, int check_hostname)
596 {
597 assert (common_args);
598
599 if (check_hostname
600 && (common_args->driver_type == IPMI_DEVICE_LAN
601 || common_args->driver_type == IPMI_DEVICE_LAN_2_0)
602 && !common_args->hostname)
603 {
604 fprintf (stderr, "hostname not specified\n");
605 exit (EXIT_FAILURE);
606 }
607
608 /* We default to IPMI 1.5 if the user doesn't specify LAN vs. LAN_2_0 */
609
610 if (((common_args->hostname
611 && common_args->driver_type == IPMI_DEVICE_UNKNOWN)
612 || common_args->driver_type == IPMI_DEVICE_LAN)
613 && common_args->password
614 && strlen (common_args->password) > IPMI_1_5_MAX_PASSWORD_LENGTH)
615 {
616 fprintf (stderr, "password too long\n");
617 exit (EXIT_FAILURE);
618 }
619 /* else, 2_0 password length was checked in argp_parse() previously */
620
621 if (common_args->retransmission_timeout > common_args->session_timeout)
622 {
623 fprintf (stderr, "retransmission timeout larger than session timeout\n");
624 exit (EXIT_FAILURE);
625 }
626
627 if (common_args->k_g_len)
628 {
629 unsigned int i;
630 int all_zeroes = 1;
631
632 /* Special case, check to make sure user didn't input zero as a
633 * k_g key.
634 */
635 for (i = 0; i < IPMI_MAX_K_G_LENGTH; i++)
636 {
637 if (common_args->k_g[i] != 0)
638 {
639 all_zeroes = 0;
640 break;
641 }
642 }
643
644 if (all_zeroes)
645 common_args->k_g_len = 0;
646 }
647 }
648
649 void
verify_common_cmd_args(struct common_cmd_args * common_args)650 verify_common_cmd_args (struct common_cmd_args *common_args)
651 {
652 assert (common_args);
653
654 verify_common_cmd_args_inband (common_args);
655 verify_common_cmd_args_outofband (common_args, 1);
656
657 if (common_args->sdr_cache_directory)
658 {
659 if (access (common_args->sdr_cache_directory, R_OK|W_OK|X_OK) < 0)
660 {
661 fprintf (stderr, "insufficient permission on SDR cache directory '%s'\n",
662 common_args->sdr_cache_directory);
663 exit (EXIT_FAILURE);
664 }
665 }
666
667 if (common_args->buffer_output && common_args->consolidate_output)
668 {
669 fprintf (stderr, "cannot buffer and consolidate hostrange output, please select only one\n");
670 exit (EXIT_FAILURE);
671 }
672 }
673
674