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 if (!server_info->public_key || !server_info->private_key) {
434 got_errno = SILC_CONFIG_EMISSFIELDS;
437 return SILC_CONFIG_OK;
439 if (!strcmp(name, "hostname")) {
440 CONFIG_IS_DOUBLE(server_info->server_name);
441 server_info->server_name = strdup((char *) val);
443 else if (!strcmp(name, "ip")) {
444 CONFIG_IS_DOUBLE(server_info->server_ip);
445 server_info->server_ip = strdup((char *) val);
447 else if (!strcmp(name, "port")) {
448 int port = *(int *)val;
449 if ((port <= 0) || (port > 65535)) {
450 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
451 return SILC_CONFIG_ESILENT;
453 server_info->port = (SilcUInt16) port;
455 else if (!strcmp(name, "servertype")) {
456 CONFIG_IS_DOUBLE(server_info->server_type);
457 server_info->server_type = strdup((char *) val);
459 else if (!strcmp(name, "admin")) {
460 CONFIG_IS_DOUBLE(server_info->admin);
461 server_info->admin = strdup((char *) val);
463 else if (!strcmp(name, "adminemail")) {
464 CONFIG_IS_DOUBLE(server_info->email);
465 server_info->email = strdup((char *) val);
467 else if (!strcmp(name, "location")) {
468 CONFIG_IS_DOUBLE(server_info->location);
469 server_info->location = strdup((char *) val);
471 else if (!strcmp(name, "user")) {
472 CONFIG_IS_DOUBLE(server_info->user);
473 server_info->user = strdup((char *) val);
475 else if (!strcmp(name, "group")) {
476 CONFIG_IS_DOUBLE(server_info->group);
477 server_info->group = strdup((char *) val);
479 else if (!strcmp(name, "motdfile")) {
480 CONFIG_IS_DOUBLE(server_info->motd_file);
481 server_info->motd_file = strdup((char *) val);
483 else if (!strcmp(name, "pidfile")) {
484 CONFIG_IS_DOUBLE(server_info->pid_file);
485 server_info->pid_file = strdup((char *) val);
487 else if (!strcmp(name, "publickey")) {
488 char *file_tmp = (char *) val;
490 /* try to load specified file, if fail stop config parsing */
491 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
493 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
494 SILC_PKCS_FILE_BIN)) {
495 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
496 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
497 return SILC_CONFIG_ESILENT;
500 else if (!strcmp(name, "privatekey")) {
501 char *file_tmp = (char *) val;
503 /* try to load specified file, if fail stop config parsing */
504 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
506 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
507 SILC_PKCS_FILE_PEM)) {
508 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
509 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
510 return SILC_CONFIG_ESILENT;
514 return SILC_CONFIG_EINTERNAL;
515 return SILC_CONFIG_OK;
521 SILC_CONFIG_CALLBACK(fetch_logging)
523 SilcServerConfig config = (SilcServerConfig) context;
524 SilcServerConfigLogging *tmp =
525 (SilcServerConfigLogging *) config->tmp;
528 if (!strcmp(name, "quicklogs")) {
529 config->logging_quick = *(bool *)val;
531 else if (!strcmp(name, "flushdelay")) {
532 int flushdelay = *(int *)val;
533 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
534 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use "
535 "quicklogs if you want real-time logging.\n", line));
536 return SILC_CONFIG_ESILENT;
538 config->logging_flushdelay = (long) flushdelay;
540 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
541 else if (!strcmp(name, __chan__)) { \
542 if (!tmp) return SILC_CONFIG_OK; \
544 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
546 config->__member__ = tmp; \
547 config->tmp = NULL; \
549 FETCH_LOGGING_CHAN("info", logging_info)
550 FETCH_LOGGING_CHAN("warnings", logging_warnings)
551 FETCH_LOGGING_CHAN("errors", logging_errors)
552 FETCH_LOGGING_CHAN("fatals", logging_fatals)
553 #undef FETCH_LOGGING_CHAN
554 else if (!strcmp(name, "file")) {
555 if (!tmp) { /* FIXME: what the fuck is this? */
556 config->tmp = silc_calloc(1, sizeof(*tmp));
557 tmp = (SilcServerConfigLogging *) config->tmp;
560 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
562 tmp->file = strdup((char *) val);
564 else if (!strcmp(name, "size")) {
566 config->tmp = silc_calloc(1, sizeof(*tmp));
567 tmp = (SilcServerConfigLogging *) config->tmp;
569 tmp->maxsize = *(SilcUInt32 *) val;
572 return SILC_CONFIG_EINTERNAL;
573 return SILC_CONFIG_OK;
576 silc_free(tmp->file);
582 SILC_CONFIG_CALLBACK(fetch_connparam)
584 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
586 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
587 type, name, context));
589 if (type == SILC_CONFIG_ARG_BLOCK) {
591 return SILC_CONFIG_OK;
594 got_errno = SILC_CONFIG_EMISSFIELDS;
599 my_set_param_defaults(tmp, &config->param);
601 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
603 return SILC_CONFIG_OK;
606 /* if there isn't a temporary struct alloc one */
608 config->tmp = silc_calloc(1, sizeof(*findtmp));
609 tmp = (SilcServerConfigConnParams *) config->tmp;
612 if (!strcmp(name, "name")) {
613 CONFIG_IS_DOUBLE(tmp->name);
614 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
616 else if (!strcmp(name, "connections_max")) {
617 tmp->connections_max = *(SilcUInt32 *)val;
619 else if (!strcmp(name, "connections_max_per_host")) {
620 tmp->connections_max_per_host = *(SilcUInt32 *)val;
622 else if (!strcmp(name, "keepalive_secs")) {
623 tmp->keepalive_secs = *(SilcUInt32 *)val;
625 else if (!strcmp(name, "reconnect_count")) {
626 tmp->reconnect_count = *(SilcUInt32 *)val;
628 else if (!strcmp(name, "reconnect_interval")) {
629 tmp->reconnect_interval = *(SilcUInt32 *)val;
631 else if (!strcmp(name, "reconnect_interval_max")) {
632 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
634 else if (!strcmp(name, "reconnect_keep_trying")) {
635 tmp->reconnect_keep_trying = *(bool *)val;
637 else if (!strcmp(name, "key_exchange_rekey")) {
638 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "key_exchange_pfs")) {
641 tmp->key_exchange_pfs = *(bool *)val;
643 else if (!strcmp(name, "version_protocol")) {
644 CONFIG_IS_DOUBLE(tmp->version_protocol);
645 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
647 else if (!strcmp(name, "version_software")) {
648 CONFIG_IS_DOUBLE(tmp->version_software);
649 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
651 else if (!strcmp(name, "version_software_vendor")) {
652 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
653 tmp->version_software_vendor =
654 (*(char *)val ? strdup((char *) val) : NULL);
657 return SILC_CONFIG_EINTERNAL;
659 return SILC_CONFIG_OK;
662 silc_free(tmp->name);
668 SILC_CONFIG_CALLBACK(fetch_client)
670 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
672 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
673 type, name, context));
675 /* alloc tmp before block checking (empty sub-blocks are welcome here) */
677 config->tmp = silc_calloc(1, sizeof(*findtmp));
678 tmp = (SilcServerConfigClient *) config->tmp;
681 if (type == SILC_CONFIG_ARG_BLOCK) {
682 /* closing the block */
683 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
685 return SILC_CONFIG_OK;
688 /* Identify and save this value */
689 if (!strcmp(name, "host")) {
690 CONFIG_IS_DOUBLE(tmp->host);
691 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
693 else if (!strcmp(name, "passphrase")) {
694 CONFIG_IS_DOUBLE(tmp->passphrase);
695 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
696 (void **)&tmp->passphrase,
697 &tmp->passphrase_len)) {
698 got_errno = SILC_CONFIG_ESILENT;
702 else if (!strcmp(name, "publickey")) {
703 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
704 (void **)&tmp->publickeys, NULL)) {
705 got_errno = SILC_CONFIG_ESILENT;
709 else if (!strcmp(name, "params")) {
710 CONFIG_IS_DOUBLE(tmp->param);
711 tmp->param = my_find_param(config, (char *) val, line);
712 if (!tmp->param) { /* error already output */
713 got_errno = SILC_CONFIG_ESILENT;
718 return SILC_CONFIG_EINTERNAL;
719 return SILC_CONFIG_OK;
722 silc_free(tmp->host);
723 CONFIG_FREE_AUTH(tmp);
729 SILC_CONFIG_CALLBACK(fetch_admin)
731 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
733 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
734 type, name, context));
736 if (type == SILC_CONFIG_ARG_BLOCK) {
737 /* check the temporary struct's fields */
738 if (!tmp) /* empty sub-block? */
739 return SILC_CONFIG_OK;
741 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
743 return SILC_CONFIG_OK;
746 /* if there isn't a temporary struct alloc one */
748 config->tmp = silc_calloc(1, sizeof(*findtmp));
749 tmp = (SilcServerConfigAdmin *) config->tmp;
752 /* Identify and save this value */
753 if (!strcmp(name, "host")) {
754 CONFIG_IS_DOUBLE(tmp->host);
755 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
757 else if (!strcmp(name, "user")) {
758 CONFIG_IS_DOUBLE(tmp->user);
759 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
761 else if (!strcmp(name, "nick")) {
762 CONFIG_IS_DOUBLE(tmp->nick);
763 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
765 else if (!strcmp(name, "passphrase")) {
766 CONFIG_IS_DOUBLE(tmp->passphrase);
767 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
768 (void **)&tmp->passphrase,
769 &tmp->passphrase_len)) {
770 got_errno = SILC_CONFIG_ESILENT;
774 else if (!strcmp(name, "publickey")) {
775 CONFIG_IS_DOUBLE(tmp->publickeys);
776 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
777 (void **)&tmp->publickeys, NULL)) {
778 got_errno = SILC_CONFIG_ESILENT;
783 return SILC_CONFIG_EINTERNAL;
784 return SILC_CONFIG_OK;
787 silc_free(tmp->host);
788 silc_free(tmp->user);
789 silc_free(tmp->nick);
790 CONFIG_FREE_AUTH(tmp);
796 SILC_CONFIG_CALLBACK(fetch_deny)
798 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
800 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
801 type, name, context));
802 if (type == SILC_CONFIG_ARG_BLOCK) {
803 /* check the temporary struct's fields */
804 if (!tmp) /* empty sub-block? */
805 return SILC_CONFIG_OK;
807 got_errno = SILC_CONFIG_EMISSFIELDS;
810 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
812 return SILC_CONFIG_OK;
814 /* if there isn't a temporary struct alloc one */
816 config->tmp = silc_calloc(1, sizeof(*findtmp));
817 tmp = (SilcServerConfigDeny *) config->tmp;
820 /* Identify and save this value */
821 if (!strcmp(name, "host")) {
822 CONFIG_IS_DOUBLE(tmp->host);
823 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
825 else if (!strcmp(name, "reason")) {
826 CONFIG_IS_DOUBLE(tmp->reason);
827 tmp->reason = strdup((char *) val);
830 return SILC_CONFIG_EINTERNAL;
831 return SILC_CONFIG_OK;
834 silc_free(tmp->host);
835 silc_free(tmp->reason);
841 SILC_CONFIG_CALLBACK(fetch_server)
843 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
845 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
846 type, name, context));
848 if (type == SILC_CONFIG_ARG_BLOCK) {
849 /* check the temporary struct's fields */
850 if (!tmp) /* empty sub-block? */
851 return SILC_CONFIG_OK;
853 /* the temporary struct is ok, append it to the list */
854 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
856 return SILC_CONFIG_OK;
859 /* if there isn't a temporary struct alloc one */
861 config->tmp = silc_calloc(1, sizeof(*findtmp));
862 tmp = (SilcServerConfigServer *) config->tmp;
865 /* Identify and save this value */
866 if (!strcmp(name, "host")) {
867 CONFIG_IS_DOUBLE(tmp->host);
868 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
870 else if (!strcmp(name, "passphrase")) {
871 CONFIG_IS_DOUBLE(tmp->passphrase);
872 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
873 (void **)&tmp->passphrase,
874 &tmp->passphrase_len)) {
875 got_errno = SILC_CONFIG_ESILENT;
879 else if (!strcmp(name, "publickey")) {
880 CONFIG_IS_DOUBLE(tmp->publickeys);
881 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
882 (void **)&tmp->publickeys, NULL)) {
883 got_errno = SILC_CONFIG_ESILENT;
887 else if (!strcmp(name, "versionid")) {
888 CONFIG_IS_DOUBLE(tmp->version);
889 tmp->version = strdup((char *) val);
891 else if (!strcmp(name, "params")) {
892 CONFIG_IS_DOUBLE(tmp->param);
893 tmp->param = my_find_param(config, (char *) val, line);
894 if (!tmp->param) { /* error already output */
895 got_errno = SILC_CONFIG_ESILENT;
899 else if (!strcmp(name, "backup")) {
900 tmp->backup_router = *(bool *)val;
903 return SILC_CONFIG_EINTERNAL;
905 return SILC_CONFIG_OK;
908 silc_free(tmp->host);
909 silc_free(tmp->version);
910 CONFIG_FREE_AUTH(tmp);
916 SILC_CONFIG_CALLBACK(fetch_router)
918 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
920 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
921 type, name, context));
923 if (type == SILC_CONFIG_ARG_BLOCK) {
924 if (!tmp) /* empty sub-block? */
925 return SILC_CONFIG_OK;
927 /* the temporary struct is ok, append it to the list */
928 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
930 return SILC_CONFIG_OK;
933 /* if there isn't a temporary struct alloc one */
935 config->tmp = silc_calloc(1, sizeof(*findtmp));
936 tmp = (SilcServerConfigRouter *) config->tmp;
939 /* Identify and save this value */
940 if (!strcmp(name, "host")) {
941 CONFIG_IS_DOUBLE(tmp->host);
942 tmp->host = strdup((char *) val);
944 else if (!strcmp(name, "port")) {
945 int port = *(int *)val;
946 if ((port <= 0) || (port > 65535)) {
947 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
948 return SILC_CONFIG_ESILENT;
950 tmp->port = (SilcUInt16) port;
952 else if (!strcmp(name, "passphrase")) {
953 CONFIG_IS_DOUBLE(tmp->passphrase);
954 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
955 (void **)&tmp->passphrase,
956 &tmp->passphrase_len)) {
957 got_errno = SILC_CONFIG_ESILENT;
961 else if (!strcmp(name, "publickey")) {
962 CONFIG_IS_DOUBLE(tmp->publickeys);
963 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
964 (void **)&tmp->publickeys, NULL)) {
965 got_errno = SILC_CONFIG_ESILENT;
969 else if (!strcmp(name, "versionid")) {
970 CONFIG_IS_DOUBLE(tmp->version);
971 tmp->version = strdup((char *) val);
973 else if (!strcmp(name, "params")) {
974 CONFIG_IS_DOUBLE(tmp->param);
975 tmp->param = my_find_param(config, (char *) val, line);
976 if (!tmp->param) { /* error already output */
977 got_errno = SILC_CONFIG_ESILENT;
981 else if (!strcmp(name, "initiator")) {
982 tmp->initiator = *(bool *)val;
984 else if (!strcmp(name, "backuphost")) {
985 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
986 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
989 else if (!strcmp(name, "backupport")) {
990 int port = *(int *)val;
991 if ((port <= 0) || (port > 65535)) {
992 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
993 return SILC_CONFIG_ESILENT;
995 tmp->backup_replace_port = (SilcUInt16) port;
997 else if (!strcmp(name, "backuplocal")) {
998 tmp->backup_local = *(bool *)val;
1001 return SILC_CONFIG_EINTERNAL;
1003 return SILC_CONFIG_OK;
1006 silc_free(tmp->host);
1007 silc_free(tmp->version);
1008 silc_free(tmp->backup_replace_ip);
1009 CONFIG_FREE_AUTH(tmp);
1015 /* known config options tables */
1016 static const SilcConfigTable table_general[] = {
1017 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1018 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1019 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1020 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1021 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1022 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1023 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1024 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1025 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1026 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1027 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1028 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1029 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1030 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1031 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1032 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1033 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1034 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1038 static const SilcConfigTable table_cipher[] = {
1039 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1040 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1041 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1042 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1046 static const SilcConfigTable table_hash[] = {
1047 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1048 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1049 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1050 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1054 static const SilcConfigTable table_hmac[] = {
1055 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1056 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1057 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1061 static const SilcConfigTable table_pkcs[] = {
1062 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1066 static const SilcConfigTable table_serverinfo[] = {
1067 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1070 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1072 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1073 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1074 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1075 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1076 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1077 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1078 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1079 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1083 static const SilcConfigTable table_logging_c[] = {
1084 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1085 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1086 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1090 static const SilcConfigTable table_logging[] = {
1091 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1092 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1093 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1094 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1095 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1096 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1100 static const SilcConfigTable table_connparam[] = {
1101 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1102 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1103 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1106 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1107 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1108 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1109 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1110 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1111 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1112 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1113 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1114 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1118 static const SilcConfigTable table_client[] = {
1119 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1120 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1121 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1122 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1126 static const SilcConfigTable table_admin[] = {
1127 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1128 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1129 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1130 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1131 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1132 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1133 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1137 static const SilcConfigTable table_deny[] = {
1138 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1139 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1143 static const SilcConfigTable table_serverconn[] = {
1144 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1145 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1146 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1147 { "versionid", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1148 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1149 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1153 static const SilcConfigTable table_routerconn[] = {
1154 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1155 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1156 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1157 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1158 { "versionid", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1159 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1160 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1161 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1162 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1163 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1167 static const SilcConfigTable table_main[] = {
1168 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1169 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1170 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1171 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1172 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1173 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1174 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1175 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1176 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1177 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1178 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1179 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1180 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1184 /* Set default values to stuff that was not configured. */
1186 static void silc_server_config_set_defaults(SilcServerConfig config)
1188 my_set_param_defaults(&config->param, NULL);
1190 config->channel_rekey_secs = (config->channel_rekey_secs ?
1191 config->channel_rekey_secs :
1192 SILC_SERVER_CHANNEL_REKEY);
1193 config->key_exchange_timeout = (config->key_exchange_timeout ?
1194 config->key_exchange_timeout :
1195 SILC_SERVER_SKE_TIMEOUT);
1196 config->conn_auth_timeout = (config->conn_auth_timeout ?
1197 config->conn_auth_timeout :
1198 SILC_SERVER_CONNAUTH_TIMEOUT);
1201 /* Allocates a new configuration object, opens configuration file and
1202 parses it. The parsed data is returned to the newly allocated
1203 configuration object. The SilcServerConfig must be freed by calling
1204 the silc_server_config_destroy function. */
1206 SilcServerConfig silc_server_config_alloc(const char *filename)
1208 SilcServerConfig config_new;
1209 SilcConfigEntity ent;
1210 SilcConfigFile *file;
1212 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1214 /* alloc a config object */
1215 config_new = silc_calloc(1, sizeof(*config_new));
1219 /* obtain a config file object */
1220 file = silc_config_open(filename);
1222 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1227 /* obtain a SilcConfig entity, we can use it to start the parsing */
1228 ent = silc_config_init(file);
1230 /* load the known configuration options, give our empty object as context */
1231 silc_config_register_table(ent, table_main, (void *) config_new);
1233 /* enter the main parsing loop. When this returns, we have the parsing
1234 * result and the object filled (or partially, in case of errors). */
1235 ret = silc_config_main(ent);
1236 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1237 silc_config_strerror(ret)));
1239 /* Check if the parser returned errors */
1241 /* handle this special error return which asks to quietly return */
1242 if (ret != SILC_CONFIG_ESILENT) {
1243 char *linebuf, *filename = silc_config_get_filename(file);
1244 SilcUInt32 line = silc_config_get_line(file);
1245 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1246 silc_config_strerror(ret)));
1247 linebuf = silc_config_read_line(file, line);
1248 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1252 silc_server_config_destroy(config_new);
1256 /* close (destroy) the file object */
1257 silc_config_close(file);
1259 /* If config_new is incomplete, abort the object and return NULL */
1260 if (!config_new->server_info) {
1261 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1262 "`server_info'\n"));
1263 silc_server_config_destroy(config_new);
1267 /* XXX are there any other mandatory sections in the config file? */
1269 /* Set default to configuration parameters */
1270 silc_server_config_set_defaults(config_new);
1272 config_new->refcount = 1;
1276 /* Increments the reference counter of a config object */
1278 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1283 ref->config = config;
1284 ref->ref_ptr = ref_ptr;
1285 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %hu->%hu", config,
1286 config->refcount - 1, config->refcount));
1290 /* Decrements the reference counter of a config object. If the counter
1291 reaches 0, the config object is destroyed. */
1293 void silc_server_config_unref(SilcServerConfigRef *ref)
1296 silc_server_config_destroy(ref->config);
1299 /* Destroy a config object with all his children lists */
1301 void silc_server_config_destroy(SilcServerConfig config)
1306 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
1307 config->refcount + 1, config->refcount));
1308 if (config->refcount > 0)
1311 SILC_LOG_DEBUG(("Freeing config context"));
1313 silc_free(config->module_path);
1315 /* Destroy Logging channels */
1316 if (config->logging_info)
1317 silc_free(config->logging_info->file);
1318 if (config->logging_warnings)
1319 silc_free(config->logging_warnings->file);
1320 if (config->logging_errors)
1321 silc_free(config->logging_errors->file);
1322 if (config->logging_fatals)
1323 silc_free(config->logging_fatals->file);
1325 /* Destroy the ServerInfo struct */
1326 if (config->server_info) {
1327 register SilcServerConfigServerInfo *si = config->server_info;
1328 silc_free(si->server_name);
1329 silc_free(si->server_ip);
1330 silc_free(si->server_type);
1331 silc_free(si->location);
1332 silc_free(si->admin);
1333 silc_free(si->email);
1334 silc_free(si->user);
1335 silc_free(si->group);
1336 silc_free(si->motd_file);
1337 silc_free(si->pid_file);
1338 silc_pkcs_public_key_free(si->public_key);
1339 silc_pkcs_private_key_free(si->private_key);
1342 /* Now let's destroy the lists */
1344 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1346 silc_free(di->name);
1347 silc_free(di->module);
1350 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1351 silc_free(di->name);
1352 silc_free(di->module);
1355 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1356 silc_free(di->name);
1357 silc_free(di->hash);
1360 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1361 silc_free(di->name);
1364 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient,
1366 silc_free(di->host);
1367 CONFIG_FREE_AUTH(di);
1370 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1371 silc_free(di->host);
1372 silc_free(di->user);
1373 silc_free(di->nick);
1374 CONFIG_FREE_AUTH(di);
1377 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1378 silc_free(di->host);
1379 silc_free(di->reason);
1382 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1384 silc_free(di->host);
1385 silc_free(di->version);
1386 CONFIG_FREE_AUTH(di);
1389 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1391 silc_free(di->host);
1392 silc_free(di->version);
1393 silc_free(di->backup_replace_ip);
1394 CONFIG_FREE_AUTH(di);
1398 memset(config, 'F', sizeof(*config));
1402 /* Registers configured ciphers. These can then be allocated by the
1403 server when needed. */
1405 bool silc_server_config_register_ciphers(SilcServer server)
1407 SilcServerConfig config = server->config;
1408 SilcServerConfigCipher *cipher = config->cipher;
1409 char *module_path = config->module_path;
1411 SILC_LOG_DEBUG(("Registering configured ciphers"));
1413 if (!cipher) /* any cipher in the config file? */
1417 /* if there isn't a module_path OR there isn't a module sim name try to
1418 * use buil-in functions */
1419 if (!module_path || !cipher->module) {
1421 for (i = 0; silc_default_ciphers[i].name; i++)
1422 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1423 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1426 if (!silc_cipher_is_supported(cipher->name)) {
1427 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1428 silc_server_stop(server);
1433 /* Load (try at least) the crypto SIM module */
1434 char buf[1023], *alg_name;
1435 SilcCipherObject cipher_obj;
1438 memset(&cipher_obj, 0, sizeof(cipher_obj));
1439 cipher_obj.name = cipher->name;
1440 cipher_obj.block_len = cipher->block_length;
1441 cipher_obj.key_len = cipher->key_length * 8;
1443 /* build the libname */
1444 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1446 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1448 alg_name = strdup(cipher->name);
1449 if (strchr(alg_name, '-'))
1450 *strchr(alg_name, '-') = '\0';
1452 if (silc_sim_load(sim)) {
1453 cipher_obj.set_key =
1454 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1455 SILC_CIPHER_SIM_SET_KEY));
1456 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1457 cipher_obj.set_key_with_string =
1458 silc_sim_getsym(sim,
1459 silc_sim_symname(alg_name,
1460 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1461 SILC_LOG_DEBUG(("set_key_with_string=%p",
1462 cipher_obj.set_key_with_string));
1463 cipher_obj.encrypt =
1464 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1465 SILC_CIPHER_SIM_ENCRYPT_CBC));
1466 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1467 cipher_obj.decrypt =
1468 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1469 SILC_CIPHER_SIM_DECRYPT_CBC));
1470 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1471 cipher_obj.context_len =
1472 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1473 SILC_CIPHER_SIM_CONTEXT_LEN));
1474 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1476 /* Put the SIM to the list of all SIM's in server */
1477 silc_dlist_add(server->sim, sim);
1479 silc_free(alg_name);
1481 SILC_LOG_ERROR(("Error configuring ciphers"));
1482 silc_server_stop(server);
1486 /* Register the cipher */
1487 silc_cipher_register(&cipher_obj);
1489 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1490 "can't load modules!"));
1491 silc_server_stop(server);
1495 cipher = cipher->next;
1501 /* Registers configured hash functions. These can then be allocated by the
1502 server when needed. */
1504 bool silc_server_config_register_hashfuncs(SilcServer server)
1506 SilcServerConfig config = server->config;
1507 SilcServerConfigHash *hash = config->hash;
1508 char *module_path = config->module_path;
1510 SILC_LOG_DEBUG(("Registering configured hash functions"));
1512 if (!hash) /* any hash func in the config file? */
1516 /* if there isn't a module_path OR there isn't a module sim name try to
1517 * use buil-in functions */
1518 if (!module_path || !hash->module) {
1520 for (i = 0; silc_default_hash[i].name; i++)
1521 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1522 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1525 if (!silc_hash_is_supported(hash->name)) {
1526 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1527 silc_server_stop(server);
1532 /* Load (try at least) the hash SIM module */
1533 SilcHashObject hash_obj;
1536 memset(&hash_obj, 0, sizeof(hash_obj));
1537 hash_obj.name = hash->name;
1538 hash_obj.block_len = hash->block_length;
1539 hash_obj.hash_len = hash->digest_length;
1541 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1543 if ((silc_sim_load(sim))) {
1545 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1546 SILC_HASH_SIM_INIT));
1547 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1549 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1550 SILC_HASH_SIM_UPDATE));
1551 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1553 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1554 SILC_HASH_SIM_FINAL));
1555 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1556 hash_obj.context_len =
1557 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1558 SILC_HASH_SIM_CONTEXT_LEN));
1559 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1561 /* Put the SIM to the table of all SIM's in server */
1562 silc_dlist_add(server->sim, sim);
1564 SILC_LOG_ERROR(("Error configuring hash functions"));
1565 silc_server_stop(server);
1569 /* Register the hash function */
1570 silc_hash_register(&hash_obj);
1572 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1573 "can't load modules!"));
1574 silc_server_stop(server);
1584 /* Registers configure HMACs. These can then be allocated by the server
1587 bool silc_server_config_register_hmacs(SilcServer server)
1589 SilcServerConfig config = server->config;
1590 SilcServerConfigHmac *hmac = config->hmac;
1592 SILC_LOG_DEBUG(("Registering configured HMACs"));
1598 SilcHmacObject hmac_obj;
1599 if (!silc_hash_is_supported(hmac->hash)) {
1600 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1601 silc_server_stop(server);
1605 /* Register the HMAC */
1606 memset(&hmac_obj, 0, sizeof(hmac_obj));
1607 hmac_obj.name = hmac->name;
1608 hmac_obj.len = hmac->mac_length;
1609 silc_hmac_register(&hmac_obj);
1617 /* Registers configured PKCS's. */
1619 bool silc_server_config_register_pkcs(SilcServer server)
1621 SilcServerConfig config = server->config;
1622 SilcServerConfigPkcs *pkcs = config->pkcs;
1624 SILC_LOG_DEBUG(("Registering configured PKCS"));
1631 for (i = 0; silc_default_pkcs[i].name; i++)
1632 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1633 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1636 if (!silc_pkcs_is_supported(pkcs->name)) {
1637 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1638 silc_server_stop(server);
1647 /* Sets log files where log messages are saved by the server logger. */
1649 void silc_server_config_setlogfiles(SilcServer server)
1651 SilcServerConfig config = server->config;
1652 SilcServerConfigLogging *this;
1654 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1656 silc_log_quick = config->logging_quick;
1657 silc_log_flushdelay = (config->logging_flushdelay ?
1658 config->logging_flushdelay :
1659 SILC_SERVER_LOG_FLUSH_DELAY);
1661 if ((this = config->logging_fatals))
1662 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1664 if ((this = config->logging_errors))
1665 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1667 if ((this = config->logging_warnings))
1668 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1670 if ((this = config->logging_info))
1671 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1675 /* Returns client authentication information from configuration file by host
1678 SilcServerConfigClient *
1679 silc_server_config_find_client(SilcServer server, char *host)
1681 SilcServerConfig config = server->config;
1682 SilcServerConfigClient *client;
1684 if (!config || !host)
1687 for (client = config->clients; client; client = client->next) {
1688 if (client->host && !silc_string_compare(client->host, host))
1693 /* if none matched, then client is already NULL */
1697 /* Returns admin connection configuration by host, username and/or
1700 SilcServerConfigAdmin *
1701 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1704 SilcServerConfig config = server->config;
1705 SilcServerConfigAdmin *admin;
1707 /* make sure we have a value for the matching parameters */
1715 for (admin = config->admins; admin; admin = admin->next) {
1716 if (admin->host && !silc_string_compare(admin->host, host))
1718 if (admin->user && !silc_string_compare(admin->user, user))
1720 if (admin->nick && !silc_string_compare(admin->nick, nick))
1722 /* no checks failed -> this entry matches */
1726 /* if none matched, then admin is already NULL */
1730 /* Returns the denied connection configuration entry by host. */
1732 SilcServerConfigDeny *
1733 silc_server_config_find_denied(SilcServer server, char *host)
1735 SilcServerConfig config = server->config;
1736 SilcServerConfigDeny *deny;
1738 /* make sure we have a value for the matching parameters */
1739 if (!config || !host)
1742 for (deny = config->denied; deny; deny = deny->next) {
1743 if (deny->host && !silc_string_compare(deny->host, host))
1748 /* if none matched, then deny is already NULL */
1752 /* Returns server connection info from server configuartion by host
1755 SilcServerConfigServer *
1756 silc_server_config_find_server_conn(SilcServer server, char *host)
1758 SilcServerConfig config = server->config;
1759 SilcServerConfigServer *serv = NULL;
1764 if (!config->servers)
1767 for (serv = config->servers; serv; serv = serv->next) {
1768 if (!silc_string_compare(serv->host, host))
1776 /* Returns router connection info from server configuration by
1777 host (name or ip). */
1779 SilcServerConfigRouter *
1780 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1782 SilcServerConfig config = server->config;
1783 SilcServerConfigRouter *serv = NULL;
1788 if (!config->routers)
1791 for (serv = config->routers; serv; serv = serv->next) {
1792 if (!silc_string_compare(serv->host, host))
1794 if (port && serv->port && serv->port != port)
1802 /* Returns TRUE if configuration for a router connection that we are
1803 initiating exists. */
1805 bool silc_server_config_is_primary_route(SilcServer server)
1807 SilcServerConfig config = server->config;
1808 SilcServerConfigRouter *serv = NULL;
1812 serv = config->routers;
1813 for (i = 0; serv; i++) {
1814 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1825 /* Returns our primary connection configuration or NULL if we do not
1826 have primary router configured. */
1828 SilcServerConfigRouter *
1829 silc_server_config_get_primary_router(SilcServer server)
1831 SilcServerConfig config = server->config;
1832 SilcServerConfigRouter *serv = NULL;
1835 serv = config->routers;
1836 for (i = 0; serv; i++) {
1837 if (serv->initiator == TRUE && serv->backup_router == FALSE)