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                                        &section_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