5 Author: Johnny Mnemonic <johnny@themnemonic.org>
7 Copyright (C) 1997 - 2002 Johnny Mnemonic
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 return SILC_CONFIG_OK;
435 if (!strcmp(name, "hostname")) {
436 CONFIG_IS_DOUBLE(server_info->server_name);
437 server_info->server_name = strdup((char *) val);
439 else if (!strcmp(name, "ip")) {
440 CONFIG_IS_DOUBLE(server_info->server_ip);
441 server_info->server_ip = strdup((char *) val);
443 else if (!strcmp(name, "port")) {
444 int port = *(int *)val;
445 if ((port <= 0) || (port > 65535)) {
446 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
447 return SILC_CONFIG_ESILENT;
449 server_info->port = (SilcUInt16) port;
451 else if (!strcmp(name, "servertype")) {
452 CONFIG_IS_DOUBLE(server_info->server_type);
453 server_info->server_type = strdup((char *) val);
455 else if (!strcmp(name, "admin")) {
456 CONFIG_IS_DOUBLE(server_info->admin);
457 server_info->admin = strdup((char *) val);
459 else if (!strcmp(name, "adminemail")) {
460 CONFIG_IS_DOUBLE(server_info->email);
461 server_info->email = strdup((char *) val);
463 else if (!strcmp(name, "location")) {
464 CONFIG_IS_DOUBLE(server_info->location);
465 server_info->location = strdup((char *) val);
467 else if (!strcmp(name, "user")) {
468 CONFIG_IS_DOUBLE(server_info->user);
469 server_info->user = strdup((char *) val);
471 else if (!strcmp(name, "group")) {
472 CONFIG_IS_DOUBLE(server_info->group);
473 server_info->group = strdup((char *) val);
475 else if (!strcmp(name, "motdfile")) {
476 CONFIG_IS_DOUBLE(server_info->motd_file);
477 server_info->motd_file = strdup((char *) val);
479 else if (!strcmp(name, "pidfile")) {
480 CONFIG_IS_DOUBLE(server_info->pid_file);
481 server_info->pid_file = strdup((char *) val);
483 else if (!strcmp(name, "publickey")) {
484 char *file_tmp = (char *) val;
486 /* try to load specified file, if fail stop config parsing */
487 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
489 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
490 SILC_PKCS_FILE_BIN)) {
491 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
492 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
493 return SILC_CONFIG_ESILENT;
496 else if (!strcmp(name, "privatekey")) {
497 char *file_tmp = (char *) val;
499 /* try to load specified file, if fail stop config parsing */
500 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
502 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
503 SILC_PKCS_FILE_PEM)) {
504 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
505 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
506 return SILC_CONFIG_ESILENT;
510 return SILC_CONFIG_EINTERNAL;
511 return SILC_CONFIG_OK;
517 SILC_CONFIG_CALLBACK(fetch_logging)
519 SilcServerConfig config = (SilcServerConfig) context;
520 SilcServerConfigLogging *tmp =
521 (SilcServerConfigLogging *) config->tmp;
524 if (!strcmp(name, "quicklogs")) {
525 config->logging_quick = *(bool *)val;
527 else if (!strcmp(name, "flushdelay")) {
528 int flushdelay = *(int *)val;
529 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
530 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use "
531 "quicklogs if you want real-time logging.\n", line));
532 return SILC_CONFIG_ESILENT;
534 config->logging_flushdelay = (long) flushdelay;
536 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
537 else if (!strcmp(name, __chan__)) { \
538 if (!tmp) return SILC_CONFIG_OK; \
540 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
542 config->__member__ = tmp; \
543 config->tmp = NULL; \
545 FETCH_LOGGING_CHAN("info", logging_info)
546 FETCH_LOGGING_CHAN("warnings", logging_warnings)
547 FETCH_LOGGING_CHAN("errors", logging_errors)
548 FETCH_LOGGING_CHAN("fatals", logging_fatals)
549 #undef FETCH_LOGGING_CHAN
550 else if (!strcmp(name, "file")) {
551 if (!tmp) { /* FIXME: what the fuck is this? */
552 config->tmp = silc_calloc(1, sizeof(*tmp));
553 tmp = (SilcServerConfigLogging *) config->tmp;
556 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
558 tmp->file = strdup((char *) val);
560 else if (!strcmp(name, "size")) {
562 config->tmp = silc_calloc(1, sizeof(*tmp));
563 tmp = (SilcServerConfigLogging *) config->tmp;
565 tmp->maxsize = *(SilcUInt32 *) val;
568 return SILC_CONFIG_EINTERNAL;
569 return SILC_CONFIG_OK;
572 silc_free(tmp->file);
578 SILC_CONFIG_CALLBACK(fetch_connparam)
580 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
582 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
583 type, name, context));
585 if (type == SILC_CONFIG_ARG_BLOCK) {
587 return SILC_CONFIG_OK;
590 got_errno = SILC_CONFIG_EMISSFIELDS;
595 my_set_param_defaults(tmp, &config->param);
597 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
599 return SILC_CONFIG_OK;
602 /* if there isn't a temporary struct alloc one */
604 config->tmp = silc_calloc(1, sizeof(*findtmp));
605 tmp = (SilcServerConfigConnParams *) config->tmp;
608 if (!strcmp(name, "name")) {
609 CONFIG_IS_DOUBLE(tmp->name);
610 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
612 else if (!strcmp(name, "connections_max")) {
613 tmp->connections_max = *(SilcUInt32 *)val;
615 else if (!strcmp(name, "connections_max_per_host")) {
616 tmp->connections_max_per_host = *(SilcUInt32 *)val;
618 else if (!strcmp(name, "keepalive_secs")) {
619 tmp->keepalive_secs = *(SilcUInt32 *)val;
621 else if (!strcmp(name, "reconnect_count")) {
622 tmp->reconnect_count = *(SilcUInt32 *)val;
624 else if (!strcmp(name, "reconnect_interval")) {
625 tmp->reconnect_interval = *(SilcUInt32 *)val;
627 else if (!strcmp(name, "reconnect_interval_max")) {
628 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
630 else if (!strcmp(name, "reconnect_keep_trying")) {
631 tmp->reconnect_keep_trying = *(bool *)val;
633 else if (!strcmp(name, "key_exchange_rekey")) {
634 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
636 else if (!strcmp(name, "key_exchange_pfs")) {
637 tmp->key_exchange_pfs = *(bool *)val;
639 else if (!strcmp(name, "version_protocol")) {
640 CONFIG_IS_DOUBLE(tmp->version_protocol);
641 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
643 else if (!strcmp(name, "version_software")) {
644 CONFIG_IS_DOUBLE(tmp->version_software);
645 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
647 else if (!strcmp(name, "version_software_vendor")) {
648 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
649 tmp->version_software_vendor =
650 (*(char *)val ? strdup((char *) val) : NULL);
653 return SILC_CONFIG_EINTERNAL;
655 return SILC_CONFIG_OK;
658 silc_free(tmp->name);
664 SILC_CONFIG_CALLBACK(fetch_client)
666 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
668 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
669 type, name, context));
671 /* alloc tmp before block checking (empty sub-blocks are welcome here) */
673 config->tmp = silc_calloc(1, sizeof(*findtmp));
674 tmp = (SilcServerConfigClient *) config->tmp;
677 if (type == SILC_CONFIG_ARG_BLOCK) {
678 /* closing the block */
679 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
681 return SILC_CONFIG_OK;
684 /* Identify and save this value */
685 if (!strcmp(name, "host")) {
686 CONFIG_IS_DOUBLE(tmp->host);
687 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
689 else if (!strcmp(name, "passphrase")) {
690 CONFIG_IS_DOUBLE(tmp->passphrase);
691 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
692 (void **)&tmp->passphrase,
693 &tmp->passphrase_len)) {
694 got_errno = SILC_CONFIG_ESILENT;
698 else if (!strcmp(name, "publickey")) {
699 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
700 (void **)&tmp->publickeys, NULL)) {
701 got_errno = SILC_CONFIG_ESILENT;
705 else if (!strcmp(name, "params")) {
706 CONFIG_IS_DOUBLE(tmp->param);
707 tmp->param = my_find_param(config, (char *) val, line);
708 if (!tmp->param) { /* error already output */
709 got_errno = SILC_CONFIG_ESILENT;
714 return SILC_CONFIG_EINTERNAL;
715 return SILC_CONFIG_OK;
718 silc_free(tmp->host);
719 CONFIG_FREE_AUTH(tmp);
725 SILC_CONFIG_CALLBACK(fetch_admin)
727 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
729 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
730 type, name, context));
732 if (type == SILC_CONFIG_ARG_BLOCK) {
733 /* check the temporary struct's fields */
734 if (!tmp) /* empty sub-block? */
735 return SILC_CONFIG_OK;
737 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
739 return SILC_CONFIG_OK;
742 /* if there isn't a temporary struct alloc one */
744 config->tmp = silc_calloc(1, sizeof(*findtmp));
745 tmp = (SilcServerConfigAdmin *) config->tmp;
748 /* Identify and save this value */
749 if (!strcmp(name, "host")) {
750 CONFIG_IS_DOUBLE(tmp->host);
751 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
753 else if (!strcmp(name, "user")) {
754 CONFIG_IS_DOUBLE(tmp->user);
755 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
757 else if (!strcmp(name, "nick")) {
758 CONFIG_IS_DOUBLE(tmp->nick);
759 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
761 else if (!strcmp(name, "passphrase")) {
762 CONFIG_IS_DOUBLE(tmp->passphrase);
763 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
764 (void **)&tmp->passphrase,
765 &tmp->passphrase_len)) {
766 got_errno = SILC_CONFIG_ESILENT;
770 else if (!strcmp(name, "publickey")) {
771 CONFIG_IS_DOUBLE(tmp->publickeys);
772 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
773 (void **)&tmp->publickeys, NULL)) {
774 got_errno = SILC_CONFIG_ESILENT;
779 return SILC_CONFIG_EINTERNAL;
780 return SILC_CONFIG_OK;
783 silc_free(tmp->host);
784 silc_free(tmp->user);
785 silc_free(tmp->nick);
786 CONFIG_FREE_AUTH(tmp);
792 SILC_CONFIG_CALLBACK(fetch_deny)
794 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
796 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
797 type, name, context));
798 if (type == SILC_CONFIG_ARG_BLOCK) {
799 /* check the temporary struct's fields */
800 if (!tmp) /* empty sub-block? */
801 return SILC_CONFIG_OK;
803 got_errno = SILC_CONFIG_EMISSFIELDS;
806 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
808 return SILC_CONFIG_OK;
810 /* if there isn't a temporary struct alloc one */
812 config->tmp = silc_calloc(1, sizeof(*findtmp));
813 tmp = (SilcServerConfigDeny *) config->tmp;
816 /* Identify and save this value */
817 if (!strcmp(name, "host")) {
818 CONFIG_IS_DOUBLE(tmp->host);
819 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
821 else if (!strcmp(name, "reason")) {
822 CONFIG_IS_DOUBLE(tmp->reason);
823 tmp->reason = strdup((char *) val);
826 return SILC_CONFIG_EINTERNAL;
827 return SILC_CONFIG_OK;
830 silc_free(tmp->host);
831 silc_free(tmp->reason);
837 SILC_CONFIG_CALLBACK(fetch_server)
839 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
841 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
842 type, name, context));
844 if (type == SILC_CONFIG_ARG_BLOCK) {
845 /* check the temporary struct's fields */
846 if (!tmp) /* empty sub-block? */
847 return SILC_CONFIG_OK;
849 /* the temporary struct is ok, append it to the list */
850 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
852 return SILC_CONFIG_OK;
855 /* if there isn't a temporary struct alloc one */
857 config->tmp = silc_calloc(1, sizeof(*findtmp));
858 tmp = (SilcServerConfigServer *) config->tmp;
861 /* Identify and save this value */
862 if (!strcmp(name, "host")) {
863 CONFIG_IS_DOUBLE(tmp->host);
864 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
866 else if (!strcmp(name, "passphrase")) {
867 CONFIG_IS_DOUBLE(tmp->passphrase);
868 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
869 (void **)&tmp->passphrase,
870 &tmp->passphrase_len)) {
871 got_errno = SILC_CONFIG_ESILENT;
875 else if (!strcmp(name, "publickey")) {
876 CONFIG_IS_DOUBLE(tmp->publickeys);
877 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
878 (void **)&tmp->publickeys, NULL)) {
879 got_errno = SILC_CONFIG_ESILENT;
883 else if (!strcmp(name, "versionid")) {
884 CONFIG_IS_DOUBLE(tmp->version);
885 tmp->version = strdup((char *) val);
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 silc_free(tmp->version);
906 CONFIG_FREE_AUTH(tmp);
912 SILC_CONFIG_CALLBACK(fetch_router)
914 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
916 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
917 type, name, context));
919 if (type == SILC_CONFIG_ARG_BLOCK) {
920 if (!tmp) /* empty sub-block? */
921 return SILC_CONFIG_OK;
923 /* the temporary struct is ok, append it to the list */
924 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
926 return SILC_CONFIG_OK;
929 /* if there isn't a temporary struct alloc one */
931 config->tmp = silc_calloc(1, sizeof(*findtmp));
932 tmp = (SilcServerConfigRouter *) config->tmp;
935 /* Identify and save this value */
936 if (!strcmp(name, "host")) {
937 CONFIG_IS_DOUBLE(tmp->host);
938 tmp->host = strdup((char *) val);
940 else if (!strcmp(name, "port")) {
941 int port = *(int *)val;
942 if ((port <= 0) || (port > 65535)) {
943 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
944 return SILC_CONFIG_ESILENT;
946 tmp->port = (SilcUInt16) port;
948 else if (!strcmp(name, "passphrase")) {
949 CONFIG_IS_DOUBLE(tmp->passphrase);
950 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
951 (void **)&tmp->passphrase,
952 &tmp->passphrase_len)) {
953 got_errno = SILC_CONFIG_ESILENT;
957 else if (!strcmp(name, "publickey")) {
958 CONFIG_IS_DOUBLE(tmp->publickeys);
959 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
960 (void **)&tmp->publickeys, NULL)) {
961 got_errno = SILC_CONFIG_ESILENT;
965 else if (!strcmp(name, "versionid")) {
966 CONFIG_IS_DOUBLE(tmp->version);
967 tmp->version = strdup((char *) val);
969 else if (!strcmp(name, "params")) {
970 CONFIG_IS_DOUBLE(tmp->param);
971 tmp->param = my_find_param(config, (char *) val, line);
972 if (!tmp->param) { /* error already output */
973 got_errno = SILC_CONFIG_ESILENT;
977 else if (!strcmp(name, "initiator")) {
978 tmp->initiator = *(bool *)val;
980 else if (!strcmp(name, "backuphost")) {
981 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
982 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
985 else if (!strcmp(name, "backupport")) {
986 int port = *(int *)val;
987 if ((port <= 0) || (port > 65535)) {
988 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
989 return SILC_CONFIG_ESILENT;
991 tmp->backup_replace_port = (SilcUInt16) port;
993 else if (!strcmp(name, "backuplocal")) {
994 tmp->backup_local = *(bool *)val;
997 return SILC_CONFIG_EINTERNAL;
999 return SILC_CONFIG_OK;
1002 silc_free(tmp->host);
1003 silc_free(tmp->version);
1004 silc_free(tmp->backup_replace_ip);
1005 CONFIG_FREE_AUTH(tmp);
1011 /* known config options tables */
1012 static const SilcConfigTable table_general[] = {
1013 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1014 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1015 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1016 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1017 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1018 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1019 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1020 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1021 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1022 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1023 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1024 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1025 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1026 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1027 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1028 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1029 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1030 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1034 static const SilcConfigTable table_cipher[] = {
1035 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1036 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1037 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1038 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1042 static const SilcConfigTable table_hash[] = {
1043 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1044 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1045 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1046 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1050 static const SilcConfigTable table_hmac[] = {
1051 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1052 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1053 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1057 static const SilcConfigTable table_pkcs[] = {
1058 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1062 static const SilcConfigTable table_serverinfo[] = {
1063 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1066 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1072 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1073 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1074 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1075 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1079 static const SilcConfigTable table_logging_c[] = {
1080 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1081 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1082 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1086 static const SilcConfigTable table_logging[] = {
1087 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1088 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1089 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1090 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1091 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1092 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1096 static const SilcConfigTable table_connparam[] = {
1097 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1098 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1099 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1100 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1103 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1106 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1107 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1108 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1109 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1110 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1114 static const SilcConfigTable table_client[] = {
1115 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1116 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1117 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1118 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1122 static const SilcConfigTable table_admin[] = {
1123 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1124 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1125 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1126 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1127 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1128 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1129 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1133 static const SilcConfigTable table_deny[] = {
1134 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1135 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1139 static const SilcConfigTable table_serverconn[] = {
1140 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1141 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1142 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1143 { "versionid", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1144 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1145 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1149 static const SilcConfigTable table_routerconn[] = {
1150 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1151 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1152 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1153 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1154 { "versionid", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1155 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1156 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1157 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1158 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1159 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1163 static const SilcConfigTable table_main[] = {
1164 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1165 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1166 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1167 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1168 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1169 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1170 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1171 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1172 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1173 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1174 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1175 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1176 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1180 /* Set default values to stuff that was not configured. */
1182 static void silc_server_config_set_defaults(SilcServerConfig config)
1184 my_set_param_defaults(&config->param, NULL);
1186 config->channel_rekey_secs = (config->channel_rekey_secs ?
1187 config->channel_rekey_secs :
1188 SILC_SERVER_CHANNEL_REKEY);
1189 config->key_exchange_timeout = (config->key_exchange_timeout ?
1190 config->key_exchange_timeout :
1191 SILC_SERVER_SKE_TIMEOUT);
1192 config->conn_auth_timeout = (config->conn_auth_timeout ?
1193 config->conn_auth_timeout :
1194 SILC_SERVER_CONNAUTH_TIMEOUT);
1197 /* Allocates a new configuration object, opens configuration file and
1198 * parses it. The parsed data is returned to the newly allocated
1199 * configuration object. */
1201 SilcServerConfig silc_server_config_alloc(SilcServer server,
1202 const char *filename)
1204 SilcServerConfig config_new;
1205 SilcConfigEntity ent;
1206 SilcConfigFile *file;
1208 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1210 /* alloc a config object */
1211 config_new = silc_calloc(1, sizeof(*config_new));
1215 /* obtain a config file object */
1216 file = silc_config_open(filename);
1218 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1223 /* obtain a SilcConfig entity, we can use it to start the parsing */
1224 ent = silc_config_init(file);
1226 /* load the known configuration options, give our empty object as context */
1227 silc_config_register_table(ent, table_main, (void *) config_new);
1229 /* enter the main parsing loop. When this returns, we have the parsing
1230 * result and the object filled (or partially, in case of errors). */
1231 ret = silc_config_main(ent);
1232 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1233 silc_config_strerror(ret)));
1235 /* Check if the parser returned errors */
1237 /* handle this special error return which asks to quietly return */
1238 if (ret != SILC_CONFIG_ESILENT) {
1239 char *linebuf, *filename = silc_config_get_filename(file);
1240 SilcUInt32 line = silc_config_get_line(file);
1241 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1242 silc_config_strerror(ret)));
1243 linebuf = silc_config_read_line(file, line);
1244 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1248 silc_server_config_destroy(config_new);
1252 /* close (destroy) the file object */
1253 silc_config_close(file);
1255 /* If config_new is incomplete, abort the object and return NULL */
1256 if (!config_new->server_info) {
1257 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1258 "`server_info'\n"));
1259 silc_server_config_destroy(config_new);
1263 /* XXX are there any other mandatory sections in the config file? */
1265 /* Set default to configuration parameters */
1266 silc_server_config_set_defaults(config_new);
1268 silc_server_config_ref(&server->config_ref, config_new, config_new);
1272 /* Increments the reference counter of a config object */
1274 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1279 ref->config = config;
1280 ref->ref_ptr = ref_ptr;
1281 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %hu->%hu", config,
1282 config->refcount - 1, config->refcount));
1286 /* Decrements the reference counter of a config object. If the counter
1287 reaches 0, the config object is destroyed. */
1289 void silc_server_config_unref(SilcServerConfigRef *ref)
1291 SilcServerConfig config = ref->config;
1294 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
1295 config->refcount + 1, config->refcount));
1296 if (!config->refcount)
1297 silc_server_config_destroy(config);
1301 /* Destroy a config object with all his children lists */
1303 void silc_server_config_destroy(SilcServerConfig config)
1307 if (config->refcount > 0) {
1309 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
1310 config->refcount + 1, config->refcount));
1311 if (config->refcount > 0)
1315 SILC_LOG_DEBUG(("Freeing config context"));
1317 silc_free(config->module_path);
1319 /* Destroy Logging channels */
1320 if (config->logging_info)
1321 silc_free(config->logging_info->file);
1322 if (config->logging_warnings)
1323 silc_free(config->logging_warnings->file);
1324 if (config->logging_errors)
1325 silc_free(config->logging_errors->file);
1326 if (config->logging_fatals)
1327 silc_free(config->logging_fatals->file);
1329 /* Destroy the ServerInfo struct */
1330 if (config->server_info) {
1331 register SilcServerConfigServerInfo *si = config->server_info;
1332 silc_free(si->server_name);
1333 silc_free(si->server_ip);
1334 silc_free(si->server_type);
1335 silc_free(si->location);
1336 silc_free(si->admin);
1337 silc_free(si->email);
1338 silc_free(si->user);
1339 silc_free(si->group);
1340 silc_free(si->motd_file);
1341 silc_free(si->pid_file);
1344 /* Now let's destroy the lists */
1346 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1348 silc_free(di->name);
1349 silc_free(di->module);
1352 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1353 silc_free(di->name);
1354 silc_free(di->module);
1357 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1358 silc_free(di->name);
1359 silc_free(di->hash);
1362 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1363 silc_free(di->name);
1366 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient,
1368 silc_free(di->host);
1369 CONFIG_FREE_AUTH(di);
1372 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1373 silc_free(di->host);
1374 silc_free(di->user);
1375 silc_free(di->nick);
1376 CONFIG_FREE_AUTH(di);
1379 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1380 silc_free(di->host);
1381 silc_free(di->reason);
1384 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1386 silc_free(di->host);
1387 silc_free(di->version);
1388 CONFIG_FREE_AUTH(di);
1391 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1393 silc_free(di->host);
1394 silc_free(di->version);
1395 silc_free(di->backup_replace_ip);
1396 CONFIG_FREE_AUTH(di);
1400 memset(config, 'F', sizeof(*config));
1404 /* Registers configured ciphers. These can then be allocated by the
1405 server when needed. */
1407 bool silc_server_config_register_ciphers(SilcServer server)
1409 SilcServerConfig config = server->config;
1410 SilcServerConfigCipher *cipher = config->cipher;
1411 char *module_path = config->module_path;
1413 SILC_LOG_DEBUG(("Registering configured ciphers"));
1415 if (!cipher) /* any cipher in the config file? */
1419 /* if there isn't a module_path OR there isn't a module sim name try to
1420 * use buil-in functions */
1421 if (!module_path || !cipher->module) {
1423 for (i = 0; silc_default_ciphers[i].name; i++)
1424 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1425 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1428 if (!silc_cipher_is_supported(cipher->name)) {
1429 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1430 silc_server_stop(server);
1435 /* Load (try at least) the crypto SIM module */
1436 char buf[1023], *alg_name;
1437 SilcCipherObject cipher_obj;
1440 memset(&cipher_obj, 0, sizeof(cipher_obj));
1441 cipher_obj.name = cipher->name;
1442 cipher_obj.block_len = cipher->block_length;
1443 cipher_obj.key_len = cipher->key_length * 8;
1445 /* build the libname */
1446 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1448 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1450 alg_name = strdup(cipher->name);
1451 if (strchr(alg_name, '-'))
1452 *strchr(alg_name, '-') = '\0';
1454 if (silc_sim_load(sim)) {
1455 cipher_obj.set_key =
1456 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1457 SILC_CIPHER_SIM_SET_KEY));
1458 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1459 cipher_obj.set_key_with_string =
1460 silc_sim_getsym(sim,
1461 silc_sim_symname(alg_name,
1462 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1463 SILC_LOG_DEBUG(("set_key_with_string=%p",
1464 cipher_obj.set_key_with_string));
1465 cipher_obj.encrypt =
1466 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1467 SILC_CIPHER_SIM_ENCRYPT_CBC));
1468 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1469 cipher_obj.decrypt =
1470 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1471 SILC_CIPHER_SIM_DECRYPT_CBC));
1472 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1473 cipher_obj.context_len =
1474 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1475 SILC_CIPHER_SIM_CONTEXT_LEN));
1476 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1478 /* Put the SIM to the list of all SIM's in server */
1479 silc_dlist_add(server->sim, sim);
1481 silc_free(alg_name);
1483 SILC_LOG_ERROR(("Error configuring ciphers"));
1484 silc_server_stop(server);
1488 /* Register the cipher */
1489 silc_cipher_register(&cipher_obj);
1491 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1492 "can't load modules!"));
1493 silc_server_stop(server);
1497 cipher = cipher->next;
1503 /* Registers configured hash functions. These can then be allocated by the
1504 server when needed. */
1506 bool silc_server_config_register_hashfuncs(SilcServer server)
1508 SilcServerConfig config = server->config;
1509 SilcServerConfigHash *hash = config->hash;
1510 char *module_path = config->module_path;
1512 SILC_LOG_DEBUG(("Registering configured hash functions"));
1514 if (!hash) /* any hash func in the config file? */
1518 /* if there isn't a module_path OR there isn't a module sim name try to
1519 * use buil-in functions */
1520 if (!module_path || !hash->module) {
1522 for (i = 0; silc_default_hash[i].name; i++)
1523 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1524 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1527 if (!silc_hash_is_supported(hash->name)) {
1528 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1529 silc_server_stop(server);
1534 /* Load (try at least) the hash SIM module */
1535 SilcHashObject hash_obj;
1538 memset(&hash_obj, 0, sizeof(hash_obj));
1539 hash_obj.name = hash->name;
1540 hash_obj.block_len = hash->block_length;
1541 hash_obj.hash_len = hash->digest_length;
1543 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1545 if ((silc_sim_load(sim))) {
1547 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1548 SILC_HASH_SIM_INIT));
1549 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1551 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1552 SILC_HASH_SIM_UPDATE));
1553 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1555 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1556 SILC_HASH_SIM_FINAL));
1557 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1558 hash_obj.context_len =
1559 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1560 SILC_HASH_SIM_CONTEXT_LEN));
1561 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1563 /* Put the SIM to the table of all SIM's in server */
1564 silc_dlist_add(server->sim, sim);
1566 SILC_LOG_ERROR(("Error configuring hash functions"));
1567 silc_server_stop(server);
1571 /* Register the hash function */
1572 silc_hash_register(&hash_obj);
1574 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1575 "can't load modules!"));
1576 silc_server_stop(server);
1586 /* Registers configure HMACs. These can then be allocated by the server
1589 bool silc_server_config_register_hmacs(SilcServer server)
1591 SilcServerConfig config = server->config;
1592 SilcServerConfigHmac *hmac = config->hmac;
1594 SILC_LOG_DEBUG(("Registering configured HMACs"));
1600 SilcHmacObject hmac_obj;
1601 if (!silc_hash_is_supported(hmac->hash)) {
1602 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1603 silc_server_stop(server);
1607 /* Register the HMAC */
1608 memset(&hmac_obj, 0, sizeof(hmac_obj));
1609 hmac_obj.name = hmac->name;
1610 hmac_obj.len = hmac->mac_length;
1611 silc_hmac_register(&hmac_obj);
1619 /* Registers configured PKCS's. */
1621 bool silc_server_config_register_pkcs(SilcServer server)
1623 SilcServerConfig config = server->config;
1624 SilcServerConfigPkcs *pkcs = config->pkcs;
1626 SILC_LOG_DEBUG(("Registering configured PKCS"));
1633 for (i = 0; silc_default_pkcs[i].name; i++)
1634 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1635 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1638 if (!silc_pkcs_is_supported(pkcs->name)) {
1639 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1640 silc_server_stop(server);
1649 /* Sets log files where log messages are saved by the server logger. */
1651 void silc_server_config_setlogfiles(SilcServer server)
1653 SilcServerConfig config = server->config;
1654 SilcServerConfigLogging *this;
1656 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1658 silc_log_quick = config->logging_quick;
1659 silc_log_flushdelay = (config->logging_flushdelay ?
1660 config->logging_flushdelay :
1661 SILC_SERVER_LOG_FLUSH_DELAY);
1663 if ((this = config->logging_fatals))
1664 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1666 if ((this = config->logging_errors))
1667 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1669 if ((this = config->logging_warnings))
1670 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1672 if ((this = config->logging_info))
1673 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1677 /* Returns client authentication information from configuration file by host
1680 SilcServerConfigClient *
1681 silc_server_config_find_client(SilcServer server, char *host)
1683 SilcServerConfig config = server->config;
1684 SilcServerConfigClient *client;
1686 if (!config || !host)
1689 for (client = config->clients; client; client = client->next) {
1690 if (client->host && !silc_string_compare(client->host, host))
1695 /* if none matched, then client is already NULL */
1699 /* Returns admin connection configuration by host, username and/or
1702 SilcServerConfigAdmin *
1703 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1706 SilcServerConfig config = server->config;
1707 SilcServerConfigAdmin *admin;
1709 /* make sure we have a value for the matching parameters */
1717 for (admin = config->admins; admin; admin = admin->next) {
1718 if (admin->host && !silc_string_compare(admin->host, host))
1720 if (admin->user && !silc_string_compare(admin->user, user))
1722 if (admin->nick && !silc_string_compare(admin->nick, nick))
1724 /* no checks failed -> this entry matches */
1728 /* if none matched, then admin is already NULL */
1732 /* Returns the denied connection configuration entry by host. */
1734 SilcServerConfigDeny *
1735 silc_server_config_find_denied(SilcServer server, char *host)
1737 SilcServerConfig config = server->config;
1738 SilcServerConfigDeny *deny;
1740 /* make sure we have a value for the matching parameters */
1741 if (!config || !host)
1744 for (deny = config->denied; deny; deny = deny->next) {
1745 if (deny->host && !silc_string_compare(deny->host, host))
1750 /* if none matched, then deny is already NULL */
1754 /* Returns server connection info from server configuartion by host
1757 SilcServerConfigServer *
1758 silc_server_config_find_server_conn(SilcServer server, char *host)
1760 SilcServerConfig config = server->config;
1761 SilcServerConfigServer *serv = NULL;
1766 if (!config->servers)
1769 for (serv = config->servers; serv; serv = serv->next) {
1770 if (!silc_string_compare(serv->host, host))
1778 /* Returns router connection info from server configuration by
1779 host (name or ip). */
1781 SilcServerConfigRouter *
1782 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1784 SilcServerConfig config = server->config;
1785 SilcServerConfigRouter *serv = NULL;
1790 if (!config->routers)
1793 for (serv = config->routers; serv; serv = serv->next) {
1794 if (!silc_string_compare(serv->host, host))
1796 if (port && serv->port && serv->port != port)
1804 /* Returns TRUE if configuration for a router connection that we are
1805 initiating exists. */
1807 bool silc_server_config_is_primary_route(SilcServer server)
1809 SilcServerConfig config = server->config;
1810 SilcServerConfigRouter *serv = NULL;
1814 serv = config->routers;
1815 for (i = 0; serv; i++) {
1816 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1827 /* Returns our primary connection configuration or NULL if we do not
1828 have primary router configured. */
1830 SilcServerConfigRouter *
1831 silc_server_config_get_primary_router(SilcServer server)
1833 SilcServerConfig config = server->config;
1834 SilcServerConfigRouter *serv = NULL;
1837 serv = config->routers;
1838 for (i = 0; serv; i++) {
1839 if (serv->initiator == TRUE && serv->backup_router == FALSE)