use execvpe() with NULL env for wget calls
This commit is contained in:
+9
-31
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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***/
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user