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 /* append the tmp field to the specified list */
38 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
42 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
43 findtmp->next = tmp; \
46 /* loops all elements in a list and provides a di struct pointer of the
47 * specified type containing the current element */
48 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
49 for (tmp = (void *) __list__; tmp;) { \
50 __type__ *di = (__type__ *) tmp; \
51 tmp = (void *) di->next;
53 /* Set EDOUBLE error value and bail out if necessary */
54 #define CONFIG_IS_DOUBLE(__x__) \
56 got_errno = SILC_CONFIG_EDOUBLE; \
60 /* Free the authentication fields in the specified struct
61 * Expands to two instructions */
62 #define CONFIG_FREE_AUTH(__section__) \
63 silc_free(__section__->passphrase); \
64 if (__section__->publickeys) \
65 silc_hash_table_free(__section__->publickeys);
67 static void my_free_public_key(void *key, void *context, void *user_data)
69 silc_pkcs_public_key_free(context);
72 /* Set default values to those parameters that have not been defined */
74 my_set_param_defaults(SilcServerConfigConnParams *params,
75 SilcServerConfigConnParams *defaults)
77 #define SET_PARAM_DEFAULT(p, d) params->p = \
78 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
80 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
81 SET_PARAM_DEFAULT(connections_max_per_host,
82 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
83 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
84 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
85 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
86 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
87 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
89 #undef SET_PARAM_DEFAULT
92 /* Find connection parameters by the parameter block name. */
93 static SilcServerConfigConnParams *
94 my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line)
96 SilcServerConfigConnParams *param;
98 for (param = config->conn_params; param; param = param->next) {
99 if (!strcasecmp(param->name, name))
103 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
104 "Cannot find Param \"%s\".\n", line, name));
109 /* parse an authdata according to its auth method */
110 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
111 SilcUInt32 line, void **auth_data,
112 SilcUInt32 *auth_data_len)
114 if (auth_meth == SILC_AUTH_PASSWORD) {
115 /* p is a plain text password */
117 *auth_data = (void *) strdup(p);
119 *auth_data_len = (SilcUInt32) strlen(p);
120 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
121 /* p is a public key file name */
122 SilcPublicKey public_key;
124 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
125 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
126 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
127 "Could not load public key file!\n", line));
131 /* The auth_data is a pointer to the hash table of public keys. */
133 if (*auth_data == NULL)
134 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
136 my_free_public_key, NULL,
138 silc_hash_table_add(*auth_data, public_key, public_key);
141 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
142 "Unknown authentication method.\n", line));
150 SILC_CONFIG_CALLBACK(fetch_generic)
152 SilcServerConfig config = (SilcServerConfig) context;
155 if (!strcmp(name, "module_path")) {
156 CONFIG_IS_DOUBLE(config->module_path);
157 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
159 else if (!strcmp(name, "prefer_passphrase_auth")) {
160 config->prefer_passphrase_auth = *(bool *)val;
162 else if (!strcmp(name, "require_reverse_lookup")) {
163 config->require_reverse_lookup = *(bool *)val;
165 else if (!strcmp(name, "connections_max")) {
166 config->param.connections_max = (SilcUInt32) *(int *)val;
168 else if (!strcmp(name, "connections_max_per_host")) {
169 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
171 else if (!strcmp(name, "keepalive_secs")) {
172 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
174 else if (!strcmp(name, "reconnect_count")) {
175 config->param.reconnect_count = (SilcUInt32) *(int *)val;
177 else if (!strcmp(name, "reconnect_interval")) {
178 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
180 else if (!strcmp(name, "reconnect_interval_max")) {
181 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
183 else if (!strcmp(name, "reconnect_keep_trying")) {
184 config->param.reconnect_keep_trying = *(bool *)val;
186 else if (!strcmp(name, "key_exchange_rekey")) {
187 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
189 else if (!strcmp(name, "key_exchange_pfs")) {
190 config->param.key_exchange_pfs = *(bool *)val;
192 else if (!strcmp(name, "channel_rekey_secs")) {
193 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
195 else if (!strcmp(name, "key_exchange_timeout")) {
196 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
198 else if (!strcmp(name, "conn_auth_timeout")) {
199 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
201 else if (!strcmp(name, "version_protocol")) {
202 CONFIG_IS_DOUBLE(config->param.version_protocol);
203 config->param.version_protocol =
204 (*(char *)val ? strdup((char *) val) : NULL);
206 else if (!strcmp(name, "version_software")) {
207 CONFIG_IS_DOUBLE(config->param.version_software);
208 config->param.version_software =
209 (*(char *)val ? strdup((char *) val) : NULL);
211 else if (!strcmp(name, "version_software_vendor")) {
212 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
213 config->param.version_software_vendor =
214 (*(char *)val ? strdup((char *) val) : NULL);
217 return SILC_CONFIG_EINTERNAL;
219 return SILC_CONFIG_OK;
225 SILC_CONFIG_CALLBACK(fetch_cipher)
227 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
229 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
230 type, name, context));
231 if (type == SILC_CONFIG_ARG_BLOCK) {
232 /* check the temporary struct's fields */
233 if (!tmp) /* empty sub-block? */
234 return SILC_CONFIG_OK;
236 got_errno = SILC_CONFIG_EMISSFIELDS;
239 /* the temporary struct is ok, append it to the list */
240 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
242 return SILC_CONFIG_OK;
244 /* if there isn't a temporary struct alloc one */
246 config->tmp = silc_calloc(1, sizeof(*findtmp));
247 tmp = (SilcServerConfigCipher *) config->tmp;
250 /* Identify and save this value */
251 if (!strcmp(name, "name")) {
252 CONFIG_IS_DOUBLE(tmp->name);
253 tmp->name = strdup((char *) val);
255 else if (!strcmp(name, "module")) {
256 CONFIG_IS_DOUBLE(tmp->module);
257 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
259 else if (!strcmp(name, "keylength")) {
260 tmp->key_length = *(SilcUInt32 *)val;
262 else if (!strcmp(name, "blocklength")) {
263 tmp->block_length = *(SilcUInt32 *)val;
266 return SILC_CONFIG_EINTERNAL;
267 return SILC_CONFIG_OK;
270 silc_free(tmp->name);
271 silc_free(tmp->module);
277 SILC_CONFIG_CALLBACK(fetch_hash)
279 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
281 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
282 type, name, context));
283 if (type == SILC_CONFIG_ARG_BLOCK) {
284 /* check the temporary struct's fields */
285 if (!tmp) /* empty sub-block? */
286 return SILC_CONFIG_OK;
287 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
288 got_errno = SILC_CONFIG_EMISSFIELDS;
291 /* the temporary struct in tmp is ok */
292 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
294 return SILC_CONFIG_OK;
297 /* if there isn't a temporary struct alloc one */
299 config->tmp = silc_calloc(1, sizeof(*findtmp));
300 tmp = (SilcServerConfigHash *) config->tmp;
303 /* Identify and save this value */
304 if (!strcmp(name, "name")) {
305 CONFIG_IS_DOUBLE(tmp->name);
306 tmp->name = strdup((char *) val);
308 else if (!strcmp(name, "module")) {
309 CONFIG_IS_DOUBLE(tmp->module);
310 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
312 else if (!strcmp(name, "blocklength")) {
313 tmp->block_length = *(int *)val;
315 else if (!strcmp(name, "digestlength")) {
316 tmp->digest_length = *(int *)val;
319 return SILC_CONFIG_EINTERNAL;
320 return SILC_CONFIG_OK;
323 silc_free(tmp->name);
324 silc_free(tmp->module);
330 SILC_CONFIG_CALLBACK(fetch_hmac)
332 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
334 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
335 type, name, context));
336 if (type == SILC_CONFIG_ARG_BLOCK) {
337 /* check the temporary struct's fields */
338 if (!tmp) /* empty sub-block? */
339 return SILC_CONFIG_OK;
340 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
341 got_errno = SILC_CONFIG_EMISSFIELDS;
344 /* the temporary struct is ok, append it to the list */
345 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
347 return SILC_CONFIG_OK;
349 /* if there isn't a temporary struct alloc one */
351 config->tmp = silc_calloc(1, sizeof(*findtmp));
352 tmp = (SilcServerConfigHmac *) config->tmp;
355 /* Identify and save this value */
356 if (!strcmp(name, "name")) {
357 CONFIG_IS_DOUBLE(tmp->name);
358 tmp->name = strdup((char *) val);
360 else if (!strcmp(name, "hash")) {
361 CONFIG_IS_DOUBLE(tmp->hash);
362 tmp->hash = strdup((char *) val);
364 else if (!strcmp(name, "maclength")) {
365 tmp->mac_length = *(int *)val;
368 return SILC_CONFIG_EINTERNAL;
369 return SILC_CONFIG_OK;
372 silc_free(tmp->name);
373 silc_free(tmp->hash);
379 SILC_CONFIG_CALLBACK(fetch_pkcs)
381 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
383 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
384 type, name, context));
385 if (type == SILC_CONFIG_ARG_BLOCK) {
386 /* check the temporary struct's fields */
387 if (!tmp) /* empty sub-block? */
388 return SILC_CONFIG_OK;
390 got_errno = SILC_CONFIG_EMISSFIELDS;
393 /* the temporary struct is ok, append it to the list */
394 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
396 return SILC_CONFIG_OK;
398 /* if there isn't a temporary struct alloc one */
400 config->tmp = silc_calloc(1, sizeof(*findtmp));
401 tmp = (SilcServerConfigPkcs *) config->tmp;
404 /* Identify and save this value */
405 if (!strcmp(name, "name")) {
406 CONFIG_IS_DOUBLE(tmp->name);
407 tmp->name = strdup((char *) val);
410 return SILC_CONFIG_EINTERNAL;
411 return SILC_CONFIG_OK;
414 silc_free(tmp->name);
420 SILC_CONFIG_CALLBACK(fetch_serverinfo)
422 SilcServerConfig config = (SilcServerConfig) context;
423 SilcServerConfigServerInfo *server_info = config->server_info;
426 /* if there isn't the struct alloc it */
428 config->server_info = server_info = (SilcServerConfigServerInfo *)
429 silc_calloc(1, sizeof(*server_info));
431 if (type == SILC_CONFIG_ARG_BLOCK) {
432 /* check for mandatory inputs */
433 if (!server_info->public_key || !server_info->private_key) {
434 got_errno = SILC_CONFIG_EMISSFIELDS;
437 return SILC_CONFIG_OK;
439 if (!strcmp(name, "hostname")) {
440 CONFIG_IS_DOUBLE(server_info->server_name);
441 server_info->server_name = strdup((char *) val);
443 else if (!strcmp(name, "ip")) {
444 CONFIG_IS_DOUBLE(server_info->server_ip);
445 server_info->server_ip = strdup((char *) val);
447 else if (!strcmp(name, "port")) {
448 int port = *(int *)val;
449 if ((port <= 0) || (port > 65535)) {
450 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
451 return SILC_CONFIG_ESILENT;
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 SilcServerConfig config = (SilcServerConfig) context;
524 SilcServerConfigLogging *tmp =
525 (SilcServerConfigLogging *) config->tmp;
528 if (!strcmp(name, "quicklogs")) {
529 config->logging_quick = *(bool *)val;
531 else if (!strcmp(name, "flushdelay")) {
532 int flushdelay = *(int *)val;
533 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
534 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use "
535 "quicklogs if you want real-time logging.\n", line));
536 return SILC_CONFIG_ESILENT;
538 config->logging_flushdelay = (long) flushdelay;
540 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
541 else if (!strcmp(name, __chan__)) { \
542 if (!tmp) return SILC_CONFIG_OK; \
544 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
546 config->__member__ = tmp; \
547 config->tmp = NULL; \
549 FETCH_LOGGING_CHAN("info", logging_info)
550 FETCH_LOGGING_CHAN("warnings", logging_warnings)
551 FETCH_LOGGING_CHAN("errors", logging_errors)
552 FETCH_LOGGING_CHAN("fatals", logging_fatals)
553 #undef FETCH_LOGGING_CHAN
554 else if (!strcmp(name, "file")) {
555 if (!tmp) { /* FIXME: what the fuck is this? */
556 config->tmp = silc_calloc(1, sizeof(*tmp));
557 tmp = (SilcServerConfigLogging *) config->tmp;
560 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
562 tmp->file = strdup((char *) val);
564 else if (!strcmp(name, "size")) {
566 config->tmp = silc_calloc(1, sizeof(*tmp));
567 tmp = (SilcServerConfigLogging *) config->tmp;
569 tmp->maxsize = *(SilcUInt32 *) val;
572 return SILC_CONFIG_EINTERNAL;
573 return SILC_CONFIG_OK;
576 silc_free(tmp->file);
582 SILC_CONFIG_CALLBACK(fetch_connparam)
584 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
586 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
587 type, name, context));
589 if (type == SILC_CONFIG_ARG_BLOCK) {
591 return SILC_CONFIG_OK;
594 got_errno = SILC_CONFIG_EMISSFIELDS;
599 my_set_param_defaults(tmp, &config->param);
601 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
603 return SILC_CONFIG_OK;
606 /* if there isn't a temporary struct alloc one */
608 config->tmp = silc_calloc(1, sizeof(*findtmp));
609 tmp = (SilcServerConfigConnParams *) config->tmp;
612 if (!strcmp(name, "name")) {
613 CONFIG_IS_DOUBLE(tmp->name);
614 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
616 else if (!strcmp(name, "connections_max")) {
617 tmp->connections_max = *(SilcUInt32 *)val;
619 else if (!strcmp(name, "connections_max_per_host")) {
620 tmp->connections_max_per_host = *(SilcUInt32 *)val;
622 else if (!strcmp(name, "keepalive_secs")) {
623 tmp->keepalive_secs = *(SilcUInt32 *)val;
625 else if (!strcmp(name, "reconnect_count")) {
626 tmp->reconnect_count = *(SilcUInt32 *)val;
628 else if (!strcmp(name, "reconnect_interval")) {
629 tmp->reconnect_interval = *(SilcUInt32 *)val;
631 else if (!strcmp(name, "reconnect_interval_max")) {
632 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
634 else if (!strcmp(name, "reconnect_keep_trying")) {
635 tmp->reconnect_keep_trying = *(bool *)val;
637 else if (!strcmp(name, "key_exchange_rekey")) {
638 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "key_exchange_pfs")) {
641 tmp->key_exchange_pfs = *(bool *)val;
643 else if (!strcmp(name, "version_protocol")) {
644 CONFIG_IS_DOUBLE(tmp->version_protocol);
645 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
647 else if (!strcmp(name, "version_software")) {
648 CONFIG_IS_DOUBLE(tmp->version_software);
649 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
651 else if (!strcmp(name, "version_software_vendor")) {
652 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
653 tmp->version_software_vendor =
654 (*(char *)val ? strdup((char *) val) : NULL);
657 return SILC_CONFIG_EINTERNAL;
659 return SILC_CONFIG_OK;
662 silc_free(tmp->name);
668 SILC_CONFIG_CALLBACK(fetch_client)
670 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
672 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
673 type, name, context));
675 /* alloc tmp before block checking (empty sub-blocks are welcome here) */
677 config->tmp = silc_calloc(1, sizeof(*findtmp));
678 tmp = (SilcServerConfigClient *) config->tmp;
681 if (type == SILC_CONFIG_ARG_BLOCK) {
682 /* closing the block */
683 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
685 return SILC_CONFIG_OK;
688 /* Identify and save this value */
689 if (!strcmp(name, "host")) {
690 CONFIG_IS_DOUBLE(tmp->host);
691 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
693 else if (!strcmp(name, "passphrase")) {
694 CONFIG_IS_DOUBLE(tmp->passphrase);
695 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
696 (void **)&tmp->passphrase,
697 &tmp->passphrase_len)) {
698 got_errno = SILC_CONFIG_ESILENT;
702 else if (!strcmp(name, "publickey")) {
703 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
704 (void **)&tmp->publickeys, NULL)) {
705 got_errno = SILC_CONFIG_ESILENT;
709 else if (!strcmp(name, "params")) {
710 CONFIG_IS_DOUBLE(tmp->param);
711 tmp->param = my_find_param(config, (char *) val, line);
712 if (!tmp->param) { /* error already output */
713 got_errno = SILC_CONFIG_ESILENT;
718 return SILC_CONFIG_EINTERNAL;
719 return SILC_CONFIG_OK;
722 silc_free(tmp->host);
723 CONFIG_FREE_AUTH(tmp);
729 SILC_CONFIG_CALLBACK(fetch_admin)
731 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
733 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
734 type, name, context));
736 if (type == SILC_CONFIG_ARG_BLOCK) {
737 /* check the temporary struct's fields */
738 if (!tmp) /* empty sub-block? */
739 return SILC_CONFIG_OK;
741 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
743 return SILC_CONFIG_OK;
746 /* if there isn't a temporary struct alloc one */
748 config->tmp = silc_calloc(1, sizeof(*findtmp));
749 tmp = (SilcServerConfigAdmin *) config->tmp;
752 /* Identify and save this value */
753 if (!strcmp(name, "host")) {
754 CONFIG_IS_DOUBLE(tmp->host);
755 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
757 else if (!strcmp(name, "user")) {
758 CONFIG_IS_DOUBLE(tmp->user);
759 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
761 else if (!strcmp(name, "nick")) {
762 CONFIG_IS_DOUBLE(tmp->nick);
763 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
765 else if (!strcmp(name, "passphrase")) {
766 CONFIG_IS_DOUBLE(tmp->passphrase);
767 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
768 (void **)&tmp->passphrase,
769 &tmp->passphrase_len)) {
770 got_errno = SILC_CONFIG_ESILENT;
774 else if (!strcmp(name, "publickey")) {
775 CONFIG_IS_DOUBLE(tmp->publickeys);
776 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
777 (void **)&tmp->publickeys, NULL)) {
778 got_errno = SILC_CONFIG_ESILENT;
783 return SILC_CONFIG_EINTERNAL;
784 return SILC_CONFIG_OK;
787 silc_free(tmp->host);
788 silc_free(tmp->user);
789 silc_free(tmp->nick);
790 CONFIG_FREE_AUTH(tmp);
796 SILC_CONFIG_CALLBACK(fetch_deny)
798 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
800 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
801 type, name, context));
802 if (type == SILC_CONFIG_ARG_BLOCK) {
803 /* check the temporary struct's fields */
804 if (!tmp) /* empty sub-block? */
805 return SILC_CONFIG_OK;
807 got_errno = SILC_CONFIG_EMISSFIELDS;
810 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
812 return SILC_CONFIG_OK;
814 /* if there isn't a temporary struct alloc one */
816 config->tmp = silc_calloc(1, sizeof(*findtmp));
817 tmp = (SilcServerConfigDeny *) config->tmp;
820 /* Identify and save this value */
821 if (!strcmp(name, "host")) {
822 CONFIG_IS_DOUBLE(tmp->host);
823 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
825 else if (!strcmp(name, "reason")) {
826 CONFIG_IS_DOUBLE(tmp->reason);
827 tmp->reason = strdup((char *) val);
830 return SILC_CONFIG_EINTERNAL;
831 return SILC_CONFIG_OK;
834 silc_free(tmp->host);
835 silc_free(tmp->reason);
841 SILC_CONFIG_CALLBACK(fetch_server)
843 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
845 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
846 type, name, context));
848 if (type == SILC_CONFIG_ARG_BLOCK) {
849 /* check the temporary struct's fields */
850 if (!tmp) /* empty sub-block? */
851 return SILC_CONFIG_OK;
853 /* the temporary struct is ok, append it to the list */
854 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
856 return SILC_CONFIG_OK;
859 /* if there isn't a temporary struct alloc one */
861 config->tmp = silc_calloc(1, sizeof(*findtmp));
862 tmp = (SilcServerConfigServer *) config->tmp;
865 /* Identify and save this value */
866 if (!strcmp(name, "host")) {
867 CONFIG_IS_DOUBLE(tmp->host);
868 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
870 else if (!strcmp(name, "passphrase")) {
871 CONFIG_IS_DOUBLE(tmp->passphrase);
872 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
873 (void **)&tmp->passphrase,
874 &tmp->passphrase_len)) {
875 got_errno = SILC_CONFIG_ESILENT;
879 else if (!strcmp(name, "publickey")) {
880 CONFIG_IS_DOUBLE(tmp->publickeys);
881 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
882 (void **)&tmp->publickeys, NULL)) {
883 got_errno = SILC_CONFIG_ESILENT;
887 else if (!strcmp(name, "params")) {
888 CONFIG_IS_DOUBLE(tmp->param);
889 tmp->param = my_find_param(config, (char *) val, line);
890 if (!tmp->param) { /* error already output */
891 got_errno = SILC_CONFIG_ESILENT;
895 else if (!strcmp(name, "backup")) {
896 tmp->backup_router = *(bool *)val;
899 return SILC_CONFIG_EINTERNAL;
901 return SILC_CONFIG_OK;
904 silc_free(tmp->host);
905 CONFIG_FREE_AUTH(tmp);
911 SILC_CONFIG_CALLBACK(fetch_router)
913 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
915 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
916 type, name, context));
918 if (type == SILC_CONFIG_ARG_BLOCK) {
919 if (!tmp) /* empty sub-block? */
920 return SILC_CONFIG_OK;
922 /* the temporary struct is ok, append it to the list */
923 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
925 return SILC_CONFIG_OK;
928 /* if there isn't a temporary struct alloc one */
930 config->tmp = silc_calloc(1, sizeof(*findtmp));
931 tmp = (SilcServerConfigRouter *) config->tmp;
934 /* Identify and save this value */
935 if (!strcmp(name, "host")) {
936 CONFIG_IS_DOUBLE(tmp->host);
937 tmp->host = strdup((char *) val);
939 else if (!strcmp(name, "port")) {
940 int port = *(int *)val;
941 if ((port <= 0) || (port > 65535)) {
942 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
943 return SILC_CONFIG_ESILENT;
945 tmp->port = (SilcUInt16) port;
947 else if (!strcmp(name, "passphrase")) {
948 CONFIG_IS_DOUBLE(tmp->passphrase);
949 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
950 (void **)&tmp->passphrase,
951 &tmp->passphrase_len)) {
952 got_errno = SILC_CONFIG_ESILENT;
956 else if (!strcmp(name, "publickey")) {
957 CONFIG_IS_DOUBLE(tmp->publickeys);
958 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
959 (void **)&tmp->publickeys, NULL)) {
960 got_errno = SILC_CONFIG_ESILENT;
964 else if (!strcmp(name, "params")) {
965 CONFIG_IS_DOUBLE(tmp->param);
966 tmp->param = my_find_param(config, (char *) val, line);
967 if (!tmp->param) { /* error already output */
968 got_errno = SILC_CONFIG_ESILENT;
972 else if (!strcmp(name, "initiator")) {
973 tmp->initiator = *(bool *)val;
975 else if (!strcmp(name, "backuphost")) {
976 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
977 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
980 else if (!strcmp(name, "backupport")) {
981 int port = *(int *)val;
982 if ((port <= 0) || (port > 65535)) {
983 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
984 return SILC_CONFIG_ESILENT;
986 tmp->backup_replace_port = (SilcUInt16) port;
988 else if (!strcmp(name, "backuplocal")) {
989 tmp->backup_local = *(bool *)val;
992 return SILC_CONFIG_EINTERNAL;
994 return SILC_CONFIG_OK;
997 silc_free(tmp->host);
998 silc_free(tmp->backup_replace_ip);
999 CONFIG_FREE_AUTH(tmp);
1005 /* known config options tables */
1006 static const SilcConfigTable table_general[] = {
1007 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1008 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1009 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1010 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1011 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1012 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1014 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1017 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1018 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1019 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1020 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1021 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1022 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1023 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1024 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1028 static const SilcConfigTable table_cipher[] = {
1029 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1030 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1031 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1032 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1036 static const SilcConfigTable table_hash[] = {
1037 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1038 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1039 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1040 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1044 static const SilcConfigTable table_hmac[] = {
1045 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1046 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1047 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1051 static const SilcConfigTable table_pkcs[] = {
1052 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1056 static const SilcConfigTable table_serverinfo[] = {
1057 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1058 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1059 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1060 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1061 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1062 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1063 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1069 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1073 static const SilcConfigTable table_logging_c[] = {
1074 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1075 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1076 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1080 static const SilcConfigTable table_logging[] = {
1081 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1082 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1083 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1084 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1085 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1086 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1090 static const SilcConfigTable table_connparam[] = {
1091 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1092 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1093 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1094 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1095 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1096 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1097 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1098 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1099 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1100 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1102 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1103 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1104 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1108 static const SilcConfigTable table_client[] = {
1109 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1110 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1111 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1112 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1116 static const SilcConfigTable table_admin[] = {
1117 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1118 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1119 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1120 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1121 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1122 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1123 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1127 static const SilcConfigTable table_deny[] = {
1128 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1129 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1133 static const SilcConfigTable table_serverconn[] = {
1134 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1135 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1136 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1137 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1138 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1142 static const SilcConfigTable table_routerconn[] = {
1143 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1144 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1145 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1146 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1147 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1148 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1149 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1150 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1151 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1155 static const SilcConfigTable table_main[] = {
1156 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1157 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1158 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1159 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1160 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1161 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1162 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1163 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1164 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1165 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1166 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1167 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1168 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1172 /* Set default values to stuff that was not configured. */
1174 static void silc_server_config_set_defaults(SilcServerConfig config)
1176 my_set_param_defaults(&config->param, NULL);
1178 config->channel_rekey_secs = (config->channel_rekey_secs ?
1179 config->channel_rekey_secs :
1180 SILC_SERVER_CHANNEL_REKEY);
1181 config->key_exchange_timeout = (config->key_exchange_timeout ?
1182 config->key_exchange_timeout :
1183 SILC_SERVER_SKE_TIMEOUT);
1184 config->conn_auth_timeout = (config->conn_auth_timeout ?
1185 config->conn_auth_timeout :
1186 SILC_SERVER_CONNAUTH_TIMEOUT);
1189 /* Allocates a new configuration object, opens configuration file and
1190 parses it. The parsed data is returned to the newly allocated
1191 configuration object. The SilcServerConfig must be freed by calling
1192 the silc_server_config_destroy function. */
1194 SilcServerConfig silc_server_config_alloc(const char *filename)
1196 SilcServerConfig config_new;
1197 SilcConfigEntity ent;
1198 SilcConfigFile *file;
1200 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1202 /* alloc a config object */
1203 config_new = silc_calloc(1, sizeof(*config_new));
1207 /* obtain a config file object */
1208 file = silc_config_open(filename);
1210 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1215 /* obtain a SilcConfig entity, we can use it to start the parsing */
1216 ent = silc_config_init(file);
1218 /* load the known configuration options, give our empty object as context */
1219 silc_config_register_table(ent, table_main, (void *) config_new);
1221 /* enter the main parsing loop. When this returns, we have the parsing
1222 * result and the object filled (or partially, in case of errors). */
1223 ret = silc_config_main(ent);
1224 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1225 silc_config_strerror(ret)));
1227 /* Check if the parser returned errors */
1229 /* handle this special error return which asks to quietly return */
1230 if (ret != SILC_CONFIG_ESILENT) {
1231 char *linebuf, *filename = silc_config_get_filename(file);
1232 SilcUInt32 line = silc_config_get_line(file);
1233 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1234 silc_config_strerror(ret)));
1235 linebuf = silc_config_read_line(file, line);
1236 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1240 silc_server_config_destroy(config_new);
1244 /* close (destroy) the file object */
1245 silc_config_close(file);
1247 /* If config_new is incomplete, abort the object and return NULL */
1248 if (!config_new->server_info) {
1249 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1250 "`server_info'\n"));
1251 silc_server_config_destroy(config_new);
1255 /* XXX are there any other mandatory sections in the config file? */
1257 /* Set default to configuration parameters */
1258 silc_server_config_set_defaults(config_new);
1260 config_new->refcount = 1;
1264 /* Increments the reference counter of a config object */
1266 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1271 ref->config = config;
1272 ref->ref_ptr = ref_ptr;
1273 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %hu->%hu", config,
1274 config->refcount - 1, config->refcount));
1278 /* Decrements the reference counter of a config object. If the counter
1279 reaches 0, the config object is destroyed. */
1281 void silc_server_config_unref(SilcServerConfigRef *ref)
1284 silc_server_config_destroy(ref->config);
1287 /* Destroy a config object with all his children lists */
1289 void silc_server_config_destroy(SilcServerConfig config)
1294 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
1295 config->refcount + 1, config->refcount));
1296 if (config->refcount > 0)
1299 SILC_LOG_DEBUG(("Freeing config context"));
1301 /* Destroy general config stuff */
1302 silc_free(config->module_path);
1303 silc_free(config->param.version_protocol);
1304 silc_free(config->param.version_software);
1305 silc_free(config->param.version_software_vendor);
1307 /* Destroy Logging channels */
1308 if (config->logging_info)
1309 silc_free(config->logging_info->file);
1310 if (config->logging_warnings)
1311 silc_free(config->logging_warnings->file);
1312 if (config->logging_errors)
1313 silc_free(config->logging_errors->file);
1314 if (config->logging_fatals)
1315 silc_free(config->logging_fatals->file);
1317 /* Destroy the ServerInfo struct */
1318 if (config->server_info) {
1319 register SilcServerConfigServerInfo *si = config->server_info;
1320 silc_free(si->server_name);
1321 silc_free(si->server_ip);
1322 silc_free(si->server_type);
1323 silc_free(si->location);
1324 silc_free(si->admin);
1325 silc_free(si->email);
1326 silc_free(si->user);
1327 silc_free(si->group);
1328 silc_free(si->motd_file);
1329 silc_free(si->pid_file);
1330 silc_pkcs_public_key_free(si->public_key);
1331 silc_pkcs_private_key_free(si->private_key);
1334 /* Now let's destroy the lists */
1336 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1338 silc_free(di->name);
1339 silc_free(di->module);
1342 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1343 silc_free(di->name);
1344 silc_free(di->module);
1347 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1348 silc_free(di->name);
1349 silc_free(di->hash);
1352 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1353 silc_free(di->name);
1356 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1357 config->conn_params)
1358 silc_free(di->name);
1359 silc_free(di->version_protocol);
1360 silc_free(di->version_software);
1361 silc_free(di->version_software_vendor);
1364 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1365 silc_free(di->host);
1366 CONFIG_FREE_AUTH(di);
1369 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1370 silc_free(di->host);
1371 silc_free(di->user);
1372 silc_free(di->nick);
1373 CONFIG_FREE_AUTH(di);
1376 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1377 silc_free(di->host);
1378 silc_free(di->reason);
1381 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1383 silc_free(di->host);
1384 CONFIG_FREE_AUTH(di);
1387 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1389 silc_free(di->host);
1390 silc_free(di->backup_replace_ip);
1391 CONFIG_FREE_AUTH(di);
1395 memset(config, 'F', sizeof(*config));
1399 /* Registers configured ciphers. These can then be allocated by the
1400 server when needed. */
1402 bool silc_server_config_register_ciphers(SilcServer server)
1404 SilcServerConfig config = server->config;
1405 SilcServerConfigCipher *cipher = config->cipher;
1406 char *module_path = config->module_path;
1408 SILC_LOG_DEBUG(("Registering configured ciphers"));
1410 if (!cipher) /* any cipher in the config file? */
1414 /* if there isn't a module_path OR there isn't a module sim name try to
1415 * use buil-in functions */
1416 if (!module_path || !cipher->module) {
1418 for (i = 0; silc_default_ciphers[i].name; i++)
1419 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1420 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1423 if (!silc_cipher_is_supported(cipher->name)) {
1424 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1425 silc_server_stop(server);
1430 /* Load (try at least) the crypto SIM module */
1431 char buf[1023], *alg_name;
1432 SilcCipherObject cipher_obj;
1435 memset(&cipher_obj, 0, sizeof(cipher_obj));
1436 cipher_obj.name = cipher->name;
1437 cipher_obj.block_len = cipher->block_length;
1438 cipher_obj.key_len = cipher->key_length * 8;
1440 /* build the libname */
1441 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1443 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1445 alg_name = strdup(cipher->name);
1446 if (strchr(alg_name, '-'))
1447 *strchr(alg_name, '-') = '\0';
1449 if (silc_sim_load(sim)) {
1450 cipher_obj.set_key =
1451 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1452 SILC_CIPHER_SIM_SET_KEY));
1453 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1454 cipher_obj.set_key_with_string =
1455 silc_sim_getsym(sim,
1456 silc_sim_symname(alg_name,
1457 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1458 SILC_LOG_DEBUG(("set_key_with_string=%p",
1459 cipher_obj.set_key_with_string));
1460 cipher_obj.encrypt =
1461 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1462 SILC_CIPHER_SIM_ENCRYPT_CBC));
1463 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1464 cipher_obj.decrypt =
1465 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1466 SILC_CIPHER_SIM_DECRYPT_CBC));
1467 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1468 cipher_obj.context_len =
1469 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1470 SILC_CIPHER_SIM_CONTEXT_LEN));
1471 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1473 /* Put the SIM to the list of all SIM's in server */
1474 silc_dlist_add(server->sim, sim);
1476 silc_free(alg_name);
1478 SILC_LOG_ERROR(("Error configuring ciphers"));
1479 silc_server_stop(server);
1483 /* Register the cipher */
1484 silc_cipher_register(&cipher_obj);
1486 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1487 "can't load modules!"));
1488 silc_server_stop(server);
1492 cipher = cipher->next;
1498 /* Registers configured hash functions. These can then be allocated by the
1499 server when needed. */
1501 bool silc_server_config_register_hashfuncs(SilcServer server)
1503 SilcServerConfig config = server->config;
1504 SilcServerConfigHash *hash = config->hash;
1505 char *module_path = config->module_path;
1507 SILC_LOG_DEBUG(("Registering configured hash functions"));
1509 if (!hash) /* any hash func in the config file? */
1513 /* if there isn't a module_path OR there isn't a module sim name try to
1514 * use buil-in functions */
1515 if (!module_path || !hash->module) {
1517 for (i = 0; silc_default_hash[i].name; i++)
1518 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1519 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1522 if (!silc_hash_is_supported(hash->name)) {
1523 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1524 silc_server_stop(server);
1529 /* Load (try at least) the hash SIM module */
1530 SilcHashObject hash_obj;
1533 memset(&hash_obj, 0, sizeof(hash_obj));
1534 hash_obj.name = hash->name;
1535 hash_obj.block_len = hash->block_length;
1536 hash_obj.hash_len = hash->digest_length;
1538 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1540 if ((silc_sim_load(sim))) {
1542 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1543 SILC_HASH_SIM_INIT));
1544 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1546 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1547 SILC_HASH_SIM_UPDATE));
1548 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1550 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1551 SILC_HASH_SIM_FINAL));
1552 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1553 hash_obj.context_len =
1554 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1555 SILC_HASH_SIM_CONTEXT_LEN));
1556 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1558 /* Put the SIM to the table of all SIM's in server */
1559 silc_dlist_add(server->sim, sim);
1561 SILC_LOG_ERROR(("Error configuring hash functions"));
1562 silc_server_stop(server);
1566 /* Register the hash function */
1567 silc_hash_register(&hash_obj);
1569 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1570 "can't load modules!"));
1571 silc_server_stop(server);
1581 /* Registers configure HMACs. These can then be allocated by the server
1584 bool silc_server_config_register_hmacs(SilcServer server)
1586 SilcServerConfig config = server->config;
1587 SilcServerConfigHmac *hmac = config->hmac;
1589 SILC_LOG_DEBUG(("Registering configured HMACs"));
1595 SilcHmacObject hmac_obj;
1596 if (!silc_hash_is_supported(hmac->hash)) {
1597 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1598 silc_server_stop(server);
1602 /* Register the HMAC */
1603 memset(&hmac_obj, 0, sizeof(hmac_obj));
1604 hmac_obj.name = hmac->name;
1605 hmac_obj.len = hmac->mac_length;
1606 silc_hmac_register(&hmac_obj);
1614 /* Registers configured PKCS's. */
1616 bool silc_server_config_register_pkcs(SilcServer server)
1618 SilcServerConfig config = server->config;
1619 SilcServerConfigPkcs *pkcs = config->pkcs;
1621 SILC_LOG_DEBUG(("Registering configured PKCS"));
1628 for (i = 0; silc_default_pkcs[i].name; i++)
1629 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1630 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1633 if (!silc_pkcs_is_supported(pkcs->name)) {
1634 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1635 silc_server_stop(server);
1644 /* Sets log files where log messages are saved by the server logger. */
1646 void silc_server_config_setlogfiles(SilcServer server)
1648 SilcServerConfig config = server->config;
1649 SilcServerConfigLogging *this;
1651 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1653 silc_log_quick = config->logging_quick;
1654 silc_log_flushdelay = (config->logging_flushdelay ?
1655 config->logging_flushdelay :
1656 SILC_SERVER_LOG_FLUSH_DELAY);
1658 if ((this = config->logging_fatals))
1659 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1661 if ((this = config->logging_errors))
1662 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1664 if ((this = config->logging_warnings))
1665 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1667 if ((this = config->logging_info))
1668 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1672 /* Returns client authentication information from configuration file by host
1675 SilcServerConfigClient *
1676 silc_server_config_find_client(SilcServer server, char *host)
1678 SilcServerConfig config = server->config;
1679 SilcServerConfigClient *client;
1681 if (!config || !host)
1684 for (client = config->clients; client; client = client->next) {
1685 if (client->host && !silc_string_compare(client->host, host))
1690 /* if none matched, then client is already NULL */
1694 /* Returns admin connection configuration by host, username and/or
1697 SilcServerConfigAdmin *
1698 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1701 SilcServerConfig config = server->config;
1702 SilcServerConfigAdmin *admin;
1704 /* make sure we have a value for the matching parameters */
1712 for (admin = config->admins; admin; admin = admin->next) {
1713 if (admin->host && !silc_string_compare(admin->host, host))
1715 if (admin->user && !silc_string_compare(admin->user, user))
1717 if (admin->nick && !silc_string_compare(admin->nick, nick))
1719 /* no checks failed -> this entry matches */
1723 /* if none matched, then admin is already NULL */
1727 /* Returns the denied connection configuration entry by host. */
1729 SilcServerConfigDeny *
1730 silc_server_config_find_denied(SilcServer server, char *host)
1732 SilcServerConfig config = server->config;
1733 SilcServerConfigDeny *deny;
1735 /* make sure we have a value for the matching parameters */
1736 if (!config || !host)
1739 for (deny = config->denied; deny; deny = deny->next) {
1740 if (deny->host && !silc_string_compare(deny->host, host))
1745 /* if none matched, then deny is already NULL */
1749 /* Returns server connection info from server configuartion by host
1752 SilcServerConfigServer *
1753 silc_server_config_find_server_conn(SilcServer server, char *host)
1755 SilcServerConfig config = server->config;
1756 SilcServerConfigServer *serv = NULL;
1761 if (!config->servers)
1764 for (serv = config->servers; serv; serv = serv->next) {
1765 if (!silc_string_compare(serv->host, host))
1773 /* Returns router connection info from server configuration by
1774 host (name or ip). */
1776 SilcServerConfigRouter *
1777 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1779 SilcServerConfig config = server->config;
1780 SilcServerConfigRouter *serv = NULL;
1785 if (!config->routers)
1788 for (serv = config->routers; serv; serv = serv->next) {
1789 if (!silc_string_compare(serv->host, host))
1791 if (port && serv->port && serv->port != port)
1799 /* Returns TRUE if configuration for a router connection that we are
1800 initiating exists. */
1802 bool silc_server_config_is_primary_route(SilcServer server)
1804 SilcServerConfig config = server->config;
1805 SilcServerConfigRouter *serv = NULL;
1809 serv = config->routers;
1810 for (i = 0; serv; i++) {
1811 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1822 /* Returns our primary connection configuration or NULL if we do not
1823 have primary router configured. */
1825 SilcServerConfigRouter *
1826 silc_server_config_get_primary_router(SilcServer server)
1828 SilcServerConfig config = server->config;
1829 SilcServerConfigRouter *serv = NULL;
1832 serv = config->routers;
1833 for (i = 0; serv; i++) {
1834 if (serv->initiator == TRUE && serv->backup_router == FALSE)