Set FD_CLOEXEC on pid file descriptor.

Added support for setting the URL for resolving source IP via command-line or the .fwknoprc file.
This commit is contained in:
Damien Stuart 2011-07-07 08:12:49 -04:00
parent ca5f82c067
commit 69f41eb399
7 changed files with 172 additions and 12 deletions

View File

@ -350,6 +350,20 @@ parse_rc_param(fko_cli_options_t *options, char *var, char * val)
{
strlcpy(options->http_user_agent, val, HTTP_MAX_USER_AGENT_LEN);
}
/* Resolve URL */
else if(CONF_VAR_IS(var, "RESOLVE_URL"))
{
if(options->resolve_url != NULL)
free(options->resolve_url);
tmpint = strlen(val)+1;
options->resolve_url = malloc(tmpint);
if(options->resolve_url == NULL)
{
fprintf(stderr, "Memory allocation error for resolve URL.\n");
exit(EXIT_FAILURE);
}
strlcpy(options->resolve_url, val, tmpint);
}
/* NAT Local ? */
else if(CONF_VAR_IS(var, "NAT_LOCAL"))
{
@ -562,6 +576,9 @@ validate_options(fko_cli_options_t *options)
exit(EXIT_FAILURE);
}
if (options->resolve_url != NULL)
options->resolve_ip_http = 1;
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
{
fprintf(stderr,
@ -742,6 +759,17 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'R':
options->resolve_ip_http = 1;
break;
case RESOLVE_URL:
if(options->resolve_url != NULL)
free(options->resolve_url);
options->resolve_url = malloc(strlen(optarg)+1);
if(options->resolve_url == NULL)
{
fprintf(stderr, "Memory allocation error for resolve URL.\n");
exit(EXIT_FAILURE);
}
strcpy(options->resolve_url, optarg);
break;
case SHOW_LAST_ARGS:
options->show_last_command = 1;
break;
@ -857,8 +885,12 @@ usage(void)
" -S, --source-port Set the source port for outgoing SPA packet.\n"
" -Q, --spoof-source Set the source IP for outgoing SPA packet.\n"
" -R, --resolve-ip-http Resolve the external network IP by\n"
" connecting to the URL:\n"
" connecting to a URL such as the default of:\n"
" http://" HTTP_RESOLVE_HOST HTTP_RESOLVE_URL "\n"
" This can be overridden with the --resolve-url\n"
" option.\n"
" --resolve-url Override the default URL used for resolving\n"
" the source IP address.\n"
" -u, --user-agent Set the HTTP User-Agent for resolving the\n"
" external IP via -R, or for sending SPA\n"
" packets over HTTP.\n"

View File

@ -49,6 +49,7 @@ enum {
TIME_OFFSET_PLUS,
NO_SAVE_ARGS,
SHOW_LAST_ARGS,
RESOLVE_URL,
/* Put GPG-related items below the following line */
GPG_ENCRYPTION = 0x200,
GPG_RECIP_KEY,
@ -94,6 +95,7 @@ static struct option cmd_opts[] =
{"spoof-src", 1, NULL, 'Q'},
{"rand-port", 0, NULL, 'r'},
{"resolve-ip-http", 0, NULL, 'R'},
{"resolve-url", 1, NULL, RESOLVE_URL},
{"show-last", 0, NULL, SHOW_LAST_ARGS},
{"source-ip", 0, NULL, 's'},
{"source-port", 1, NULL, 'S'},

View File

@ -2,12 +2,12 @@
.\" Title: fwknop
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: 07/08/2010
.\" Date: 07/06/2011
.\" Manual: Fwknop Client
.\" Source: Fwknop Client
.\" Language: English
.\"
.TH "FWKNOP" "8" "07/08/2010" "Fwknop Client" "Fwknop Client"
.TH "FWKNOP" "8" "07/06/2011" "Fwknop Client" "Fwknop Client"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@ -333,6 +333,11 @@ uses the URL:
to resolve the caller IP\&.
.RE
.PP
\fB\-\-resolve\-url\fR
.RS 4
Override the default URL used for resolving the source IP address\&. For best results, the URL specified here should point to a web service that provides just an IP address in the body of the HTTP response\&.
.RE
.PP
\fB\-s, \-\-source\-ip\fR
.RS 4
Instruct the
@ -472,6 +477,11 @@ resolve the external network IP via HTTP request (the
option)\&.
.RE
.PP
\fBRESOLVE_URL\fR
.RS 4
Set to a URL that will be used for resolving the source IP address (\-\-resolve\-url)\&.
.RE
.PP
\fBTIME_OFFSET\fR
.RS 4
Set a value to apply to the timestamp in the SPA packet\&. This can be either a positive or negative value (\fI\-\-time\-offset\-plus/minus\fR)\&.

View File

@ -62,12 +62,14 @@
* so we will make the default run on cipherdyne website
* for now.
*/
#define HTTP_RESOLVE_HOST "www.cipherdyne.org"
#define HTTP_RESOLVE_URL "/cgi-bin/myip"
#define HTTP_MAX_REQUEST_LEN 2000
#define HTTP_MAX_RESPONSE_LEN 2000
#define HTTP_MAX_USER_AGENT_LEN 50
#define MAX_HOSTNAME_LEN 70
#define HTTP_RESOLVE_HOST "www.cipherdyne.org"
#define HTTP_RESOLVE_URL "/cgi-bin/myip"
#define HTTP_MAX_REQUEST_LEN 2000
#define HTTP_MAX_RESPONSE_LEN 2000
#define HTTP_MAX_USER_AGENT_LEN 50
#define MAX_HOSTNAME_LEN 70
#define MAX_URL_HOST_LEN 256
#define MAX_URL_PATH_LEN 1024
/* fwknop client configuration parameters and values
*/
@ -101,6 +103,7 @@ typedef struct fko_cli_options
/* External IP resolution via HTTP
*/
int resolve_ip_http;
char *resolve_url;
char http_user_agent[HTTP_MAX_USER_AGENT_LEN];
/* HTTP proxy support

View File

@ -44,12 +44,97 @@
#include <netdb.h>
#endif
struct url
{
char port[6];
char host[256];
char path[1024];
};
static int
parse_url(char *res_url, struct url* url)
{
char *s_ndx, *e_ndx;
int tlen, tlen_offset, port;
/* https is not supported.
*/
if(strncasecmp(res_url, "https", 5) == 0)
{
fprintf(stderr, "https is not yet supported for http-resolve-ip.\n");
return(-1);
}
/* Strip off http:// portion if necessary
*/
if(strncasecmp(res_url, "http://", 7) == 0)
s_ndx = res_url + 7;
else
s_ndx = res_url;
/* Look for a colon in case an alternate port was specified.
*/
e_ndx = strchr(s_ndx, ':');
if(e_ndx != NULL)
{
port = atoi(e_ndx+1);
if(port < 1 || port > 65535)
{
fprintf(stderr, "resolve-url port value is invalid.\n");
return(-1);
}
sprintf(url->port, "%u", port);
/* Get the offset we need to skip the port portion when we
* extract the hostname part.
*/
tlen_offset = strlen(url->port)+1;
}
else
{
strcpy(url->port, "80");
tlen_offset = 0;
}
e_ndx = strchr(s_ndx, '/');
if(e_ndx == NULL)
tlen = strlen(s_ndx)+1;
else
tlen = (e_ndx-s_ndx)+1;
tlen -= tlen_offset;
if(tlen > MAX_URL_HOST_LEN)
{
fprintf(stderr, "resolve-url hostname portion is too large.\n");
return(-1);
}
strlcpy(url->host, s_ndx, tlen);
if(e_ndx != NULL)
{
if(strlen(e_ndx) > MAX_URL_PATH_LEN)
{
fprintf(stderr, "resolve-url path portion is too large.\n");
return(-1);
}
strlcpy(url->path, e_ndx, MAX_URL_PATH_LEN);
}
else
*(url->path) = '\0';
return(0);
}
int
resolve_ip_http(fko_cli_options_t *options)
{
int sock, res, error, http_buf_len, i;
int o1, o2, o3, o4;
struct addrinfo *result, *rp, hints;
struct url url;
char http_buf[HTTP_MAX_REQUEST_LEN];
char http_response[HTTP_MAX_RESPONSE_LEN] = {0};
char *ndx;
@ -67,13 +152,28 @@ resolve_ip_http(fko_cli_options_t *options)
}
#endif
if(options->resolve_url != NULL)
{
if(parse_url(options->resolve_url, &url) < 0)
{
fprintf(stderr, "Error parsing resolve-url\n");
return(-1);
}
} else {
strlcpy(url.port, "80", 3);
strlcpy(url.host, HTTP_RESOLVE_HOST, MAX_URL_HOST_LEN);
strlcpy(url.path, HTTP_RESOLVE_URL, MAX_URL_PATH_LEN);
}
/* Build our HTTP request to resolve the external IP (this is similar to
* to contacting whatismyip.org, but using a different URL).
*/
snprintf(http_buf, HTTP_MAX_REQUEST_LEN,
"GET %s HTTP/1.0\r\nUser-Agent: %s\r\nAccept: */*\r\n"
"Host: %s\r\nConnection: Keep-Alive\r\n\r\n",
HTTP_RESOLVE_URL, options->http_user_agent, HTTP_RESOLVE_HOST
url.path,
options->http_user_agent,
url.host
);
http_buf_len = strlen(http_buf);
@ -84,7 +184,7 @@ resolve_ip_http(fko_cli_options_t *options)
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(HTTP_RESOLVE_HOST, "80", &hints, &result);
error = getaddrinfo(url.host, url.port, &hints, &result);
if (error != 0)
{
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
@ -173,7 +273,9 @@ resolve_ip_http(fko_cli_options_t *options)
if(options->verbose)
printf("Resolved external IP (via http://%s%s) as: %s\n",
HTTP_RESOLVE_HOST, HTTP_RESOLVE_URL, options->allow_ip_str);
url.host,
url.path,
options->allow_ip_str);
return(0);
}

View File

@ -273,6 +273,11 @@ SPA OPTIONS
NAT address. Presently, *fwknop* uses the URL:
'http://www.cipherdyne.org/cgi-bin/myip' to resolve the caller IP.
*--resolve-url*::
Override the default URL used for resolving the source IP address. For
best results, the URL specified here should point to a web service that
provides just an IP address in the body of the HTTP response.
*-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
@ -391,6 +396,10 @@ description and its matching command-line option(s):
to allow (the *-s* option), or use the word "resolve" to have *fwknop*
resolve the external network IP via HTTP request (the *-R* option).
*RESOLVE_URL*::
Set to a URL that will be used for resolving the source IP address
(--resolve-url).
*TIME_OFFSET*::
Set a value to apply to the timestamp in the SPA packet. This can
be either a positive or negative value ('--time-offset-plus/minus').

View File

@ -586,6 +586,8 @@ write_pid_file(fko_srv_options_t *opts)
return -1;
}
fcntl(op_fd, F_SETFD, FD_CLOEXEC);
/* Attempt to lock the PID file. If we get an EWOULDBLOCK
* error, another instance already has the lock. So we grab
* the pid from the existing lock file, complain and bail.