5 Author: Johnny Mnemonic <johnny@themnemonic.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
26 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #define SERVER_CONFIG_DEBUG(fmt)
31 /* auto-declare needed variables for the common list parsing */
32 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__) \
33 SilcServerConfig config = (SilcServerConfig) context; \
34 __type__ *findtmp, *tmp = (__type__ *) config->tmp; \
37 /* allocate the tmp field for fetching data */
38 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
40 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
41 tmp = (__type__ *) config->tmp; \
44 /* append the tmp field to the specified list */
45 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
49 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
50 findtmp->next = tmp; \
53 /* loops all elements in a list and provides a di struct pointer of the
54 * specified type containing the current element */
55 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
56 for (tmp = (void *) __list__; tmp;) { \
57 __type__ *di = (__type__ *) tmp; \
58 tmp = (void *) di->next;
60 /* Set EDOUBLE error value and bail out if necessary */
61 #define CONFIG_IS_DOUBLE(__x__) \
63 got_errno = SILC_CONFIG_EDOUBLE; \
67 /* Free the authentication fields in the specified struct
68 * Expands to two instructions */
69 #define CONFIG_FREE_AUTH(__section__) \
70 silc_free(__section__->passphrase); \
71 if (__section__->publickeys) \
72 silc_hash_table_free(__section__->publickeys);
74 static void my_free_public_key(void *key, void *context, void *user_data)
76 silc_pkcs_public_key_free(context);
79 /* Set default values to those parameters that have not been defined */
81 my_set_param_defaults(SilcServerConfigConnParams *params,
82 SilcServerConfigConnParams *defaults)
84 #define SET_PARAM_DEFAULT(p, d) params->p = \
85 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
87 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
88 SET_PARAM_DEFAULT(connections_max_per_host,
89 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
90 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
91 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
92 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
93 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
94 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
96 #undef SET_PARAM_DEFAULT
99 /* Find connection parameters by the parameter block name. */
100 static SilcServerConfigConnParams *
101 my_find_param(SilcServerConfig config, const char *name)
103 SilcServerConfigConnParams *param;
105 for (param = config->conn_params; param; param = param->next) {
106 if (!strcasecmp(param->name, name))
110 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
111 "Cannot find Params \"%s\".\n", name));
116 /* parse an authdata according to its auth method */
117 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
118 SilcUInt32 line, void **auth_data,
119 SilcUInt32 *auth_data_len)
121 if (auth_meth == SILC_AUTH_PASSWORD) {
122 /* p is a plain text password */
123 if (auth_data && auth_data_len) {
124 if (!silc_utf8_valid(p, strlen(p))) {
125 *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0);
126 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127 silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
130 *auth_data = (void *) strdup(p);
131 *auth_data_len = (SilcUInt32) strlen(p);
134 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
135 /* p is a public key file name */
136 SilcPublicKey public_key;
138 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
139 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
140 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
141 "%lu: Could not load public key file!\n",
146 /* The auth_data is a pointer to the hash table of public keys. */
148 if (*auth_data == NULL)
149 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
151 my_free_public_key, NULL,
153 silc_hash_table_add(*auth_data, public_key, public_key);
156 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
157 "Unknown authentication method.\n", line));
165 SILC_CONFIG_CALLBACK(fetch_generic)
167 SilcServerConfig config = (SilcServerConfig) context;
170 if (!strcmp(name, "module_path")) {
171 CONFIG_IS_DOUBLE(config->module_path);
172 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
174 else if (!strcmp(name, "prefer_passphrase_auth")) {
175 config->prefer_passphrase_auth = *(bool *)val;
177 else if (!strcmp(name, "require_reverse_lookup")) {
178 config->require_reverse_lookup = *(bool *)val;
180 else if (!strcmp(name, "connections_max")) {
181 config->param.connections_max = (SilcUInt32) *(int *)val;
183 else if (!strcmp(name, "connections_max_per_host")) {
184 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
186 else if (!strcmp(name, "keepalive_secs")) {
187 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
189 else if (!strcmp(name, "reconnect_count")) {
190 config->param.reconnect_count = (SilcUInt32) *(int *)val;
192 else if (!strcmp(name, "reconnect_interval")) {
193 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
195 else if (!strcmp(name, "reconnect_interval_max")) {
196 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
198 else if (!strcmp(name, "reconnect_keep_trying")) {
199 config->param.reconnect_keep_trying = *(bool *)val;
201 else if (!strcmp(name, "key_exchange_rekey")) {
202 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
204 else if (!strcmp(name, "key_exchange_pfs")) {
205 config->param.key_exchange_pfs = *(bool *)val;
207 else if (!strcmp(name, "channel_rekey_secs")) {
208 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
210 else if (!strcmp(name, "key_exchange_timeout")) {
211 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
213 else if (!strcmp(name, "conn_auth_timeout")) {
214 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
216 else if (!strcmp(name, "version_protocol")) {
217 CONFIG_IS_DOUBLE(config->param.version_protocol);
218 config->param.version_protocol =
219 (*(char *)val ? strdup((char *) val) : NULL);
221 else if (!strcmp(name, "version_software")) {
222 CONFIG_IS_DOUBLE(config->param.version_software);
223 config->param.version_software =
224 (*(char *)val ? strdup((char *) val) : NULL);
226 else if (!strcmp(name, "version_software_vendor")) {
227 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
228 config->param.version_software_vendor =
229 (*(char *)val ? strdup((char *) val) : NULL);
232 return SILC_CONFIG_EINTERNAL;
234 return SILC_CONFIG_OK;
240 SILC_CONFIG_CALLBACK(fetch_cipher)
242 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
244 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
245 type, name, context));
246 if (type == SILC_CONFIG_ARG_BLOCK) {
247 /* check the temporary struct's fields */
248 if (!tmp) /* discard empty sub-blocks */
249 return SILC_CONFIG_OK;
251 got_errno = SILC_CONFIG_EMISSFIELDS;
255 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
257 return SILC_CONFIG_OK;
259 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
261 /* Identify and save this value */
262 if (!strcmp(name, "name")) {
263 CONFIG_IS_DOUBLE(tmp->name);
264 tmp->name = strdup((char *) val);
266 else if (!strcmp(name, "module")) {
267 CONFIG_IS_DOUBLE(tmp->module);
268 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
270 else if (!strcmp(name, "keylength")) {
271 tmp->key_length = *(SilcUInt32 *)val;
273 else if (!strcmp(name, "blocklength")) {
274 tmp->block_length = *(SilcUInt32 *)val;
277 return SILC_CONFIG_EINTERNAL;
278 return SILC_CONFIG_OK;
281 silc_free(tmp->name);
282 silc_free(tmp->module);
288 SILC_CONFIG_CALLBACK(fetch_hash)
290 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
292 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
293 type, name, context));
294 if (type == SILC_CONFIG_ARG_BLOCK) {
295 /* check the temporary struct's fields */
296 if (!tmp) /* discard empty sub-blocks */
297 return SILC_CONFIG_OK;
298 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
299 got_errno = SILC_CONFIG_EMISSFIELDS;
303 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
305 return SILC_CONFIG_OK;
307 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
309 /* Identify and save this value */
310 if (!strcmp(name, "name")) {
311 CONFIG_IS_DOUBLE(tmp->name);
312 tmp->name = strdup((char *) val);
314 else if (!strcmp(name, "module")) {
315 CONFIG_IS_DOUBLE(tmp->module);
316 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
318 else if (!strcmp(name, "blocklength")) {
319 tmp->block_length = *(int *)val;
321 else if (!strcmp(name, "digestlength")) {
322 tmp->digest_length = *(int *)val;
325 return SILC_CONFIG_EINTERNAL;
326 return SILC_CONFIG_OK;
329 silc_free(tmp->name);
330 silc_free(tmp->module);
336 SILC_CONFIG_CALLBACK(fetch_hmac)
338 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
340 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
341 type, name, context));
342 if (type == SILC_CONFIG_ARG_BLOCK) {
343 /* check the temporary struct's fields */
344 if (!tmp) /* discard empty sub-blocks */
345 return SILC_CONFIG_OK;
346 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
347 got_errno = SILC_CONFIG_EMISSFIELDS;
351 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
353 return SILC_CONFIG_OK;
355 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
357 /* Identify and save this value */
358 if (!strcmp(name, "name")) {
359 CONFIG_IS_DOUBLE(tmp->name);
360 tmp->name = strdup((char *) val);
362 else if (!strcmp(name, "hash")) {
363 CONFIG_IS_DOUBLE(tmp->hash);
364 tmp->hash = strdup((char *) val);
366 else if (!strcmp(name, "maclength")) {
367 tmp->mac_length = *(int *)val;
370 return SILC_CONFIG_EINTERNAL;
371 return SILC_CONFIG_OK;
374 silc_free(tmp->name);
375 silc_free(tmp->hash);
381 SILC_CONFIG_CALLBACK(fetch_pkcs)
383 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
385 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
386 type, name, context));
387 if (type == SILC_CONFIG_ARG_BLOCK) {
388 /* check the temporary struct's fields */
389 if (!tmp) /* discard empty sub-blocks */
390 return SILC_CONFIG_OK;
392 got_errno = SILC_CONFIG_EMISSFIELDS;
396 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
398 return SILC_CONFIG_OK;
400 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
402 /* Identify and save this value */
403 if (!strcmp(name, "name")) {
404 CONFIG_IS_DOUBLE(tmp->name);
405 tmp->name = strdup((char *) val);
408 return SILC_CONFIG_EINTERNAL;
409 return SILC_CONFIG_OK;
412 silc_free(tmp->name);
418 SILC_CONFIG_CALLBACK(fetch_serverinfo)
420 SilcServerConfig config = (SilcServerConfig) context;
421 SilcServerConfigServerInfo *server_info = config->server_info;
424 /* if there isn't the struct alloc it */
426 config->server_info = server_info = (SilcServerConfigServerInfo *)
427 silc_calloc(1, sizeof(*server_info));
429 if (type == SILC_CONFIG_ARG_BLOCK) {
430 /* check for mandatory inputs */
431 if (!server_info->public_key || !server_info->private_key) {
432 got_errno = SILC_CONFIG_EMISSFIELDS;
435 return SILC_CONFIG_OK;
437 if (!strcmp(name, "hostname")) {
438 CONFIG_IS_DOUBLE(server_info->server_name);
439 server_info->server_name = strdup((char *) val);
441 else if (!strcmp(name, "ip")) {
442 CONFIG_IS_DOUBLE(server_info->server_ip);
443 server_info->server_ip = strdup((char *) val);
445 else if (!strcmp(name, "port")) {
446 int port = *(int *)val;
447 if ((port <= 0) || (port > 65535)) {
448 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
449 "Invalid port number!\n"));
450 got_errno = SILC_CONFIG_EPRINTLINE;
453 server_info->port = (SilcUInt16) port;
455 else if (!strcmp(name, "servertype")) {
456 CONFIG_IS_DOUBLE(server_info->server_type);
457 server_info->server_type = strdup((char *) val);
459 else if (!strcmp(name, "admin")) {
460 CONFIG_IS_DOUBLE(server_info->admin);
461 server_info->admin = strdup((char *) val);
463 else if (!strcmp(name, "adminemail")) {
464 CONFIG_IS_DOUBLE(server_info->email);
465 server_info->email = strdup((char *) val);
467 else if (!strcmp(name, "location")) {
468 CONFIG_IS_DOUBLE(server_info->location);
469 server_info->location = strdup((char *) val);
471 else if (!strcmp(name, "user")) {
472 CONFIG_IS_DOUBLE(server_info->user);
473 server_info->user = strdup((char *) val);
475 else if (!strcmp(name, "group")) {
476 CONFIG_IS_DOUBLE(server_info->group);
477 server_info->group = strdup((char *) val);
479 else if (!strcmp(name, "motdfile")) {
480 CONFIG_IS_DOUBLE(server_info->motd_file);
481 server_info->motd_file = strdup((char *) val);
483 else if (!strcmp(name, "pidfile")) {
484 CONFIG_IS_DOUBLE(server_info->pid_file);
485 server_info->pid_file = strdup((char *) val);
487 else if (!strcmp(name, "publickey")) {
488 char *file_tmp = (char *) val;
490 /* try to load specified file, if fail stop config parsing */
491 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
493 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
494 SILC_PKCS_FILE_BIN)) {
495 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
496 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
497 return SILC_CONFIG_ESILENT;
500 else if (!strcmp(name, "privatekey")) {
501 char *file_tmp = (char *) val;
503 /* try to load specified file, if fail stop config parsing */
504 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
506 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
507 SILC_PKCS_FILE_PEM)) {
508 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
509 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
510 return SILC_CONFIG_ESILENT;
514 return SILC_CONFIG_EINTERNAL;
515 return SILC_CONFIG_OK;
521 SILC_CONFIG_CALLBACK(fetch_logging)
523 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
525 if (!strcmp(name, "quicklogs")) {
526 config->logging_quick = *(bool *)val;
528 else if (!strcmp(name, "flushdelay")) {
529 int flushdelay = *(int *)val;
530 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
531 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
532 "Invalid flushdelay value, use quicklogs if you "
533 "want real-time logging.\n"));
534 return SILC_CONFIG_EPRINTLINE;
536 config->logging_flushdelay = (long) flushdelay;
539 /* The following istances happens only in Logging's sub-blocks, a match
540 for the sub-block name means that you should store the filename/maxsize
541 temporary struct to the proper logging channel.
542 If we get a match for "file" or "maxsize" this means that we are inside
543 a sub-sub-block and it is safe to alloc a new tmp. */
544 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
545 else if (!strcmp(name, __chan__)) { \
546 if (!tmp) return SILC_CONFIG_OK; \
548 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
550 config->__member__ = tmp; \
551 config->tmp = NULL; \
553 FETCH_LOGGING_CHAN("info", logging_info)
554 FETCH_LOGGING_CHAN("warnings", logging_warnings)
555 FETCH_LOGGING_CHAN("errors", logging_errors)
556 FETCH_LOGGING_CHAN("fatals", logging_fatals)
557 #undef FETCH_LOGGING_CHAN
558 else if (!strcmp(name, "file")) {
559 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
560 CONFIG_IS_DOUBLE(tmp->file);
561 tmp->file = strdup((char *) val);
563 else if (!strcmp(name, "size")) {
565 config->tmp = silc_calloc(1, sizeof(*tmp));
566 tmp = (SilcServerConfigLogging *) config->tmp;
568 tmp->maxsize = *(SilcUInt32 *) val;
571 return SILC_CONFIG_EINTERNAL;
572 return SILC_CONFIG_OK;
575 silc_free(tmp->file);
581 SILC_CONFIG_CALLBACK(fetch_connparam)
583 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
585 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
586 type, name, context));
587 if (type == SILC_CONFIG_ARG_BLOCK) {
588 /* check the temporary struct's fields */
589 if (!tmp) /* discard empty sub-blocks */
590 return SILC_CONFIG_OK;
592 got_errno = SILC_CONFIG_EMISSFIELDS;
596 my_set_param_defaults(tmp, &config->param);
598 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
600 return SILC_CONFIG_OK;
602 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
604 if (!strcmp(name, "name")) {
605 CONFIG_IS_DOUBLE(tmp->name);
606 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
608 else if (!strcmp(name, "connections_max")) {
609 tmp->connections_max = *(SilcUInt32 *)val;
611 else if (!strcmp(name, "connections_max_per_host")) {
612 tmp->connections_max_per_host = *(SilcUInt32 *)val;
614 else if (!strcmp(name, "keepalive_secs")) {
615 tmp->keepalive_secs = *(SilcUInt32 *)val;
617 else if (!strcmp(name, "reconnect_count")) {
618 tmp->reconnect_count = *(SilcUInt32 *)val;
620 else if (!strcmp(name, "reconnect_interval")) {
621 tmp->reconnect_interval = *(SilcUInt32 *)val;
623 else if (!strcmp(name, "reconnect_interval_max")) {
624 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
626 else if (!strcmp(name, "reconnect_keep_trying")) {
627 tmp->reconnect_keep_trying = *(bool *)val;
629 else if (!strcmp(name, "key_exchange_rekey")) {
630 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
632 else if (!strcmp(name, "key_exchange_pfs")) {
633 tmp->key_exchange_pfs = *(bool *)val;
635 else if (!strcmp(name, "version_protocol")) {
636 CONFIG_IS_DOUBLE(tmp->version_protocol);
637 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
639 else if (!strcmp(name, "version_software")) {
640 CONFIG_IS_DOUBLE(tmp->version_software);
641 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
643 else if (!strcmp(name, "version_software_vendor")) {
644 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
645 tmp->version_software_vendor =
646 (*(char *)val ? strdup((char *) val) : NULL);
649 return SILC_CONFIG_EINTERNAL;
651 return SILC_CONFIG_OK;
654 silc_free(tmp->name);
660 SILC_CONFIG_CALLBACK(fetch_client)
662 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
664 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
665 type, name, context));
667 /* Alloc before block checking, because empty sub-blocks are welcome here */
668 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
670 if (type == SILC_CONFIG_ARG_BLOCK) {
671 /* empty sub-blocks are welcome */
672 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
674 return SILC_CONFIG_OK;
677 /* Identify and save this value */
678 if (!strcmp(name, "host")) {
679 CONFIG_IS_DOUBLE(tmp->host);
680 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
682 else if (!strcmp(name, "passphrase")) {
683 CONFIG_IS_DOUBLE(tmp->passphrase);
684 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
685 (void **)&tmp->passphrase,
686 &tmp->passphrase_len)) {
687 got_errno = SILC_CONFIG_ESILENT;
691 else if (!strcmp(name, "publickey")) {
692 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
693 (void **)&tmp->publickeys, NULL)) {
694 got_errno = SILC_CONFIG_ESILENT;
698 else if (!strcmp(name, "params")) {
699 CONFIG_IS_DOUBLE(tmp->param);
700 tmp->param = my_find_param(config, (char *) val);
701 if (!tmp->param) { /* error message already output */
702 got_errno = SILC_CONFIG_EPRINTLINE;
707 return SILC_CONFIG_EINTERNAL;
708 return SILC_CONFIG_OK;
711 silc_free(tmp->host);
712 CONFIG_FREE_AUTH(tmp);
718 SILC_CONFIG_CALLBACK(fetch_admin)
720 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
722 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
723 type, name, context));
724 if (type == SILC_CONFIG_ARG_BLOCK) {
725 /* check the temporary struct's fields */
726 if (!tmp) /* discard empty sub-blocks */
727 return SILC_CONFIG_OK;
729 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
731 return SILC_CONFIG_OK;
733 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
735 /* Identify and save this value */
736 if (!strcmp(name, "host")) {
737 CONFIG_IS_DOUBLE(tmp->host);
738 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
740 else if (!strcmp(name, "user")) {
741 CONFIG_IS_DOUBLE(tmp->user);
742 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
744 else if (!strcmp(name, "nick")) {
745 CONFIG_IS_DOUBLE(tmp->nick);
746 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
748 else if (!strcmp(name, "passphrase")) {
749 CONFIG_IS_DOUBLE(tmp->passphrase);
750 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
751 (void **)&tmp->passphrase,
752 &tmp->passphrase_len)) {
753 got_errno = SILC_CONFIG_ESILENT;
757 else if (!strcmp(name, "publickey")) {
758 CONFIG_IS_DOUBLE(tmp->publickeys);
759 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
760 (void **)&tmp->publickeys, NULL)) {
761 got_errno = SILC_CONFIG_ESILENT;
766 return SILC_CONFIG_EINTERNAL;
767 return SILC_CONFIG_OK;
770 silc_free(tmp->host);
771 silc_free(tmp->user);
772 silc_free(tmp->nick);
773 CONFIG_FREE_AUTH(tmp);
779 SILC_CONFIG_CALLBACK(fetch_deny)
781 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
783 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
784 type, name, context));
785 if (type == SILC_CONFIG_ARG_BLOCK) {
786 /* check the temporary struct's fields */
787 if (!tmp) /* discard empty sub-blocks */
788 return SILC_CONFIG_OK;
790 got_errno = SILC_CONFIG_EMISSFIELDS;
794 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
796 return SILC_CONFIG_OK;
798 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
800 /* Identify and save this value */
801 if (!strcmp(name, "host")) {
802 CONFIG_IS_DOUBLE(tmp->host);
803 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
805 else if (!strcmp(name, "reason")) {
806 CONFIG_IS_DOUBLE(tmp->reason);
807 tmp->reason = strdup((char *) val);
810 return SILC_CONFIG_EINTERNAL;
811 return SILC_CONFIG_OK;
814 silc_free(tmp->host);
815 silc_free(tmp->reason);
821 SILC_CONFIG_CALLBACK(fetch_server)
823 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
825 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
826 type, name, context));
827 if (type == SILC_CONFIG_ARG_BLOCK) {
828 /* check the temporary struct's fields */
829 if (!tmp) /* discard empty sub-blocks */
830 return SILC_CONFIG_OK;
832 /* the temporary struct is ok, append it to the list */
833 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
835 return SILC_CONFIG_OK;
837 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
839 /* Identify and save this value */
840 if (!strcmp(name, "host")) {
841 CONFIG_IS_DOUBLE(tmp->host);
842 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
844 else if (!strcmp(name, "passphrase")) {
845 CONFIG_IS_DOUBLE(tmp->passphrase);
846 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
847 (void **)&tmp->passphrase,
848 &tmp->passphrase_len)) {
849 got_errno = SILC_CONFIG_ESILENT;
853 else if (!strcmp(name, "publickey")) {
854 CONFIG_IS_DOUBLE(tmp->publickeys);
855 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
856 (void **)&tmp->publickeys, NULL)) {
857 got_errno = SILC_CONFIG_ESILENT;
861 else if (!strcmp(name, "params")) {
862 CONFIG_IS_DOUBLE(tmp->param);
863 tmp->param = my_find_param(config, (char *) val);
864 if (!tmp->param) { /* error message already output */
865 got_errno = SILC_CONFIG_EPRINTLINE;
869 else if (!strcmp(name, "backup")) {
870 tmp->backup_router = *(bool *)val;
873 return SILC_CONFIG_EINTERNAL;
875 return SILC_CONFIG_OK;
878 silc_free(tmp->host);
879 CONFIG_FREE_AUTH(tmp);
885 SILC_CONFIG_CALLBACK(fetch_router)
887 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
889 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
890 type, name, context));
891 if (type == SILC_CONFIG_ARG_BLOCK) {
892 if (!tmp) /* discard empty sub-blocks */
893 return SILC_CONFIG_OK;
895 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
897 return SILC_CONFIG_OK;
899 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
901 /* Identify and save this value */
902 if (!strcmp(name, "host")) {
903 CONFIG_IS_DOUBLE(tmp->host);
904 tmp->host = strdup((char *) val);
906 else if (!strcmp(name, "port")) {
907 int port = *(int *)val;
908 if ((port <= 0) || (port > 65535)) {
909 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
910 "Invalid port number!\n"));
911 got_errno = SILC_CONFIG_EPRINTLINE;
914 tmp->port = (SilcUInt16) port;
916 else if (!strcmp(name, "passphrase")) {
917 CONFIG_IS_DOUBLE(tmp->passphrase);
918 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
919 (void **)&tmp->passphrase,
920 &tmp->passphrase_len)) {
921 got_errno = SILC_CONFIG_ESILENT;
925 else if (!strcmp(name, "publickey")) {
926 CONFIG_IS_DOUBLE(tmp->publickeys);
927 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
928 (void **)&tmp->publickeys, NULL)) {
929 got_errno = SILC_CONFIG_ESILENT;
933 else if (!strcmp(name, "params")) {
934 CONFIG_IS_DOUBLE(tmp->param);
935 tmp->param = my_find_param(config, (char *) val);
936 if (!tmp->param) { /* error message already output */
937 got_errno = SILC_CONFIG_EPRINTLINE;
941 else if (!strcmp(name, "initiator")) {
942 tmp->initiator = *(bool *)val;
944 else if (!strcmp(name, "backuphost")) {
945 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
946 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
949 else if (!strcmp(name, "backupport")) {
950 int port = *(int *)val;
951 if ((port <= 0) || (port > 65535)) {
952 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
953 "Invalid port number!\n"));
954 got_errno = SILC_CONFIG_EPRINTLINE;
957 tmp->backup_replace_port = (SilcUInt16) port;
959 else if (!strcmp(name, "backuplocal")) {
960 tmp->backup_local = *(bool *)val;
963 return SILC_CONFIG_EINTERNAL;
965 return SILC_CONFIG_OK;
968 silc_free(tmp->host);
969 silc_free(tmp->backup_replace_ip);
970 CONFIG_FREE_AUTH(tmp);
976 /* known config options tables */
977 static const SilcConfigTable table_general[] = {
978 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
979 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
980 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
981 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
982 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
983 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
984 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
985 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
986 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
987 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
988 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
989 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
990 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
991 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
992 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
993 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
994 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
995 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
999 static const SilcConfigTable table_cipher[] = {
1000 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1001 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1002 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1003 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1007 static const SilcConfigTable table_hash[] = {
1008 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1009 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1010 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1011 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1015 static const SilcConfigTable table_hmac[] = {
1016 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1017 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1018 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1022 static const SilcConfigTable table_pkcs[] = {
1023 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1027 static const SilcConfigTable table_serverinfo[] = {
1028 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1029 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1030 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1031 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1032 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1033 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1034 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1035 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1036 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1037 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1038 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1039 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1040 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1044 static const SilcConfigTable table_logging_c[] = {
1045 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1046 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1047 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1051 static const SilcConfigTable table_logging[] = {
1052 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1053 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1054 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1055 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1056 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1057 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1061 static const SilcConfigTable table_connparam[] = {
1062 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1063 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1064 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1065 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1066 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1067 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1068 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1069 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1070 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1071 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1072 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1073 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1074 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1075 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1079 static const SilcConfigTable table_client[] = {
1080 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1081 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1082 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1083 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1087 static const SilcConfigTable table_admin[] = {
1088 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1089 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1090 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1091 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1092 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1093 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1094 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1098 static const SilcConfigTable table_deny[] = {
1099 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1100 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1104 static const SilcConfigTable table_serverconn[] = {
1105 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1106 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1107 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1108 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1109 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1113 static const SilcConfigTable table_routerconn[] = {
1114 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1115 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1116 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1117 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1118 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1119 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1120 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1121 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1122 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1126 static const SilcConfigTable table_main[] = {
1127 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1128 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1129 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1130 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1131 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1132 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1133 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1134 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1135 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1136 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1137 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1138 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1139 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1143 /* Set default values to stuff that was not configured. */
1145 static void silc_server_config_set_defaults(SilcServerConfig config)
1147 my_set_param_defaults(&config->param, NULL);
1149 config->channel_rekey_secs = (config->channel_rekey_secs ?
1150 config->channel_rekey_secs :
1151 SILC_SERVER_CHANNEL_REKEY);
1152 config->key_exchange_timeout = (config->key_exchange_timeout ?
1153 config->key_exchange_timeout :
1154 SILC_SERVER_SKE_TIMEOUT);
1155 config->conn_auth_timeout = (config->conn_auth_timeout ?
1156 config->conn_auth_timeout :
1157 SILC_SERVER_CONNAUTH_TIMEOUT);
1160 /* Allocates a new configuration object, opens configuration file and
1161 parses it. The parsed data is returned to the newly allocated
1162 configuration object. The SilcServerConfig must be freed by calling
1163 the silc_server_config_destroy function. */
1165 SilcServerConfig silc_server_config_alloc(const char *filename)
1167 SilcServerConfig config_new;
1168 SilcConfigEntity ent;
1169 SilcConfigFile *file;
1171 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1173 /* alloc a config object */
1174 config_new = silc_calloc(1, sizeof(*config_new));
1175 config_new->refcount = 1;
1179 /* obtain a config file object */
1180 file = silc_config_open(filename);
1182 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1187 /* obtain a SilcConfig entity, we can use it to start the parsing */
1188 ent = silc_config_init(file);
1190 /* load the known configuration options, give our empty object as context */
1191 silc_config_register_table(ent, table_main, (void *) config_new);
1193 /* enter the main parsing loop. When this returns, we have the parsing
1194 * result and the object filled (or partially, in case of errors). */
1195 ret = silc_config_main(ent);
1196 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1197 silc_config_strerror(ret)));
1199 /* Check if the parser returned errors */
1201 /* handle this special error return which asks to quietly return */
1202 if (ret != SILC_CONFIG_ESILENT) {
1203 char *linebuf, *filename = silc_config_get_filename(file);
1204 SilcUInt32 line = silc_config_get_line(file);
1205 if (ret != SILC_CONFIG_EPRINTLINE)
1206 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1207 silc_config_strerror(ret)));
1208 linebuf = silc_config_read_line(file, line);
1209 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1213 silc_server_config_destroy(config_new);
1217 /* close (destroy) the file object */
1218 silc_config_close(file);
1220 /* If config_new is incomplete, abort the object and return NULL */
1221 if (!config_new->server_info) {
1222 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1223 "`server_info'\n"));
1224 silc_server_config_destroy(config_new);
1228 /* XXX are there any other mandatory sections in the config file? */
1230 /* Set default to configuration parameters */
1231 silc_server_config_set_defaults(config_new);
1236 /* Increments the reference counter of a config object */
1238 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1243 ref->config = config;
1244 ref->ref_ptr = ref_ptr;
1245 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1246 config->refcount - 1, config->refcount));
1250 /* Decrements the reference counter of a config object. If the counter
1251 reaches 0, the config object is destroyed. */
1253 void silc_server_config_unref(SilcServerConfigRef *ref)
1256 silc_server_config_destroy(ref->config);
1259 /* Destroy a config object with all his children lists */
1261 void silc_server_config_destroy(SilcServerConfig config)
1266 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1267 config->refcount + 1, config->refcount));
1268 if (config->refcount > 0)
1271 SILC_LOG_DEBUG(("Freeing config context"));
1273 /* Destroy general config stuff */
1274 silc_free(config->module_path);
1275 silc_free(config->param.version_protocol);
1276 silc_free(config->param.version_software);
1277 silc_free(config->param.version_software_vendor);
1279 /* Destroy Logging channels */
1280 if (config->logging_info)
1281 silc_free(config->logging_info->file);
1282 if (config->logging_warnings)
1283 silc_free(config->logging_warnings->file);
1284 if (config->logging_errors)
1285 silc_free(config->logging_errors->file);
1286 if (config->logging_fatals)
1287 silc_free(config->logging_fatals->file);
1289 /* Destroy the ServerInfo struct */
1290 if (config->server_info) {
1291 register SilcServerConfigServerInfo *si = config->server_info;
1292 silc_free(si->server_name);
1293 silc_free(si->server_ip);
1294 silc_free(si->server_type);
1295 silc_free(si->location);
1296 silc_free(si->admin);
1297 silc_free(si->email);
1298 silc_free(si->user);
1299 silc_free(si->group);
1300 silc_free(si->motd_file);
1301 silc_free(si->pid_file);
1302 silc_pkcs_public_key_free(si->public_key);
1303 silc_pkcs_private_key_free(si->private_key);
1306 /* Now let's destroy the lists */
1308 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1310 silc_free(di->name);
1311 silc_free(di->module);
1314 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1315 silc_free(di->name);
1316 silc_free(di->module);
1319 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1320 silc_free(di->name);
1321 silc_free(di->hash);
1324 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1325 silc_free(di->name);
1328 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1329 config->conn_params)
1330 silc_free(di->name);
1331 silc_free(di->version_protocol);
1332 silc_free(di->version_software);
1333 silc_free(di->version_software_vendor);
1336 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1337 silc_free(di->host);
1338 CONFIG_FREE_AUTH(di);
1341 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1342 silc_free(di->host);
1343 silc_free(di->user);
1344 silc_free(di->nick);
1345 CONFIG_FREE_AUTH(di);
1348 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1349 silc_free(di->host);
1350 silc_free(di->reason);
1353 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1355 silc_free(di->host);
1356 CONFIG_FREE_AUTH(di);
1359 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1361 silc_free(di->host);
1362 silc_free(di->backup_replace_ip);
1363 CONFIG_FREE_AUTH(di);
1367 memset(config, 'F', sizeof(*config));
1371 /* Registers configured ciphers. These can then be allocated by the
1372 server when needed. */
1374 bool silc_server_config_register_ciphers(SilcServer server)
1376 SilcServerConfig config = server->config;
1377 SilcServerConfigCipher *cipher = config->cipher;
1378 char *module_path = config->module_path;
1380 SILC_LOG_DEBUG(("Registering configured ciphers"));
1382 if (!cipher) /* any cipher in the config file? */
1386 /* if there isn't a module_path OR there isn't a module sim name try to
1387 * use buil-in functions */
1388 if (!module_path || !cipher->module) {
1390 for (i = 0; silc_default_ciphers[i].name; i++)
1391 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1392 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1395 if (!silc_cipher_is_supported(cipher->name)) {
1396 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1397 silc_server_stop(server);
1402 /* Load (try at least) the crypto SIM module */
1403 char buf[1023], *alg_name;
1404 SilcCipherObject cipher_obj;
1407 memset(&cipher_obj, 0, sizeof(cipher_obj));
1408 cipher_obj.name = cipher->name;
1409 cipher_obj.block_len = cipher->block_length;
1410 cipher_obj.key_len = cipher->key_length * 8;
1412 /* build the libname */
1413 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1415 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1417 alg_name = strdup(cipher->name);
1418 if (strchr(alg_name, '-'))
1419 *strchr(alg_name, '-') = '\0';
1421 if (silc_sim_load(sim)) {
1422 cipher_obj.set_key =
1423 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1424 SILC_CIPHER_SIM_SET_KEY));
1425 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1426 cipher_obj.set_key_with_string =
1427 silc_sim_getsym(sim,
1428 silc_sim_symname(alg_name,
1429 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1430 SILC_LOG_DEBUG(("set_key_with_string=%p",
1431 cipher_obj.set_key_with_string));
1432 cipher_obj.encrypt =
1433 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1434 SILC_CIPHER_SIM_ENCRYPT_CBC));
1435 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1436 cipher_obj.decrypt =
1437 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1438 SILC_CIPHER_SIM_DECRYPT_CBC));
1439 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1440 cipher_obj.context_len =
1441 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1442 SILC_CIPHER_SIM_CONTEXT_LEN));
1443 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1445 /* Put the SIM to the list of all SIM's in server */
1446 silc_dlist_add(server->sim, sim);
1448 silc_free(alg_name);
1450 SILC_LOG_ERROR(("Error configuring ciphers"));
1451 silc_server_stop(server);
1455 /* Register the cipher */
1456 silc_cipher_register(&cipher_obj);
1458 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1459 "can't load modules!"));
1460 silc_server_stop(server);
1464 cipher = cipher->next;
1470 /* Registers configured hash functions. These can then be allocated by the
1471 server when needed. */
1473 bool silc_server_config_register_hashfuncs(SilcServer server)
1475 SilcServerConfig config = server->config;
1476 SilcServerConfigHash *hash = config->hash;
1477 char *module_path = config->module_path;
1479 SILC_LOG_DEBUG(("Registering configured hash functions"));
1481 if (!hash) /* any hash func in the config file? */
1485 /* if there isn't a module_path OR there isn't a module sim name try to
1486 * use buil-in functions */
1487 if (!module_path || !hash->module) {
1489 for (i = 0; silc_default_hash[i].name; i++)
1490 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1491 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1494 if (!silc_hash_is_supported(hash->name)) {
1495 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1496 silc_server_stop(server);
1501 /* Load (try at least) the hash SIM module */
1502 SilcHashObject hash_obj;
1505 memset(&hash_obj, 0, sizeof(hash_obj));
1506 hash_obj.name = hash->name;
1507 hash_obj.block_len = hash->block_length;
1508 hash_obj.hash_len = hash->digest_length;
1510 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1512 if ((silc_sim_load(sim))) {
1514 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1515 SILC_HASH_SIM_INIT));
1516 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1518 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1519 SILC_HASH_SIM_UPDATE));
1520 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1522 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1523 SILC_HASH_SIM_FINAL));
1524 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1525 hash_obj.context_len =
1526 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1527 SILC_HASH_SIM_CONTEXT_LEN));
1528 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1530 /* Put the SIM to the table of all SIM's in server */
1531 silc_dlist_add(server->sim, sim);
1533 SILC_LOG_ERROR(("Error configuring hash functions"));
1534 silc_server_stop(server);
1538 /* Register the hash function */
1539 silc_hash_register(&hash_obj);
1541 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1542 "can't load modules!"));
1543 silc_server_stop(server);
1553 /* Registers configure HMACs. These can then be allocated by the server
1556 bool silc_server_config_register_hmacs(SilcServer server)
1558 SilcServerConfig config = server->config;
1559 SilcServerConfigHmac *hmac = config->hmac;
1561 SILC_LOG_DEBUG(("Registering configured HMACs"));
1567 SilcHmacObject hmac_obj;
1568 if (!silc_hash_is_supported(hmac->hash)) {
1569 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1570 silc_server_stop(server);
1574 /* Register the HMAC */
1575 memset(&hmac_obj, 0, sizeof(hmac_obj));
1576 hmac_obj.name = hmac->name;
1577 hmac_obj.len = hmac->mac_length;
1578 silc_hmac_register(&hmac_obj);
1586 /* Registers configured PKCS's. */
1588 bool silc_server_config_register_pkcs(SilcServer server)
1590 SilcServerConfig config = server->config;
1591 SilcServerConfigPkcs *pkcs = config->pkcs;
1593 SILC_LOG_DEBUG(("Registering configured PKCS"));
1600 for (i = 0; silc_default_pkcs[i].name; i++)
1601 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1602 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1605 if (!silc_pkcs_is_supported(pkcs->name)) {
1606 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1607 silc_server_stop(server);
1616 /* Sets log files where log messages are saved by the server logger. */
1618 void silc_server_config_setlogfiles(SilcServer server)
1620 SilcServerConfig config = server->config;
1621 SilcServerConfigLogging *this;
1623 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1625 silc_log_quick = config->logging_quick;
1626 silc_log_flushdelay = (config->logging_flushdelay ?
1627 config->logging_flushdelay :
1628 SILC_SERVER_LOG_FLUSH_DELAY);
1630 if ((this = config->logging_fatals))
1631 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1633 if ((this = config->logging_errors))
1634 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1636 if ((this = config->logging_warnings))
1637 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1639 if ((this = config->logging_info))
1640 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1644 /* Returns client authentication information from configuration file by host
1647 SilcServerConfigClient *
1648 silc_server_config_find_client(SilcServer server, char *host)
1650 SilcServerConfig config = server->config;
1651 SilcServerConfigClient *client;
1653 if (!config || !host)
1656 for (client = config->clients; client; client = client->next) {
1657 if (client->host && !silc_string_compare(client->host, host))
1662 /* if none matched, then client is already NULL */
1666 /* Returns admin connection configuration by host, username and/or
1669 SilcServerConfigAdmin *
1670 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1673 SilcServerConfig config = server->config;
1674 SilcServerConfigAdmin *admin;
1676 /* make sure we have a value for the matching parameters */
1684 for (admin = config->admins; admin; admin = admin->next) {
1685 if (admin->host && !silc_string_compare(admin->host, host))
1687 if (admin->user && !silc_string_compare(admin->user, user))
1689 if (admin->nick && !silc_string_compare(admin->nick, nick))
1691 /* no checks failed -> this entry matches */
1695 /* if none matched, then admin is already NULL */
1699 /* Returns the denied connection configuration entry by host. */
1701 SilcServerConfigDeny *
1702 silc_server_config_find_denied(SilcServer server, char *host)
1704 SilcServerConfig config = server->config;
1705 SilcServerConfigDeny *deny;
1707 /* make sure we have a value for the matching parameters */
1708 if (!config || !host)
1711 for (deny = config->denied; deny; deny = deny->next) {
1712 if (deny->host && !silc_string_compare(deny->host, host))
1717 /* if none matched, then deny is already NULL */
1721 /* Returns server connection info from server configuartion by host
1724 SilcServerConfigServer *
1725 silc_server_config_find_server_conn(SilcServer server, char *host)
1727 SilcServerConfig config = server->config;
1728 SilcServerConfigServer *serv = NULL;
1733 if (!config->servers)
1736 for (serv = config->servers; serv; serv = serv->next) {
1737 if (!silc_string_compare(serv->host, host))
1745 /* Returns router connection info from server configuration by
1746 host (name or ip). */
1748 SilcServerConfigRouter *
1749 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1751 SilcServerConfig config = server->config;
1752 SilcServerConfigRouter *serv = NULL;
1757 if (!config->routers)
1760 for (serv = config->routers; serv; serv = serv->next) {
1761 if (!silc_string_compare(serv->host, host))
1763 if (port && serv->port && serv->port != port)
1771 /* Returns TRUE if configuration for a router connection that we are
1772 initiating exists. */
1774 bool silc_server_config_is_primary_route(SilcServer server)
1776 SilcServerConfig config = server->config;
1777 SilcServerConfigRouter *serv = NULL;
1781 serv = config->routers;
1782 for (i = 0; serv; i++) {
1783 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1794 /* Returns our primary connection configuration or NULL if we do not
1795 have primary router configured. */
1797 SilcServerConfigRouter *
1798 silc_server_config_get_primary_router(SilcServer server)
1800 SilcServerConfig config = server->config;
1801 SilcServerConfigRouter *serv = NULL;
1804 serv = config->routers;
1805 for (i = 0; serv; i++) {
1806 if (serv->initiator == TRUE && serv->backup_router == FALSE)