#include "serverincludes.h"
#include "server_internal.h"
-/* XXX
- All possible configuration sections for SILC server.
-
- <Cipher>
-
- Format:
-
- +<Cipher name>:<SIM path>
-
- <PKCS>
-
- Format:
-
- +<PKCS name>:<key length>
-
- <HashFunction>
-
- Format:
-
- +<Hash function name>:<SIM path>
-
- <ServerInfo>
-
- This section is used to set the server informations.
-
- Format:
-
- +<Server DNS name>:<Server IP>:<Geographic location>:<Port>
-
- <AdminInfo>
-
- This section is used to set the server's administrative information.
-
- Format:
-
- +<Location>:<Server type>:<Admin's name>:<Admin's email address>
-
- <ListenPort>
-
- This section is used to set ports the server is listenning.
-
- Format:
-
- +<Local IP/UNIX socket path>:<Remote IP>:<Port>
-
- <Identity>
-
- This section is used to set both the user and group which silcd
- sets itself upon starting.
-
- Format:
-
- <user>:<group>
-
- <Logging>
-
- This section is used to set various logging files, their paths
- and maximum sizes. All the other directives except those defined
- below are ignored in this section. Log files are purged after they
- reach the maximum set byte size.
-
- Format:
-
- +infologfile:<path>:<max byte size>
- +errorlogfile:<path>:<max byte size>
-
- <ConnectionClass>
-
- This section is used to define connection classes. These can be
- used to optimize the server and the connections.
-
- Format:
-
- +<Class number>:<Ping freq>:<Connect freq>:<Max links>
-
- <ClientAuth>
-
- This section is used to define client authentications.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/cert/key/???>:<Port>:<Class>
-
- <AdminAuth>
-
- This section is used to define the server's administration
- authentications.
-
- Format:
-
- +<Hostname>:<auth method>:<password/cert/key/???>:<Nickname hash>:<Class>
-
- <ServerConnection>
-
- This section is used to define the server connections to this
- server/router. Only routers can have normal server connections.
- Normal servers leave this section epmty. The remote server cannot be
- older than specified Version ID.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/key/???>:<Port>:<Version ID>:<Class>
-
- <RouterConnection>
-
- This section is used to define the router connections to this
- server/router. Both normal server and router can have router
- connections. Normal server usually has only one connection while
- a router can have multiple. The remote server cannot be older than
- specified Version ID.
-
- Format:
-
- +<Remote address or name>:<auth method>:<password/key/???>:
- <Port>:<Version ID>:<Class>:<Initiator>
-
- <DenyConnection>
-
- This section is used to deny specific connections to your server. This
- can be used to deny both clients and servers.
-
- Format:
-
- +<Remote address or name or nickname>:<Time interval>:<Comment>:<Port>
-
- <RedirectClient>
-
- This section is used to set the alternate servers that clients will be
- redirected to when our server is full.
-
- Format:
-
- +<Remote address or name>:<Port>
-
-*/
SilcServerConfigSection silc_server_config_sections[] = {
{ "[Cipher]",
SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
{ "[PKCS]",
SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 2 },
- { "[HashFunction]",
+ { "[Hash]",
SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
+ { "[hmac]",
+ SILC_CONFIG_SERVER_SECTION_TYPE_HMAC, 3 },
{ "[ServerInfo]",
SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, 4 },
{ "[AdminInfo]",
SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION, 5 },
{ "[DenyConnection]",
SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION, 4 },
- { "[RedirectClient]",
- SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT, 2 },
{ "[motd]",
SILC_CONFIG_SERVER_SECTION_TYPE_MOTD, 1 },
silc_free(config->servers);
silc_free(config->routers);
silc_free(config->denied);
- silc_free(config->redirect);
silc_free(config->motd);
silc_free(config);
}
int silc_server_config_parse(SilcServerConfig config, SilcBuffer buffer,
SilcServerConfigParse *return_config)
{
- int i, begin;
- unsigned int linenum;
+ int i, begin, linenum;
char line[1024], *cp;
SilcServerConfigSection *cptr = NULL;
SilcServerConfigParse parse = *return_config, first = NULL;
SilcServerConfigParse parse_config)
{
int ret, check = FALSE;
- unsigned int checkmask;
+ uint32 checkmask;
char *tmp;
SilcServerConfigParse pc = parse_config;
SilcBuffer line;
if (ret < 0)
break;
- /* Get block length */
+ /* Get key length */
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
break;
if (ret == 0) {
- fprintf(stderr, "%s:%d: Cipher block length not defined\n",
+ fprintf(stderr, "%s:%d: Cipher key length not defined\n",
config->filename, pc->linenum);
break;
}
- config->cipher->block_len = atoi(tmp);
+ config->cipher->key_len = atoi(tmp);
silc_free(tmp);
- /* Get key length */
+ /* Get block length */
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
break;
if (ret == 0) {
- fprintf(stderr, "%s:%d: Cipher key length not defined\n",
+ fprintf(stderr, "%s:%d: Cipher block length not defined\n",
config->filename, pc->linenum);
break;
}
- config->cipher->key_len = atoi(tmp);
+ config->cipher->block_len = atoi(tmp);
silc_free(tmp);
check = TRUE;
checkmask |= (1L << pc->section->type);
break;
+ case SILC_CONFIG_SERVER_SECTION_TYPE_HMAC:
+
+ SILC_SERVER_CONFIG_LIST_ALLOC(config->hmac);
+
+ /* Get HMAC name */
+ ret = silc_config_get_token(line, &config->hmac->alg_name);
+ if (ret < 0)
+ break;
+ if (ret == 0) {
+ fprintf(stderr, "%s:%d: HMAC name not defined\n",
+ config->filename, pc->linenum);
+ break;
+ }
+
+ /* Get hash name */
+ ret = silc_config_get_token(line, &config->hmac->sim_name);
+ if (ret < 0)
+ break;
+ if (ret == 0) {
+ fprintf(stderr, "%s:%d: Hash function name not defined\n",
+ config->filename, pc->linenum);
+ break;
+ }
+
+ /* Get MAC length */
+ ret = silc_config_get_token(line, &tmp);
+ if (ret < 0)
+ break;
+ if (ret == 0) {
+ fprintf(stderr, "%s:%d: HMAC's MAC length not defined\n",
+ config->filename, pc->linenum);
+ break;
+ }
+ config->hmac->key_len = atoi(tmp);
+ silc_free(tmp);
+
+ check = TRUE;
+ checkmask |= (1L << pc->section->type);
+ break;
+
case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO:
if (!config->server_info)
}
/* Get authentication data */
- ret = silc_config_get_token(line, &config->clients->auth_data);
+ ret = silc_config_get_token(line, (char **)&config->clients->auth_data);
if (ret < 0)
break;
- if (ret == 0)
- /* Any host */
- config->clients->host = strdup("*");
+
+ if (config->clients->auth_meth == SILC_AUTH_PASSWORD) {
+ config->clients->auth_data_len = strlen(config->clients->auth_data);
+ } else if (config->clients->auth_meth == SILC_AUTH_PUBLIC_KEY) {
+ /* Get the public key */
+ SilcPublicKey public_key;
+
+ if (!silc_pkcs_load_public_key(config->clients->auth_data,
+ &public_key, SILC_PKCS_FILE_PEM))
+ if (!silc_pkcs_load_public_key(config->clients->auth_data,
+ &public_key, SILC_PKCS_FILE_BIN)) {
+ fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
+ config->filename, pc->linenum,
+ (char *)config->clients->auth_data);
+ break;
+ }
+
+ silc_free(config->clients->auth_data);
+ config->clients->auth_data = (void *)public_key;
+ config->clients->auth_data_len = 0;
+ }
/* Get port */
ret = silc_config_get_token(line, &tmp);
}
/* Get authentication data */
- ret = silc_config_get_token(line, &config->servers->auth_data);
+ ret = silc_config_get_token(line, (char **)&config->servers->auth_data);
if (ret < 0)
break;
+ if (config->servers->auth_meth == SILC_AUTH_PASSWORD) {
+ config->servers->auth_data_len = strlen(config->servers->auth_data);
+ } else if (config->servers->auth_meth == SILC_AUTH_PUBLIC_KEY) {
+ /* Get the public key */
+ SilcPublicKey public_key;
+
+ if (!silc_pkcs_load_public_key(config->servers->auth_data,
+ &public_key, SILC_PKCS_FILE_PEM))
+ if (!silc_pkcs_load_public_key(config->servers->auth_data,
+ &public_key, SILC_PKCS_FILE_BIN)) {
+ fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
+ config->filename, pc->linenum,
+ (char *)config->servers->auth_data);
+ break;
+ }
+
+ silc_free(config->servers->auth_data);
+ config->servers->auth_data = (void *)public_key;
+ config->servers->auth_data_len = 0;
+ }
+
/* Get port */
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
}
/* Get authentication data */
- ret = silc_config_get_token(line, &config->routers->auth_data);
+ ret = silc_config_get_token(line, (char **)&config->routers->auth_data);
if (ret < 0)
break;
+ if (config->routers->auth_meth == SILC_AUTH_PASSWORD) {
+ config->routers->auth_data_len = strlen(config->routers->auth_data);
+ } else if (config->routers->auth_meth == SILC_AUTH_PUBLIC_KEY) {
+ /* Get the public key */
+ SilcPublicKey public_key;
+
+ if (!silc_pkcs_load_public_key(config->routers->auth_data,
+ &public_key, SILC_PKCS_FILE_PEM))
+ if (!silc_pkcs_load_public_key(config->routers->auth_data,
+ &public_key, SILC_PKCS_FILE_BIN)) {
+ fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
+ config->filename, pc->linenum,
+ (char *)config->routers->auth_data);
+ break;
+ }
+
+ silc_free(config->routers->auth_data);
+ config->routers->auth_data = (void *)public_key;
+ config->routers->auth_data_len = 0;
+ }
+
/* Get port */
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
/* Any host */
config->admins->host = strdup("*");
+ /* Get username */
+ ret = silc_config_get_token(line, &config->admins->username);
+ if (ret < 0)
+ break;
+ if (ret == 0)
+ /* Any username */
+ config->admins->username = strdup("*");
+
+ /* Get nickname */
+ ret = silc_config_get_token(line, &config->admins->nickname);
+ if (ret < 0)
+ break;
+ if (ret == 0)
+ /* Any nickname */
+ config->admins->nickname = strdup("*");
+
/* Get authentication method */
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
}
/* Get authentication data */
- ret = silc_config_get_token(line, &config->admins->auth_data);
+ ret = silc_config_get_token(line, (char **)&config->admins->auth_data);
if (ret < 0)
break;
- /* Get nickname */
- ret = silc_config_get_token(line, &config->admins->nickname);
- if (ret < 0)
- break;
+ if (config->admins->auth_meth == SILC_AUTH_PASSWORD) {
+ config->admins->auth_data_len = strlen(config->admins->auth_data);
+ } else if (config->admins->auth_meth == SILC_AUTH_PUBLIC_KEY) {
+ /* Get the public key */
+ SilcPublicKey public_key;
+
+ if (!silc_pkcs_load_public_key(config->admins->auth_data,
+ &public_key, SILC_PKCS_FILE_PEM))
+ if (!silc_pkcs_load_public_key(config->admins->auth_data,
+ &public_key, SILC_PKCS_FILE_BIN)) {
+ fprintf(stderr, "%s:%d: Could not load public key file `%s'\n",
+ config->filename, pc->linenum,
+ (char *)config->admins->auth_data);
+ break;
+ }
- /* Get class number */
- ret = silc_config_get_token(line, &tmp);
- if (ret < 0)
- break;
- if (ret) {
- config->admins->class = atoi(tmp);
- silc_free(tmp);
+ silc_free(config->admins->auth_data);
+ config->admins->auth_data = (void *)public_key;
+ config->admins->auth_data_len = 0;
}
check = TRUE;
check = TRUE;
break;
- case SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT:
- /* Not implemented yet */
- check = TRUE;
- break;
-
case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
if (!config->motd)
}
pc = pc->next;
- /* XXXX */
- // silc_free(pc->prev);
- // pc->prev = NULL;
}
if (check == FALSE)
config->pkcs = config->pkcs->prev;
while (config->hash_func && config->hash_func->prev)
config->hash_func = config->hash_func->prev;
+ while (config->hmac && config->hmac->prev)
+ config->hmac = config->hmac->prev;
while (config->listen_port && config->listen_port->prev)
config->listen_port = config->listen_port->prev;
while (config->logging && config->logging->prev)
/* This function checks that the mask sent as argument includes all the
sections that are mandatory in SILC server. */
-int silc_server_config_check_sections(unsigned int checkmask)
+int silc_server_config_check_sections(uint32 checkmask)
{
if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
return FALSE;
}
- if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
+ if (!(checkmask &
+ (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
return FALSE;
}
{
SilcServerConfigSectionLogging *log;
char *info, *warning, *error, *fatal;
- unsigned int info_size, warning_size, error_size, fatal_size;
+ uint32 info_size, warning_size, error_size, fatal_size;
SILC_LOG_DEBUG(("Setting configured log file names"));
/* Load (try at least) the crypto SIM module */
SilcCipherObject cipher;
SilcSimContext *sim;
+ char *alg_name;
memset(&cipher, 0, sizeof(cipher));
cipher.name = alg->alg_name;
sim->type = SILC_SIM_CIPHER;
sim->libname = alg->sim_name;
+ alg_name = strdup(alg->alg_name);
+ if (strchr(alg_name, '-'))
+ *strchr(alg_name, '-') = '\0';
+
if ((silc_sim_load(sim))) {
cipher.set_key =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_SET_KEY));
SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
cipher.set_key_with_string =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
cipher.encrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_ENCRYPT_CBC));
SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
cipher.decrypt =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_DECRYPT_CBC));
SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
cipher.context_len =
- silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+ silc_sim_getsym(sim, silc_sim_symname(alg_name,
SILC_CIPHER_SIM_CONTEXT_LEN));
SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
/* Put the SIM to the list of all SIM's in server */
silc_dlist_add(server->sim, sim);
+
+ silc_free(alg_name);
} else {
SILC_LOG_ERROR(("Error configuring ciphers"));
silc_server_stop(server);
silc_server_stop(server);
exit(1);
}
- silc_free(tmp);
+ silc_hash_free(tmp);
#ifdef SILC_SIM
} else {
exit(1);
}
- /* Register the cipher */
+ /* Register the hash function */
silc_hash_register(&hash);
#endif
}
}
}
+/* Registers configure HMACs. These can then be allocated by the server
+ when needed. */
+
+void silc_server_config_register_hmacs(SilcServerConfig config)
+{
+ SilcServerConfigSectionAlg *alg;
+ SilcServer server = (SilcServer)config->server;
+
+ SILC_LOG_DEBUG(("Registering configured HMACs"));
+
+ if (!config->hmac) {
+ SILC_LOG_ERROR(("HMACs are not configured. SILC cannot work without "
+ "HMACs"));
+ silc_server_stop(server);
+ exit(1);
+ }
+
+ alg = config->hmac;
+ while(alg) {
+ SilcHmacObject hmac;
+
+ if (!silc_hash_is_supported(alg->sim_name)) {
+ SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->sim_name));
+ silc_server_stop(server);
+ exit(1);
+ }
+
+ /* Register the HMAC */
+ memset(&hmac, 0, sizeof(hmac));
+ hmac.name = alg->alg_name;
+ hmac.len = alg->key_len;
+ silc_hmac_register(&hmac);
+
+ alg = alg->next;
+ }
+}
+
/* Returns client authentication information from server configuration
by host (name or ip). */
return serv;
}
+/* Returns Admin connection configuration by host, username and/or
+ nickname. */
+
+SilcServerConfigSectionAdminConnection *
+silc_server_config_find_admin(SilcServerConfig config,
+ char *host, char *username, char *nickname)
+{
+ SilcServerConfigSectionAdminConnection *admin = NULL;
+ int i;
+
+ if (!config->admins)
+ return NULL;
+
+ if (!host)
+ host = "*";
+ if (!username)
+ username = "*";
+ if (!nickname)
+ nickname = "*";
+
+ admin = config->admins;
+ for (i = 0; admin; i++) {
+ if (silc_string_compare(admin->host, host) &&
+ silc_string_compare(admin->username, username) &&
+ silc_string_compare(admin->nickname, nickname))
+ break;
+
+ admin = admin->next;
+ }
+
+ if (!admin)
+ return NULL;
+
+ return admin;
+}
+
/* Prints out example configuration file with default built in
configuration values. */
<RouterConnection>
<DenyConnection>
-<RedirectClient>
*/
fprintf(stdout, "%s\n", buf);