added the --resolve-ip-http and --user-agent command line args so the fwknop-c client can resolve the external network via http://www.cipherdyne.org/cgi/myip.cgi

git-svn-id: file:///home/mbr/svn/fwknop/trunk@121 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Michael Rash
2009-07-27 05:33:21 +00:00
parent 9bc2b1539e
commit 3029e01238
5 changed files with 173 additions and 17 deletions
+37 -9
View File
@@ -26,7 +26,6 @@
#include "fwknop_common.h"
#include "config_init.h"
#include "getopt.h"
#include "spa_comm.h"
#include "utils.h"
#include "ctype.h"
@@ -202,16 +201,30 @@ static void
validate_options(fko_cli_options_t *options)
{
/* Gotta have a Destination unless we are just testing or getting the
* the version.
* the version, and must use one of [-s|-R|-a].
*/
if (!options->test && !options->version && !options->show_last_command
&& options->spa_server_str[0] == 0x0)
if(!options->test && !options->version && !options->show_last_command)
{
fprintf(stderr,
"[*] Must use --destination unless --test mode is used\n");
exit(EXIT_FAILURE);
if (options->spa_server_str[0] == 0x0)
{
fprintf(stderr,
"[*] Must use --destination unless --test mode is used\n");
exit(EXIT_FAILURE);
}
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
{
fprintf(stderr,
"[*] Must use one of [-s|-R|-a] to specify IP for SPA access.\n");
exit(EXIT_FAILURE);
}
}
if(options->resolve_ip_http || options->spa_proto == FKO_PROTO_HTTP)
if (options->http_user_agent[0] == '\0')
snprintf(options->http_user_agent, HTTP_MAX_USER_AGENT_LEN,
"%s%s", "Fwknop/", MY_VERSION);
/* If we are using gpg, we must at least have the recipient set.
*/
if(options->use_gpg)
@@ -250,7 +263,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
options->fw_timeout = -1;
while ((cmd_arg = getopt_long(argc, argv,
"a:A:bB:C:D:f:gG:hIm:nN:p:P:qQ:rsS:TU:vV", cmd_opts, &index)) != -1) {
"a:A:bB:C:D:f:gG:hIm:nN:p:P:qQ:rRsS:Tu:U:vV", cmd_opts, &index)) != -1) {
switch(cmd_arg) {
case 'a':
@@ -340,6 +353,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'r':
options->rand_port = 1;
break;
case 'R':
options->resolve_ip_http = 1;
break;
case SHOW_LAST_ARGS:
options->show_last_command = 1;
break;
@@ -356,6 +372,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
case 'T':
options->test = 1;
break;
case 'u':
strlcpy(options->http_user_agent, optarg, HTTP_MAX_USER_AGENT_LEN);
break;
case 'U':
strlcpy(options->spoof_user, optarg, MAX_USERNAME_LEN);
break;
@@ -447,12 +466,21 @@ usage(void)
" the outgoing SPA packet. Note: The 'tcpraw'\n"
" and 'icmp' modes use raw sockets and thus\n"
" require root access to run.\n"
" -S, --source-port - Set the source port for outgoing SPA packet.\n"
" -s, --source-ip - Tell the fwknopd server to accept whatever\n"
" source IP the SPA packet has as the IP that\n"
" needs access (not recommended, and the\n"
" fwknopd server can ignore such requests).\n"
" -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"
" http://"
HTTP_RESOLVE_HOST
HTTP_RESOLVE_URL
"\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"
" -U, --spoof-user - Set the username within outgoing SPA packet.\n"
" -q, --quiet - Perform fwknop functions quietly.\n"
" -G, --get-key - Load an encryption key/password from a file.\n"
+3 -1
View File
@@ -77,14 +77,16 @@ static struct option cmd_opts[] =
{"server-port", 1, NULL, 'p'},
{"server-proto", 1, NULL, 'P'},
{"quiet", 0, NULL, 'q'},
{"rand-port", 0, NULL, 'r'},
{"spoof-src", 1, NULL, 'Q'},
{"rand-port", 0, NULL, 'r'},
{"resolve-ip-http", 0, NULL, 'R'},
{"show-last", 0, NULL, SHOW_LAST_ARGS},
{"source-ip", 0, NULL, 's'},
{"source-port", 1, NULL, 'S'},
{"test", 0, NULL, 'T'},
{"time-offset-plus", 1, NULL, TIME_OFFSET_PLUS},
{"time-offset-minus", 1, NULL, TIME_OFFSET_MINUS},
{"user-agent", 1, NULL, 'u'},
{"spoof-user", 1, NULL, 'U'},
{"verbose", 0, NULL, 'v'},
{"version", 0, NULL, 'V'},
+115
View File
@@ -40,6 +40,7 @@ static int set_message_type(fko_ctx_t ctx, fko_cli_options_t *options);
static int set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options);
static int get_rand_port(fko_ctx_t ctx);
static void dump_transmit_options(fko_cli_options_t *options);
static void resolve_ip_http(fko_cli_options_t *options);
int
main(int argc, char **argv)
@@ -113,6 +114,9 @@ main(int argc, char **argv)
}
else
{
if (options.resolve_ip_http)
resolve_ip_http(&options);
/* Set a message string by combining the allow IP and the
* port/protocol. The fwknopd server allows no port/protocol
* to be specified as well, so in this case append the string
@@ -443,6 +447,117 @@ ipv4_str_has_port(char *str)
return rv;
}
static void resolve_ip_http(fko_cli_options_t *options)
{
int sock, res, error, http_buf_len, i;
struct addrinfo *result, *rp, hints;
char http_buf[HTTP_MAX_REQUEST_LEN];
char http_response[HTTP_MAX_RESPONSE_LEN];
char ip_str[MAX_IP_STR_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,
"%s%s%s%s%s%s%s",
"GET ",
HTTP_RESOLVE_URL,
" HTTP/1.0\r\nUser-Agent: ",
options->http_user_agent,
"\r\nAccept: */*\r\nHost: ",
HTTP_RESOLVE_HOST,
"\r\nConnection: Keep-Alive\r\n\r\n"
);
http_buf_len = strlen(http_buf);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(HTTP_RESOLVE_HOST, "80", &hints, &result);
if (error != 0)
{
fprintf(stderr, "[*] error in getaddrinfo: %s\n", gai_strerror(error));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock < 0)
continue;
if (error = connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* made it */
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
}
if (rp == NULL) {
perror("[*] resolve_ip_http: Could not create socket: ");
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
res = send(sock, http_buf, http_buf_len, 0);
if(res < 0)
{
perror("[*] resolve_ip_http: write error: ");
}
else if(res != http_buf_len)
{
fprintf(stderr,
"[#] Warning: bytes sent (%i) not spa data length (%i).\n",
res, http_buf_len
);
}
res = read(sock, http_response, HTTP_MAX_RESPONSE_LEN);
http_response[HTTP_MAX_RESPONSE_LEN-1] = '\0';
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
/* Now parse the response for the IP address (which should be at
* the end of the string
*/
for (i=res-3; i >= 0; i--)
{
if(http_response[i] == '\n')
break;
if(http_response[i] != '.' && ! isdigit(http_response[i]))
{
fprintf(stderr, "[*] Invalid IP in HTTP response.\n");
exit(EXIT_FAILURE);
}
}
if (i < MIN_IP_STR_LEN)
{
fprintf(stderr, "[*] Invalid IP in HTTP response.\n");
exit(EXIT_FAILURE);
}
http_response[res-1] = '\0';
strlcpy(options->allow_ip_str,
(http_response + i+1), (res - (i+2)));
printf("[+] Resolved external IP (via http://%s%s) as: %s\n",
HTTP_RESOLVE_HOST, HTTP_RESOLVE_URL, options->allow_ip_str);
return;
}
/* Set NAT access string
*/
static int
+18 -3
View File
@@ -97,6 +97,7 @@ enum {
#define MAX_PORT_STR_LEN 6
#define MAX_PROTO_STR_LEN 6
#define MAX_IP_STR_LEN 16
#define MIN_IP_STR_LEN 9
#define MAX_SERVER_STR_LEN 50
#define MAX_LINE_LEN 1024
@@ -104,6 +105,17 @@ enum {
#define MAX_GPG_KEY_ID 128
#define MAX_USERNAME_LEN 30
/* For resolving the allow IP via HTTP and sending SPA packets over
* HTTP
*/
#define HTTP_RESOLVE_HOST "www.cipherdyne.org"
#define HTTP_RESOLVE_URL "/cgi/myip.cgi"
#define HTTP_MAX_REQUEST_LEN 2000
#define HTTP_MAX_RESPONSE_LEN 2000
#define HTTP_MAX_USER_AGENT_LEN 50
/* For time offset handling
*/
#define MAX_TIME_STR_LEN 9
enum {
TIME_OFFSET_SECONDS,
@@ -112,9 +124,7 @@ enum {
TIME_OFFSET_DAYS
};
#define RAND_FILE "/dev/urandom"
/* fwkop client configuration parameters and values
/* fwknop client configuration parameters and values
*/
typedef struct fko_cli_options
{
@@ -142,6 +152,11 @@ typedef struct fko_cli_options
int nat_port;
int nat_rand_port;
/* External IP resolution via HTTP
*/
int resolve_ip_http;
char http_user_agent[HTTP_MAX_USER_AGENT_LEN];
/* SPA packet transmission port and protocol
*/
int spa_proto;
-4
View File
@@ -124,10 +124,6 @@ struct icmphdr
} un;
};
/* for sending SPA packets over HTTP
*/
#define HTTP_MAX_REQUEST_LEN 2000 /* bytes - reasonable maximum */
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */