Replace obsolete getpass()
[vpnc.git] / config.c
blob9dd6014805e4c75f8d0c1745358f704c35645f87
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/utsname.h>
33 #include <gcrypt.h>
35 #include "sysdep.h"
36 #include "config.h"
37 #include "vpnc.h"
38 #include "supp.h"
39 #include "decrypt-utils.h"
41 const char *config[LAST_CONFIG];
43 int opt_debug = 0;
44 int opt_nd;
45 int opt_1des, opt_no_encryption, opt_auth_mode;
46 enum natt_mode_enum opt_natt_mode;
47 enum vendor_enum opt_vendor;
48 enum if_mode_enum opt_if_mode;
49 uint16_t opt_udpencapport;
51 static void log_to_stderr(int priority __attribute__((unused)), const char *format, ...)
53 va_list ap;
55 fprintf(stderr, "vpnc: ");
56 va_start(ap, format);
57 vfprintf(stderr, format, ap);
58 fprintf(stderr, "\n");
59 va_end(ap);
62 void (*logmsg)(int priority, const char *format, ...) = log_to_stderr;
65 void hex_dump(const char *str, const void *data, ssize_t len, const struct debug_strings *decode)
67 size_t i;
68 const uint8_t *p = data;
69 const char *decodedval;
71 if (opt_debug < 3)
72 return;
74 printf(" ");
75 switch (len) {
76 case DUMP_UINT8:
77 decodedval = val_to_string(*(uint8_t *)p, decode);
78 printf("%s: %02x%s\n", str, *(uint8_t *)p, decodedval);
79 return;
80 case DUMP_UINT16:
81 decodedval = val_to_string(*(uint16_t *)p, decode);
82 printf("%s: %04x%s\n", str, *(uint16_t *)p, decodedval);
83 return;
84 case DUMP_UINT32:
85 decodedval = val_to_string(*(uint32_t *)p, decode);
86 printf("%s: %08x%s\n", str, *(uint32_t *)p, decodedval);
87 return;
90 printf("%s:%s", str, (len <= 16) ? " " : "\n ");
91 for (i = 0; i < (size_t)len; i++) {
92 if (i && !(i % 32))
93 printf("\n ");
94 else if (i && !(i % 4))
95 printf(" ");
96 printf("%02x", p[i]);
98 printf("\n");
101 #define GETLINE_MAX_BUFLEN 200
104 * mostly match getline() semantics but:
105 * 1) accept CEOT (Ctrl-D, 0x04) at begining of line as an input terminator
106 * 2) allocate the buffer at max line size of GETLINE_MAX_BUFLEN bytes
107 * 3) remove trailing newline
109 * Returns:
110 * -1 for errors or no line (EOF or CEOT)
111 * n the characters in line, excluding (removed) newline and training '\0'
113 static ssize_t vpnc_getline(char **lineptr, size_t *n, FILE *stream)
115 char *buf;
116 size_t buflen, llen = 0;
117 int c, buf_allocated = 0;
119 if (lineptr == NULL || n == NULL) {
120 errno = EINVAL;
121 return -1;
124 buf = *lineptr;
125 buflen = *n;
126 if (buf == NULL || buflen == 0) {
127 buflen = GETLINE_MAX_BUFLEN;
128 buf = (char *)malloc(buflen);
129 if (buf == NULL)
130 return -1;
131 buf_allocated = 1;
134 /* Read a line from the input */
135 while (llen < buflen - 1) {
136 c = fgetc(stream);
137 if (c == EOF || feof(stream)) {
138 if (llen == 0)
139 goto eof_or_ceot;
140 else
141 break;
143 if (llen == 0 && c == CEOT)
144 goto eof_or_ceot;
145 if (c == '\n' || c == '\r')
146 break;
147 buf[llen++] = (char) c;
150 buf[llen] = 0;
151 if (buf_allocated) {
152 *lineptr = buf;
153 *n = buflen;
155 return llen;
157 eof_or_ceot:
158 if (buf_allocated)
159 free(buf);
160 return -1;
163 char *vpnc_getpass(const char *prompt)
165 struct termios t;
166 char *buf = NULL;
167 size_t len = 0;
169 printf("%s", prompt);
170 tcgetattr(STDIN_FILENO, &t);
171 t.c_lflag &= ~ECHO;
172 tcsetattr(STDIN_FILENO, TCSANOW, &t);
174 vpnc_getline(&buf, &len, stdin);
176 t.c_lflag |= ECHO;
177 tcsetattr(STDIN_FILENO, TCSANOW, &t);
178 printf("\n");
180 return buf;
183 static void config_deobfuscate(int obfuscated, int clear)
185 int ret, len = 0;
186 char *bin = NULL;
188 if (config[obfuscated] == NULL)
189 return;
191 if (config[clear] != NULL) {
192 config[obfuscated] = NULL;
193 error(0, 0, "warning: ignoring obfuscated password because cleartext password set");
194 return;
197 ret = hex2bin(config[obfuscated], &bin, &len);
198 if (ret != 0) {
199 error(1, 0, "error: deobfuscating of password failed (input not a hex string)");
202 ret = deobfuscate(bin, len, config+clear, NULL);
203 free(bin);
204 if (ret != 0) {
205 error(1, 0, "error: deobfuscating of password failed");
208 config[obfuscated] = NULL;
209 return;
212 static const char *config_def_ike_dh(void)
214 return "dh2";
217 static const char *config_def_pfs(void)
219 return "server";
222 static const char *config_def_local_addr(void)
224 return "0.0.0.0";
227 static const char *config_def_local_port(void)
229 return "500";
232 static const char *config_def_if_mode(void)
234 return "tun";
237 static const char *config_def_natt_mode(void)
239 return "natt";
242 static const char *config_def_udp_port(void)
244 return "10000";
247 static const char *config_def_dpd_idle(void)
249 return "300";
252 static const char *config_ca_dir(void)
254 return "/etc/ssl/certs";
257 static const char *config_def_auth_mode(void)
259 return "psk";
262 static const char *config_def_app_version(void)
264 struct utsname uts;
265 char *version;
267 uname(&uts);
268 asprintf(&version, "Cisco Systems VPN Client %s:%s", VERSION, uts.sysname);
269 return version;
272 static const char *config_def_script(void)
274 return "/etc/vpnc/vpnc-script";
277 static const char *config_def_pid_file(void)
279 return "/var/run/vpnc.pid";
282 static const char *config_def_vendor(void)
284 return "cisco";
287 static const char *config_def_target_network(void)
289 return "0.0.0.0/0.0.0.0";
292 static const struct config_names_s {
293 enum config_enum nm;
294 const int needsArgument;
295 const int long_only;
296 const char *option;
297 const char *name;
298 const char *type;
299 const char *desc;
300 const char *(*get_def) (void);
301 } config_names[] = {
302 /* Note: broken config file parser does only support option
303 * names where one is a prefix of another option IF the longer
304 * option name comes first in this list. */
306 CONFIG_IPSEC_GATEWAY, 1, 0,
307 "--gateway",
308 "IPSec gateway",
309 "<ip/hostname>",
310 "IP/name of your IPSec gateway",
311 NULL
312 }, {
313 CONFIG_IPSEC_ID, 1, 0,
314 "--id",
315 "IPSec ID",
316 "<ASCII string>",
317 "your group name",
318 NULL
319 }, {
320 CONFIG_IPSEC_SECRET, 1, 0,
321 NULL,
322 "IPSec secret",
323 "<ASCII string>",
324 "your group password (cleartext)",
325 NULL
326 }, {
327 CONFIG_IPSEC_SECRET_OBF, 1, 1,
328 NULL,
329 "IPSec obfuscated secret",
330 "<hex string>",
331 "your group password (obfuscated)",
332 NULL
333 }, {
334 CONFIG_XAUTH_USERNAME, 1, 0,
335 "--username",
336 "Xauth username",
337 "<ASCII string>",
338 "your username",
339 NULL
340 }, {
341 CONFIG_XAUTH_PASSWORD, 1, 0,
342 NULL,
343 "Xauth password",
344 "<ASCII string>",
345 "your password (cleartext)",
346 NULL
347 }, {
348 CONFIG_XAUTH_PASSWORD_OBF, 1, 1,
349 NULL,
350 "Xauth obfuscated password",
351 "<hex string>",
352 "your password (obfuscated)",
353 NULL
354 }, {
355 CONFIG_DOMAIN, 1, 1,
356 "--domain",
357 "Domain",
358 "<ASCII string>",
359 "(NT-) Domain name for authentication",
360 NULL
361 }, {
362 CONFIG_XAUTH_INTERACTIVE, 0, 1,
363 "--xauth-inter",
364 "Xauth interactive",
365 NULL,
366 "enable interactive extended authentication (for challenge response auth)",
367 NULL
368 }, {
369 CONFIG_VENDOR, 1, 1,
370 "--vendor",
371 "Vendor",
372 "<cisco/netscreen>",
373 "vendor of your IPSec gateway",
374 config_def_vendor
375 }, {
376 CONFIG_NATT_MODE, 1, 1,
377 "--natt-mode",
378 "NAT Traversal Mode",
379 "<natt/none/force-natt/cisco-udp>",
380 "Which NAT-Traversal Method to use:\n"
381 " * natt -- NAT-T as defined in RFC3947\n"
382 " * none -- disable use of any NAT-T method\n"
383 " * force-natt -- always use NAT-T encapsulation even\n"
384 " without presence of a NAT device\n"
385 " (useful if the OS captures all ESP traffic)\n"
386 " * cisco-udp -- Cisco proprietary UDP encapsulation, commonly over Port 10000\n"
387 "Note: cisco-tcp encapsulation is not yet supported\n",
388 config_def_natt_mode
389 }, {
390 CONFIG_SCRIPT, 1, 1,
391 "--script",
392 "Script",
393 "<command>",
394 "command is executed using system() to configure the interface,\n"
395 "routing and so on. Device name, IP, etc. are passed using environment\n"
396 "variables, see README. This script is executed right after ISAKMP is\n"
397 "done, but before tunneling is enabled. It is called when vpnc\n"
398 "terminates, too\n",
399 config_def_script
400 }, {
401 CONFIG_IKE_DH, 1, 1,
402 "--dh",
403 "IKE DH Group",
404 "<dh1/dh2/dh5>",
405 "name of the IKE DH Group",
406 config_def_ike_dh
407 }, {
408 CONFIG_IPSEC_PFS, 1, 1,
409 "--pfs",
410 "Perfect Forward Secrecy",
411 "<nopfs/dh1/dh2/dh5/server>",
412 "Diffie-Hellman group to use for PFS",
413 config_def_pfs
414 }, {
415 CONFIG_ENABLE_1DES, 0, 1,
416 "--enable-1des",
417 "Enable Single DES",
418 NULL,
419 "enables weak single DES encryption",
420 NULL
421 }, {
422 CONFIG_ENABLE_NO_ENCRYPTION, 0, 1,
423 "--enable-no-encryption",
424 "Enable no encryption",
425 NULL,
426 "enables using no encryption for data traffic (key exchanged must be encrypted)",
427 NULL
428 }, {
429 CONFIG_VERSION, 1, 1,
430 "--application-version",
431 "Application version",
432 "<ASCII string>",
433 "Application Version to report. Note: Default string is generated at runtime.",
434 config_def_app_version
435 }, {
436 CONFIG_IF_NAME, 1, 1,
437 "--ifname",
438 "Interface name",
439 "<ASCII string>",
440 "visible name of the TUN/TAP interface",
441 NULL
442 }, {
443 CONFIG_IF_MODE, 1, 1,
444 "--ifmode",
445 "Interface mode",
446 "<tun/tap>",
447 "mode of TUN/TAP interface:\n"
448 " * tun: virtual point to point interface (default)\n"
449 " * tap: virtual ethernet interface\n",
450 config_def_if_mode
451 }, {
452 CONFIG_IF_MTU, 1, 1,
453 "--ifmtu",
454 "Interface MTU",
455 "<0-65535>",
456 "Set MTU for TUN/TAP interface (default 0 == automatic detect)",
457 NULL
458 }, {
459 CONFIG_DEBUG, 1, 1,
460 "--debug",
461 "Debug",
462 "<0/1/2/3/99>",
463 "Show verbose debug messages\n"
464 " * 0: Do not print debug information.\n"
465 " * 1: Print minimal debug information.\n"
466 " * 2: Show statemachine and packet/payload type information.\n"
467 " * 3: Dump everything exluding authentication data.\n"
468 " * 99: Dump everything INCLUDING AUTHENTICATION data (e.g. PASSWORDS).\n",
469 NULL
470 }, {
471 CONFIG_ND, 0, 1,
472 "--no-detach",
473 "No Detach",
474 NULL,
475 "Don't detach from the console after login",
476 NULL
477 }, {
478 CONFIG_PID_FILE, 1, 1,
479 "--pid-file",
480 "Pidfile",
481 "<filename>",
482 "store the pid of background process in <filename>",
483 config_def_pid_file
484 }, {
485 CONFIG_LOCAL_ADDR, 1, 1,
486 "--local-addr",
487 "Local Addr",
488 "<ip/hostname>",
489 "local IP to use for ISAKMP / ESP / ... (0.0.0.0 == automatically assign)",
490 config_def_local_addr
491 }, {
492 CONFIG_LOCAL_PORT, 1, 1,
493 "--local-port",
494 "Local Port",
495 "<0-65535>",
496 "local ISAKMP port number to use (0 == use random port)",
497 config_def_local_port
498 }, {
499 CONFIG_UDP_ENCAP_PORT, 1, 1,
500 "--udp-port",
501 "Cisco UDP Encapsulation Port",
502 "<0-65535>",
503 "Local UDP port number to use (0 == use random port).\n"
504 "This is only relevant if cisco-udp nat-traversal is used.\n"
505 "This is the _local_ port, the remote udp port is discovered automatically.\n"
506 "It is especially not the cisco-tcp port.\n",
507 config_def_udp_port
508 }, {
509 CONFIG_DPD_IDLE, 1, 1,
510 "--dpd-idle",
511 "DPD idle timeout (our side)",
512 "<0,10-86400>",
513 "Send DPD packet after not receiving anything for <idle> seconds.\n"
514 "Use 0 to disable DPD completely (both ways).\n",
515 config_def_dpd_idle
516 }, {
517 CONFIG_NON_INTERACTIVE, 0, 1,
518 "--non-inter",
519 "Noninteractive",
520 NULL,
521 "Don't ask anything, exit on missing options",
522 NULL
523 }, {
524 CONFIG_AUTH_MODE, 1, 1,
525 "--auth-mode",
526 "IKE Authmode",
527 "<psk/cert/hybrid>",
528 "Authentication mode:\n"
529 " * psk: pre-shared key (default)\n"
530 " * cert: server + client certificate (not implemented yet)\n"
531 " * hybrid: server certificate + xauth (if built with openssl support)\n",
532 config_def_auth_mode
533 }, {
534 CONFIG_CA_FILE, 1, 1,
535 "--ca-file",
536 "CA-File",
537 "<filename>",
538 "filename and path to the CA-PEM-File",
539 NULL
540 }, {
541 CONFIG_CA_DIR, 1, 1,
542 "--ca-dir",
543 "CA-Dir",
544 "<directory>",
545 "path of the trusted CA-Directory",
546 config_ca_dir
547 }, {
548 CONFIG_IPSEC_TARGET_NETWORK, 1, 1,
549 "--target-network",
550 "IPSEC target network",
551 "<target network/netmask>",
552 "Target network in dotted decimal or CIDR notation\n",
553 config_def_target_network
554 }, {
555 0, 0, 0, NULL, NULL, NULL, NULL, NULL
559 static char *get_config_filename(const char *name, int add_dot_conf)
561 char *realname;
563 asprintf(&realname, "%s%s%s", index(name, '/') ? "" : "/etc/vpnc/", name, add_dot_conf ? ".conf" : "");
564 return realname;
567 static void read_config_file(const char *name, const char **configs, int missingok)
569 FILE *f;
570 char *line = NULL;
571 size_t line_length = 0;
572 int linenum = 0;
573 char *realname;
575 if (!strcmp(name, "-")) {
576 f = stdin;
577 realname = strdup("stdin");
578 } else {
579 realname = get_config_filename(name, 0);
580 f = fopen(realname, "r");
581 if (f == NULL && errno == ENOENT) {
582 free(realname);
583 realname = get_config_filename(name, 1);
584 f = fopen(realname, "r");
586 if (missingok && f == NULL && errno == ENOENT) {
587 free(realname);
588 return;
590 if (f == NULL)
591 error(1, errno, "couldn't open `%s'", realname);
593 for (;;) {
594 ssize_t llen;
595 int i;
597 errno = 0;
598 llen = vpnc_getline(&line, &line_length, f);
599 if (llen == -1 && errno)
600 error(1, errno, "reading `%s'", realname);
601 if (llen == -1)
602 break;
603 linenum++;
604 for (i = 0; config_names[i].name != NULL; i++) {
605 if (strncasecmp(config_names[i].name, line,
606 strlen(config_names[i].name)) == 0) {
607 /* boolean implementation, using harmless pointer targets as true */
608 if (!config_names[i].needsArgument) {
609 configs[config_names[i].nm] = config_names[i].name;
610 break;
612 /* get option value*/
613 if (configs[config_names[i].nm] == NULL) {
614 ssize_t start;
615 start = strlen(config_names[i].name);
616 /* ensure whitespace after option name */
617 if (line[start] == 0)
618 error(0, 0, "option '%s' requires a value!", config_names[i].name);
619 if (!(line[start] == ' ' || line[start] == '\t'))
620 continue; /* fallthrough: "unknown configuration directive" */
621 /* skip further trailing and leading whitespace */
622 for (llen--; line[llen] == ' ' || line[llen] == '\t' ; llen--)
623 line[llen] = 0;
624 for (start++; line[start] == ' ' || line[start] == '\t'; start++)
626 /* remove optional quotes */
627 if (start != llen && line[start] == '"' && line[llen] == '"') {
628 start++;
629 line[llen--] = 0;
631 if (start > llen)
632 error(0, 0, "option '%s' requires a value!", config_names[i].name);
633 configs[config_names[i].nm] = strdup(line + start);
635 if (configs[config_names[i].nm] == NULL)
636 error(1, errno, "can't allocate memory");
637 break;
640 if (config_names[i].name == NULL && line[0] != '#' && line[0] != 0)
641 error(0, 0, "warning: unknown configuration directive in %s at line %d",
642 realname, linenum);
644 free(line);
645 free(realname);
646 if (strcmp(name, "-"))
647 fclose(f);
650 static void print_desc(const char *pre, const char *text)
652 const char *p, *q;
654 for (p = text, q = strchr(p, '\n'); q; p = q+1, q = strchr(p, '\n'))
655 printf("%s%.*s\n", pre, (int)(q-p), p);
657 if (*p != '\0')
658 printf("%s%s\n", pre, p);
661 static void print_usage(char *argv0, int print_level)
663 int c;
665 printf("Usage: %s [--version] [--print-config] [--help] [--long-help] [options] [config files]\n\n",
666 argv0);
667 printf("Options:\n");
668 for (c = 0; config_names[c].name != NULL; c++) {
669 if (config_names[c].long_only > print_level)
670 continue;
672 printf(" %s %s\n", (config_names[c].option == NULL ?
673 "(configfile only option)" : config_names[c].option),
674 ((config_names[c].type == NULL || config_names[c].option == NULL) ?
675 "" : config_names[c].type));
677 print_desc(" ", config_names[c].desc);
679 if (config_names[c].get_def != NULL)
680 printf(" Default: %s\n", config_names[c].get_def());
682 printf(" conf-variable: %s%s\n", config_names[c].name,
683 (config_names[c].type == NULL ? "" : config_names[c].type));
685 printf("\n");
688 if (!print_level)
689 printf("Use --long-help to see all options\n\n");
691 printf("Report bugs to vpnc@unix-ag.uni-kl.de\n");
694 static void print_version(void)
696 unsigned int i;
698 printf("vpnc version " VERSION "\n");
699 printf("Copyright (C) 2002-2006 Geoffrey Keating, Maurice Massar, others\n");
700 printf("vpnc comes with NO WARRANTY, to the extent permitted by law.\n"
701 "You may redistribute copies of vpnc under the terms of the GNU General\n"
702 "Public License. For more information about these matters, see the files\n"
703 "named COPYING.\n");
704 #ifdef OPENSSL_GPL_VIOLATION
705 printf("Built with openssl certificate support. Be aware of the\n"
706 "license implications.\n");
707 #else /* OPENSSL_GPL_VIOLATION */
708 printf("Built with certificate support.\n");
709 #endif /* OPENSSL_GPL_VIOLATION */
710 printf("\n");
712 printf("Supported DH-Groups:");
713 for (i = 0; supp_dh_group[i].name != NULL; i++)
714 printf(" %s", supp_dh_group[i].name);
715 printf("\n");
717 printf("Supported Hash-Methods:");
718 for (i = 0; supp_hash[i].name != NULL; i++)
719 printf(" %s", supp_hash[i].name);
720 printf("\n");
722 printf("Supported Encryptions:");
723 for (i = 0; supp_crypt[i].name != NULL; i++)
724 printf(" %s", supp_crypt[i].name);
725 printf("\n");
727 printf("Supported Auth-Methods:");
728 for (i = 0; supp_auth[i].name != NULL; i++)
729 printf(" %s", supp_auth[i].name);
730 printf("\n");
733 void do_config(int argc, char **argv)
735 char *s;
736 int i, c, known;
737 int got_conffile = 0, print_config = 0;
738 size_t s_len;
740 for (i = 1; i < argc; i++) {
741 if (argv[i][0] && (argv[i][0] != '-' || argv[i][1] == '\0')) {
742 read_config_file(argv[i], config, 0);
743 got_conffile = 1;
744 continue;
747 known = 0;
749 for (c = 0; config_names[c].name != NULL && !known; c++) {
750 if (config_names[c].option == NULL
751 || strncmp(argv[i], config_names[c].option,
752 strlen(config_names[c].option)) != 0)
753 continue;
755 s = NULL;
757 known = 1;
758 if (argv[i][strlen(config_names[c].option)] == '=')
759 s = argv[i] + strlen(config_names[c].option) + 1;
760 else if (argv[i][strlen(config_names[c].option)] == 0) {
761 if (config_names[c].needsArgument) {
762 if (i + 1 < argc)
763 s = argv[++i];
764 else
765 known = 0;
766 } else
767 s = argv[i]; /* no arg, fill in something */
768 } else
769 known = 0;
770 if (known)
771 config[config_names[c].nm] = s;
774 if (!known && strcmp(argv[i], "--version") == 0) {
775 print_version();
776 exit(0);
778 if (!known && strcmp(argv[i], "--print-config") == 0) {
779 print_config = 1;
780 known = 1;
782 if (!known && strcmp(argv[i], "--help") == 0) {
783 print_usage(argv[0], 0);
784 exit(0);
786 if (!known && strcmp(argv[i], "--long-help") == 0) {
787 print_usage(argv[0], 1);
788 exit(0);
790 if (!known) {
791 printf("%s: unknown option %s\n\n", argv[0], argv[i]);
793 print_usage(argv[0], 1);
794 exit(1);
798 if (!got_conffile) {
799 read_config_file("/etc/vpnc/default.conf", config, 1);
800 read_config_file("/etc/vpnc.conf", config, 1);
803 if (!print_config) {
804 for (i = 0; config_names[i].name != NULL; i++)
805 if (!config[config_names[i].nm]
806 && config_names[i].get_def != NULL)
807 config[config_names[i].nm] = config_names[i].get_def();
809 opt_debug = (config[CONFIG_DEBUG]) ? atoi(config[CONFIG_DEBUG]) : 0;
810 opt_nd = (config[CONFIG_ND]) ? 1 : 0;
811 opt_1des = (config[CONFIG_ENABLE_1DES]) ? 1 : 0;
813 if (!strcmp(config[CONFIG_AUTH_MODE], "psk")) {
814 opt_auth_mode = AUTH_MODE_PSK;
815 } else if (!strcmp(config[CONFIG_AUTH_MODE], "cert")) {
816 opt_auth_mode = AUTH_MODE_CERT;
817 } else if (!strcmp(config[CONFIG_AUTH_MODE], "hybrid")) {
818 opt_auth_mode = AUTH_MODE_HYBRID;
819 } else {
820 printf("%s: unknown authentication mode %s\nknown modes: psk cert hybrid\n", argv[0], config[CONFIG_AUTH_MODE]);
821 exit(1);
823 opt_no_encryption = (config[CONFIG_ENABLE_NO_ENCRYPTION]) ? 1 : 0;
824 opt_udpencapport=atoi(config[CONFIG_UDP_ENCAP_PORT]);
826 if (!strcmp(config[CONFIG_NATT_MODE], "natt")) {
827 opt_natt_mode = NATT_NORMAL;
828 } else if (!strcmp(config[CONFIG_NATT_MODE], "none")) {
829 opt_natt_mode = NATT_NONE;
830 } else if (!strcmp(config[CONFIG_NATT_MODE], "force-natt")) {
831 opt_natt_mode = NATT_FORCE;
832 } else if (!strcmp(config[CONFIG_NATT_MODE], "cisco-udp")) {
833 opt_natt_mode = NATT_CISCO_UDP;
834 } else {
835 printf("%s: unknown nat traversal mode %s\nknown modes: natt none force-natt cisco-udp\n", argv[0], config[CONFIG_NATT_MODE]);
836 exit(1);
839 if (!strcmp(config[CONFIG_IF_MODE], "tun")) {
840 opt_if_mode = IF_MODE_TUN;
841 } else if (!strcmp(config[CONFIG_IF_MODE], "tap")) {
842 opt_if_mode = IF_MODE_TAP;
843 } else {
844 printf("%s: unknown interface mode %s\nknown modes: tun tap\n", argv[0], config[CONFIG_IF_MODE]);
845 exit(1);
848 if (!strcmp(config[CONFIG_VENDOR], "cisco")) {
849 opt_vendor = VENDOR_CISCO;
850 } else if (!strcmp(config[CONFIG_VENDOR], "netscreen")) {
851 opt_vendor = VENDOR_NETSCREEN;
852 } else {
853 printf("%s: unknown vendor %s\nknown vendors: cisco netscreen\n", argv[0], config[CONFIG_VENDOR]);
854 exit(1);
858 if (opt_debug >= 99) {
859 printf("WARNING! active debug level is >= 99, output includes username and password (hex encoded)\n");
860 fprintf(stderr,
861 "WARNING! active debug level is >= 99, output includes username and password (hex encoded)\n");
864 config_deobfuscate(CONFIG_IPSEC_SECRET_OBF, CONFIG_IPSEC_SECRET);
865 config_deobfuscate(CONFIG_XAUTH_PASSWORD_OBF, CONFIG_XAUTH_PASSWORD);
867 for (i = 0; i < LAST_CONFIG; i++) {
868 if (config[i] != NULL || config[CONFIG_NON_INTERACTIVE] != NULL)
869 continue;
870 if (config[CONFIG_XAUTH_INTERACTIVE] && i == CONFIG_XAUTH_PASSWORD)
871 continue;
873 s = NULL;
874 s_len = 0;
876 switch (i) {
877 case CONFIG_IPSEC_GATEWAY:
878 printf("Enter IPSec gateway address: ");
879 break;
880 case CONFIG_IPSEC_ID:
881 printf("Enter IPSec ID for %s: ", config[CONFIG_IPSEC_GATEWAY]);
882 break;
883 case CONFIG_IPSEC_SECRET:
884 printf("Enter IPSec secret for %s@%s: ",
885 config[CONFIG_IPSEC_ID], config[CONFIG_IPSEC_GATEWAY]);
886 break;
887 case CONFIG_XAUTH_USERNAME:
888 printf("Enter username for %s: ", config[CONFIG_IPSEC_GATEWAY]);
889 break;
890 case CONFIG_XAUTH_PASSWORD:
891 printf("Enter password for %s@%s: ",
892 config[CONFIG_XAUTH_USERNAME],
893 config[CONFIG_IPSEC_GATEWAY]);
894 break;
895 default:
896 continue;
898 fflush(stdout);
899 switch (i) {
900 case CONFIG_IPSEC_SECRET:
901 case CONFIG_XAUTH_PASSWORD:
902 s = vpnc_getpass("");
903 if (s == NULL)
904 error(1, 0, "unable to get password");
905 break;
906 case CONFIG_IPSEC_GATEWAY:
907 case CONFIG_IPSEC_ID:
908 case CONFIG_XAUTH_USERNAME:
909 vpnc_getline(&s, &s_len, stdin);
911 config[i] = s;
914 if (print_config) {
915 fprintf(stderr, "vpnc.conf:\n\n");
916 for (i = 0; config_names[i].name != NULL; i++) {
917 if (config[config_names[i].nm] == NULL || config[config_names[i].nm][0] == 0)
918 continue;
919 printf("%s", config_names[i].name);
920 if (config_names[i].needsArgument) {
921 ssize_t last;
922 last = strlen(config[config_names[i].nm]) - 1;
923 if ( config[config_names[i].nm][0] == ' ' || config[config_names[i].nm][last] == ' '
924 || config[config_names[i].nm][0] == '\t' || config[config_names[i].nm][last] == '\t'
925 || ( config[config_names[i].nm][0] == '"' && config[config_names[i].nm][last] == '"' )
927 printf(" %s%s%s", "\"", config[config_names[i].nm], "\"");
928 } else {
929 printf(" %s", config[config_names[i].nm]);
932 printf("\n");
934 exit(0);
937 if (!config[CONFIG_IPSEC_GATEWAY])
938 error(1, 0, "missing IPSec gatway address");
939 if (!config[CONFIG_IPSEC_ID])
940 error(1, 0, "missing IPSec ID");
941 if (!config[CONFIG_IPSEC_SECRET])
942 error(1, 0, "missing IPSec secret");
943 if (!config[CONFIG_XAUTH_USERNAME])
944 error(1, 0, "missing Xauth username");
945 if (!config[CONFIG_XAUTH_PASSWORD] && !config[CONFIG_XAUTH_INTERACTIVE])
946 error(1, 0, "missing Xauth password");
947 if (get_dh_group_ike() == NULL)
948 error(1, 0, "IKE DH Group \"%s\" unsupported\n", config[CONFIG_IKE_DH]);
949 if (get_dh_group_ipsec(-1) == NULL)
950 error(1, 0, "Perfect Forward Secrecy \"%s\" unsupported\n",
951 config[CONFIG_IPSEC_PFS]);
952 if (get_dh_group_ike()->ike_sa_id == 0)
953 error(1, 0, "IKE DH Group must not be nopfs\n");
955 return;