Print a warning if an illegal value is used for the spi but continue
[vpnc.git] / config.c
blob57778e3c314e7b1c9fef24d9bc5ab0b719b0baf3
1 /* IPSec VPN client compatible with Cisco equipment.
2 Copyright (C) 2004-2005 Maurice Massar
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 2 of the License, or
7 (at your option) any later version.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 $Id$
21 #define _GNU_SOURCE
23 #include <inttypes.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <termios.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/utsname.h>
33 #include <sys/wait.h>
35 #include <gcrypt.h>
37 #include "sysdep.h"
38 #include "config.h"
39 #include "vpnc.h"
40 #include "supp.h"
41 #include "decrypt-utils.h"
43 const char *config[LAST_CONFIG];
45 int opt_debug = 0;
46 int opt_nd;
47 int opt_1des, opt_no_encryption, opt_auth_mode;
48 enum natt_mode_enum opt_natt_mode;
49 enum vendor_enum opt_vendor;
50 enum if_mode_enum opt_if_mode;
51 uint16_t opt_udpencapport;
53 static void log_to_stderr(int priority __attribute__((unused)), const char *format, ...)
55 va_list ap;
57 fprintf(stderr, "vpnc: ");
58 va_start(ap, format);
59 vfprintf(stderr, format, ap);
60 fprintf(stderr, "\n");
61 va_end(ap);
64 void (*logmsg)(int priority, const char *format, ...) = log_to_stderr;
67 void hex_dump(const char *str, const void *data, ssize_t len, const struct debug_strings *decode)
69 size_t i;
70 const uint8_t *p = data;
71 const char *decodedval;
73 if (opt_debug < 3)
74 return;
76 printf(" ");
77 switch (len) {
78 case DUMP_UINT8:
79 decodedval = val_to_string(*(uint8_t *)p, decode);
80 printf("%s: %02x%s\n", str, *(uint8_t *)p, decodedval);
81 return;
82 case DUMP_UINT16:
83 decodedval = val_to_string(*(uint16_t *)p, decode);
84 printf("%s: %04x%s\n", str, *(uint16_t *)p, decodedval);
85 return;
86 case DUMP_UINT32:
87 decodedval = val_to_string(*(uint32_t *)p, decode);
88 printf("%s: %08x%s\n", str, *(uint32_t *)p, decodedval);
89 return;
92 printf("%s:%s", str, (len <= 16) ? " " : "\n ");
93 for (i = 0; i < (size_t)len; i++) {
94 if (i && !(i % 32))
95 printf("\n ");
96 else if (i && !(i % 4))
97 printf(" ");
98 printf("%02x", p[i]);
100 printf("\n");
103 #define GETLINE_MAX_BUFLEN 200
106 * mostly match getline() semantics but:
107 * 1) accept CEOT (Ctrl-D, 0x04) at begining of line as an input terminator
108 * 2) allocate the buffer at max line size of GETLINE_MAX_BUFLEN bytes
109 * 3) remove trailing newline
111 * Returns:
112 * -1 for errors or no line (EOF or CEOT)
113 * n the characters in line, excluding (removed) newline and training '\0'
115 static ssize_t vpnc_getline(char **lineptr, size_t *n, FILE *stream)
117 char *buf;
118 size_t buflen, llen = 0;
119 int c, buf_allocated = 0;
121 if (lineptr == NULL || n == NULL) {
122 errno = EINVAL;
123 return -1;
126 buf = *lineptr;
127 buflen = *n;
128 if (buf == NULL || buflen == 0) {
129 buflen = GETLINE_MAX_BUFLEN;
130 buf = (char *)malloc(buflen);
131 if (buf == NULL)
132 return -1;
133 buf_allocated = 1;
136 /* Read a line from the input */
137 while (llen < buflen - 1) {
138 c = fgetc(stream);
139 if (c == EOF || feof(stream)) {
140 if (llen == 0)
141 goto eof_or_ceot;
142 else
143 break;
145 if (llen == 0 && c == CEOT)
146 goto eof_or_ceot;
147 if (c == '\n' || c == '\r')
148 break;
149 buf[llen++] = (char) c;
152 buf[llen] = 0;
153 if (buf_allocated) {
154 *lineptr = buf;
155 *n = buflen;
157 return llen;
159 eof_or_ceot:
160 if (buf_allocated)
161 free(buf);
162 return -1;
165 static char *vpnc_getpass_program(const char *prompt)
167 int status, r, i;
168 pid_t pid;
169 int fds[2] = {-1, -1};
170 char *pass;
171 ssize_t bytes;
173 if (pipe(fds) == -1)
174 goto out;
176 pid = fork();
177 if (pid == -1)
178 goto out;
180 if (pid == 0) {
181 const char *program = config[CONFIG_PASSWORD_HELPER];
183 close(fds[0]);
184 fds[0] = -1;
186 if (dup2(fds[1], 1) == -1)
187 _exit(1);
189 close(fds[1]);
190 fds[1] = -1;
192 execl(program, program, prompt, NULL);
194 _exit(1);
197 close(fds[1]);
198 fds[1] = -1;
200 while ((r = waitpid(pid, &status, 0)) == 0 ||
201 (r == -1 && errno == EINTR))
204 if (r == -1)
205 goto out;
207 if (!WIFEXITED(status)) {
208 errno = EFAULT;
209 goto out;
212 if (WEXITSTATUS(status) != 0) {
213 errno = EIO;
214 goto out;
217 pass = (char *)malloc(GETLINE_MAX_BUFLEN);
218 if (pass == NULL)
219 goto out;
221 bytes = read(fds[0], pass, GETLINE_MAX_BUFLEN - 1);
222 if (bytes == -1) {
223 free(pass);
224 pass = NULL;
225 goto out;
228 pass[bytes] = '\0';
229 for (i = 0 ; i < bytes ; i++)
230 if (pass[i] == '\n' || pass[i] == '\r') {
231 pass[i] = 0;
232 break;
235 out:
236 if (fds[0] != -1)
237 close(fds[0]);
239 if (fds[1] != -1)
240 close(fds[1]);
242 return pass;
245 char *vpnc_getpass(const char *prompt)
247 struct termios t;
248 char *buf = NULL;
249 size_t len = 0;
251 if (config[CONFIG_PASSWORD_HELPER]) {
252 buf = vpnc_getpass_program(prompt);
253 if (buf == NULL)
254 error(1, errno, "can't run password helper program");
255 return buf;
258 printf("%s", prompt);
259 fflush(stdout);
261 tcgetattr(STDIN_FILENO, &t);
262 t.c_lflag &= ~ECHO;
263 tcsetattr(STDIN_FILENO, TCSANOW, &t);
265 vpnc_getline(&buf, &len, stdin);
267 t.c_lflag |= ECHO;
268 tcsetattr(STDIN_FILENO, TCSANOW, &t);
269 printf("\n");
271 return buf;
274 static void config_deobfuscate(int obfuscated, int clear)
276 int ret, len = 0;
277 char *bin = NULL;
279 if (config[obfuscated] == NULL)
280 return;
282 if (config[clear] != NULL) {
283 config[obfuscated] = NULL;
284 error(0, 0, "warning: ignoring obfuscated password because cleartext password set");
285 return;
288 ret = hex2bin(config[obfuscated], &bin, &len);
289 if (ret != 0) {
290 error(1, 0, "error: deobfuscating of password failed (input not a hex string)");
293 ret = deobfuscate(bin, len, config+clear, NULL);
294 free(bin);
295 if (ret != 0) {
296 error(1, 0, "error: deobfuscating of password failed");
299 config[obfuscated] = NULL;
300 return;
303 static const char *config_def_ike_dh(void)
305 return "dh2";
308 static const char *config_def_pfs(void)
310 return "server";
313 static const char *config_def_local_addr(void)
315 return "0.0.0.0";
318 static const char *config_def_local_port(void)
320 return "500";
323 static const char *config_def_if_mode(void)
325 return "tun";
328 static const char *config_def_natt_mode(void)
330 return "natt";
333 static const char *config_def_udp_port(void)
335 return "10000";
338 static const char *config_def_dpd_idle(void)
340 return "300";
343 static const char *config_ca_dir(void)
345 return "/etc/ssl/certs";
348 static const char *config_def_auth_mode(void)
350 return "psk";
353 static const char *config_def_app_version(void)
355 struct utsname uts;
356 char *version;
358 uname(&uts);
359 asprintf(&version, "Cisco Systems VPN Client %s:%s", VERSION, uts.sysname);
360 return version;
363 static const char *config_def_script(void)
365 return "/etc/vpnc/vpnc-script";
368 static const char *config_def_pid_file(void)
370 return "/var/run/vpnc.pid";
373 static const char *config_def_vendor(void)
375 return "cisco";
378 static const char *config_def_target_network(void)
380 return "0.0.0.0/0.0.0.0";
383 static const struct config_names_s {
384 enum config_enum nm;
385 const int needsArgument;
386 const int long_only;
387 const char *option;
388 const char *name;
389 const char *type;
390 const char *desc;
391 const char *(*get_def) (void);
392 } config_names[] = {
393 /* Note: broken config file parser does only support option
394 * names where one is a prefix of another option IF the longer
395 * option name comes first in this list. */
397 CONFIG_IPSEC_GATEWAY, 1, 0,
398 "--gateway",
399 "IPSec gateway",
400 "<ip/hostname>",
401 "IP/name of your IPSec gateway",
402 NULL
403 }, {
404 CONFIG_IPSEC_ID, 1, 0,
405 "--id",
406 "IPSec ID",
407 "<ASCII string>",
408 "your group name",
409 NULL
410 }, {
411 CONFIG_IPSEC_SECRET, 1, 0,
412 NULL,
413 "IPSec secret",
414 "<ASCII string>",
415 "your group password (cleartext)",
416 NULL
417 }, {
418 CONFIG_IPSEC_SECRET_OBF, 1, 1,
419 NULL,
420 "IPSec obfuscated secret",
421 "<hex string>",
422 "your group password (obfuscated)",
423 NULL
424 }, {
425 CONFIG_XAUTH_USERNAME, 1, 0,
426 "--username",
427 "Xauth username",
428 "<ASCII string>",
429 "your username",
430 NULL
431 }, {
432 CONFIG_XAUTH_PASSWORD, 1, 0,
433 NULL,
434 "Xauth password",
435 "<ASCII string>",
436 "your password (cleartext)",
437 NULL
438 }, {
439 CONFIG_XAUTH_PASSWORD_OBF, 1, 1,
440 NULL,
441 "Xauth obfuscated password",
442 "<hex string>",
443 "your password (obfuscated)",
444 NULL
445 }, {
446 CONFIG_DOMAIN, 1, 1,
447 "--domain",
448 "Domain",
449 "<ASCII string>",
450 "(NT-) Domain name for authentication",
451 NULL
452 }, {
453 CONFIG_XAUTH_INTERACTIVE, 0, 1,
454 "--xauth-inter",
455 "Xauth interactive",
456 NULL,
457 "enable interactive extended authentication (for challenge response auth)",
458 NULL
459 }, {
460 CONFIG_VENDOR, 1, 1,
461 "--vendor",
462 "Vendor",
463 "<cisco/netscreen>",
464 "vendor of your IPSec gateway",
465 config_def_vendor
466 }, {
467 CONFIG_NATT_MODE, 1, 1,
468 "--natt-mode",
469 "NAT Traversal Mode",
470 "<natt/none/force-natt/cisco-udp>",
471 "Which NAT-Traversal Method to use:\n"
472 " * natt -- NAT-T as defined in RFC3947\n"
473 " * none -- disable use of any NAT-T method\n"
474 " * force-natt -- always use NAT-T encapsulation even\n"
475 " without presence of a NAT device\n"
476 " (useful if the OS captures all ESP traffic)\n"
477 " * cisco-udp -- Cisco proprietary UDP encapsulation, commonly over Port 10000\n"
478 "Note: cisco-tcp encapsulation is not yet supported\n",
479 config_def_natt_mode
480 }, {
481 CONFIG_SCRIPT, 1, 1,
482 "--script",
483 "Script",
484 "<command>",
485 "command is executed using system() to configure the interface,\n"
486 "routing and so on. Device name, IP, etc. are passed using environment\n"
487 "variables, see README. This script is executed right after ISAKMP is\n"
488 "done, but before tunneling is enabled. It is called when vpnc\n"
489 "terminates, too\n",
490 config_def_script
491 }, {
492 CONFIG_IKE_DH, 1, 1,
493 "--dh",
494 "IKE DH Group",
495 "<dh1/dh2/dh5>",
496 "name of the IKE DH Group",
497 config_def_ike_dh
498 }, {
499 CONFIG_IPSEC_PFS, 1, 1,
500 "--pfs",
501 "Perfect Forward Secrecy",
502 "<nopfs/dh1/dh2/dh5/server>",
503 "Diffie-Hellman group to use for PFS",
504 config_def_pfs
505 }, {
506 CONFIG_ENABLE_1DES, 0, 1,
507 "--enable-1des",
508 "Enable Single DES",
509 NULL,
510 "enables weak single DES encryption",
511 NULL
512 }, {
513 CONFIG_ENABLE_NO_ENCRYPTION, 0, 1,
514 "--enable-no-encryption",
515 "Enable no encryption",
516 NULL,
517 "enables using no encryption for data traffic (key exchanged must be encrypted)",
518 NULL
519 }, {
520 CONFIG_VERSION, 1, 1,
521 "--application-version",
522 "Application version",
523 "<ASCII string>",
524 "Application Version to report. Note: Default string is generated at runtime.",
525 config_def_app_version
526 }, {
527 CONFIG_IF_NAME, 1, 1,
528 "--ifname",
529 "Interface name",
530 "<ASCII string>",
531 "visible name of the TUN/TAP interface",
532 NULL
533 }, {
534 CONFIG_IF_MODE, 1, 1,
535 "--ifmode",
536 "Interface mode",
537 "<tun/tap>",
538 "mode of TUN/TAP interface:\n"
539 " * tun: virtual point to point interface (default)\n"
540 " * tap: virtual ethernet interface\n",
541 config_def_if_mode
542 }, {
543 CONFIG_IF_MTU, 1, 1,
544 "--ifmtu",
545 "Interface MTU",
546 "<0-65535>",
547 "Set MTU for TUN/TAP interface (default 0 == automatic detect)",
548 NULL
549 }, {
550 CONFIG_DEBUG, 1, 1,
551 "--debug",
552 "Debug",
553 "<0/1/2/3/99>",
554 "Show verbose debug messages\n"
555 " * 0: Do not print debug information.\n"
556 " * 1: Print minimal debug information.\n"
557 " * 2: Show statemachine and packet/payload type information.\n"
558 " * 3: Dump everything exluding authentication data.\n"
559 " * 99: Dump everything INCLUDING AUTHENTICATION data (e.g. PASSWORDS).\n",
560 NULL
561 }, {
562 CONFIG_ND, 0, 1,
563 "--no-detach",
564 "No Detach",
565 NULL,
566 "Don't detach from the console after login",
567 NULL
568 }, {
569 CONFIG_PID_FILE, 1, 1,
570 "--pid-file",
571 "Pidfile",
572 "<filename>",
573 "store the pid of background process in <filename>",
574 config_def_pid_file
575 }, {
576 CONFIG_LOCAL_ADDR, 1, 1,
577 "--local-addr",
578 "Local Addr",
579 "<ip/hostname>",
580 "local IP to use for ISAKMP / ESP / ... (0.0.0.0 == automatically assign)",
581 config_def_local_addr
582 }, {
583 CONFIG_LOCAL_PORT, 1, 1,
584 "--local-port",
585 "Local Port",
586 "<0-65535>",
587 "local ISAKMP port number to use (0 == use random port)",
588 config_def_local_port
589 }, {
590 CONFIG_UDP_ENCAP_PORT, 1, 1,
591 "--udp-port",
592 "Cisco UDP Encapsulation Port",
593 "<0-65535>",
594 "Local UDP port number to use (0 == use random port).\n"
595 "This is only relevant if cisco-udp nat-traversal is used.\n"
596 "This is the _local_ port, the remote udp port is discovered automatically.\n"
597 "It is especially not the cisco-tcp port.\n",
598 config_def_udp_port
599 }, {
600 CONFIG_DPD_IDLE, 1, 1,
601 "--dpd-idle",
602 "DPD idle timeout (our side)",
603 "<0,10-86400>",
604 "Send DPD packet after not receiving anything for <idle> seconds.\n"
605 "Use 0 to disable DPD completely (both ways).\n",
606 config_def_dpd_idle
607 }, {
608 CONFIG_NON_INTERACTIVE, 0, 1,
609 "--non-inter",
610 "Noninteractive",
611 NULL,
612 "Don't ask anything, exit on missing options",
613 NULL
614 }, {
615 CONFIG_AUTH_MODE, 1, 1,
616 "--auth-mode",
617 "IKE Authmode",
618 "<psk/cert/hybrid>",
619 "Authentication mode:\n"
620 " * psk: pre-shared key (default)\n"
621 " * cert: server + client certificate (not implemented yet)\n"
622 " * hybrid: server certificate + xauth (if built with openssl support)\n",
623 config_def_auth_mode
624 }, {
625 CONFIG_CA_FILE, 1, 1,
626 "--ca-file",
627 "CA-File",
628 "<filename>",
629 "filename and path to the CA-PEM-File",
630 NULL
631 }, {
632 CONFIG_CA_DIR, 1, 1,
633 "--ca-dir",
634 "CA-Dir",
635 "<directory>",
636 "path of the trusted CA-Directory",
637 config_ca_dir
638 }, {
639 CONFIG_IPSEC_TARGET_NETWORK, 1, 1,
640 "--target-network",
641 "IPSEC target network",
642 "<target network/netmask>",
643 "Target network in dotted decimal or CIDR notation\n",
644 config_def_target_network
645 }, {
646 CONFIG_PASSWORD_HELPER, 1, 1,
647 "--password-helper",
648 "Password helper",
649 "<executable>",
650 "path to password program or helper name\n",
651 NULL
652 }, {
653 0, 0, 0, NULL, NULL, NULL, NULL, NULL
657 static char *get_config_filename(const char *name, int add_dot_conf)
659 char *realname;
661 asprintf(&realname, "%s%s%s", index(name, '/') ? "" : "/etc/vpnc/", name, add_dot_conf ? ".conf" : "");
662 return realname;
665 static void read_config_file(const char *name, const char **configs, int missingok)
667 FILE *f;
668 char *line = NULL;
669 size_t line_length = 0;
670 int linenum = 0;
671 char *realname;
673 if (!strcmp(name, "-")) {
674 f = stdin;
675 realname = strdup("stdin");
676 } else {
677 realname = get_config_filename(name, 0);
678 f = fopen(realname, "r");
679 if (f == NULL && errno == ENOENT) {
680 free(realname);
681 realname = get_config_filename(name, 1);
682 f = fopen(realname, "r");
684 if (missingok && f == NULL && errno == ENOENT) {
685 free(realname);
686 return;
688 if (f == NULL)
689 error(1, errno, "couldn't open `%s'", realname);
691 for (;;) {
692 ssize_t llen;
693 int i;
695 errno = 0;
696 llen = vpnc_getline(&line, &line_length, f);
697 if (llen == -1 && errno)
698 error(1, errno, "reading `%s'", realname);
699 if (llen == -1)
700 break;
701 linenum++;
702 for (i = 0; config_names[i].name != NULL; i++) {
703 if (strncasecmp(config_names[i].name, line,
704 strlen(config_names[i].name)) == 0) {
705 /* boolean implementation, using harmless pointer targets as true */
706 if (!config_names[i].needsArgument) {
707 configs[config_names[i].nm] = config_names[i].name;
708 break;
710 /* get option value*/
711 if (configs[config_names[i].nm] == NULL) {
712 ssize_t start;
713 start = strlen(config_names[i].name);
714 /* ensure whitespace after option name */
715 if (line[start] == 0)
716 error(0, 0, "option '%s' requires a value!", config_names[i].name);
717 if (!(line[start] == ' ' || line[start] == '\t'))
718 continue; /* fallthrough: "unknown configuration directive" */
719 /* skip further trailing and leading whitespace */
720 for (llen--; line[llen] == ' ' || line[llen] == '\t' ; llen--)
721 line[llen] = 0;
722 for (start++; line[start] == ' ' || line[start] == '\t'; start++)
724 /* remove optional quotes */
725 if (start != llen && line[start] == '"' && line[llen] == '"') {
726 start++;
727 line[llen--] = 0;
729 if (start > llen)
730 error(0, 0, "option '%s' requires a value!", config_names[i].name);
731 configs[config_names[i].nm] = strdup(line + start);
733 if (configs[config_names[i].nm] == NULL)
734 error(1, errno, "can't allocate memory");
735 break;
738 if (config_names[i].name == NULL && line[0] != '#' && line[0] != 0)
739 error(0, 0, "warning: unknown configuration directive in %s at line %d",
740 realname, linenum);
742 free(line);
743 free(realname);
744 if (strcmp(name, "-"))
745 fclose(f);
748 static void print_desc(const char *pre, const char *text)
750 const char *p, *q;
752 for (p = text, q = strchr(p, '\n'); q; p = q+1, q = strchr(p, '\n'))
753 printf("%s%.*s\n", pre, (int)(q-p), p);
755 if (*p != '\0')
756 printf("%s%s\n", pre, p);
759 static void print_usage(char *argv0, int print_level)
761 int c;
763 printf("Usage: %s [--version] [--print-config] [--help] [--long-help] [options] [config files]\n\n",
764 argv0);
765 printf("Options:\n");
766 for (c = 0; config_names[c].name != NULL; c++) {
767 if (config_names[c].long_only > print_level)
768 continue;
770 printf(" %s %s\n", (config_names[c].option == NULL ?
771 "(configfile only option)" : config_names[c].option),
772 ((config_names[c].type == NULL || config_names[c].option == NULL) ?
773 "" : config_names[c].type));
775 print_desc(" ", config_names[c].desc);
777 if (config_names[c].get_def != NULL)
778 printf(" Default: %s\n", config_names[c].get_def());
780 printf(" conf-variable: %s%s\n", config_names[c].name,
781 (config_names[c].type == NULL ? "" : config_names[c].type));
783 printf("\n");
786 if (!print_level)
787 printf("Use --long-help to see all options\n\n");
789 printf("Report bugs to vpnc@unix-ag.uni-kl.de\n");
792 static void print_version(void)
794 unsigned int i;
796 printf("vpnc version " VERSION "\n");
797 printf("Copyright (C) 2002-2006 Geoffrey Keating, Maurice Massar, others\n");
798 printf("vpnc comes with NO WARRANTY, to the extent permitted by law.\n"
799 "You may redistribute copies of vpnc under the terms of the GNU General\n"
800 "Public License. For more information about these matters, see the files\n"
801 "named COPYING.\n");
802 #ifdef OPENSSL_GPL_VIOLATION
803 printf("Built with openssl certificate support. Be aware of the\n"
804 "license implications.\n");
805 #else /* OPENSSL_GPL_VIOLATION */
806 printf("Built with certificate support.\n");
807 #endif /* OPENSSL_GPL_VIOLATION */
808 printf("\n");
810 printf("Supported DH-Groups:");
811 for (i = 0; supp_dh_group[i].name != NULL; i++)
812 printf(" %s", supp_dh_group[i].name);
813 printf("\n");
815 printf("Supported Hash-Methods:");
816 for (i = 0; supp_hash[i].name != NULL; i++)
817 printf(" %s", supp_hash[i].name);
818 printf("\n");
820 printf("Supported Encryptions:");
821 for (i = 0; supp_crypt[i].name != NULL; i++)
822 printf(" %s", supp_crypt[i].name);
823 printf("\n");
825 printf("Supported Auth-Methods:");
826 for (i = 0; supp_auth[i].name != NULL; i++)
827 printf(" %s", supp_auth[i].name);
828 printf("\n");
831 void do_config(int argc, char **argv)
833 char *s, *prompt;
834 int i, c, known;
835 int got_conffile = 0, print_config = 0;
836 size_t s_len;
838 for (i = 1; i < argc; i++) {
839 if (argv[i][0] && (argv[i][0] != '-' || argv[i][1] == '\0')) {
840 read_config_file(argv[i], config, 0);
841 got_conffile = 1;
842 continue;
845 known = 0;
847 for (c = 0; config_names[c].name != NULL && !known; c++) {
848 if (config_names[c].option == NULL
849 || strncmp(argv[i], config_names[c].option,
850 strlen(config_names[c].option)) != 0)
851 continue;
853 s = NULL;
855 known = 1;
856 if (argv[i][strlen(config_names[c].option)] == '=')
857 s = argv[i] + strlen(config_names[c].option) + 1;
858 else if (argv[i][strlen(config_names[c].option)] == 0) {
859 if (config_names[c].needsArgument) {
860 if (i + 1 < argc)
861 s = argv[++i];
862 else
863 known = 0;
864 } else
865 s = argv[i]; /* no arg, fill in something */
866 } else
867 known = 0;
868 if (known)
869 config[config_names[c].nm] = s;
872 if (!known && strcmp(argv[i], "--version") == 0) {
873 print_version();
874 exit(0);
876 if (!known && strcmp(argv[i], "--print-config") == 0) {
877 print_config = 1;
878 known = 1;
880 if (!known && strcmp(argv[i], "--help") == 0) {
881 print_usage(argv[0], 0);
882 exit(0);
884 if (!known && strcmp(argv[i], "--long-help") == 0) {
885 print_usage(argv[0], 1);
886 exit(0);
888 if (!known) {
889 printf("%s: unknown option %s\n\n", argv[0], argv[i]);
891 print_usage(argv[0], 1);
892 exit(1);
896 if (!got_conffile) {
897 read_config_file("/etc/vpnc/default.conf", config, 1);
898 read_config_file("/etc/vpnc.conf", config, 1);
901 if (!print_config) {
902 for (i = 0; config_names[i].name != NULL; i++)
903 if (!config[config_names[i].nm]
904 && config_names[i].get_def != NULL)
905 config[config_names[i].nm] = config_names[i].get_def();
907 opt_debug = (config[CONFIG_DEBUG]) ? atoi(config[CONFIG_DEBUG]) : 0;
908 opt_nd = (config[CONFIG_ND]) ? 1 : 0;
909 opt_1des = (config[CONFIG_ENABLE_1DES]) ? 1 : 0;
911 if (!strcmp(config[CONFIG_AUTH_MODE], "psk")) {
912 opt_auth_mode = AUTH_MODE_PSK;
913 } else if (!strcmp(config[CONFIG_AUTH_MODE], "cert")) {
914 opt_auth_mode = AUTH_MODE_CERT;
915 } else if (!strcmp(config[CONFIG_AUTH_MODE], "hybrid")) {
916 opt_auth_mode = AUTH_MODE_HYBRID;
917 } else {
918 printf("%s: unknown authentication mode %s\nknown modes: psk cert hybrid\n", argv[0], config[CONFIG_AUTH_MODE]);
919 exit(1);
921 opt_no_encryption = (config[CONFIG_ENABLE_NO_ENCRYPTION]) ? 1 : 0;
922 opt_udpencapport=atoi(config[CONFIG_UDP_ENCAP_PORT]);
924 if (!strcmp(config[CONFIG_NATT_MODE], "natt")) {
925 opt_natt_mode = NATT_NORMAL;
926 } else if (!strcmp(config[CONFIG_NATT_MODE], "none")) {
927 opt_natt_mode = NATT_NONE;
928 } else if (!strcmp(config[CONFIG_NATT_MODE], "force-natt")) {
929 opt_natt_mode = NATT_FORCE;
930 } else if (!strcmp(config[CONFIG_NATT_MODE], "cisco-udp")) {
931 opt_natt_mode = NATT_CISCO_UDP;
932 } else {
933 printf("%s: unknown nat traversal mode %s\nknown modes: natt none force-natt cisco-udp\n", argv[0], config[CONFIG_NATT_MODE]);
934 exit(1);
937 if (!strcmp(config[CONFIG_IF_MODE], "tun")) {
938 opt_if_mode = IF_MODE_TUN;
939 } else if (!strcmp(config[CONFIG_IF_MODE], "tap")) {
940 opt_if_mode = IF_MODE_TAP;
941 } else {
942 printf("%s: unknown interface mode %s\nknown modes: tun tap\n", argv[0], config[CONFIG_IF_MODE]);
943 exit(1);
946 if (!strcmp(config[CONFIG_VENDOR], "cisco")) {
947 opt_vendor = VENDOR_CISCO;
948 } else if (!strcmp(config[CONFIG_VENDOR], "netscreen")) {
949 opt_vendor = VENDOR_NETSCREEN;
950 } else {
951 printf("%s: unknown vendor %s\nknown vendors: cisco netscreen\n", argv[0], config[CONFIG_VENDOR]);
952 exit(1);
956 if (opt_debug >= 99) {
957 printf("WARNING! active debug level is >= 99, output includes username and password (hex encoded)\n");
958 fprintf(stderr,
959 "WARNING! active debug level is >= 99, output includes username and password (hex encoded)\n");
962 config_deobfuscate(CONFIG_IPSEC_SECRET_OBF, CONFIG_IPSEC_SECRET);
963 config_deobfuscate(CONFIG_XAUTH_PASSWORD_OBF, CONFIG_XAUTH_PASSWORD);
965 for (i = 0; i < LAST_CONFIG; i++) {
966 if (config[i] != NULL || config[CONFIG_NON_INTERACTIVE] != NULL)
967 continue;
968 if (config[CONFIG_XAUTH_INTERACTIVE] && i == CONFIG_XAUTH_PASSWORD)
969 continue;
971 s = NULL;
972 s_len = 0;
974 switch (i) {
975 case CONFIG_IPSEC_GATEWAY:
976 printf("Enter IPSec gateway address: ");
977 break;
978 case CONFIG_IPSEC_ID:
979 printf("Enter IPSec ID for %s: ", config[CONFIG_IPSEC_GATEWAY]);
980 break;
981 case CONFIG_IPSEC_SECRET:
982 asprintf(&prompt, "Enter IPSec secret for %s@%s: ",
983 config[CONFIG_IPSEC_ID], config[CONFIG_IPSEC_GATEWAY]);
984 break;
985 case CONFIG_XAUTH_USERNAME:
986 printf("Enter username for %s: ", config[CONFIG_IPSEC_GATEWAY]);
987 break;
988 case CONFIG_XAUTH_PASSWORD:
989 asprintf(&prompt, "Enter password for %s@%s: ",
990 config[CONFIG_XAUTH_USERNAME],
991 config[CONFIG_IPSEC_GATEWAY]);
992 break;
993 default:
994 continue;
996 fflush(stdout);
997 switch (i) {
998 case CONFIG_IPSEC_SECRET:
999 case CONFIG_XAUTH_PASSWORD:
1000 s = vpnc_getpass(prompt);
1001 free(prompt);
1002 if (s == NULL)
1003 error(1, 0, "unable to get password");
1004 break;
1005 case CONFIG_IPSEC_GATEWAY:
1006 case CONFIG_IPSEC_ID:
1007 case CONFIG_XAUTH_USERNAME:
1008 vpnc_getline(&s, &s_len, stdin);
1010 config[i] = s;
1013 if (print_config) {
1014 fprintf(stderr, "vpnc.conf:\n\n");
1015 for (i = 0; config_names[i].name != NULL; i++) {
1016 if (config[config_names[i].nm] == NULL || config[config_names[i].nm][0] == 0)
1017 continue;
1018 printf("%s", config_names[i].name);
1019 if (config_names[i].needsArgument) {
1020 ssize_t last;
1021 last = strlen(config[config_names[i].nm]) - 1;
1022 if ( config[config_names[i].nm][0] == ' ' || config[config_names[i].nm][last] == ' '
1023 || config[config_names[i].nm][0] == '\t' || config[config_names[i].nm][last] == '\t'
1024 || ( config[config_names[i].nm][0] == '"' && config[config_names[i].nm][last] == '"' )
1026 printf(" %s%s%s", "\"", config[config_names[i].nm], "\"");
1027 } else {
1028 printf(" %s", config[config_names[i].nm]);
1031 printf("\n");
1033 exit(0);
1036 if (!config[CONFIG_IPSEC_GATEWAY])
1037 error(1, 0, "missing IPSec gatway address");
1038 if (!config[CONFIG_IPSEC_ID])
1039 error(1, 0, "missing IPSec ID");
1040 if (!config[CONFIG_IPSEC_SECRET])
1041 error(1, 0, "missing IPSec secret");
1042 if (!config[CONFIG_XAUTH_USERNAME])
1043 error(1, 0, "missing Xauth username");
1044 if (!config[CONFIG_XAUTH_PASSWORD] && !config[CONFIG_XAUTH_INTERACTIVE])
1045 error(1, 0, "missing Xauth password");
1046 if (get_dh_group_ike() == NULL)
1047 error(1, 0, "IKE DH Group \"%s\" unsupported\n", config[CONFIG_IKE_DH]);
1048 if (get_dh_group_ipsec(-1) == NULL)
1049 error(1, 0, "Perfect Forward Secrecy \"%s\" unsupported\n",
1050 config[CONFIG_IPSEC_PFS]);
1051 if (get_dh_group_ike()->ike_sa_id == 0)
1052 error(1, 0, "IKE DH Group must not be nopfs\n");
1054 return;