use execvpe() with NULL env for wget calls

This commit is contained in:
Michael Rash
2014-09-30 21:59:01 -04:00
parent b1358d564d
commit 2247dfeab8
5 changed files with 161 additions and 59 deletions
+9 -31
View File
@@ -64,7 +64,6 @@ static int is_hostname_str_with_port(const char *str,
static void enable_fault_injections(fko_cli_options_t * const opts);
#endif
#define MAX_CMDLINE_ARGS 50 /*!< should be way more than enough */
#define NAT_ACCESS_STR_TEMPLATE "%s,%d" /*!< Template for a nat access string ip,port with sscanf*/
#define HOSTNAME_BUFSIZE 64 /*!< Maximum size of a hostname string */
#define CTX_DUMP_BUFSIZE 4096 /*!< Maximum size allocated to a FKO context dump */
@@ -985,13 +984,15 @@ run_last_args(fko_cli_options_t *options, const char * const args_save_file)
FILE *args_file_ptr = NULL;
int current_arg_ctr = 0;
int argc_new = 0, args_broken = 0, buf_size=0;
int argc_new = 0;
int i = 0;
char args_str[MAX_LINE_LEN] = {0};
char arg_tmp[MAX_LINE_LEN] = {0};
char *argv_new[MAX_CMDLINE_ARGS]; /* should be way more than enough */
memset(argv_new, 0x0, sizeof(argv_new));
if(verify_file_perms_ownership(args_save_file) != 1)
return 0;
@@ -1016,49 +1017,26 @@ run_last_args(fko_cli_options_t *options, const char * const args_save_file)
else
{
arg_tmp[current_arg_ctr] = '\0';
buf_size = strlen(arg_tmp) + 1;
argv_new[argc_new] = calloc(1, buf_size);
if (argv_new[argc_new] == NULL)
if (add_argv(argv_new, &argc_new, arg_tmp, options) != 1)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] calloc failure for cmd line arg.");
fclose(args_file_ptr);
return 0;
}
strlcpy(argv_new[argc_new], arg_tmp, buf_size);
current_arg_ctr = 0;
argc_new++;
if(argc_new >= MAX_CMDLINE_ARGS)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] max command line args exceeded.");
args_broken = 1;
break;
}
}
}
}
fclose(args_file_ptr);
if(! args_broken)
{
/* Reset the options index so we can run through them again.
*/
optind = 0;
/* Reset the options index so we can run through them again.
*/
optind = 0;
config_init(options, argc_new, argv_new);
}
config_init(options, argc_new, argv_new);
/* Since we passed in our own copies, free up malloc'd memory
*/
for (i=0; i < argc_new; i++)
{
if(argv_new[i] == NULL)
break;
else
free(argv_new[i]);
}
if(args_broken)
return 0;
free_argv(argv_new, &argc_new);
return 1;
}
+4 -1
View File
@@ -47,6 +47,10 @@
*/
#define DEF_CONFIG_FILE MY_NAME".conf"
/* Command line argument / argv handling
*/
#define MAX_CMDLINE_ARGS 50 /*!< should be way more than enough */
/* For time offset handling
*/
#define MAX_TIME_STR_LEN 9
@@ -63,7 +67,6 @@
#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_ARGS " --secure-protocol=auto --quiet"
#define HTTP_MAX_REQUEST_LEN 2000
#define HTTP_MAX_RESPONSE_LEN 2000
#define HTTP_MAX_USER_AGENT_LEN 100
+96 -27
View File
@@ -31,6 +31,7 @@
*/
#include "fwknop_common.h"
#include "utils.h"
#include <sys/wait.h>
#include <errno.h>
@@ -306,20 +307,40 @@ parse_url(char *res_url, struct url* url)
int
resolve_ip_https(fko_cli_options_t *options)
{
int o1, o2, o3, o4, got_resp=0, i;
int o1, o2, o3, o4, got_resp=0, i=0;
char *ndx, resp[MAX_IPV4_STR_LEN+1] = {0};
char wget_ssl_cmd[MAX_URL_PATH_LEN] = {0};
struct url url; /* for validation only */
FILE *wget;
char wget_ssl_cmd[MAX_URL_PATH_LEN] = {0}; /* for verbose logging only */
memset(&url, 0, sizeof(url));
char *wget_argv[MAX_CMDLINE_ARGS]; /* for execvpe() with no environment */
char *output_args[4] = {"--secure-protocol=auto", "--quiet", "-O", "-"};
int wget_argc=0;
int pipe_fd[2];
pid_t pid=0;
FILE *output;
int status;
memset(&url, 0x0, sizeof(url));
memset(wget_argv, 0x0, sizeof(wget_argv));
if(options->wget_bin != NULL)
{
strlcpy(wget_ssl_cmd, options->wget_bin, sizeof(wget_ssl_cmd));
if (add_argv(wget_argv, &wget_argc, options->wget_bin, options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
}
else
{
#ifdef WGET_EXE
strlcpy(wget_ssl_cmd, WGET_EXE, sizeof(wget_ssl_cmd));
if (add_argv(wget_argv, &wget_argc, WGET_EXE, options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
#else
log_msg(LOG_VERBOSITY_ERROR,
"[*] Use --wget-cmd <path> to specify path to the wget command.");
@@ -327,22 +348,36 @@ resolve_ip_https(fko_cli_options_t *options)
#endif
}
/* Tack on the SSL args to wget
*/
strlcat(wget_ssl_cmd, WGET_RESOLVE_ARGS, sizeof(wget_ssl_cmd));
/* See whether we're supposed to change the default wget user agent
*/
if(! options->use_wget_user_agent)
{
strlcat(wget_ssl_cmd, " -U '", sizeof(wget_ssl_cmd));
strlcat(wget_ssl_cmd, " -U ", sizeof(wget_ssl_cmd));
strlcat(wget_ssl_cmd, options->http_user_agent, sizeof(wget_ssl_cmd));
strlcat(wget_ssl_cmd, "'", sizeof(wget_ssl_cmd));
if (add_argv(wget_argv, &wget_argc, "-U", options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
if (add_argv(wget_argv, &wget_argc, options->http_user_agent, options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
}
/* We collect the IP from wget's stdout
*/
strlcat(wget_ssl_cmd, " -O - ", sizeof(wget_ssl_cmd));
strlcat(wget_ssl_cmd,
" --secure-protocol=auto --quiet -O - ", sizeof(wget_ssl_cmd));
for (i=0; i < 4; i++)
{
if (add_argv(wget_argv, &wget_argc, output_args[i], options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
}
if(options->resolve_url != NULL)
{
@@ -361,44 +396,79 @@ resolve_ip_https(fko_cli_options_t *options)
/* tack on the original URL to the wget command
*/
strlcat(wget_ssl_cmd, options->resolve_url, sizeof(wget_ssl_cmd));
if (add_argv(wget_argv, &wget_argc, options->resolve_url, options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
}
else
{
/* tack on the default URL to the wget command
*/
strlcat(wget_ssl_cmd, WGET_RESOLVE_URL_SSL, sizeof(wget_ssl_cmd));
if (add_argv(wget_argv, &wget_argc, WGET_RESOLVE_URL_SSL, options) != 1)
{
free_argv(wget_argv, &wget_argc);
return -1;
}
}
/* 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_ssl_cmd, "r");
if(wget == NULL)
if(pipe(pipe_fd) < 0)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] Could not run cmd: %s",
wget_ssl_cmd);
log_msg(LOG_VERBOSITY_ERROR, "[*] pipe() error");
return -1;
}
/* Expecting one line of wget output that contains the resolved IP.
*/
if ((fgets(resp, sizeof(resp), wget)) != NULL)
pid = fork();
if (pid == 0)
{
got_resp = 1;
close(pipe_fd[0]);
dup2(pipe_fd[1], STDOUT_FILENO);
dup2(pipe_fd[1], STDERR_FILENO);
execvpe(wget_argv[0], wget_argv, (char * const *)NULL);
}
else if(pid == -1)
{
log_msg(LOG_VERBOSITY_INFO, "[*] Could not fork() for wget.");
return -1;
}
pclose(wget);
ndx = resp;
for(i=0; i<MAX_IPV4_STR_LEN; i++) {
if(! isdigit(*(ndx+i)) && *(ndx+i) != '.')
break;
/* Only the parent process makes it here
*/
close(pipe_fd[1]);
if ((output = fdopen(pipe_fd[0], "r")) != NULL)
{
if(fgets(resp, sizeof(resp), output) != NULL)
{
got_resp = 1;
}
}
*(ndx+i) = '\0';
else
{
log_msg(LOG_VERBOSITY_INFO,
"[*] Could not fdopen() pipe output file descriptor.");
return -1;
}
fclose(output);
waitpid(pid, &status, 0);
free_argv(wget_argv, &wget_argc);
if(got_resp)
{
ndx = resp;
for(i=0; i<MAX_IPV4_STR_LEN; i++) {
if(! isdigit(*(ndx+i)) && *(ndx+i) != '.')
break;
}
*(ndx+i) = '\0';
if((sscanf(ndx, "%u.%u.%u.%u", &o1, &o2, &o3, &o4)) == 4
&& o1 >= 0 && o1 <= 255
&& o2 >= 0 && o2 <= 255
@@ -413,7 +483,6 @@ resolve_ip_https(fko_cli_options_t *options)
return 1;
}
}
log_msg(LOG_VERBOSITY_ERROR,
"[-] Could not resolve IP via: '%s'", wget_ssl_cmd);
return -1;
+50
View File
@@ -275,4 +275,54 @@ proto_strtoint(const char *pr_str)
return proto_int;
}
int
add_argv(char **argv_new, int *argc_new,
const char *new_arg, fko_cli_options_t *opts)
{
int buf_size = 0;
if(opts->verbose > 2)
log_msg(LOG_VERBOSITY_NORMAL, "[+] add_argv() + arg: %s", new_arg);
buf_size = strlen(new_arg) + 1;
argv_new[*argc_new] = calloc(1, buf_size);
if(argv_new[*argc_new] == NULL)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] Memory allocation error.");
return 0;
}
strlcpy(argv_new[*argc_new], new_arg, buf_size);
*argc_new += 1;
if(*argc_new >= MAX_CMDLINE_ARGS-1)
{
log_msg(LOG_VERBOSITY_ERROR, "[*] max command line args exceeded.");
return 0;
}
argv_new[*argc_new] = NULL;
return 1;
}
void
free_argv(char **argv_new, int *argc_new)
{
int i;
if(argv_new == NULL || *argv_new == NULL)
return;
for (i=0; i < *argc_new; i++)
{
if(argv_new[i] == NULL)
break;
else
free(argv_new[i]);
}
return;
}
/***EOF***/
+2
View File
@@ -59,5 +59,7 @@ int verify_file_perms_ownership(const char *file);
int resolve_dest_adr(const char *dns_str, struct addrinfo *hints, char *ip_str, size_t ip_bufsize);
short proto_inttostr(int proto, char *proto_str, size_t proto_size);
short proto_strtoint(const char *pr_str);
int add_argv(char **argv_new, int *argc_new, const char *new_arg, fko_cli_options_t *opts);
void free_argv(char **argv_new, int *argc_new);
#endif /* UTILS_H */