[client] have autoconf resolve the absolute path to wget for SSL IP resolution

This commit is contained in:
Michael Rash 2014-07-27 22:03:58 -04:00
parent 4fcd5b317a
commit b06447384e
10 changed files with 207 additions and 16 deletions

View File

@ -78,7 +78,7 @@ enum {
/* Our getopt_long options string.
*/
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:E:f:gG:hH:kK:lm:M:n:N:p:P:Q:rRsS:Tu:U:vV"
#define GETOPTS_OPTION_STRING "a:A:bB:C:D:E:f:gG:hH:kK:lm:M:n:N:p:P:Q:rRsS:Tu:U:vVw:"
/* Our program command-line options...
*/
@ -150,6 +150,7 @@ static struct option cmd_opts[] =
{"spoof-user", 1, NULL, 'U'},
{"verbose", 0, NULL, 'v'},
{"version", 0, NULL, 'V'},
{"wget-cmd", 1, NULL, 'w'},
{0, 0, 0, 0}
};

View File

@ -125,6 +125,7 @@ enum
FWKNOP_CLI_ARG_RESOLVE_IP_HTTP,
FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS,
FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY,
FWKNOP_CLI_ARG_WGET_CMD,
FWKNOP_CLI_LAST_ARG
} fwknop_cli_arg_t;
@ -169,7 +170,8 @@ static fko_var_t fko_var_array[FWKNOP_CLI_LAST_ARG] =
{ "VERBOSE", FWKNOP_CLI_ARG_VERBOSE },
{ "RESOLVE_IP_HTTP", FWKNOP_CLI_ARG_RESOLVE_IP_HTTP },
{ "RESOLVE_IP_HTTPS", FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS },
{ "RESOLVE_HTTP_ONLY", FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY }
{ "RESOLVE_HTTP_ONLY", FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY },
{ "WGET_CMD", FWKNOP_CLI_ARG_WGET_CMD }
};
/* Array to define which conf. variables are critical and should not be
@ -1177,6 +1179,20 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
}
strlcpy(options->resolve_url, val, tmpint);
}
/* wget command */
else if (var->pos == FWKNOP_CLI_ARG_WGET_CMD)
{
if(options->wget_bin != NULL)
free(options->wget_bin);
tmpint = strlen(val)+1;
options->wget_bin = calloc(1, tmpint);
if(options->wget_bin == NULL)
{
log_msg(LOG_VERBOSITY_ERROR,"Memory allocation error for wget command path.");
exit(EXIT_FAILURE);
}
strlcpy(options->wget_bin, val, tmpint);
}
/* NAT Local ? */
else if (var->pos == FWKNOP_CLI_ARG_NAT_LOCAL)
{
@ -1233,6 +1249,14 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
options->resolve_ip_http_https = 1;
else;
}
/* RESOLVE_HTTP_ONLY ? Force HTTP instead of HTTPS IP resolution.
*/
else if (var->pos == FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY)
{
if (is_yes_str(val))
options->resolve_http_only = 1;
else;
}
/* The variable is not a configuration variable */
else
{
@ -1388,6 +1412,13 @@ add_single_var_to_rc(FILE* fhandle, short var_pos, fko_cli_options_t *options)
case FWKNOP_CLI_ARG_RESOLVE_IP_HTTP:
bool_to_yesno(options->resolve_ip_http_https, val, sizeof(val));
break;
case FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY:
bool_to_yesno(options->resolve_http_only, val, sizeof(val));
break;
case FWKNOP_CLI_ARG_WGET_CMD :
if (options->wget_bin != NULL)
strlcpy(val, options->wget_bin, sizeof(val));
break;
default:
log_msg(LOG_VERBOSITY_WARNING, "Warning from add_single_var_to_rc() : Bad variable position %u", var->pos);
return;
@ -2181,8 +2212,8 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case RESOLVE_HTTP_ONLY:
options->resolve_http_only = 1;
options->resolve_ip_http_https = 1;
add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_IP_HTTP, &var_bitmask);
add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_HTTP_ONLY, &var_bitmask);
add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_IP_HTTPS, &var_bitmask);
break;
case RESOLVE_URL:
if(options->resolve_url != NULL)
@ -2197,6 +2228,19 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
strlcpy(options->resolve_url, optarg, rlen);
add_var_to_bitmask(FWKNOP_CLI_ARG_RESOLVE_URL, &var_bitmask);
break;
case 'w':
if(options->wget_bin != NULL)
free(options->wget_bin);
rlen = strlen(optarg) + 1;
options->wget_bin = calloc(1, rlen);
if(options->wget_bin == NULL)
{
log_msg(LOG_VERBOSITY_ERROR, "Memory allocation error for resolve URL.");
exit(EXIT_FAILURE);
}
strlcpy(options->wget_bin, optarg, rlen);
add_var_to_bitmask(FWKNOP_CLI_ARG_WGET_CMD, &var_bitmask);
break;
case SHOW_LAST_ARGS:
options->show_last_command = 1;
break;

View File

@ -2,12 +2,12 @@
.\" Title: fwknop
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 07/25/2014
.\" Date: 07/27/2014
.\" Manual: Fwknop Client
.\" Source: Fwknop Client
.\" Language: English
.\"
.TH "FWKNOP" "8" "07/25/2014" "Fwknop Client" "Fwknop Client"
.TH "FWKNOP" "8" "07/27/2014" "Fwknop Client" "Fwknop Client"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -528,6 +528,17 @@ is not available (or hasn\(cqt been compiled with SSL support), but generally th
and omit this option\&.
.RE
.PP
\fB\-w, \-\-wget\-cmd\fR=\fI<wget full path>\fR
.RS 4
Manually set the full path to the
\fIwget\fR
command\&. Normally the
\fIconfigure\fR
script finds the
\fIwget\fR
command, but this option can be used to specify the path if it is located in a non\-standard place\&.
.RE
.PP
\fB\-s, \-\-source\-ip\fR
.RS 4
Instruct the
@ -811,9 +822,44 @@ Set the source port to use for sending the SPA packet (\fI\-S, \-\-source\-port\
Set the firewall rule timeout value (\fI\-f, \-\-fw\-timeout\fR)\&.
.RE
.PP
\fBRESOLVE_IP_HTTPS\fR \fI<Y/N>\fR
.RS 4
Set to
\fIY\fR
to automatically resolve the externally routable IP associated with the
\fBfwknop\fR
client\&. This is done over SSL via
\fIwget\fR
in
\fI\-\-secure\-protocol\fR
mode against the IP resolution service available at
\fIhttps://www\&.cipherdyne\&.org/cgi\-bin/myip\fR\&.
.RE
.PP
\fBRESOLVE_HTTP_ONLY\fR \fI<Y/N>\fR
.RS 4
When the
\fBfwknop\fR
client is instructed to resolve the external client IP, this option can be used to force an
\fIHTTP\fR
connection instead of an
\fIHTTPS\fR
connection when set to
\fIY\fR\&. This option is useful when
\fIwget\fR
is not installed on the local OS, or when it is not compiled against an SSL library\&.
.RE
.PP
\fBRESOLVE_URL\fR \fI<url>\fR
.RS 4
Set to a URL that will be used for resolving the source IP address (\-\-resolve\-url)\&.
Set to a URL that will be used for resolving the source IP address (\fI\-\-resolve\-url\fR)\&.
.RE
.PP
\fBWGET_CMD\fR \fI<wget full path>\fR
.RS 4
Set the full path to the
\fIwget\fR
command (used for client IP resolution)\&.
.RE
.PP
\fBTIME_OFFSET\fR \fI<time>\fR

View File

@ -665,6 +665,8 @@ free_configs(fko_cli_options_t *opts)
{
if (opts->resolve_url != NULL)
free(opts->resolve_url);
if (opts->wget_bin != NULL)
free(opts->wget_bin);
zero_buf_wrapper(opts->key, MAX_KEY_LEN+1);
zero_buf_wrapper(opts->key_base64, MAX_B64_KEY_LEN+1);
zero_buf_wrapper(opts->hmac_key, MAX_KEY_LEN+1);

View File

@ -63,7 +63,7 @@
#define HTTP_BACKUP_RESOLVE_HOST "www.cipherdyne.com"
#define HTTP_RESOLVE_URL "/cgi-bin/myip"
#define WGET_RESOLVE_URL_SSL "https://" HTTP_RESOLVE_HOST HTTP_RESOLVE_URL
#define WGET_RESOLVE_CMD "wget --secure-protocol=auto --quiet -O - "
#define WGET_RESOLVE_ARGS " --secure-protocol=auto --quiet -O - "
#define HTTP_MAX_REQUEST_LEN 2000
#define HTTP_MAX_RESPONSE_LEN 2000
#define HTTP_MAX_USER_AGENT_LEN 100
@ -131,6 +131,7 @@ typedef struct fko_cli_options
int resolve_http_only;
char *resolve_url;
char http_user_agent[HTTP_MAX_USER_AGENT_LEN];
char *wget_bin;
/* HTTP proxy support
*/

View File

@ -308,13 +308,28 @@ resolve_ip_https(fko_cli_options_t *options)
{
int o1, o2, o3, o4, got_resp=0, i;
char *ndx, resp[MAX_IPV4_STR_LEN+1] = {0};
char wget_cmd[MAX_URL_PATH_LEN] = {0};
char wget_ssl_cmd[MAX_URL_PATH_LEN] = {0};
struct url url; /* for validation only */
FILE *wget;
memset(&url, 0, sizeof(url));
strlcpy(wget_cmd, WGET_RESOLVE_CMD, sizeof(wget_cmd));
if(options->wget_bin != NULL)
strlcpy(wget_ssl_cmd, options->wget_bin, sizeof(wget_ssl_cmd));
else
{
#ifdef WGET_EXE
strlcpy(wget_ssl_cmd, WGET_EXE, sizeof(wget_ssl_cmd));
#else
log_msg(LOG_VERBOSITY_ERROR,
"[*] Use --wget-cmd <path> to specify path to the wget command.");
return(-1);
#endif
}
/* Tack on the SSL args to wget
*/
strlcat(wget_ssl_cmd, WGET_RESOLVE_ARGS, sizeof(wget_ssl_cmd));
if(options->resolve_url != NULL)
{
@ -332,25 +347,25 @@ resolve_ip_https(fko_cli_options_t *options)
}
/* tack on the original URL to the wget command
*/
strlcat(wget_cmd, options->resolve_url, sizeof(wget_cmd));
strlcat(wget_ssl_cmd, options->resolve_url, sizeof(wget_ssl_cmd));
}
else
{
/* tack on the default URL to the wget command
*/
strlcat(wget_cmd, WGET_RESOLVE_URL_SSL, sizeof(wget_cmd));
strlcat(wget_ssl_cmd, WGET_RESOLVE_URL_SSL, sizeof(wget_ssl_cmd));
}
/* We drive wget to resolve the external IP via SSL. This may not
* work on all platforms, but is a better strategy for now than
* requiring that fwknop link against an SSL library.
*/
wget = popen(wget_cmd, "r");
wget = popen(wget_ssl_cmd, "r");
if(wget == NULL)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] Could not run cmd: %s",
wget_cmd);
wget_ssl_cmd);
return -1;
}
@ -381,13 +396,13 @@ resolve_ip_https(fko_cli_options_t *options)
log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via '%s') as: %s",
wget_cmd, options->allow_ip_str);
wget_ssl_cmd, options->allow_ip_str);
return 1;
}
}
log_msg(LOG_VERBOSITY_ERROR,
"[-] Could not resolve IP via: '%s'", wget_cmd);
"[-] Could not resolve IP via: '%s'", wget_ssl_cmd);
return -1;
}

View File

@ -405,6 +405,28 @@ case "$host" in
esac
fi
dnl Check for wget (used by the fwknop client for SSL external IP resolution)
dnl
AC_ARG_WITH([wget],
[AS_HELP_STRING([--with-wget=/path/to/wget],
[Specify path to the wget executable @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ],
[AC_MSG_ERROR([--with-wget requires an argument specifying a path to wget])],
[ WGET_EXE=$withval ]
)
],
[
AC_PATH_PROG(WGET_EXE, [wget], [], [$APP_PATH])
]
)
AS_IF([test "x$WGET_EXE" != x],
[
AC_DEFINE_UNQUOTED([WGET_EXE], ["$WGET_EXE"], [Path to wget executable])
wget_exe=$WGET_EXE
], [ wget_exe="(not found)"]
)
dnl Check for libpcap, gdbm (or ndbm) if we are building the server component
dnl
AS_IF([test "$want_server" = yes], [

View File

@ -437,6 +437,11 @@ SPA OPTIONS
HTTP response. Either specify the IP manually with *-a*, or use *-R*
and omit this option.
*-w, --wget-cmd*='<wget full path>'::
Manually set the full path to the 'wget' command. Normally the 'configure'
script finds the 'wget' command, but this option can be used to specify
the path if it is located in a non-standard place.
*-s, --source-ip*::
Instruct the *fwknop* client to form an SPA packet that contains the
special-case IP address ``+0.0.0.0+'' which will inform the destination
@ -660,9 +665,25 @@ description and its matching command-line option(s):
*FW_TIMEOUT* '<seconds>'::
Set the firewall rule timeout value ('-f, --fw-timeout').
*RESOLVE_IP_HTTPS* '<Y/N>'::
Set to 'Y' to automatically resolve the externally routable IP associated
with the *fwknop* client. This is done over SSL via 'wget' in
'--secure-protocol' mode against the IP resolution service available at
'https://www.cipherdyne.org/cgi-bin/myip'.
*RESOLVE_HTTP_ONLY* '<Y/N>'::
When the *fwknop* client is instructed to resolve the external client IP,
this option can be used to force an 'HTTP' connection instead of an 'HTTPS'
connection when set to 'Y'. This option is useful when 'wget' is not
installed on the local OS, or when it is not compiled against an SSL
library.
*RESOLVE_URL* '<url>'::
Set to a URL that will be used for resolving the source IP address
(--resolve-url).
('--resolve-url').
*WGET_CMD* '<wget full path>'::
Set the full path to the 'wget' command (used for client IP resolution).
*TIME_OFFSET* '<time>'::
Set a value to apply to the timestamp in the SPA packet. This can

View File

@ -1414,6 +1414,45 @@
'positive_output_matches' => [qr/Resolved/],
'rc_positive_output_matches' => [qr/RESOLVE_IP_HTTPS.*Y/],
},
{
'category' => 'basic operations',
'subcategory' => 'client save rc file',
'detail' => '-R resolve valid wget',
'function' => \&client_rc_file,
'cmdline' => "$client_save_rc_args -n default -R --wget-cmd wget",
'save_rc_stanza' => [{'name' => 'default',
'vars' => {'KEY' => 'testtest', 'HMAC_KEY' => 'hmactest',
'HMAC_DIGEST_TYPE' => 'SHA1'}}],
'exec_err' => $NO,
'rc_positive_output_matches' => [qr/RESOLVE_IP_HTTPS.*Y/],
},
{
'category' => 'basic operations',
'subcategory' => 'client save rc file',
'detail' => '-R resolve http only',
'function' => \&client_rc_file,
'cmdline' => "$client_save_rc_args -n default -R --resolve-http-only",
'save_rc_stanza' => [{'name' => 'default',
'vars' => {'KEY' => 'testtest', 'HMAC_KEY' => 'hmactest',
'HMAC_DIGEST_TYPE' => 'SHA1'}}],
'exec_err' => $NO,
'rc_positive_output_matches' => [qr/RESOLVE_IP_HTTPS.*Y/,
qr/RESOLVE_HTTP_ONLY.*Y/],
},
{
'category' => 'basic operations',
'subcategory' => 'client save rc file',
'detail' => '-R resolve invalid wget',
'function' => \&client_rc_file,
'cmdline' => "$client_save_rc_args -n default -R --wget-cmd invalidpath",
'save_rc_stanza' => [{'name' => 'default',
'vars' => {'KEY' => 'testtest', 'HMAC_KEY' => 'hmactest',
'HMAC_DIGEST_TYPE' => 'SHA1'}}],
'exec_err' => $YES,
'positive_output_matches' => [qr/Could not resolve IP/],
'rc_positive_output_matches' => [qr/RESOLVE_IP_HTTPS.*Y/],
},
{
'category' => 'basic operations',