X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserverconfig.c;h=911caff0dde735085b13ccc4fa628097740cbe6e;hp=f90a6938e3aefa235a4a43f28f21ab3a8745d027;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=dc44e6c61393a3f69a02e7e5c22df5e0506eb8bc diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index f90a6938..911caff0 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -21,6 +21,7 @@ #include "serverincludes.h" #include "server_internal.h" +#include #if 0 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt) @@ -92,6 +93,10 @@ my_set_param_defaults(SilcServerConfigConnParams *params, SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN); SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX); SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY); + SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT); + SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT); + SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC); + SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC); #undef SET_PARAM_DEFAULT } @@ -108,15 +113,14 @@ my_find_param(SilcServerConfig config, const char *name) } SILC_SERVER_LOG_ERROR(("Error while parsing config file: " - "Cannot find Params \"%s\".\n", name)); + "Cannot find Params \"%s\".", name)); return NULL; } /* parse an authdata according to its auth method */ -static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, - SilcUInt32 line, void **auth_data, - SilcUInt32 *auth_data_len) +static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p, + void **auth_data, SilcUInt32 *auth_data_len) { if (auth_meth == SILC_AUTH_PASSWORD) { /* p is a plain text password */ @@ -135,15 +139,25 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) { /* p is a public key file name */ SilcPublicKey public_key; + SilcPublicKey cached_key; if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM)) if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) { - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line " - "%lu: Could not load public key file!\n", - line)); + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Could not load public key file!")); return FALSE; } + if (*auth_data && + silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key, + NULL, silc_hash_public_key, NULL, + silc_hash_public_key_compare, NULL)) { + silc_pkcs_public_key_free(public_key); + SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already " + "configured, ignoring this key", p)); + return TRUE; /* non fatal error */ + } + /* The auth_data is a pointer to the hash table of public keys. */ if (auth_data) { if (*auth_data == NULL) @@ -153,11 +167,50 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, TRUE); silc_hash_table_add(*auth_data, public_key, public_key); } - } else { - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: " - "Unknown authentication method.\n", line)); + } else + abort(); + + return TRUE; +} + +static bool my_parse_publickeydir(const char *dirname, void **auth_data) +{ + int total = 0; + struct dirent *get_file; + DIR *dp; + + if (!(dp = opendir(dirname))) { + SILC_SERVER_LOG_ERROR(("Error while parsing config file: " + "Could not open directory \"%s\"", dirname)); return FALSE; } + + /* errors are not considered fatal */ + while ((get_file = readdir(dp))) { + const char *filename = get_file->d_name; + char buf[1024]; + int dirname_len = strlen(dirname), filename_len = strlen(filename); + struct stat check_file; + + /* Ignore "." and "..", and take files only with ".pub" suffix. */ + if (!strcmp(filename, ".") || !strcmp(filename, "..") || + (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub")) + continue; + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname, + (dirname[dirname_len - 1] == '/' ? "" : "/"), filename); + + if (stat(buf, &check_file) < 0) { + SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf, + strerror(errno))); + } else if (S_ISREG(check_file.st_mode)) { + my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL); + total++; + } + } + + SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname)); return TRUE; } @@ -235,6 +288,21 @@ SILC_CONFIG_CALLBACK(fetch_generic) else if (!strcmp(name, "detach_timeout")) { config->detach_timeout = (SilcUInt32) *(int *)val; } + else if (!strcmp(name, "qos")) { + config->param.qos = *(bool *)val; + } + else if (!strcmp(name, "qos_rate_limit")) { + config->param.qos_rate_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_bytes_limit")) { + config->param.qos_bytes_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_sec")) { + config->param.qos_limit_sec = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_usec")) { + config->param.qos_limit_usec = *(SilcUInt32 *)val; + } else return SILC_CONFIG_EINTERNAL; @@ -466,7 +534,7 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface); if ((port <= 0) || (port > 65535)) { SILC_SERVER_LOG_ERROR(("Error while parsing config file: " - "Invalid port number!\n")); + "Invalid port number!")); got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } @@ -506,28 +574,28 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo) } else if (!strcmp(name, "publickey")) { char *file_tmp = (char *) val; + CONFIG_IS_DOUBLE(server_info->public_key); /* try to load specified file, if fail stop config parsing */ if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key, SILC_PKCS_FILE_PEM)) if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key, SILC_PKCS_FILE_BIN)) { - SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n")); - SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp)); - return SILC_CONFIG_ESILENT; + SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.")); + return SILC_CONFIG_EPRINTLINE; } } else if (!strcmp(name, "privatekey")) { char *file_tmp = (char *) val; + CONFIG_IS_DOUBLE(server_info->private_key); /* try to load specified file, if fail stop config parsing */ if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key, - SILC_PKCS_FILE_BIN)) + "", 0, SILC_PKCS_FILE_BIN)) if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key, - SILC_PKCS_FILE_PEM)) { - SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n")); - SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp)); - return SILC_CONFIG_ESILENT; + "", 0, SILC_PKCS_FILE_PEM)) { + SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.")); + return SILC_CONFIG_EPRINTLINE; } } else @@ -556,7 +624,7 @@ SILC_CONFIG_CALLBACK(fetch_logging) if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */ SILC_SERVER_LOG_ERROR(("Error while parsing config file: " "Invalid flushdelay value, use quicklogs if you " - "want real-time logging.\n")); + "want real-time logging.")); return SILC_CONFIG_EPRINTLINE; } config->logging_flushdelay = (long) flushdelay; @@ -674,6 +742,21 @@ SILC_CONFIG_CALLBACK(fetch_connparam) else if (!strcmp(name, "anonymous")) { tmp->anonymous = *(bool *)val; } + else if (!strcmp(name, "qos")) { + tmp->qos = *(bool *)val; + } + else if (!strcmp(name, "qos_rate_limit")) { + tmp->qos_rate_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_bytes_limit")) { + tmp->qos_bytes_limit = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_sec")) { + tmp->qos_limit_sec = *(SilcUInt32 *)val; + } + else if (!strcmp(name, "qos_limit_usec")) { + tmp->qos_limit_usec = *(SilcUInt32 *)val; + } else return SILC_CONFIG_EINTERNAL; @@ -710,17 +793,23 @@ SILC_CONFIG_CALLBACK(fetch_client) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; + } + } + else if (!strcmp(name, "publickeydir")) { + if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) { + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -776,18 +865,23 @@ SILC_CONFIG_CALLBACK(fetch_admin) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { - CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; + goto got_err; + } + } + else if (!strcmp(name, "publickeydir")) { + if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) { + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -872,18 +966,18 @@ SILC_CONFIG_CALLBACK(fetch_server) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -936,7 +1030,7 @@ SILC_CONFIG_CALLBACK(fetch_router) int port = *(int *)val; if ((port <= 0) || (port > 65535)) { SILC_SERVER_LOG_ERROR(("Error while parsing config file: " - "Invalid port number!\n")); + "Invalid port number!")); got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } @@ -944,18 +1038,18 @@ SILC_CONFIG_CALLBACK(fetch_router) } else if (!strcmp(name, "passphrase")) { CONFIG_IS_DOUBLE(tmp->passphrase); - if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, (void **)&tmp->passphrase, &tmp->passphrase_len)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } else if (!strcmp(name, "publickey")) { CONFIG_IS_DOUBLE(tmp->publickeys); - if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line, + if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, (void **)&tmp->publickeys, NULL)) { - got_errno = SILC_CONFIG_ESILENT; + got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } } @@ -980,7 +1074,7 @@ SILC_CONFIG_CALLBACK(fetch_router) int port = *(int *)val; if ((port <= 0) || (port > 65535)) { SILC_SERVER_LOG_ERROR(("Error while parsing config file: " - "Invalid port number!\n")); + "Invalid port number!")); got_errno = SILC_CONFIG_EPRINTLINE; goto got_err; } @@ -1025,6 +1119,11 @@ static const SilcConfigTable table_general[] = { { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL }, { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, + { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { 0, 0, 0, 0 } }; @@ -1113,6 +1212,11 @@ static const SilcConfigTable table_connparam[] = { { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL }, { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL }, { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL }, + { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL }, + { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, + { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL }, { 0, 0, 0, 0 } }; @@ -1120,6 +1224,7 @@ static const SilcConfigTable table_client[] = { { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL }, + { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL }, { 0, 0, 0, 0 } }; @@ -1130,6 +1235,7 @@ static const SilcConfigTable table_admin[] = { { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL }, { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, + { "publickeydir", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL }, { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL }, { 0, 0, 0, 0 } @@ -1164,11 +1270,11 @@ static const SilcConfigTable table_routerconn[] = { }; static const SilcConfigTable table_main[] = { - { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general }, { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher }, { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash }, { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac }, { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs }, + { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general }, { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo }, { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging }, { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam }, @@ -1197,6 +1303,82 @@ static void silc_server_config_set_defaults(SilcServerConfig config) SILC_SERVER_CONNAUTH_TIMEOUT); } +/* Check for correctness of the configuration */ + +static bool silc_server_config_check(SilcServerConfig config) +{ + bool ret = TRUE; + SilcServerConfigServer *s; + SilcServerConfigRouter *r; + bool b = FALSE; + + /* ServerConfig is mandatory */ + if (!config->server_info) { + SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `ServerInfo'")); + ret = FALSE; + } + + /* RouterConnection sanity checks */ + + if (config->routers && config->routers->backup_router == TRUE && + !config->servers) { + SILC_SERVER_LOG_ERROR(( + "\nError: First RouterConnection block must be primary router " + "connection. You have marked it incorrectly as backup router.")); + ret = FALSE; + } + if (config->routers && config->routers->initiator == FALSE && + config->routers->backup_router == FALSE) { + SILC_SERVER_LOG_ERROR(( + "\nError: First RouterConnection block must be primary router " + "connection and it must be marked as Initiator.")); + ret = FALSE; + } + if (config->routers && config->routers->backup_router == TRUE && + !config->servers && !config->routers->next) { + SILC_SERVER_LOG_ERROR(( + "\nError: You have configured backup router but not primary router. " + "If backup router is configured also primary router must be " + "configured.")); + ret = FALSE; + } + + /* Backup router sanity checks */ + + for (r = config->routers; r; r = r->next) { + if (r->backup_router && !strcmp(r->host, r->backup_replace_ip)) { + SILC_SERVER_LOG_ERROR(( + "\nError: Backup router connection incorrectly configured to use " + "primary and backup router as same host `%s'. They must not be " + "same host.", r->host)); + ret = FALSE; + } + } + + /* ServerConnection sanity checks */ + + for (s = config->servers; s; s = s->next) { + if (s->backup_router) { + b = TRUE; + break; + } + } + if (b) { + for (s = config->servers; s; s = s->next) { + if (!s->backup_router) { + SILC_SERVER_LOG_ERROR(( + "\nError: Your server is backup router but not all ServerConnection " + "blocks were marked as backup connections. They all must be " + "marked as backup connections.")); + ret = FALSE; + break; + } + } + } + + return ret; +} + /* Allocates a new configuration object, opens configuration file and parses it. The parsed data is returned to the newly allocated configuration object. The SilcServerConfig must be freed by calling @@ -1212,17 +1394,17 @@ SilcServerConfig silc_server_config_alloc(const char *filename) /* alloc a config object */ config_new = silc_calloc(1, sizeof(*config_new)); - config_new->refcount = 1; if (!config_new) return NULL; /* general config defaults */ + config_new->refcount = 1; config_new->logging_timestamp = TRUE; /* obtain a config file object */ file = silc_config_open(filename); if (!file) { - SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", + SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'", filename)); return NULL; } @@ -1246,12 +1428,14 @@ SilcServerConfig silc_server_config_alloc(const char *filename) char *linebuf, *filename = silc_config_get_filename(file); SilcUInt32 line = silc_config_get_line(file); if (ret != SILC_CONFIG_EPRINTLINE) - SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n", + SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.", silc_config_strerror(ret))); linebuf = silc_config_read_line(file, line); - SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename, - line, linebuf)); - silc_free(linebuf); + if (linebuf) { + SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename, + line, linebuf)); + silc_free(linebuf); + } } silc_server_config_destroy(config_new); return NULL; @@ -1260,10 +1444,8 @@ SilcServerConfig silc_server_config_alloc(const char *filename) /* close (destroy) the file object */ silc_config_close(file); - /* If config_new is incomplete, abort the object and return NULL */ - if (!config_new->server_info) { - SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block " - "`server_info'\n")); + /* Check the configuration */ + if (!silc_server_config_check(config_new)) { silc_server_config_destroy(config_new); return NULL; } @@ -1502,6 +1684,7 @@ bool silc_server_config_register_ciphers(SilcServer server) silc_free(alg_name); } else { SILC_LOG_ERROR(("Error configuring ciphers")); + silc_sim_free(sim); silc_server_stop(server); exit(1); } @@ -1585,6 +1768,7 @@ bool silc_server_config_register_hashfuncs(SilcServer server) silc_dlist_add(server->sim, sim); } else { SILC_LOG_ERROR(("Error configuring hash functions")); + silc_sim_free(sim); silc_server_stop(server); exit(1); }