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
31 #include <sys/utsname.h>
39 #include "decrypt-utils.h"
41 const char *config
[LAST_CONFIG
];
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
, ...)
55 fprintf(stderr
, "vpnc: ");
57 vfprintf(stderr
, format
, ap
);
58 fprintf(stderr
, "\n");
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
)
68 const uint8_t *p
= data
;
69 const char *decodedval
;
77 decodedval
= val_to_string(*(uint8_t *)p
, decode
);
78 printf("%s: %02x%s\n", str
, *(uint8_t *)p
, decodedval
);
81 decodedval
= val_to_string(*(uint16_t *)p
, decode
);
82 printf("%s: %04x%s\n", str
, *(uint16_t *)p
, decodedval
);
85 decodedval
= val_to_string(*(uint32_t *)p
, decode
);
86 printf("%s: %08x%s\n", str
, *(uint32_t *)p
, decodedval
);
90 printf("%s:%s", str
, (len
<= 16) ? " " : "\n ");
91 for (i
= 0; i
< (size_t)len
; i
++) {
94 else if (i
&& !(i
% 4))
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
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
)
116 size_t buflen
, llen
= 0;
117 int c
, buf_allocated
= 0;
119 if (lineptr
== NULL
|| n
== NULL
) {
126 if (buf
== NULL
|| buflen
== 0) {
127 buflen
= GETLINE_MAX_BUFLEN
;
128 buf
= (char *)malloc(buflen
);
134 /* Read a line from the input */
135 while (llen
< buflen
- 1) {
137 if (c
== EOF
|| feof(stream
)) {
143 if (llen
== 0 && c
== CEOT
)
145 if (c
== '\n' || c
== '\r')
147 buf
[llen
++] = (char) c
;
163 char *vpnc_getpass(const char *prompt
)
169 printf("%s", prompt
);
170 tcgetattr(STDIN_FILENO
, &t
);
172 tcsetattr(STDIN_FILENO
, TCSANOW
, &t
);
174 vpnc_getline(&buf
, &len
, stdin
);
177 tcsetattr(STDIN_FILENO
, TCSANOW
, &t
);
183 static void config_deobfuscate(int obfuscated
, int clear
)
188 if (config
[obfuscated
] == NULL
)
191 if (config
[clear
] != NULL
) {
192 config
[obfuscated
] = NULL
;
193 error(0, 0, "warning: ignoring obfuscated password because cleartext password set");
197 ret
= hex2bin(config
[obfuscated
], &bin
, &len
);
199 error(1, 0, "error: deobfuscating of password failed (input not a hex string)");
202 ret
= deobfuscate(bin
, len
, config
+clear
, NULL
);
205 error(1, 0, "error: deobfuscating of password failed");
208 config
[obfuscated
] = NULL
;
212 static const char *config_def_ike_dh(void)
217 static const char *config_def_pfs(void)
222 static const char *config_def_local_addr(void)
227 static const char *config_def_local_port(void)
232 static const char *config_def_if_mode(void)
237 static const char *config_def_natt_mode(void)
242 static const char *config_def_udp_port(void)
247 static const char *config_def_dpd_idle(void)
252 static const char *config_ca_dir(void)
254 return "/etc/ssl/certs";
257 static const char *config_def_auth_mode(void)
262 static const char *config_def_app_version(void)
268 asprintf(&version
, "Cisco Systems VPN Client %s:%s", VERSION
, uts
.sysname
);
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)
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
{
294 const int needsArgument
;
300 const char *(*get_def
) (void);
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,
310 "IP/name of your IPSec gateway",
313 CONFIG_IPSEC_ID
, 1, 0,
320 CONFIG_IPSEC_SECRET
, 1, 0,
324 "your group password (cleartext)",
327 CONFIG_IPSEC_SECRET_OBF
, 1, 1,
329 "IPSec obfuscated secret",
331 "your group password (obfuscated)",
334 CONFIG_XAUTH_USERNAME
, 1, 0,
341 CONFIG_XAUTH_PASSWORD
, 1, 0,
345 "your password (cleartext)",
348 CONFIG_XAUTH_PASSWORD_OBF
, 1, 1,
350 "Xauth obfuscated password",
352 "your password (obfuscated)",
359 "(NT-) Domain name for authentication",
362 CONFIG_XAUTH_INTERACTIVE
, 0, 1,
366 "enable interactive extended authentication (for challenge response auth)",
373 "vendor of your IPSec gateway",
376 CONFIG_NATT_MODE
, 1, 1,
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",
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"
405 "name of the IKE DH Group",
408 CONFIG_IPSEC_PFS
, 1, 1,
410 "Perfect Forward Secrecy",
411 "<nopfs/dh1/dh2/dh5/server>",
412 "Diffie-Hellman group to use for PFS",
415 CONFIG_ENABLE_1DES
, 0, 1,
419 "enables weak single DES encryption",
422 CONFIG_ENABLE_NO_ENCRYPTION
, 0, 1,
423 "--enable-no-encryption",
424 "Enable no encryption",
426 "enables using no encryption for data traffic (key exchanged must be encrypted)",
429 CONFIG_VERSION
, 1, 1,
430 "--application-version",
431 "Application version",
433 "Application Version to report. Note: Default string is generated at runtime.",
434 config_def_app_version
436 CONFIG_IF_NAME
, 1, 1,
440 "visible name of the TUN/TAP interface",
443 CONFIG_IF_MODE
, 1, 1,
447 "mode of TUN/TAP interface:\n"
448 " * tun: virtual point to point interface (default)\n"
449 " * tap: virtual ethernet interface\n",
456 "Set MTU for TUN/TAP interface (default 0 == automatic detect)",
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",
475 "Don't detach from the console after login",
478 CONFIG_PID_FILE
, 1, 1,
482 "store the pid of background process in <filename>",
485 CONFIG_LOCAL_ADDR
, 1, 1,
489 "local IP to use for ISAKMP / ESP / ... (0.0.0.0 == automatically assign)",
490 config_def_local_addr
492 CONFIG_LOCAL_PORT
, 1, 1,
496 "local ISAKMP port number to use (0 == use random port)",
497 config_def_local_port
499 CONFIG_UDP_ENCAP_PORT
, 1, 1,
501 "Cisco UDP Encapsulation Port",
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",
509 CONFIG_DPD_IDLE
, 1, 1,
511 "DPD idle timeout (our side)",
513 "Send DPD packet after not receiving anything for <idle> seconds.\n"
514 "Use 0 to disable DPD completely (both ways).\n",
517 CONFIG_NON_INTERACTIVE
, 0, 1,
521 "Don't ask anything, exit on missing options",
524 CONFIG_AUTH_MODE
, 1, 1,
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",
534 CONFIG_CA_FILE
, 1, 1,
538 "filename and path to the CA-PEM-File",
545 "path of the trusted CA-Directory",
548 CONFIG_IPSEC_TARGET_NETWORK
, 1, 1,
550 "IPSEC target network",
551 "<target network/netmask>",
552 "Target network in dotted decimal or CIDR notation\n",
553 config_def_target_network
555 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
559 static char *get_config_filename(const char *name
, int add_dot_conf
)
563 asprintf(&realname
, "%s%s%s", index(name
, '/') ? "" : "/etc/vpnc/", name
, add_dot_conf
? ".conf" : "");
567 static void read_config_file(const char *name
, const char **configs
, int missingok
)
571 size_t line_length
= 0;
575 if (!strcmp(name
, "-")) {
577 realname
= strdup("stdin");
579 realname
= get_config_filename(name
, 0);
580 f
= fopen(realname
, "r");
581 if (f
== NULL
&& errno
== ENOENT
) {
583 realname
= get_config_filename(name
, 1);
584 f
= fopen(realname
, "r");
586 if (missingok
&& f
== NULL
&& errno
== ENOENT
) {
591 error(1, errno
, "couldn't open `%s'", realname
);
598 llen
= vpnc_getline(&line
, &line_length
, f
);
599 if (llen
== -1 && errno
)
600 error(1, errno
, "reading `%s'", realname
);
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
;
612 /* get option value*/
613 if (configs
[config_names
[i
].nm
] == NULL
) {
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
--)
624 for (start
++; line
[start
] == ' ' || line
[start
] == '\t'; start
++)
626 /* remove optional quotes */
627 if (start
!= llen
&& line
[start
] == '"' && line
[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");
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",
646 if (strcmp(name
, "-"))
650 static void print_desc(const char *pre
, const char *text
)
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
);
658 printf("%s%s\n", pre
, p
);
661 static void print_usage(char *argv0
, int print_level
)
665 printf("Usage: %s [--version] [--print-config] [--help] [--long-help] [options] [config files]\n\n",
667 printf("Options:\n");
668 for (c
= 0; config_names
[c
].name
!= NULL
; c
++) {
669 if (config_names
[c
].long_only
> print_level
)
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
));
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)
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"
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 */
712 printf("Supported DH-Groups:");
713 for (i
= 0; supp_dh_group
[i
].name
!= NULL
; i
++)
714 printf(" %s", supp_dh_group
[i
].name
);
717 printf("Supported Hash-Methods:");
718 for (i
= 0; supp_hash
[i
].name
!= NULL
; i
++)
719 printf(" %s", supp_hash
[i
].name
);
722 printf("Supported Encryptions:");
723 for (i
= 0; supp_crypt
[i
].name
!= NULL
; i
++)
724 printf(" %s", supp_crypt
[i
].name
);
727 printf("Supported Auth-Methods:");
728 for (i
= 0; supp_auth
[i
].name
!= NULL
; i
++)
729 printf(" %s", supp_auth
[i
].name
);
733 void do_config(int argc
, char **argv
)
737 int got_conffile
= 0, print_config
= 0;
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);
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)
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
) {
767 s
= argv
[i
]; /* no arg, fill in something */
771 config
[config_names
[c
].nm
] = s
;
774 if (!known
&& strcmp(argv
[i
], "--version") == 0) {
778 if (!known
&& strcmp(argv
[i
], "--print-config") == 0) {
782 if (!known
&& strcmp(argv
[i
], "--help") == 0) {
783 print_usage(argv
[0], 0);
786 if (!known
&& strcmp(argv
[i
], "--long-help") == 0) {
787 print_usage(argv
[0], 1);
791 printf("%s: unknown option %s\n\n", argv
[0], argv
[i
]);
793 print_usage(argv
[0], 1);
799 read_config_file("/etc/vpnc/default.conf", config
, 1);
800 read_config_file("/etc/vpnc.conf", config
, 1);
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
;
820 printf("%s: unknown authentication mode %s\nknown modes: psk cert hybrid\n", argv
[0], config
[CONFIG_AUTH_MODE
]);
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
;
835 printf("%s: unknown nat traversal mode %s\nknown modes: natt none force-natt cisco-udp\n", argv
[0], config
[CONFIG_NATT_MODE
]);
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
;
844 printf("%s: unknown interface mode %s\nknown modes: tun tap\n", argv
[0], config
[CONFIG_IF_MODE
]);
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
;
853 printf("%s: unknown vendor %s\nknown vendors: cisco netscreen\n", argv
[0], config
[CONFIG_VENDOR
]);
858 if (opt_debug
>= 99) {
859 printf("WARNING! active debug level is >= 99, output includes username and password (hex encoded)\n");
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
)
870 if (config
[CONFIG_XAUTH_INTERACTIVE
] && i
== CONFIG_XAUTH_PASSWORD
)
877 case CONFIG_IPSEC_GATEWAY
:
878 printf("Enter IPSec gateway address: ");
880 case CONFIG_IPSEC_ID
:
881 printf("Enter IPSec ID for %s: ", config
[CONFIG_IPSEC_GATEWAY
]);
883 case CONFIG_IPSEC_SECRET
:
884 printf("Enter IPSec secret for %s@%s: ",
885 config
[CONFIG_IPSEC_ID
], config
[CONFIG_IPSEC_GATEWAY
]);
887 case CONFIG_XAUTH_USERNAME
:
888 printf("Enter username for %s: ", config
[CONFIG_IPSEC_GATEWAY
]);
890 case CONFIG_XAUTH_PASSWORD
:
891 printf("Enter password for %s@%s: ",
892 config
[CONFIG_XAUTH_USERNAME
],
893 config
[CONFIG_IPSEC_GATEWAY
]);
900 case CONFIG_IPSEC_SECRET
:
901 case CONFIG_XAUTH_PASSWORD
:
902 s
= vpnc_getpass("");
904 error(1, 0, "unable to get password");
906 case CONFIG_IPSEC_GATEWAY
:
907 case CONFIG_IPSEC_ID
:
908 case CONFIG_XAUTH_USERNAME
:
909 vpnc_getline(&s
, &s_len
, stdin
);
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)
919 printf("%s", config_names
[i
].name
);
920 if (config_names
[i
].needsArgument
) {
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
], "\"");
929 printf(" %s", config
[config_names
[i
].nm
]);
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");