/* !DO NOT ALTER FUNCTION SIGNATURE! */
int callback_n_netopeer_n_tls_n_trusted_ca_certs_n_trusted_ca_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) {
	char* content = NULL;

	if (op & (XMLDIFF_REM | XMLDIFF_MOD)) {
		content = get_node_content(old_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		if (del_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0) != 0) {
			nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__);
		} else {
			netopeer_options.tls_opts->tls_ctx_change_flag = 1;
		}

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) {
		content = get_node_content(new_node);
		if (content == NULL) {
			*error = nc_err_new(NC_ERR_OP_FAILED);
			nc_verb_error("%s: node content missing", __func__);
			return EXIT_FAILURE;
		}

		/* TLS_CTX LOCK */
		pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock);

		add_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0);
		netopeer_options.tls_opts->tls_ctx_change_flag = 1;

		/* TLS_CTX UNLOCK */
		pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock);
	}

	return EXIT_SUCCESS;
}
Esempio n. 2
0
int main(int argc, char **argv)
{
	int ret = EXIT_FAILURE;
	struct vpn_config cfg;
	char *config_file = "/etc/openfortivpn/config";
	char *host, *username = NULL, *password = NULL;
	char *port_str;
	long int port;

	init_logging();

	// Set defaults
	init_vpn_config(&cfg);
	cfg.set_routes = 1;
	cfg.set_dns = 1;
	cfg.verify_cert = 1;
	cfg.insecure_ssl = 0;
	cfg.pppd_use_peerdns = 1;

	struct option long_options[] = {
		{"help",            no_argument,       0, 'h'},
		{"version",         no_argument,       0, 0},
		{"config",          required_argument, 0, 'c'},
		{"realm",           required_argument, 0, 0},
		{"username",        required_argument, 0, 'u'},
		{"password",        required_argument, 0, 'p'},
		{"no-routes",       no_argument, &cfg.set_routes, 0},
		{"no-dns",          no_argument, &cfg.set_dns, 0},
		{"pppd-no-peerdns", no_argument, &cfg.pppd_use_peerdns, 0},
		{"ca-file",         required_argument, 0, 0},
		{"user-cert",       required_argument, 0, 0},
		{"user-key",        required_argument, 0, 0},
		{"trusted-cert",    required_argument, 0, 0},
		{"insecure-ssl",    no_argument, &cfg.insecure_ssl, 1},
		{"cipher-list",     required_argument, 0, 0},
		{"pppd-log",        required_argument, 0, 0},
		{"pppd-plugin",     required_argument, 0, 0},
		{"plugin",          required_argument, 0, 0}, // deprecated
		{0, 0, 0, 0}
	};

	while (1) {
		/* getopt_long stores the option index here. */
		int c, option_index = 0;

		c = getopt_long(argc, argv, "hvqc:u:p:",
		                long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		switch (c) {
		case 0:
			/* If this option set a flag, do nothing else now. */
			if (long_options[option_index].flag != 0)
				break;
			if (strcmp(long_options[option_index].name,
			           "version") == 0) {
				printf(VERSION "\n");
				ret = EXIT_SUCCESS;
				goto exit;
			}
			if (strcmp(long_options[option_index].name,
			           "pppd-log") == 0) {
				cfg.pppd_log = optarg;
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "pppd-plugin") == 0) {
				cfg.pppd_plugin = optarg;
				break;
			}
			// --plugin is deprecated, --pppd-plugin should be used
			if (cfg.pppd_plugin == NULL &&
			    strcmp(long_options[option_index].name,
			           "plugin") == 0) {
				cfg.pppd_plugin = optarg;
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "ca-file") == 0) {
				cfg.ca_file = strdup(optarg);
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "user-cert") == 0) {
				cfg.user_cert = strdup(optarg);
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "user-key") == 0) {
				cfg.user_key = strdup(optarg);
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "realm") == 0) {
				strncpy(cfg.realm, optarg, FIELD_SIZE);
				cfg.realm[FIELD_SIZE] = '\0';
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "trusted-cert") == 0) {
				if (add_trusted_cert(&cfg, optarg))
					log_warn("Could not add certificate "
					         "digest to whitelist.\n");
				break;
			}
			if (strcmp(long_options[option_index].name,
			           "cipher-list") == 0) {
				cfg.cipher_list = strdup(optarg);
				break;
			}
			goto user_error;
		case 'h':
			printf(HELP);
			ret = EXIT_SUCCESS;
			goto exit;
		case 'v':
			increase_verbosity();
			break;
		case 'q':
			decrease_verbosity();
			break;
		case 'c':
			config_file = optarg;
			break;
		case 'u':
			username = optarg;
			break;
		case 'p':
			password = optarg;
			break;
		default:
			goto user_error;
		}
	}

	if (optind < argc - 1 || optind > argc)
		goto user_error;

	if (password != NULL)
		log_warn("You should not pass the password on the command "
		         "line. Type it interactively or use a config file "
		         "instead.\n");

	// Load config file
	if (config_file[0] != '\0') {
		ret = load_config(&cfg, config_file);
		if (ret == 0)
			log_debug("Loaded config file \"%s\".\n", config_file);
		else
			log_warn("Could not load config file \"%s\" (%s).\n",
			         config_file, err_cfg_str(ret));
	}

	// Read host and port from the command line
	if (optind == argc - 1) {
		host = argv[optind++];
		port_str = strchr(host, ':');
		if (port_str == NULL) {
			log_error("Specify a valid host:port couple.\n");
			goto user_error;
		}
		port_str[0] = '\0';
		strncpy(cfg.gateway_host, host, FIELD_SIZE);
		cfg.gateway_host[FIELD_SIZE] = '\0';
		port_str++;
		port = strtol(port_str, NULL, 0);
		if (port <= 0 || port > 65535) {
			log_error("Specify a valid port.\n");
			goto user_error;
		}
		cfg.gateway_port = port;
	}
	// Read username and password from the command line
	if (username != NULL) {
		strncpy(cfg.username, username, FIELD_SIZE);
		cfg.username[FIELD_SIZE] = '\0';
	}
	if (password != NULL) {
		strncpy(cfg.password, password, FIELD_SIZE);
		cfg.password[FIELD_SIZE] = '\0';
	}

	// Check host and port
	if (cfg.gateway_host[0] == '\0' || cfg.gateway_port == 0) {
		log_error("Specify a valid host:port couple.\n");
		goto user_error;
	}
	// Check username
	if (cfg.username[0] == '\0') {
		log_error("Specify an username.\n");
		goto user_error;
	}
	// If no password given, interactively ask user
	if (cfg.password[0] == '\0')
		read_password("VPN account password: "******"Specify a password.\n");
		goto user_error;
	}

	log_debug("Config host = \"%s\"\n", cfg.gateway_host);
	log_debug("Config realm = \"%s\"\n", cfg.realm);
	log_debug("Config port = \"%d\"\n", cfg.gateway_port);
	log_debug("Config username = \"%s\"\n", cfg.username);
	log_debug("Config password = \"%s\"\n", "********");

	if (geteuid() != 0)
		log_warn("This process was not spawned with root "
		         "privileges, this will probably not work.\n");

	if (run_tunnel(&cfg) == 0)
		ret = EXIT_SUCCESS;
	goto exit;

user_error:
	fprintf(stderr, USAGE);
exit:
	destroy_vpn_config(&cfg);
	exit(ret);
}