mirror of
https://github.com/openNDS/openNDS.git
synced 2026-01-09 11:57:55 -05:00
806 lines
27 KiB
C
806 lines
27 KiB
C
/********************************************************************\
|
|
* This program is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License*
|
|
* along with this program; if not, contact: *
|
|
* *
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
|
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
|
* *
|
|
\********************************************************************/
|
|
|
|
/** @file conf.c
|
|
@brief Config file parsing
|
|
@author Copyright (C) 2004 Philippe April <papril777@yahoo.com>
|
|
@author Copyright (C) 2007 Paul Kube <nodogsplash@kokoro.ucsd.edu>
|
|
@author Copyright (C) 2015-2025 Modifications and additions by BlueWave Projects and Services <opennds@blue-wave.net>
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <syslog.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <sys/stat.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/ether.h>
|
|
|
|
#include "common.h"
|
|
#include "safe.h"
|
|
#include "debug.h"
|
|
#include "conf.h"
|
|
#include "auth.h"
|
|
#include "util.h"
|
|
#include "http_microhttpd_utils.h"
|
|
#include "fw_iptables.h"
|
|
#include "commandline.h"
|
|
|
|
/** @internal
|
|
* Holds the current configuration of the gateway */
|
|
static s_config config = {{0}};
|
|
|
|
/**
|
|
* Mutex for the configuration file, used by the auth_servers related
|
|
* functions. */
|
|
pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
/** Accessor for the current gateway configuration
|
|
@return: A pointer to the current config. The pointer isn't opaque, but should be treated as READ-ONLY
|
|
*/
|
|
s_config *
|
|
config_get_config(void)
|
|
{
|
|
return &config;
|
|
}
|
|
|
|
char *set_list_str(char *list, const char *default_list, char *debug_level)
|
|
{
|
|
char msg[MID_BUF];
|
|
char debuglevel[STATUS_BUF];
|
|
|
|
memset(msg, 0, MID_BUF);
|
|
memset(debuglevel, 0, STATUS_BUF);
|
|
|
|
get_list_from_config(msg, MID_BUF, list);
|
|
|
|
if (strcmp(msg, "") == 0) {
|
|
|
|
if (strcmp(debug_level, "3") == 0 || (strcmp(debug_level, "2") == 0)) {
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_INFO, "list %s is [ %s ]", list, default_list);
|
|
closelog ();
|
|
}
|
|
|
|
return strdup(default_list);
|
|
} else {
|
|
|
|
if (strcmp(debug_level, "3") == 0 || (strcmp(debug_level, "2") == 0)) {
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_INFO, "list %s is [ %s ]", list, msg);
|
|
closelog ();
|
|
}
|
|
|
|
return safe_strdup(msg);
|
|
}
|
|
}
|
|
|
|
char *set_option_str(char *option, const char *default_option, char *debug_level)
|
|
{
|
|
char msg[SMALL_BUF];
|
|
|
|
memset(msg, 0, SMALL_BUF);
|
|
get_option_from_config(msg, SMALL_BUF, option);
|
|
|
|
if (strcmp(msg, "") == 0) {
|
|
|
|
if (strcmp(debug_level, "3") == 0 || (strcmp(debug_level, "2") == 0)) {
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_INFO, "option %s is [ %s ]", option, default_option);
|
|
closelog ();
|
|
}
|
|
|
|
return strdup(default_option);
|
|
} else {
|
|
|
|
if (strcmp(debug_level, "3") == 0 || (strcmp(debug_level, "2") == 0)) {
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_INFO, "option %s is [ %s ]", option, msg);
|
|
closelog ();
|
|
}
|
|
|
|
return safe_strdup(msg);
|
|
}
|
|
}
|
|
|
|
|
|
// Sets the default config parameters and initialises the configuration system
|
|
void
|
|
config_init(int argc, char **argv)
|
|
{
|
|
const char *gatewayname;
|
|
char *gatewayname_raw;
|
|
char *libcmd;
|
|
char *setupcmd;
|
|
char debug_level[STATUS_BUF];
|
|
char *msg;
|
|
FILE *fd;
|
|
char *lockfile;
|
|
|
|
// Check if nodogsplash is installed. If it is, issue a warning and exit
|
|
libcmd = safe_calloc(STATUS_BUF);
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
safe_snprintf(libcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh \"is_nodog\"");
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, libcmd) == 0) {
|
|
debug(LOG_DEBUG, "NoDogSplash is installed, to continue please uninstall it and restart openNDS, exiting.....");
|
|
exit (1);
|
|
}
|
|
|
|
free(libcmd);
|
|
free(msg);
|
|
|
|
// get configured debuglevel
|
|
memset(debug_level, 0, STATUS_BUF);
|
|
get_option_from_config(debug_level, STATUS_BUF, "debuglevel");
|
|
|
|
// Are we enabled?
|
|
config.debuglevel = 1;
|
|
sscanf(set_option_str("enabled", DEFAULT_ENABLED, debug_level), "%u", &config.enabled);
|
|
|
|
if(config.enabled != 1) {
|
|
debug(LOG_NOTICE, "openNDS is disabled (see \"option enabled\" in config).\n");
|
|
exit(0);
|
|
}
|
|
|
|
//parse_commandline(argc, argv);
|
|
strncpy(config.configfile, DEFAULT_CONFIGFILE, sizeof(config.configfile)-1);
|
|
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_NOTICE, "openNDS Version %s is in startup\n", VERSION);
|
|
closelog ();
|
|
|
|
printf ("openNDS Version %s is in startup - Please wait....\n", VERSION);
|
|
|
|
// get configured debuglevel
|
|
memset(debug_level, 0, STATUS_BUF);
|
|
get_option_from_config(debug_level, STATUS_BUF, "debuglevel");
|
|
|
|
/*
|
|
********** String config parameters **********
|
|
*/
|
|
|
|
// Special handling for gatewayname as library call returns a url-encoded response
|
|
gatewayname_raw = safe_calloc(SMALL_BUF);
|
|
gatewayname = set_option_str("gatewayname", DEFAULT_GATEWAYNAME, debug_level);
|
|
uh_urldecode(gatewayname_raw, SMALL_BUF, gatewayname, strlen(gatewayname));
|
|
config.gw_name = safe_strdup(gatewayname_raw);
|
|
|
|
openlog ("opennds", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
|
syslog (LOG_NOTICE, "The name of this gateway is %s", gatewayname_raw);
|
|
closelog ();
|
|
|
|
free(gatewayname_raw);
|
|
//
|
|
|
|
config.gw_fqdn = set_option_str("gatewayfqdn", DEFAULT_GATEWAYFQDN, debug_level);
|
|
config.status_path = set_option_str("statuspath", DEFAULT_STATUSPATH, debug_level);
|
|
config.gw_interface = set_option_str("gatewayinterface", DEFAULT_GATEWAYINTERFACE, debug_level);
|
|
config.gw_iprange = set_option_str("gateway_iprange", DEFAULT_GATEWAY_IPRANGE, debug_level);
|
|
config.fas_key = set_option_str("faskey", DEFAULT_FASKEY, debug_level);
|
|
config.log_mountpoint = set_option_str("log_mountpoint", DEFAULT_LOG_MOUNTPOINT, debug_level);
|
|
config.webroot = set_option_str("webroot", DEFAULT_WEBROOT, debug_level);
|
|
config.authdir = set_option_str("authdir", DEFAULT_AUTHDIR, debug_level);
|
|
config.denydir = set_option_str("denydir", DEFAULT_DENYDIR, debug_level);
|
|
config.preauthdir = set_option_str("preauthdir", DEFAULT_PREAUTHDIR, debug_level);
|
|
config.ndsctl_sock = set_option_str("ndsctl_sock", DEFAULT_NDSCTL_SOCK, debug_level);
|
|
config.authentication_mark = set_option_str("authentication_mark", DEFAULT_AUTHENTICATION_MARK, debug_level);
|
|
// Setting binauth in config is deprecated. Use DEFAULT_BINAUTH only.
|
|
config.binauth = set_option_str("binauth_deprecated", DEFAULT_BINAUTH, "0");
|
|
config.custombinauth = set_option_str("custombinauth", DEFAULT_CUSTOMBINAUTH, debug_level);
|
|
config.fas_path = set_option_str("faspath", DEFAULT_FASPATH, debug_level);
|
|
config.themespec_path = set_option_str("themespec_path", DEFAULT_THEMESPEC_PATH, debug_level);
|
|
config.fas_remoteip = set_option_str("fasremoteip", DEFAULT_FAS_REMOTEIP, debug_level);
|
|
config.fas_remotefqdn = set_option_str("fasremotefqdn", DEFAULT_FAS_REMOTEFQDN, debug_level);
|
|
config.fas_ssl = set_option_str("fas_ssl", DEFAULT_FAS_SSL, debug_level);
|
|
|
|
/*
|
|
********** Integer config parameters **********
|
|
*/
|
|
|
|
// Special handling of debuglevel - check valid level and inform externals
|
|
sscanf(set_option_str("debuglevel", DEFAULT_DEBUGLEVEL, debug_level), "%u", &config.debuglevel);
|
|
|
|
if (config.debuglevel > DEBUGLEVEL_MAX) {
|
|
config.debuglevel = DEBUGLEVEL_MAX;
|
|
}
|
|
|
|
libcmd = safe_calloc(STATUS_BUF);
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
safe_snprintf(libcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh \"debuglevel\" \"%u\"", config.debuglevel);
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, libcmd) == 0) {
|
|
debug(LOG_DEBUG, "debuglevel [%u] signaled to externals - [%s] acknowledged", config.debuglevel, msg);
|
|
} else {
|
|
debug(LOG_ERR, "debuglevel [%u] signaled to externals - unable to set", config.debuglevel);
|
|
}
|
|
|
|
free(libcmd);
|
|
free(msg);
|
|
//
|
|
|
|
sscanf(set_option_str("sessiontimeout", DEFAULT_SESSIONTIMEOUT, debug_level), "%u", &config.sessiontimeout);
|
|
sscanf(set_option_str("preauthidletimeout", DEFAULT_PREAUTH_IDLE_TIMEOUT, debug_level), "%u", &config.preauth_idle_timeout);
|
|
sscanf(set_option_str("authidletimeout", DEFAULT_AUTH_IDLE_TIMEOUT, debug_level), "%u", &config.auth_idle_timeout);
|
|
sscanf(set_option_str("maxclients", DEFAULT_MAXCLIENTS, debug_level), "%u", &config.maxclients);
|
|
sscanf(set_option_str("enable_serial_number_suffix", DEFAULT_ENABLE_SERIAL_NUMBER_SUFFIX, debug_level), "%u", &config.enable_serial_number_suffix);
|
|
sscanf(set_option_str("dhcp_default_url_enable", DEFAULT_DHCP_DEFAULT_URL_ENABLE, debug_level), "%u", &config.dhcp_default_url_enable);
|
|
sscanf(set_option_str("gatewayport", DEFAULT_GATEWAYPORT, debug_level), "%u", &config.gw_port);
|
|
sscanf(set_option_str("fasport", DEFAULT_FASPORT, debug_level), "%u", &config.fas_port);
|
|
sscanf(set_option_str("login_option_enabled", DEFAULT_LOGIN_OPTION_ENABLED, debug_level), "%u", &config.login_option_enabled);
|
|
sscanf(set_option_str("use_outdated_mhd", DEFAULT_USE_OUTDATED_MHD, debug_level), "%u", &config.use_outdated_mhd);
|
|
sscanf(set_option_str("max_page_size", DEFAULT_MAX_PAGE_SIZE, debug_level), "%llu", &config.max_page_size);
|
|
sscanf(set_option_str("max_log_entries", DEFAULT_MAX_LOG_ENTRIES, debug_level), "%llu", &config.max_log_entries);
|
|
sscanf(set_option_str("allow_preemptive_authentication", DEFAULT_ALLOW_PREEMPTIVE_AUTHENTICATION, debug_level), "%u", &config.allow_preemptive_authentication);
|
|
sscanf(set_option_str("fas_secure_enabled", DEFAULT_FAS_SECURE_ENABLED, debug_level), "%u", &config.fas_secure_enabled);
|
|
sscanf(set_option_str("remotes_refresh_interval", DEFAULT_REMOTES_REFRESH_INTERVAL, debug_level), "%u", &config.remotes_refresh_interval);
|
|
sscanf(set_option_str("checkinterval", DEFAULT_CHECKINTERVAL, debug_level), "%u", &config.checkinterval);
|
|
sscanf(set_option_str("ratecheckwindow", DEFAULT_RATE_CHECK_WINDOW, debug_level), "%u", &config.rate_check_window);
|
|
sscanf(set_option_str("uploadrate", DEFAULT_UPLOAD_RATE, debug_level), "%llu", &config.upload_rate);
|
|
sscanf(set_option_str("downloadrate", DEFAULT_DOWNLOAD_RATE, debug_level), "%llu", &config.download_rate);
|
|
sscanf(set_option_str("download_bucket_ratio", DEFAULT_DOWNLOAD_BUCKET_RATIO, debug_level), "%llu", &config.download_bucket_ratio);
|
|
sscanf(set_option_str("max_download_bucket_size", DEFAULT_MAX_DOWNLOAD_BUCKET_SIZE, debug_level), "%llu", &config.max_download_bucket_size);
|
|
sscanf(set_option_str("download_unrestricted_bursting", DEFAULT_DOWNLOAD_UNRESTRICTED_BURSTING, debug_level), "%u", &config.download_unrestricted_bursting);
|
|
sscanf(set_option_str("upload_bucket_ratio", DEFAULT_UPLOAD_BUCKET_RATIO, debug_level), "%llu", &config.upload_bucket_ratio);
|
|
sscanf(set_option_str("max_upload_bucket_size", DEFAULT_MAX_UPLOAD_BUCKET_SIZE, debug_level), "%llu", &config.max_upload_bucket_size);
|
|
sscanf(set_option_str("upload_unrestricted_bursting", DEFAULT_UPLOAD_UNRESTRICTED_BURSTING, debug_level), "%u", &config.upload_unrestricted_bursting);
|
|
sscanf(set_option_str("uploadquota", DEFAULT_UPLOAD_QUOTA, debug_level), "%llu", &config.upload_quota);
|
|
sscanf(set_option_str("downloadquota", DEFAULT_DOWNLOAD_QUOTA, debug_level), "%llu", &config.download_quota);
|
|
sscanf(set_option_str("fup_upload_throttle_rate", DEFAULT_FUP_UPLOAD_THROTTLE_RATE, debug_level), "%llu", &config.fup_upload_throttle_rate);
|
|
sscanf(set_option_str("fup_download_throttle_rate", DEFAULT_FUP_DOWNLOAD_THROTTLE_RATE, debug_level), "%llu", &config.fup_download_throttle_rate);
|
|
sscanf(set_option_str("fw_mark_authenticated", DEFAULT_FW_MARK_AUTHENTICATED, debug_level), "%x", &config.fw_mark_authenticated);
|
|
sscanf(set_option_str("fw_mark_auth_blocked", DEFAULT_FW_MARK_AUTH_BLOCKED, debug_level), "%x", &config.fw_mark_auth_blocked);
|
|
sscanf(set_option_str("fw_mark_trusted", DEFAULT_FW_MARK_TRUSTED, debug_level), "%x", &config.fw_mark_trusted);
|
|
|
|
// config.ip6 = DEFAULT_IP6;
|
|
|
|
// Parameters kept in config but have no default or config value
|
|
config.gw_address = NULL;
|
|
config.gw_ip = NULL;
|
|
config.http_encoded_gw_name = NULL;
|
|
config.url_encoded_gw_name = NULL;
|
|
config.fas_url = NULL;
|
|
config.fas_hid = NULL;
|
|
config.custom_params = NULL;
|
|
config.custom_vars = NULL;
|
|
config.custom_images = NULL;
|
|
config.custom_files = NULL;
|
|
config.tmpfsmountpoint = NULL;
|
|
config.preauth = NULL;
|
|
config.lockfd = 0;
|
|
config.online_status = 0;
|
|
|
|
// Lists
|
|
parse_trusted_mac_list(set_list_str("trustedmac", DEFAULT_TRUSTEDMACLIST, debug_level));
|
|
parse_fas_custom_parameters_list(set_list_str("fas_custom_parameters_list", DEFAULT_FAS_CUSTOM_PARAMETERS_LIST, debug_level));
|
|
parse_fas_custom_images_list(set_list_str("fas_custom_images_list", DEFAULT_FAS_CUSTOM_IMAGES_LIST, debug_level));
|
|
parse_fas_custom_files_list(set_list_str("fas_custom_files_list", DEFAULT_FAS_CUSTOM_FILES_LIST, debug_level));
|
|
|
|
// Before we do anything else, reset the firewall (cleans it, in case we are restarting or after an opennds crash)
|
|
iptables_fw_destroy();
|
|
|
|
// Call the pre setup library function to create the base nttables ruleset
|
|
setupcmd = safe_calloc(STATUS_BUF);
|
|
safe_snprintf(setupcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh \"pre_setup\"");
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, setupcmd) == 0) {
|
|
debug(LOG_INFO, "Pre-Setup request sent");
|
|
}
|
|
|
|
free(setupcmd);
|
|
free(msg);
|
|
|
|
// If we don't have the Gateway IP address, get it. Exit on failure.
|
|
if (!config.gw_ip) {
|
|
debug(LOG_DEBUG, "Finding IP address of %s", config.gw_interface);
|
|
config.gw_ip = get_iface_ip(config.gw_interface, config.ip6);
|
|
|
|
if (is_addr(config.gw_ip) != 1) {
|
|
debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config.gw_interface);
|
|
exit(1);
|
|
} else {
|
|
debug(LOG_NOTICE, "Interface %s is up", config.gw_interface);
|
|
}
|
|
}
|
|
|
|
// format gw_address accordingly depending on if gw_ip is v4 or v6
|
|
const char *ipfmt = config.ip6 ? "[%s]:%d" : "%s:%d";
|
|
safe_asprintf(&config.gw_address, ipfmt, config.gw_ip, config.gw_port);
|
|
|
|
config.gw_mac = get_iface_mac(config.gw_interface);
|
|
|
|
if (strcmp(config.gw_mac, "00:00:00:00:00:00") == 0 || config.gw_mac == NULL) {
|
|
debug(LOG_ERR, "Could not get MAC address information of %s, exiting...", config.gw_interface);
|
|
exit(1);
|
|
}
|
|
|
|
debug(LOG_NOTICE, "Interface %s is at %s (%s)", config.gw_interface, config.gw_ip, config.gw_mac);
|
|
|
|
// Generate a unique faskey if not set in config
|
|
if (strcmp(config.fas_key, DEFAULT_FASKEY) == 0) {
|
|
setupcmd = safe_calloc(STATUS_BUF);
|
|
safe_snprintf(setupcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh \"generate_key\"");
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, setupcmd) == 0) {
|
|
config.fas_key = safe_strdup(msg);
|
|
}
|
|
|
|
free(setupcmd);
|
|
free(msg);
|
|
|
|
setupcmd = safe_calloc(SMALL_BUF);
|
|
safe_snprintf(setupcmd, SMALL_BUF, "/usr/lib/opennds/libopennds.sh \"set_key\" \"%s\"", config.fas_key);
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, setupcmd) == 0) {
|
|
debug(LOG_NOTICE, "faskey generated");
|
|
}
|
|
|
|
free(setupcmd);
|
|
free(msg);
|
|
}
|
|
|
|
// Clean up any old database files and set some needed parameters
|
|
libcmd = safe_calloc(STATUS_BUF);
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
safe_snprintf(libcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh clean");
|
|
|
|
execute_ret_url_encoded(msg, STATUS_BUF, libcmd);
|
|
free(libcmd);
|
|
|
|
if (strlen(msg) == 0) {
|
|
config.tmpfsmountpoint = safe_strdup("/tmp");
|
|
} else {
|
|
config.tmpfsmountpoint = safe_strdup(msg);
|
|
}
|
|
|
|
free(msg);
|
|
lockfile = safe_calloc(STATUS_BUF);
|
|
safe_snprintf(lockfile, STATUS_BUF, "%s/ndsctl.lock", config.tmpfsmountpoint);
|
|
|
|
//Remove ndsctl lock file if it exists
|
|
if ((fd = fopen(lockfile, "r")) != NULL) {
|
|
fclose(fd);
|
|
remove(lockfile);
|
|
}
|
|
|
|
free (lockfile);
|
|
}
|
|
|
|
// Parse a string to see if it is valid decimal dotted quad IP V4 format
|
|
int check_ip_format(const char *possibleip)
|
|
{
|
|
unsigned char buf[sizeof(struct in6_addr)];
|
|
return inet_pton(AF_INET, possibleip, buf) > 0;
|
|
}
|
|
|
|
// Parse a string to see if it is valid MAC address format
|
|
int check_mac_format(const char possiblemac[])
|
|
{
|
|
return ether_aton(possiblemac) != NULL;
|
|
}
|
|
|
|
int add_to_fas_custom_parameters_list(const char possibleparam[])
|
|
{
|
|
char param[512];
|
|
t_FASPARAM *p = NULL;
|
|
|
|
sscanf(possibleparam, "%s", param);
|
|
|
|
// Add Parameter to head of list
|
|
p = safe_calloc(sizeof(t_FASPARAM));
|
|
p->fasparam = safe_strdup(param);
|
|
p->next = config.fas_custom_parameters_list;
|
|
|
|
config.fas_custom_parameters_list = p;
|
|
debug(LOG_INFO, "Added Custom Parameter [%s]", possibleparam);
|
|
return 0;
|
|
}
|
|
|
|
int add_to_fas_custom_variables_list(const char possiblevar[])
|
|
{
|
|
char var[512];
|
|
t_FASVAR *p = NULL;
|
|
|
|
sscanf(possiblevar, "%s", var);
|
|
|
|
// Add Variable to head of list
|
|
p = safe_calloc(sizeof(t_FASVAR));
|
|
p->fasvar = safe_strdup(var);
|
|
p->next = config.fas_custom_variables_list;
|
|
|
|
config.fas_custom_variables_list = p;
|
|
debug(LOG_INFO, "Added Custom Variable [%s]", possiblevar);
|
|
return 0;
|
|
}
|
|
|
|
int add_to_fas_custom_images_list(const char possibleimage[])
|
|
{
|
|
char image[512];
|
|
t_FASIMG *p = NULL;
|
|
|
|
sscanf(possibleimage, "%s", image);
|
|
|
|
// Add Image to head of list
|
|
p = safe_calloc(sizeof(t_FASIMG));
|
|
p->fasimg = safe_strdup(image);
|
|
p->next = config.fas_custom_images_list;
|
|
|
|
config.fas_custom_images_list = p;
|
|
debug(LOG_INFO, "Added Custom Image [%s]", possibleimage);
|
|
return 0;
|
|
}
|
|
|
|
int add_to_fas_custom_files_list(const char possiblefile[])
|
|
{
|
|
char file[512];
|
|
t_FASFILE *p = NULL;
|
|
|
|
sscanf(possiblefile, "%s", file);
|
|
|
|
// Add File to head of list
|
|
p = safe_calloc(sizeof(t_FASFILE));
|
|
p->fasfile = safe_strdup(file);
|
|
p->next = config.fas_custom_files_list;
|
|
|
|
config.fas_custom_files_list = p;
|
|
debug(LOG_INFO, "Added Custom File [%s]", possiblefile);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int add_to_trusted_mac_list(const char possiblemac[])
|
|
{
|
|
char mac[18];
|
|
t_MAC *p = NULL;
|
|
|
|
// check for valid format
|
|
if (!check_mac_format(possiblemac)) {
|
|
debug(LOG_WARNING, "[%s] is not a valid MAC address", possiblemac);
|
|
debug(LOG_WARNING, "[%s] - please remove from trustedmac list in config file", possiblemac);
|
|
return 1;
|
|
}
|
|
|
|
sscanf(possiblemac, "%17[A-Fa-f0-9:]", mac);
|
|
|
|
// See if MAC is already on the list; don't add duplicates
|
|
for (p = config.trustedmaclist; p != NULL; p = p->next) {
|
|
if (!strcasecmp(p->mac, mac)) {
|
|
debug(LOG_INFO, "MAC address [%s] already on trusted list", mac);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Add MAC to head of list
|
|
p = safe_calloc(sizeof(t_MAC));
|
|
p->mac = safe_strdup(mac);
|
|
p->next = config.trustedmaclist;
|
|
config.trustedmaclist = p;
|
|
debug(LOG_INFO, "Added MAC address [%s] to trusted list", mac);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Remove given MAC address from the config's trusted mac list.
|
|
* Return 0 on success, nonzero on failure
|
|
*/
|
|
int remove_from_trusted_mac_list(const char possiblemac[])
|
|
{
|
|
char mac[18];
|
|
t_MAC **p = NULL;
|
|
t_MAC *del = NULL;
|
|
|
|
// check for valid format
|
|
if (!check_mac_format(possiblemac)) {
|
|
debug(LOG_ERR, "[%s] not a valid MAC address", possiblemac);
|
|
return -1;
|
|
}
|
|
|
|
sscanf(possiblemac, "%17[A-Fa-f0-9:]", mac);
|
|
|
|
// If empty list, nothing to do
|
|
if (config.trustedmaclist == NULL) {
|
|
debug(LOG_INFO, "MAC address [%s] not on empty trusted list", mac);
|
|
return -1;
|
|
}
|
|
|
|
// Find MAC on the list, remove it
|
|
for (p = &(config.trustedmaclist); *p != NULL; p = &((*p)->next)) {
|
|
if (!strcasecmp((*p)->mac, mac)) {
|
|
// found it
|
|
del = *p;
|
|
*p = del->next;
|
|
debug(LOG_INFO, "Removed MAC address [%s] from trusted list", mac);
|
|
free(del);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// MAC was not on list
|
|
debug(LOG_INFO, "MAC address [%s] not on trusted list", mac);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* Given a pointer to a comma or whitespace delimited sequence of
|
|
* MAC addresses, add each MAC address to config.trustedmaclist.
|
|
*/
|
|
void parse_trusted_mac_list(const char ptr[])
|
|
{
|
|
char *ptrcopy = NULL, *ptrcopyptr;
|
|
char *possiblemac = NULL;
|
|
|
|
// strsep modifies original, so let's make a copy
|
|
ptrcopyptr = ptrcopy = safe_strdup(ptr);
|
|
|
|
while ((possiblemac = strsep(&ptrcopy, ", \t"))) {
|
|
if (strlen(possiblemac) > 0) {
|
|
if (add_to_trusted_mac_list(possiblemac) < 0) {
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
free(ptrcopy);
|
|
free(ptrcopyptr);
|
|
}
|
|
|
|
int is_trusted_mac(const char *mac)
|
|
{
|
|
s_config *config;
|
|
t_MAC *trust_mac;
|
|
|
|
config = config_get_config();
|
|
|
|
// Is a client even recognized here?
|
|
for (trust_mac = config->trustedmaclist; trust_mac != NULL; trust_mac = trust_mac->next) {
|
|
if (!strcmp(trust_mac->mac, mac)) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Given a pointer to a comma or whitespace delimited sequence of
|
|
* Custom FAS Parameters, add each parameter to config.fas_custom_parameters_list
|
|
*/
|
|
void parse_fas_custom_parameters_list(const char ptr[])
|
|
{
|
|
char *ptrcopy = NULL;
|
|
char *possibleparam = NULL;
|
|
char msg[512] = {0};
|
|
char *cmd = NULL;
|
|
char possibleparam_urlencoded[512] = {0};
|
|
|
|
// strsep modifies original, so let's make a copy
|
|
ptrcopy = safe_strdup(ptr);
|
|
|
|
while ((possibleparam = strsep(&ptrcopy, ", \t"))) {
|
|
if (strlen(possibleparam) > 0) {
|
|
|
|
// URL encode Parameter before parsing
|
|
memset(possibleparam_urlencoded, 0, sizeof(possibleparam_urlencoded));
|
|
uh_urlencode(possibleparam_urlencoded, sizeof(possibleparam_urlencoded), possibleparam, strlen(possibleparam));
|
|
debug(LOG_DEBUG, "[%s] is the urlencoded Custom FAS Parameter", possibleparam_urlencoded);
|
|
|
|
safe_asprintf(&cmd,
|
|
"echo \"%s\" | awk -F'%s' 'NF>1 && $1!=\"\" && $2!=\"\" {printf \"%s\",$0}'",
|
|
possibleparam_urlencoded,
|
|
CUSTOM_SEPARATOR,
|
|
FORMAT_SPECIFIER
|
|
);
|
|
debug(LOG_DEBUG, "Parse command [%s]", cmd);
|
|
memset(msg, 0, sizeof(msg));
|
|
execute_ret_url_encoded(msg, sizeof(msg) - 1, cmd);
|
|
free(cmd);
|
|
if (strcmp(msg, possibleparam_urlencoded) == 0) {
|
|
debug(LOG_INFO, "Adding parameter [%s] [%s]", possibleparam, msg);
|
|
add_to_fas_custom_parameters_list(possibleparam);
|
|
} else {
|
|
debug(LOG_WARNING, "Invalid Custom Parameter [%s] [%s] - skipping", possibleparam, msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Given a pointer to a comma or whitespace delimited sequence of
|
|
* Custom FAS Variables, add each parameter to config.fas_custom_variables_list
|
|
*/
|
|
void parse_fas_custom_variables_list(const char ptr[])
|
|
{
|
|
char *ptrcopy = NULL;
|
|
char *possiblevar = NULL;
|
|
char msg[512] = {0};
|
|
char *cmd = NULL;
|
|
char possiblevar_urlencoded[512] = {0};
|
|
|
|
debug(LOG_INFO, "Parsing list [%s] for Custom FAS Variables", ptr);
|
|
|
|
// strsep modifies original, so let's make a copy
|
|
ptrcopy = safe_strdup(ptr);
|
|
|
|
while ((possiblevar = strsep(&ptrcopy, ", \t"))) {
|
|
if (strlen(possiblevar) > 0) {
|
|
|
|
// URL encode Variable before parsing
|
|
memset(possiblevar_urlencoded, 0, sizeof(possiblevar_urlencoded));
|
|
uh_urlencode(possiblevar_urlencoded, sizeof(possiblevar_urlencoded), possiblevar, strlen(possiblevar));
|
|
debug(LOG_DEBUG, "[%s] is the urlencoded Custom FAS Variable", possiblevar_urlencoded);
|
|
|
|
safe_asprintf(&cmd,
|
|
"echo \"%s\" | awk -F'%s' 'NF>1 && $1!=\"\" && $2!=\"\" {printf \"%s\",$0}'",
|
|
possiblevar_urlencoded,
|
|
CUSTOM_SEPARATOR,
|
|
FORMAT_SPECIFIER
|
|
);
|
|
debug(LOG_DEBUG, "Parse command [%s]", cmd);
|
|
memset(msg, 0, sizeof(msg));
|
|
execute_ret_url_encoded(msg, sizeof(msg) - 1, cmd);
|
|
free(cmd);
|
|
if (strcmp(msg, possiblevar_urlencoded) == 0) {
|
|
debug(LOG_INFO, "Adding variable [%s] [%s]", possiblevar, msg);
|
|
add_to_fas_custom_variables_list(possiblevar);
|
|
} else {
|
|
debug(LOG_WARNING, "Invalid Custom Variable [%s] [%s] - skipping", possiblevar, msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Given a pointer to a comma or whitespace delimited sequence of
|
|
* Custom FAS Images, add each image to config.fas_custom_images_list
|
|
*/
|
|
void parse_fas_custom_images_list(const char ptr[])
|
|
{
|
|
char *ptrcopy = NULL;
|
|
char *possibleimage = NULL;
|
|
char msg[512] = {0};
|
|
char *cmd = NULL;
|
|
char possibleimage_urlencoded[512] = {0};
|
|
|
|
debug(LOG_INFO, "Parsing list [%s] for Custom FAS Images", ptr);
|
|
|
|
// strsep modifies original, so let's make a copy
|
|
ptrcopy = safe_strdup(ptr);
|
|
|
|
while ((possibleimage = strsep(&ptrcopy, ", \t"))) {
|
|
if (strlen(possibleimage) > 0) {
|
|
|
|
// URL encode Image before parsing
|
|
memset(possibleimage_urlencoded, 0, sizeof(possibleimage_urlencoded));
|
|
uh_urlencode(possibleimage_urlencoded, sizeof(possibleimage_urlencoded), possibleimage, strlen(possibleimage));
|
|
debug(LOG_DEBUG, "[%s] is the urlencoded Custom FAS Image", possibleimage_urlencoded);
|
|
|
|
safe_asprintf(&cmd,
|
|
"echo \"%s\" | awk -F'%s' 'NF>1 && $1!=\"\" && $2!=\"\" {printf \"%s\",$0}'",
|
|
possibleimage_urlencoded,
|
|
CUSTOM_SEPARATOR,
|
|
FORMAT_SPECIFIER
|
|
);
|
|
debug(LOG_DEBUG, "Parse command [%s]", cmd);
|
|
memset(msg, 0, sizeof(msg));
|
|
execute_ret_url_encoded(msg, sizeof(msg) - 1, cmd);
|
|
free(cmd);
|
|
if (strcmp(msg, possibleimage_urlencoded) == 0) {
|
|
debug(LOG_INFO, "Adding image [%s] [%s]", possibleimage, msg);
|
|
add_to_fas_custom_images_list(possibleimage);
|
|
} else {
|
|
debug(LOG_WARNING, "Invalid Custom Image [%s] [%s] - skipping", possibleimage, msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Given a pointer to a comma or whitespace delimited sequence of
|
|
* Custom FAS Files, add each image to config.fas_custom_files_list
|
|
*/
|
|
void parse_fas_custom_files_list(const char ptr[])
|
|
{
|
|
char *ptrcopy = NULL;
|
|
char *possiblefile = NULL;
|
|
char msg[512] = {0};
|
|
char *cmd = NULL;
|
|
char possiblefile_urlencoded[512] = {0};
|
|
|
|
debug(LOG_INFO, "Parsing list [%s] for Custom FAS Files", ptr);
|
|
|
|
// strsep modifies original, so let's make a copy
|
|
ptrcopy = safe_strdup(ptr);
|
|
|
|
while ((possiblefile = strsep(&ptrcopy, ", \t"))) {
|
|
if (strlen(possiblefile) > 0) {
|
|
|
|
// URL encode Image before parsing
|
|
memset(possiblefile_urlencoded, 0, sizeof(possiblefile_urlencoded));
|
|
uh_urlencode(possiblefile_urlencoded, sizeof(possiblefile_urlencoded), possiblefile, strlen(possiblefile));
|
|
debug(LOG_DEBUG, "[%s] is the urlencoded Custom FAS Image", possiblefile_urlencoded);
|
|
|
|
safe_asprintf(&cmd,
|
|
"echo \"%s\" | awk -F'%s' 'NF>1 && $1!=\"\" && $2!=\"\" {printf \"%s\",$0}'",
|
|
possiblefile_urlencoded,
|
|
CUSTOM_SEPARATOR,
|
|
FORMAT_SPECIFIER
|
|
);
|
|
debug(LOG_DEBUG, "Parse command [%s]", cmd);
|
|
memset(msg, 0, sizeof(msg));
|
|
execute_ret_url_encoded(msg, sizeof(msg) - 1, cmd);
|
|
free(cmd);
|
|
if (strcmp(msg, possiblefile_urlencoded) == 0) {
|
|
debug(LOG_INFO, "Adding file [%s] [%s]", possiblefile, msg);
|
|
add_to_fas_custom_files_list(possiblefile);
|
|
} else {
|
|
debug(LOG_WARNING, "Invalid Custom File [%s] [%s] - skipping", possiblefile, msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Set the debug log level. See syslog.h
|
|
* Return 0 on success.
|
|
*/
|
|
int set_debuglevel(const char opt[])
|
|
{
|
|
char *libcmd;
|
|
char *msg;
|
|
|
|
if (opt == NULL || strlen(opt) == 0) {
|
|
return 1;
|
|
}
|
|
|
|
// parse number
|
|
int level = strtol(opt, NULL, 10);
|
|
|
|
|
|
if (level >= (int) DEBUGLEVEL_MIN && level <= (int) DEBUGLEVEL_MAX) {
|
|
msg = safe_calloc(STATUS_BUF);
|
|
|
|
sscanf(opt, "%u", &config.debuglevel);
|
|
|
|
libcmd = safe_calloc(STATUS_BUF);
|
|
safe_snprintf(libcmd, STATUS_BUF, "/usr/lib/opennds/libopennds.sh \"debuglevel\" \"%s\"", opt);
|
|
|
|
if (execute_ret_url_encoded(msg, STATUS_BUF - 1, libcmd) == 0) {
|
|
debug(LOG_DEBUG, "debuglevel [%d] signaled to externals - [%s] acknowledged", level, msg);
|
|
} else {
|
|
debug(LOG_ERR, "debuglevel [%d] signaled to externals - unable to set", level);
|
|
}
|
|
|
|
free(libcmd);
|
|
free(msg);
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|