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. The SilcServerConfig must be freed by calling
1200 the silc_server_config_destroy function. */
1202 SilcServerConfig silc_server_config_alloc(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 config_new->refcount = 1;
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)
1292 silc_server_config_destroy(ref->config);
1295 /* Destroy a config object with all his children lists */
1297 void silc_server_config_destroy(SilcServerConfig config)
1302 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
1303 config->refcount + 1, config->refcount));
1304 if (config->refcount > 0)
1307 SILC_LOG_DEBUG(("Freeing config context"));
1309 silc_free(config->module_path);
1311 /* Destroy Logging channels */
1312 if (config->logging_info)
1313 silc_free(config->logging_info->file);
1314 if (config->logging_warnings)
1315 silc_free(config->logging_warnings->file);
1316 if (config->logging_errors)
1317 silc_free(config->logging_errors->file);
1318 if (config->logging_fatals)
1319 silc_free(config->logging_fatals->file);
1321 /* Destroy the ServerInfo struct */
1322 if (config->server_info) {
1323 register SilcServerConfigServerInfo *si = config->server_info;
1324 silc_free(si->server_name);
1325 silc_free(si->server_ip);
1326 silc_free(si->server_type);
1327 silc_free(si->location);
1328 silc_free(si->admin);
1329 silc_free(si->email);
1330 silc_free(si->user);
1331 silc_free(si->group);
1332 silc_free(si->motd_file);
1333 silc_free(si->pid_file);
1336 /* Now let's destroy the lists */
1338 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1340 silc_free(di->name);
1341 silc_free(di->module);
1344 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1345 silc_free(di->name);
1346 silc_free(di->module);
1349 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1350 silc_free(di->name);
1351 silc_free(di->hash);
1354 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1355 silc_free(di->name);
1358 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient,
1360 silc_free(di->host);
1361 CONFIG_FREE_AUTH(di);
1364 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1365 silc_free(di->host);
1366 silc_free(di->user);
1367 silc_free(di->nick);
1368 CONFIG_FREE_AUTH(di);
1371 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1372 silc_free(di->host);
1373 silc_free(di->reason);
1376 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1378 silc_free(di->host);
1379 silc_free(di->version);
1380 CONFIG_FREE_AUTH(di);
1383 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1385 silc_free(di->host);
1386 silc_free(di->version);
1387 silc_free(di->backup_replace_ip);
1388 CONFIG_FREE_AUTH(di);
1392 memset(config, 'F', sizeof(*config));
1396 /* Registers configured ciphers. These can then be allocated by the
1397 server when needed. */
1399 bool silc_server_config_register_ciphers(SilcServer server)
1401 SilcServerConfig config = server->config;
1402 SilcServerConfigCipher *cipher = config->cipher;
1403 char *module_path = config->module_path;
1405 SILC_LOG_DEBUG(("Registering configured ciphers"));
1407 if (!cipher) /* any cipher in the config file? */
1411 /* if there isn't a module_path OR there isn't a module sim name try to
1412 * use buil-in functions */
1413 if (!module_path || !cipher->module) {
1415 for (i = 0; silc_default_ciphers[i].name; i++)
1416 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1417 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1420 if (!silc_cipher_is_supported(cipher->name)) {
1421 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1422 silc_server_stop(server);
1427 /* Load (try at least) the crypto SIM module */
1428 char buf[1023], *alg_name;
1429 SilcCipherObject cipher_obj;
1432 memset(&cipher_obj, 0, sizeof(cipher_obj));
1433 cipher_obj.name = cipher->name;
1434 cipher_obj.block_len = cipher->block_length;
1435 cipher_obj.key_len = cipher->key_length * 8;
1437 /* build the libname */
1438 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1440 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1442 alg_name = strdup(cipher->name);
1443 if (strchr(alg_name, '-'))
1444 *strchr(alg_name, '-') = '\0';
1446 if (silc_sim_load(sim)) {
1447 cipher_obj.set_key =
1448 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1449 SILC_CIPHER_SIM_SET_KEY));
1450 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1451 cipher_obj.set_key_with_string =
1452 silc_sim_getsym(sim,
1453 silc_sim_symname(alg_name,
1454 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1455 SILC_LOG_DEBUG(("set_key_with_string=%p",
1456 cipher_obj.set_key_with_string));
1457 cipher_obj.encrypt =
1458 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1459 SILC_CIPHER_SIM_ENCRYPT_CBC));
1460 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1461 cipher_obj.decrypt =
1462 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1463 SILC_CIPHER_SIM_DECRYPT_CBC));
1464 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1465 cipher_obj.context_len =
1466 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1467 SILC_CIPHER_SIM_CONTEXT_LEN));
1468 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1470 /* Put the SIM to the list of all SIM's in server */
1471 silc_dlist_add(server->sim, sim);
1473 silc_free(alg_name);
1475 SILC_LOG_ERROR(("Error configuring ciphers"));
1476 silc_server_stop(server);
1480 /* Register the cipher */
1481 silc_cipher_register(&cipher_obj);
1483 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1484 "can't load modules!"));
1485 silc_server_stop(server);
1489 cipher = cipher->next;
1495 /* Registers configured hash functions. These can then be allocated by the
1496 server when needed. */
1498 bool silc_server_config_register_hashfuncs(SilcServer server)
1500 SilcServerConfig config = server->config;
1501 SilcServerConfigHash *hash = config->hash;
1502 char *module_path = config->module_path;
1504 SILC_LOG_DEBUG(("Registering configured hash functions"));
1506 if (!hash) /* any hash func in the config file? */
1510 /* if there isn't a module_path OR there isn't a module sim name try to
1511 * use buil-in functions */
1512 if (!module_path || !hash->module) {
1514 for (i = 0; silc_default_hash[i].name; i++)
1515 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1516 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1519 if (!silc_hash_is_supported(hash->name)) {
1520 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1521 silc_server_stop(server);
1526 /* Load (try at least) the hash SIM module */
1527 SilcHashObject hash_obj;
1530 memset(&hash_obj, 0, sizeof(hash_obj));
1531 hash_obj.name = hash->name;
1532 hash_obj.block_len = hash->block_length;
1533 hash_obj.hash_len = hash->digest_length;
1535 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1537 if ((silc_sim_load(sim))) {
1539 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1540 SILC_HASH_SIM_INIT));
1541 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1543 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1544 SILC_HASH_SIM_UPDATE));
1545 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1547 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1548 SILC_HASH_SIM_FINAL));
1549 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1550 hash_obj.context_len =
1551 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1552 SILC_HASH_SIM_CONTEXT_LEN));
1553 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1555 /* Put the SIM to the table of all SIM's in server */
1556 silc_dlist_add(server->sim, sim);
1558 SILC_LOG_ERROR(("Error configuring hash functions"));
1559 silc_server_stop(server);
1563 /* Register the hash function */
1564 silc_hash_register(&hash_obj);
1566 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1567 "can't load modules!"));
1568 silc_server_stop(server);
1578 /* Registers configure HMACs. These can then be allocated by the server
1581 bool silc_server_config_register_hmacs(SilcServer server)
1583 SilcServerConfig config = server->config;
1584 SilcServerConfigHmac *hmac = config->hmac;
1586 SILC_LOG_DEBUG(("Registering configured HMACs"));
1592 SilcHmacObject hmac_obj;
1593 if (!silc_hash_is_supported(hmac->hash)) {
1594 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1595 silc_server_stop(server);
1599 /* Register the HMAC */
1600 memset(&hmac_obj, 0, sizeof(hmac_obj));
1601 hmac_obj.name = hmac->name;
1602 hmac_obj.len = hmac->mac_length;
1603 silc_hmac_register(&hmac_obj);
1611 /* Registers configured PKCS's. */
1613 bool silc_server_config_register_pkcs(SilcServer server)
1615 SilcServerConfig config = server->config;
1616 SilcServerConfigPkcs *pkcs = config->pkcs;
1618 SILC_LOG_DEBUG(("Registering configured PKCS"));
1625 for (i = 0; silc_default_pkcs[i].name; i++)
1626 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1627 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1630 if (!silc_pkcs_is_supported(pkcs->name)) {
1631 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1632 silc_server_stop(server);
1641 /* Sets log files where log messages are saved by the server logger. */
1643 void silc_server_config_setlogfiles(SilcServer server)
1645 SilcServerConfig config = server->config;
1646 SilcServerConfigLogging *this;
1648 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1650 silc_log_quick = config->logging_quick;
1651 silc_log_flushdelay = (config->logging_flushdelay ?
1652 config->logging_flushdelay :
1653 SILC_SERVER_LOG_FLUSH_DELAY);
1655 if ((this = config->logging_fatals))
1656 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1658 if ((this = config->logging_errors))
1659 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1661 if ((this = config->logging_warnings))
1662 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1664 if ((this = config->logging_info))
1665 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1669 /* Returns client authentication information from configuration file by host
1672 SilcServerConfigClient *
1673 silc_server_config_find_client(SilcServer server, char *host)
1675 SilcServerConfig config = server->config;
1676 SilcServerConfigClient *client;
1678 if (!config || !host)
1681 for (client = config->clients; client; client = client->next) {
1682 if (client->host && !silc_string_compare(client->host, host))
1687 /* if none matched, then client is already NULL */
1691 /* Returns admin connection configuration by host, username and/or
1694 SilcServerConfigAdmin *
1695 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1698 SilcServerConfig config = server->config;
1699 SilcServerConfigAdmin *admin;
1701 /* make sure we have a value for the matching parameters */
1709 for (admin = config->admins; admin; admin = admin->next) {
1710 if (admin->host && !silc_string_compare(admin->host, host))
1712 if (admin->user && !silc_string_compare(admin->user, user))
1714 if (admin->nick && !silc_string_compare(admin->nick, nick))
1716 /* no checks failed -> this entry matches */
1720 /* if none matched, then admin is already NULL */
1724 /* Returns the denied connection configuration entry by host. */
1726 SilcServerConfigDeny *
1727 silc_server_config_find_denied(SilcServer server, char *host)
1729 SilcServerConfig config = server->config;
1730 SilcServerConfigDeny *deny;
1732 /* make sure we have a value for the matching parameters */
1733 if (!config || !host)
1736 for (deny = config->denied; deny; deny = deny->next) {
1737 if (deny->host && !silc_string_compare(deny->host, host))
1742 /* if none matched, then deny is already NULL */
1746 /* Returns server connection info from server configuartion by host
1749 SilcServerConfigServer *
1750 silc_server_config_find_server_conn(SilcServer server, char *host)
1752 SilcServerConfig config = server->config;
1753 SilcServerConfigServer *serv = NULL;
1758 if (!config->servers)
1761 for (serv = config->servers; serv; serv = serv->next) {
1762 if (!silc_string_compare(serv->host, host))
1770 /* Returns router connection info from server configuration by
1771 host (name or ip). */
1773 SilcServerConfigRouter *
1774 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1776 SilcServerConfig config = server->config;
1777 SilcServerConfigRouter *serv = NULL;
1782 if (!config->routers)
1785 for (serv = config->routers; serv; serv = serv->next) {
1786 if (!silc_string_compare(serv->host, host))
1788 if (port && serv->port && serv->port != port)
1796 /* Returns TRUE if configuration for a router connection that we are
1797 initiating exists. */
1799 bool silc_server_config_is_primary_route(SilcServer server)
1801 SilcServerConfig config = server->config;
1802 SilcServerConfigRouter *serv = NULL;
1806 serv = config->routers;
1807 for (i = 0; serv; i++) {
1808 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1819 /* Returns our primary connection configuration or NULL if we do not
1820 have primary router configured. */
1822 SilcServerConfigRouter *
1823 silc_server_config_get_primary_router(SilcServer server)
1825 SilcServerConfig config = server->config;
1826 SilcServerConfigRouter *serv = NULL;
1829 serv = config->routers;
1830 for (i = 0; serv; i++) {
1831 if (serv->initiator == TRUE && serv->backup_router == FALSE)