Esempio n. 1
0
/**
 * Check that an argument is a valid file path by
 * - solving the path
 * - ensuring result is read accessible
 *
 * @param param is the parameter to validate
 * @return the real (no symlink) full path of the file it is valid
 * @return NULL in any other case
 */
static char* cfg_get_valid_file(char* param)
{
        char buf[PATH_MAX+1]={0, };

        if (!realpath(param, buf)){
                xlog(LOG_CRITICAL, "realpath(%s) failed: %s\n", param, strerror(errno));
                return NULL;
        }

        if ( !is_readable_file(buf) ){
                xlog(LOG_CRITICAL, "Failed to read private key '%s'\n", param);
                return NULL;
        }

        return proxenet_xstrdup2(buf);
}
Esempio n. 2
0
/**
 * Checks command line arguments once and for all. Handles (de)allocation for config_t structure
 *
 * @return 0 if successfully parsed and allocated
 * @return -1
 */
static int parse_options (int argc, char** argv)
{
        int curopt, curopt_idx;
        char *logfile, *plugin_path;
        char *keyfile, *keyfile_pwd, *certfile;
        char *sslcli_keyfile, *sslcli_keyfile_pwd, *sslcli_certfile, *sslcli_domain;
        char *proxy_host, *proxy_port;
        char *intercept_pattern;
        bool use_socks_proxy;

        proxy_host = proxy_port = NULL;
        use_socks_proxy = false;

        const struct option long_opts[]  = {
                { "version",                           0, 0, 'V' },
                { "help",                              0, 0, 'h' },
                { "verbose",                           0, 0, 'v' },
                { "daemon",                            0, 0, 'd' },
                { "no-color",                          0, 0, 'n' },
                { "plugins",                           1, 0, 'x' },
                { "logfile",                           1, 0, 'l' },

                { "intercept-only",                    0, 0, 'E' },
                { "intercept-except",                  0, 0, 'I' },
                { "match",                             1, 0, 'm' },

                { "nb-threads",                        1, 0, 't' },
                { "bind",                              1, 0, 'b' },
                { "port",                              1, 0, 'p' },
                { "proxy-host",                        1, 0, 'X' },
                { "proxy-port",                        1, 0, 'P' },
                { "use-socks",                         0, 0, 'D' },

                { "certfile",                          1, 0, 'c' },
                { "keyfile",                           1, 0, 'k' },
                { "keyfile-passphrase",                1, 0, 'K' },

                { "sslcli-certfile",                   1, 0, 'z' },
                { "sslcli-domain",                     1, 0, 'Z' },
                { "sslcli-keyfile",                    1, 0, 'y' },
                { "sslcli-keyfile-passphrase",         1, 0, 'Y' },

                { "ie-compat",                         0, 0, 'i'},
                { "no-ssl-intercept",                  0, 0, 'N'},

                { 0, 0, 0, 0 }
        };

        cfg->iface		= CFG_DEFAULT_BIND_ADDR;
        cfg->port		= CFG_DEFAULT_BIND_PORT;
        cfg->logfile_fd		= CFG_DEFAULT_OUTPUT;
        cfg->nb_threads		= CFG_DEFAULT_NB_THREAD;
        cfg->use_color		= true;
        cfg->ip_version		= CFG_DEFAULT_IP_VERSION;
        cfg->try_exit		= 0;
        cfg->try_exit_max	= CFG_DEFAULT_TRY_EXIT_MAX;
        cfg->daemon		= false;

        cfg->intercept_mode	= INTERCEPT_ONLY;
        intercept_pattern	= CFG_DEFAULT_INTERCEPT_PATTERN;

        plugin_path		= CFG_DEFAULT_PLUGINS_PATH;
        logfile			= NULL;

        certfile		= CFG_DEFAULT_SSL_CERTFILE;
        keyfile			= CFG_DEFAULT_SSL_KEYFILE;
        keyfile_pwd		= CFG_DEFAULT_SSL_KEYFILE_PWD;

        cfg->certsdir		= CFG_DEFAULT_SSL_CERTSDIR;
        cfg->certskey		= CFG_DEFAULT_SSL_CERTSKEY;
        cfg->certskey_pwd	= CFG_DEFAULT_SSL_CERTSPWD;

        sslcli_certfile		= NULL;
        sslcli_domain		= CFG_DEFAULT_SSL_CLIENT_DOMAIN;
        sslcli_keyfile		= NULL;
        sslcli_keyfile_pwd	= CFG_DEFAULT_SSL_KEYFILE_PWD;

        cfg->ie_compat          = false;
        cfg->ssl_intercept      = true;


        /* parse command line arguments */
        while (1) {
                curopt_idx = 0;
                curopt = getopt_long (argc,argv,
                                      "dn46Vhvb:p:l:t:c:k:K:x:X:P:z:y:Y:IEm:NiD",
                                      long_opts, &curopt_idx);
                if (curopt == -1) break;

                switch (curopt) {
                        case 'v': cfg->verbose++; break;
                        case 'b': cfg->iface = optarg; break;
                        case 'p': cfg->port = optarg; break;
                        case 'l': logfile = optarg; break;
                        case 't': cfg->nb_threads = (unsigned short)atoi(optarg); break;
                        case 'X':
                                proxy_host = optarg;
                                proxy_port = CFG_DEFAULT_PROXY_PORT;
                                break;
                        case 'P': proxy_port = optarg; break;
                        case 'D': use_socks_proxy = true; break;
                        case 'c': certfile = optarg; break;
                        case 'k': keyfile = optarg; break;
                        case 'K': keyfile_pwd = optarg; break;
                        case 'h': help(); break;
                        case 'V': version(true); break;
                        case 'n': cfg->use_color = false; break;
                        case '4': cfg->ip_version = AF_INET; break;
                        case '6': cfg->ip_version = AF_INET6; break;
                        case 'x': plugin_path = optarg; break;
                        case 'd': cfg->daemon = true; break;
                        case 'I': cfg->intercept_mode = INTERCEPT_ONLY; break;
                        case 'E': cfg->intercept_mode = INTERCEPT_EXCEPT; break;
                        case 'm': intercept_pattern = optarg; break;
                        case 'z': sslcli_certfile = optarg; break;
                        case 'Z': sslcli_domain = optarg; break;
                        case 'y': sslcli_keyfile = optarg; break;
                        case 'Y': sslcli_keyfile_pwd = optarg; break;
                        case 'N': cfg->ssl_intercept = false; break;
                        case 'i':
                                cfg->ie_compat = true;
                                xlog(LOG_WARNING, "%s\n", "Enabling IE compatibility mode.");
                                xlog(LOG_WARNING, "%s\n", "This mode should not be used with anything but IE <10.");
                                break;

                        case '?':
                        default:
                                usage (EXIT_FAILURE);
                }
                curopt_idx = 0;
        }

        /* validate command line arguments */

        /* logfile validation : if a logfile is given, use its FILE* for output */
        if (logfile) {
                cfg->logfile = realpath(logfile, NULL);
                if (cfg->logfile == NULL){
                        xlog(LOG_CRITICAL, "realpath(logfile) failed: %s\n", strerror(errno));
                        return -1;
                }
                if(is_readable_file(cfg->logfile)) {
                        cfg->logfile_fd = fopen(cfg->logfile, "w");
                        if(!cfg->logfile_fd) {
                                cfg->logfile_fd = stderr;
                                xlog(LOG_CRITICAL, "[-] Failed to open '%s': %s\n", cfg->logfile, strerror(errno));
                                return -1;
                        }
                }
        }

        /* check if nb of threads is in boundaries */
        if (cfg->nb_threads > MAX_THREADS) {
                fprintf(stderr, "Thread number invalid. Setting to default.\n");
                cfg->nb_threads = CFG_DEFAULT_NB_THREAD;
        }

        /* setting the interception mode */
        cfg->intercept_pattern = proxenet_xstrdup2(intercept_pattern);
        if(!cfg->intercept_pattern)
                return -1;

        if(cfg->verbose) {
                switch(cfg->intercept_mode){
                        case INTERCEPT_ONLY:
                                xlog(LOG_INFO, "Intercepting only matching '%s'\n", cfg->intercept_pattern);
                                break;
                        case INTERCEPT_EXCEPT:
                                xlog(LOG_INFO, "Intercepting everything except matching '%s'\n", cfg->intercept_pattern);
                                break;
                }
        }


        /* check plugins path */
        if (!is_valid_plugin_path(plugin_path, &cfg->plugins_path, &cfg->autoload_path))
                return -1;

#ifdef DEBUG
        xlog(LOG_DEBUG, "Valid plugin tree for '%s' and '%s'\n", cfg->plugins_path, cfg->autoload_path);
#endif

        /* validate proxenet SSL configuration for interception */
        /* check ssl certificate */
        cfg->cafile = cfg_get_valid_file(certfile);
        if (!cfg->cafile)
                return -1;
        /* check ssl key */
        cfg->keyfile = cfg_get_valid_file(keyfile);
        if (!cfg->cafile)
                return -1;
        /* get the key passphrase */
        cfg->keyfile_pwd = proxenet_xstrdup2(keyfile_pwd);
        if (!cfg->keyfile_pwd)
                return -1;

        /* validate proxenet client certificate paramaters */
        /* check ssl client certificate if provided */
        if (sslcli_certfile && sslcli_keyfile) {
                cfg->sslcli_certfile = cfg_get_valid_file(sslcli_certfile);
                if (!cfg->sslcli_certfile)
                        return -1;
                /* check ssl private key associated with the client certificate */
                cfg->sslcli_keyfile = cfg_get_valid_file(sslcli_keyfile);
                if (!cfg->sslcli_keyfile)
                        return -1;
                /* get the key passphrase */
                cfg->sslcli_keyfile_pwd = proxenet_xstrdup2(sslcli_keyfile_pwd);
                if (!cfg->sslcli_keyfile_pwd)
                        return -1;
                /* get the domain */
                cfg->sslcli_domain = proxenet_xstrdup2(sslcli_domain);
                if(!cfg->sslcli_domain)
                        return -1;
        }

        /* check proxy values (if any) */
        if ( proxy_port && !proxy_host) {
                xlog(LOG_CRITICAL, "%s\n", "Cannot use proxy-port without proxy-host");
                return -1;
        }

        if (proxy_host) {
                cfg->proxy.host = proxenet_xstrdup2(proxy_host);
                if (!cfg->proxy.host) {
                        xlog(LOG_CRITICAL, "proxy %s\n", strerror(errno));
                        return -1;
                }

                cfg->proxy.port = proxenet_xstrdup2(proxy_port);
                if (!cfg->proxy.port) {
                        xlog(LOG_CRITICAL, "proxy_port %s\n", strerror(errno));
                        return -1;
                }

                if (use_socks_proxy)
                        cfg->is_socks_proxy = true;
        }

        /* become a daemon */
        if(cfg->daemon) {
                if (cfg->verbose){
                        xlog(LOG_WARNING, "%s will now run as daemon\n", PROGNAME);
                        xlog(LOG_WARNING, "%s\n", "Use `control-client.py' to interact with the process.");
                }

                if (daemon(0, 0) < 0) {
                        xlog(LOG_ERROR, "daemon failed: %s\n", strerror(errno));
                        return -1;
                }

                cfg->verbose = 0;
        }

        return 0;

}
Esempio n. 3
0
/**
 * Checks command line arguments once and for all. Handles (de)allocation for config_t structure
 *
 * @return 0 if successfully parsed and allocated
 * @return -1
 */
int parse_options (int argc, char** argv)
{
	int curopt, curopt_idx;
	char *logfile, *path, *keyfile, *certfile;
	char *proxy_host, *proxy_port;

	proxy_host = proxy_port = NULL;
	
	const struct option long_opts[] = {
		{ "help",       0, 0, 'h' },
		{ "verbose",    0, 0, 'v' },
		{ "nb-threads", 1, 0, 't' },
		{ "lbind",      1, 0, 'b' },
		{ "lport",      1, 0, 'p' },
		{ "logfile",    1, 0, 'l' },
		{ "certfile",   1, 0, 'c' },
		{ "keyfile",    1, 0, 'k' },
		{ "plugins",    1, 0, 'x' },
		{ "proxy-host", 1, 0, 'X' },
		{ "proxy-port", 1, 0, 'P' },
		{ "no-color",   0, 0, 'n' },
		{ "version",    0, 0, 'V' },
		{ 0, 0, 0, 0 } 
	};
	
	cfg->iface		= CFG_DEFAULT_BIND_ADDR;
	cfg->port		= CFG_DEFAULT_PORT;
	cfg->logfile_fd		= CFG_DEFAULT_OUTPUT;
	cfg->nb_threads		= CFG_DEFAULT_NB_THREAD;
	cfg->use_color		= true;
	cfg->ip_version		= CFG_DEFAULT_IP_VERSION;
	cfg->try_exit		= 0;
	cfg->try_exit_max	= CFG_DEFAULT_TRY_EXIT_MAX;
	
	path			= CFG_DEFAULT_PLUGINS_PATH;
	keyfile			= CFG_DEFAULT_SSL_KEYFILE;
	certfile		= CFG_DEFAULT_SSL_CERTFILE;
	logfile			= NULL;
	
	/* parse command line arguments */
	while (1) {
		curopt = -1;
		curopt_idx = 0;
		curopt = getopt_long (argc,argv,"n46Vhvb:p:l:t:c:k:x:X:P:",long_opts, &curopt_idx);
		if (curopt == -1) break;
		
		switch (curopt) {
			case 'v': cfg->verbose++; break;
			case 'b': cfg->iface = optarg; break;
			case 'p': cfg->port = optarg; break;
			case 'l': logfile = optarg; break;
			case 't': cfg->nb_threads = (unsigned short)atoi(optarg); break;
			case 'X':
				proxy_host = optarg;
				proxy_port = CFG_DEFAULT_PROXY_PORT;
				break;
			case 'P': proxy_port = optarg; break;
			case 'c': certfile = optarg; break;
			case 'k': keyfile = optarg; break;	   
			case 'h': help(argv[0]); break;
			case 'V': version(true); break;
			case 'n': cfg->use_color = false; break;
			case '4': cfg->ip_version = AF_INET; break;
			case '6': cfg->ip_version = AF_INET6; break;
			case 'x': path = optarg; break;
			case '?':
			default:
				usage (EXIT_FAILURE);
		}
		curopt_idx = 0;
	}

	/* validate command line arguments */

	/* logfile validation : if a logfile is given, use its FILE* for output */
	if (logfile) {
		cfg->logfile = realpath(logfile, NULL);
		if (cfg->logfile == NULL){
			xlog(LOG_CRITICAL, "realpath(logfile) failed: %s\n", strerror(errno));
			return -1;
		}
		if(is_readable_file(cfg->logfile)) {
			cfg->logfile_fd = fopen(cfg->logfile, "w");
			if(!cfg->logfile_fd) {
				cfg->logfile_fd = stderr;
				xlog(LOG_CRITICAL, "[-] Failed to open '%s': %s\n", cfg->logfile, strerror(errno));
				return -1;
			}
		}
	}

	/* check if nb of threads is in boundaries */
	if (cfg->nb_threads > MAX_THREADS) {
		fprintf(stderr, "Too many threads. Setting to default.\n");
		cfg->nb_threads = CFG_DEFAULT_NB_THREAD;
	}
	
	/* check plugins path */
	cfg->plugins_path = realpath(path, NULL);
	if (cfg->plugins_path == NULL){
		xlog(LOG_CRITICAL, "realpath(plugins_path) failed: %s\n", strerror(errno));
		return -1;
	}
	if (!is_valid_path(cfg->plugins_path)) {
		xlog(LOG_CRITICAL, "%s\n", "Invalid plugins path provided");
		return -1;
	}

	/* check ssl certificate */
	cfg->certfile = realpath(certfile, NULL);
	if (cfg->certfile == NULL){
		xlog(LOG_CRITICAL, "realpath(certfile) failed: %s\n", strerror(errno));
		return -1;
	}
	if ( !is_readable_file(cfg->certfile) ) {
		xlog(LOG_CRITICAL, "Failed to read certificate '%s'\n", cfg->certfile);
		return -1;
	}

	/* check ssl key */
	cfg->keyfile = realpath(keyfile, NULL);
	if (cfg->certfile == NULL){
		xlog(LOG_CRITICAL, "realpath(certfile) failed: %s\n", strerror(errno));
		return -1;
	}
	if ( !is_readable_file(cfg->keyfile) ){
		xlog(LOG_CRITICAL, "Failed to read private key '%s'\n", cfg->keyfile);
		return -1;
	}

	/* check proxy values (if any) */
	if ( proxy_port && !proxy_host) {
		xlog(LOG_CRITICAL, "%s\n", "Cannot use proxy-port without proxy-host");
		return -1;
	}

	if (proxy_host) {
		cfg->proxy.host = strdup(proxy_host);
		if (!cfg->proxy.host) {
			xlog(LOG_CRITICAL, "proxy %s\n", strerror(errno));
			return -1;
		}

		cfg->proxy.port = strdup(proxy_port);
		if (!cfg->proxy.port) {
			xlog(LOG_CRITICAL, "proxy_port %s\n", strerror(errno));
			return -1;
		}
	}
	
	return 0;

}