5 Author: Johnny Mnemonic <johnny@themnemonic.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
26 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #define SERVER_CONFIG_DEBUG(fmt)
31 /* auto-declare needed variables for the common list parsing */
32 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__) \
33 SilcServerConfig config = (SilcServerConfig) context; \
34 __type__ *findtmp, *tmp = (__type__ *) config->tmp; \
37 /* allocate the tmp field for fetching data */
38 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
40 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
41 tmp = (__type__ *) config->tmp; \
44 /* append the tmp field to the specified list */
45 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
49 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
50 findtmp->next = tmp; \
53 /* loops all elements in a list and provides a di struct pointer of the
54 * specified type containing the current element */
55 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
56 for (tmp = (void *) __list__; tmp;) { \
57 __type__ *di = (__type__ *) tmp; \
58 tmp = (void *) di->next;
60 /* Set EDOUBLE error value and bail out if necessary */
61 #define CONFIG_IS_DOUBLE(__x__) \
63 got_errno = SILC_CONFIG_EDOUBLE; \
67 /* Free the authentication fields in the specified struct
68 * Expands to two instructions */
69 #define CONFIG_FREE_AUTH(__section__) \
70 silc_free(__section__->passphrase); \
71 if (__section__->publickeys) \
72 silc_hash_table_free(__section__->publickeys);
74 static void my_free_public_key(void *key, void *context, void *user_data)
76 silc_pkcs_public_key_free(context);
79 /* Set default values to those parameters that have not been defined */
81 my_set_param_defaults(SilcServerConfigConnParams *params,
82 SilcServerConfigConnParams *defaults)
84 #define SET_PARAM_DEFAULT(p, d) params->p = \
85 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
87 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
88 SET_PARAM_DEFAULT(connections_max_per_host,
89 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
90 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
91 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
92 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
93 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
94 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
96 #undef SET_PARAM_DEFAULT
99 /* Find connection parameters by the parameter block name. */
100 static SilcServerConfigConnParams *
101 my_find_param(SilcServerConfig config, const char *name)
103 SilcServerConfigConnParams *param;
105 for (param = config->conn_params; param; param = param->next) {
106 if (!strcasecmp(param->name, name))
110 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
111 "Cannot find Params \"%s\".\n", name));
116 /* parse an authdata according to its auth method */
117 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
118 SilcUInt32 line, void **auth_data,
119 SilcUInt32 *auth_data_len)
121 if (auth_meth == SILC_AUTH_PASSWORD) {
122 /* p is a plain text password */
124 *auth_data = (void *) strdup(p);
126 *auth_data_len = (SilcUInt32) strlen(p);
127 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
128 /* p is a public key file name */
129 SilcPublicKey public_key;
131 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
132 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
133 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
134 "%lu: Could not load public key file!\n",
139 /* The auth_data is a pointer to the hash table of public keys. */
141 if (*auth_data == NULL)
142 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
144 my_free_public_key, NULL,
146 silc_hash_table_add(*auth_data, public_key, public_key);
149 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
150 "Unknown authentication method.\n", line));
158 SILC_CONFIG_CALLBACK(fetch_generic)
160 SilcServerConfig config = (SilcServerConfig) context;
163 if (!strcmp(name, "module_path")) {
164 CONFIG_IS_DOUBLE(config->module_path);
165 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
167 else if (!strcmp(name, "prefer_passphrase_auth")) {
168 config->prefer_passphrase_auth = *(bool *)val;
170 else if (!strcmp(name, "require_reverse_lookup")) {
171 config->require_reverse_lookup = *(bool *)val;
173 else if (!strcmp(name, "connections_max")) {
174 config->param.connections_max = (SilcUInt32) *(int *)val;
176 else if (!strcmp(name, "connections_max_per_host")) {
177 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
179 else if (!strcmp(name, "keepalive_secs")) {
180 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
182 else if (!strcmp(name, "reconnect_count")) {
183 config->param.reconnect_count = (SilcUInt32) *(int *)val;
185 else if (!strcmp(name, "reconnect_interval")) {
186 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
188 else if (!strcmp(name, "reconnect_interval_max")) {
189 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
191 else if (!strcmp(name, "reconnect_keep_trying")) {
192 config->param.reconnect_keep_trying = *(bool *)val;
194 else if (!strcmp(name, "key_exchange_rekey")) {
195 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
197 else if (!strcmp(name, "key_exchange_pfs")) {
198 config->param.key_exchange_pfs = *(bool *)val;
200 else if (!strcmp(name, "channel_rekey_secs")) {
201 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
203 else if (!strcmp(name, "key_exchange_timeout")) {
204 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
206 else if (!strcmp(name, "conn_auth_timeout")) {
207 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
209 else if (!strcmp(name, "version_protocol")) {
210 CONFIG_IS_DOUBLE(config->param.version_protocol);
211 config->param.version_protocol =
212 (*(char *)val ? strdup((char *) val) : NULL);
214 else if (!strcmp(name, "version_software")) {
215 CONFIG_IS_DOUBLE(config->param.version_software);
216 config->param.version_software =
217 (*(char *)val ? strdup((char *) val) : NULL);
219 else if (!strcmp(name, "version_software_vendor")) {
220 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
221 config->param.version_software_vendor =
222 (*(char *)val ? strdup((char *) val) : NULL);
225 return SILC_CONFIG_EINTERNAL;
227 return SILC_CONFIG_OK;
233 SILC_CONFIG_CALLBACK(fetch_cipher)
235 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
237 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
238 type, name, context));
239 if (type == SILC_CONFIG_ARG_BLOCK) {
240 /* check the temporary struct's fields */
241 if (!tmp) /* discard empty sub-blocks */
242 return SILC_CONFIG_OK;
244 got_errno = SILC_CONFIG_EMISSFIELDS;
248 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
250 return SILC_CONFIG_OK;
252 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
254 /* Identify and save this value */
255 if (!strcmp(name, "name")) {
256 CONFIG_IS_DOUBLE(tmp->name);
257 tmp->name = strdup((char *) val);
259 else if (!strcmp(name, "module")) {
260 CONFIG_IS_DOUBLE(tmp->module);
261 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
263 else if (!strcmp(name, "keylength")) {
264 tmp->key_length = *(SilcUInt32 *)val;
266 else if (!strcmp(name, "blocklength")) {
267 tmp->block_length = *(SilcUInt32 *)val;
270 return SILC_CONFIG_EINTERNAL;
271 return SILC_CONFIG_OK;
274 silc_free(tmp->name);
275 silc_free(tmp->module);
281 SILC_CONFIG_CALLBACK(fetch_hash)
283 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
285 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
286 type, name, context));
287 if (type == SILC_CONFIG_ARG_BLOCK) {
288 /* check the temporary struct's fields */
289 if (!tmp) /* discard empty sub-blocks */
290 return SILC_CONFIG_OK;
291 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
292 got_errno = SILC_CONFIG_EMISSFIELDS;
296 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
298 return SILC_CONFIG_OK;
300 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
302 /* Identify and save this value */
303 if (!strcmp(name, "name")) {
304 CONFIG_IS_DOUBLE(tmp->name);
305 tmp->name = strdup((char *) val);
307 else if (!strcmp(name, "module")) {
308 CONFIG_IS_DOUBLE(tmp->module);
309 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
311 else if (!strcmp(name, "blocklength")) {
312 tmp->block_length = *(int *)val;
314 else if (!strcmp(name, "digestlength")) {
315 tmp->digest_length = *(int *)val;
318 return SILC_CONFIG_EINTERNAL;
319 return SILC_CONFIG_OK;
322 silc_free(tmp->name);
323 silc_free(tmp->module);
329 SILC_CONFIG_CALLBACK(fetch_hmac)
331 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
333 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
334 type, name, context));
335 if (type == SILC_CONFIG_ARG_BLOCK) {
336 /* check the temporary struct's fields */
337 if (!tmp) /* discard empty sub-blocks */
338 return SILC_CONFIG_OK;
339 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
340 got_errno = SILC_CONFIG_EMISSFIELDS;
344 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
346 return SILC_CONFIG_OK;
348 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
350 /* Identify and save this value */
351 if (!strcmp(name, "name")) {
352 CONFIG_IS_DOUBLE(tmp->name);
353 tmp->name = strdup((char *) val);
355 else if (!strcmp(name, "hash")) {
356 CONFIG_IS_DOUBLE(tmp->hash);
357 tmp->hash = strdup((char *) val);
359 else if (!strcmp(name, "maclength")) {
360 tmp->mac_length = *(int *)val;
363 return SILC_CONFIG_EINTERNAL;
364 return SILC_CONFIG_OK;
367 silc_free(tmp->name);
368 silc_free(tmp->hash);
374 SILC_CONFIG_CALLBACK(fetch_pkcs)
376 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
378 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
379 type, name, context));
380 if (type == SILC_CONFIG_ARG_BLOCK) {
381 /* check the temporary struct's fields */
382 if (!tmp) /* discard empty sub-blocks */
383 return SILC_CONFIG_OK;
385 got_errno = SILC_CONFIG_EMISSFIELDS;
389 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
391 return SILC_CONFIG_OK;
393 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
395 /* Identify and save this value */
396 if (!strcmp(name, "name")) {
397 CONFIG_IS_DOUBLE(tmp->name);
398 tmp->name = strdup((char *) val);
401 return SILC_CONFIG_EINTERNAL;
402 return SILC_CONFIG_OK;
405 silc_free(tmp->name);
411 SILC_CONFIG_CALLBACK(fetch_serverinfo)
413 SilcServerConfig config = (SilcServerConfig) context;
414 SilcServerConfigServerInfo *server_info = config->server_info;
417 /* if there isn't the struct alloc it */
419 config->server_info = server_info = (SilcServerConfigServerInfo *)
420 silc_calloc(1, sizeof(*server_info));
422 if (type == SILC_CONFIG_ARG_BLOCK) {
423 /* check for mandatory inputs */
424 if (!server_info->public_key || !server_info->private_key) {
425 got_errno = SILC_CONFIG_EMISSFIELDS;
428 return SILC_CONFIG_OK;
430 if (!strcmp(name, "hostname")) {
431 CONFIG_IS_DOUBLE(server_info->server_name);
432 server_info->server_name = strdup((char *) val);
434 else if (!strcmp(name, "ip")) {
435 CONFIG_IS_DOUBLE(server_info->server_ip);
436 server_info->server_ip = strdup((char *) val);
438 else if (!strcmp(name, "port")) {
439 int port = *(int *)val;
440 if ((port <= 0) || (port > 65535)) {
441 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
442 "Invalid port number!\n"));
443 got_errno = SILC_CONFIG_EPRINTLINE;
446 server_info->port = (SilcUInt16) port;
448 else if (!strcmp(name, "servertype")) {
449 CONFIG_IS_DOUBLE(server_info->server_type);
450 server_info->server_type = strdup((char *) val);
452 else if (!strcmp(name, "admin")) {
453 CONFIG_IS_DOUBLE(server_info->admin);
454 server_info->admin = strdup((char *) val);
456 else if (!strcmp(name, "adminemail")) {
457 CONFIG_IS_DOUBLE(server_info->email);
458 server_info->email = strdup((char *) val);
460 else if (!strcmp(name, "location")) {
461 CONFIG_IS_DOUBLE(server_info->location);
462 server_info->location = strdup((char *) val);
464 else if (!strcmp(name, "user")) {
465 CONFIG_IS_DOUBLE(server_info->user);
466 server_info->user = strdup((char *) val);
468 else if (!strcmp(name, "group")) {
469 CONFIG_IS_DOUBLE(server_info->group);
470 server_info->group = strdup((char *) val);
472 else if (!strcmp(name, "motdfile")) {
473 CONFIG_IS_DOUBLE(server_info->motd_file);
474 server_info->motd_file = strdup((char *) val);
476 else if (!strcmp(name, "pidfile")) {
477 CONFIG_IS_DOUBLE(server_info->pid_file);
478 server_info->pid_file = strdup((char *) val);
480 else if (!strcmp(name, "publickey")) {
481 char *file_tmp = (char *) val;
483 /* try to load specified file, if fail stop config parsing */
484 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
486 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
487 SILC_PKCS_FILE_BIN)) {
488 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
489 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
490 return SILC_CONFIG_ESILENT;
493 else if (!strcmp(name, "privatekey")) {
494 char *file_tmp = (char *) val;
496 /* try to load specified file, if fail stop config parsing */
497 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
499 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
500 SILC_PKCS_FILE_PEM)) {
501 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
502 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
503 return SILC_CONFIG_ESILENT;
507 return SILC_CONFIG_EINTERNAL;
508 return SILC_CONFIG_OK;
514 SILC_CONFIG_CALLBACK(fetch_logging)
516 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
518 if (!strcmp(name, "quicklogs")) {
519 config->logging_quick = *(bool *)val;
521 else if (!strcmp(name, "flushdelay")) {
522 int flushdelay = *(int *)val;
523 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
524 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
525 "Invalid flushdelay value, use quicklogs if you "
526 "want real-time logging.\n"));
527 return SILC_CONFIG_EPRINTLINE;
529 config->logging_flushdelay = (long) flushdelay;
532 /* The following istances happens only in Logging's sub-blocks, a match
533 for the sub-block name means that you should store the filename/maxsize
534 temporary struct to the proper logging channel.
535 If we get a match for "file" or "maxsize" this means that we are inside
536 a sub-sub-block and it is safe to alloc a new tmp. */
537 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
538 else if (!strcmp(name, __chan__)) { \
539 if (!tmp) return SILC_CONFIG_OK; \
541 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
543 config->__member__ = tmp; \
544 config->tmp = NULL; \
546 FETCH_LOGGING_CHAN("info", logging_info)
547 FETCH_LOGGING_CHAN("warnings", logging_warnings)
548 FETCH_LOGGING_CHAN("errors", logging_errors)
549 FETCH_LOGGING_CHAN("fatals", logging_fatals)
550 #undef FETCH_LOGGING_CHAN
551 else if (!strcmp(name, "file")) {
552 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
553 CONFIG_IS_DOUBLE(tmp->file);
554 tmp->file = strdup((char *) val);
556 else if (!strcmp(name, "size")) {
558 config->tmp = silc_calloc(1, sizeof(*tmp));
559 tmp = (SilcServerConfigLogging *) config->tmp;
561 tmp->maxsize = *(SilcUInt32 *) val;
564 return SILC_CONFIG_EINTERNAL;
565 return SILC_CONFIG_OK;
568 silc_free(tmp->file);
574 SILC_CONFIG_CALLBACK(fetch_connparam)
576 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
578 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
579 type, name, context));
580 if (type == SILC_CONFIG_ARG_BLOCK) {
581 /* check the temporary struct's fields */
582 if (!tmp) /* discard empty sub-blocks */
583 return SILC_CONFIG_OK;
585 got_errno = SILC_CONFIG_EMISSFIELDS;
589 my_set_param_defaults(tmp, &config->param);
591 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
593 return SILC_CONFIG_OK;
595 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
597 if (!strcmp(name, "name")) {
598 CONFIG_IS_DOUBLE(tmp->name);
599 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
601 else if (!strcmp(name, "connections_max")) {
602 tmp->connections_max = *(SilcUInt32 *)val;
604 else if (!strcmp(name, "connections_max_per_host")) {
605 tmp->connections_max_per_host = *(SilcUInt32 *)val;
607 else if (!strcmp(name, "keepalive_secs")) {
608 tmp->keepalive_secs = *(SilcUInt32 *)val;
610 else if (!strcmp(name, "reconnect_count")) {
611 tmp->reconnect_count = *(SilcUInt32 *)val;
613 else if (!strcmp(name, "reconnect_interval")) {
614 tmp->reconnect_interval = *(SilcUInt32 *)val;
616 else if (!strcmp(name, "reconnect_interval_max")) {
617 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
619 else if (!strcmp(name, "reconnect_keep_trying")) {
620 tmp->reconnect_keep_trying = *(bool *)val;
622 else if (!strcmp(name, "key_exchange_rekey")) {
623 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
625 else if (!strcmp(name, "key_exchange_pfs")) {
626 tmp->key_exchange_pfs = *(bool *)val;
628 else if (!strcmp(name, "version_protocol")) {
629 CONFIG_IS_DOUBLE(tmp->version_protocol);
630 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
632 else if (!strcmp(name, "version_software")) {
633 CONFIG_IS_DOUBLE(tmp->version_software);
634 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
636 else if (!strcmp(name, "version_software_vendor")) {
637 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
638 tmp->version_software_vendor =
639 (*(char *)val ? strdup((char *) val) : NULL);
642 return SILC_CONFIG_EINTERNAL;
644 return SILC_CONFIG_OK;
647 silc_free(tmp->name);
653 SILC_CONFIG_CALLBACK(fetch_client)
655 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
657 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
658 type, name, context));
660 /* Alloc before block checking, because empty sub-blocks are welcome here */
661 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
663 if (type == SILC_CONFIG_ARG_BLOCK) {
664 /* empty sub-blocks are welcome */
665 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
667 return SILC_CONFIG_OK;
670 /* Identify and save this value */
671 if (!strcmp(name, "host")) {
672 CONFIG_IS_DOUBLE(tmp->host);
673 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
675 else if (!strcmp(name, "passphrase")) {
676 CONFIG_IS_DOUBLE(tmp->passphrase);
677 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
678 (void **)&tmp->passphrase,
679 &tmp->passphrase_len)) {
680 got_errno = SILC_CONFIG_ESILENT;
684 else if (!strcmp(name, "publickey")) {
685 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
686 (void **)&tmp->publickeys, NULL)) {
687 got_errno = SILC_CONFIG_ESILENT;
691 else if (!strcmp(name, "params")) {
692 CONFIG_IS_DOUBLE(tmp->param);
693 tmp->param = my_find_param(config, (char *) val);
694 if (!tmp->param) { /* error message already output */
695 got_errno = SILC_CONFIG_EPRINTLINE;
700 return SILC_CONFIG_EINTERNAL;
701 return SILC_CONFIG_OK;
704 silc_free(tmp->host);
705 CONFIG_FREE_AUTH(tmp);
711 SILC_CONFIG_CALLBACK(fetch_admin)
713 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
715 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
716 type, name, context));
717 if (type == SILC_CONFIG_ARG_BLOCK) {
718 /* check the temporary struct's fields */
719 if (!tmp) /* discard empty sub-blocks */
720 return SILC_CONFIG_OK;
722 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
724 return SILC_CONFIG_OK;
726 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
728 /* Identify and save this value */
729 if (!strcmp(name, "host")) {
730 CONFIG_IS_DOUBLE(tmp->host);
731 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
733 else if (!strcmp(name, "user")) {
734 CONFIG_IS_DOUBLE(tmp->user);
735 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
737 else if (!strcmp(name, "nick")) {
738 CONFIG_IS_DOUBLE(tmp->nick);
739 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
741 else if (!strcmp(name, "passphrase")) {
742 CONFIG_IS_DOUBLE(tmp->passphrase);
743 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
744 (void **)&tmp->passphrase,
745 &tmp->passphrase_len)) {
746 got_errno = SILC_CONFIG_ESILENT;
750 else if (!strcmp(name, "publickey")) {
751 CONFIG_IS_DOUBLE(tmp->publickeys);
752 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
753 (void **)&tmp->publickeys, NULL)) {
754 got_errno = SILC_CONFIG_ESILENT;
759 return SILC_CONFIG_EINTERNAL;
760 return SILC_CONFIG_OK;
763 silc_free(tmp->host);
764 silc_free(tmp->user);
765 silc_free(tmp->nick);
766 CONFIG_FREE_AUTH(tmp);
772 SILC_CONFIG_CALLBACK(fetch_deny)
774 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
776 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
777 type, name, context));
778 if (type == SILC_CONFIG_ARG_BLOCK) {
779 /* check the temporary struct's fields */
780 if (!tmp) /* discard empty sub-blocks */
781 return SILC_CONFIG_OK;
783 got_errno = SILC_CONFIG_EMISSFIELDS;
787 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
789 return SILC_CONFIG_OK;
791 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
793 /* Identify and save this value */
794 if (!strcmp(name, "host")) {
795 CONFIG_IS_DOUBLE(tmp->host);
796 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
798 else if (!strcmp(name, "reason")) {
799 CONFIG_IS_DOUBLE(tmp->reason);
800 tmp->reason = strdup((char *) val);
803 return SILC_CONFIG_EINTERNAL;
804 return SILC_CONFIG_OK;
807 silc_free(tmp->host);
808 silc_free(tmp->reason);
814 SILC_CONFIG_CALLBACK(fetch_server)
816 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
818 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
819 type, name, context));
820 if (type == SILC_CONFIG_ARG_BLOCK) {
821 /* check the temporary struct's fields */
822 if (!tmp) /* discard empty sub-blocks */
823 return SILC_CONFIG_OK;
825 /* the temporary struct is ok, append it to the list */
826 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
828 return SILC_CONFIG_OK;
830 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
832 /* Identify and save this value */
833 if (!strcmp(name, "host")) {
834 CONFIG_IS_DOUBLE(tmp->host);
835 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
837 else if (!strcmp(name, "passphrase")) {
838 CONFIG_IS_DOUBLE(tmp->passphrase);
839 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
840 (void **)&tmp->passphrase,
841 &tmp->passphrase_len)) {
842 got_errno = SILC_CONFIG_ESILENT;
846 else if (!strcmp(name, "publickey")) {
847 CONFIG_IS_DOUBLE(tmp->publickeys);
848 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
849 (void **)&tmp->publickeys, NULL)) {
850 got_errno = SILC_CONFIG_ESILENT;
854 else if (!strcmp(name, "params")) {
855 CONFIG_IS_DOUBLE(tmp->param);
856 tmp->param = my_find_param(config, (char *) val);
857 if (!tmp->param) { /* error message already output */
858 got_errno = SILC_CONFIG_EPRINTLINE;
862 else if (!strcmp(name, "backup")) {
863 tmp->backup_router = *(bool *)val;
866 return SILC_CONFIG_EINTERNAL;
868 return SILC_CONFIG_OK;
871 silc_free(tmp->host);
872 CONFIG_FREE_AUTH(tmp);
878 SILC_CONFIG_CALLBACK(fetch_router)
880 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
882 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
883 type, name, context));
884 if (type == SILC_CONFIG_ARG_BLOCK) {
885 if (!tmp) /* discard empty sub-blocks */
886 return SILC_CONFIG_OK;
888 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
890 return SILC_CONFIG_OK;
892 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
894 /* Identify and save this value */
895 if (!strcmp(name, "host")) {
896 CONFIG_IS_DOUBLE(tmp->host);
897 tmp->host = strdup((char *) val);
899 else if (!strcmp(name, "port")) {
900 int port = *(int *)val;
901 if ((port <= 0) || (port > 65535)) {
902 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
903 "Invalid port number!\n"));
904 got_errno = SILC_CONFIG_EPRINTLINE;
907 tmp->port = (SilcUInt16) port;
909 else if (!strcmp(name, "passphrase")) {
910 CONFIG_IS_DOUBLE(tmp->passphrase);
911 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
912 (void **)&tmp->passphrase,
913 &tmp->passphrase_len)) {
914 got_errno = SILC_CONFIG_ESILENT;
918 else if (!strcmp(name, "publickey")) {
919 CONFIG_IS_DOUBLE(tmp->publickeys);
920 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
921 (void **)&tmp->publickeys, NULL)) {
922 got_errno = SILC_CONFIG_ESILENT;
926 else if (!strcmp(name, "params")) {
927 CONFIG_IS_DOUBLE(tmp->param);
928 tmp->param = my_find_param(config, (char *) val);
929 if (!tmp->param) { /* error message already output */
930 got_errno = SILC_CONFIG_EPRINTLINE;
934 else if (!strcmp(name, "initiator")) {
935 tmp->initiator = *(bool *)val;
937 else if (!strcmp(name, "backuphost")) {
938 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
939 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
942 else if (!strcmp(name, "backupport")) {
943 int port = *(int *)val;
944 if ((port <= 0) || (port > 65535)) {
945 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
946 "Invalid port number!\n"));
947 got_errno = SILC_CONFIG_EPRINTLINE;
950 tmp->backup_replace_port = (SilcUInt16) port;
952 else if (!strcmp(name, "backuplocal")) {
953 tmp->backup_local = *(bool *)val;
956 return SILC_CONFIG_EINTERNAL;
958 return SILC_CONFIG_OK;
961 silc_free(tmp->host);
962 silc_free(tmp->backup_replace_ip);
963 CONFIG_FREE_AUTH(tmp);
969 /* known config options tables */
970 static const SilcConfigTable table_general[] = {
971 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
972 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
973 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
974 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
975 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
976 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
977 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
978 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
979 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
980 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
981 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
982 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
983 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
984 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
985 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
986 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
987 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
988 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
992 static const SilcConfigTable table_cipher[] = {
993 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
994 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
995 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
996 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1000 static const SilcConfigTable table_hash[] = {
1001 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1002 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1003 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1004 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1008 static const SilcConfigTable table_hmac[] = {
1009 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1010 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1011 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1015 static const SilcConfigTable table_pkcs[] = {
1016 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1020 static const SilcConfigTable table_serverinfo[] = {
1021 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1022 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1023 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1024 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1025 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1026 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1027 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1028 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1029 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1030 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1031 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1032 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1033 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1037 static const SilcConfigTable table_logging_c[] = {
1038 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1039 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1040 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1044 static const SilcConfigTable table_logging[] = {
1045 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1046 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1047 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1048 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1049 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1050 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1054 static const SilcConfigTable table_connparam[] = {
1055 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1056 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1057 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1058 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1059 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1060 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1061 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1062 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1063 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1064 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1065 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1066 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1067 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1068 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1072 static const SilcConfigTable table_client[] = {
1073 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1074 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1075 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1076 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1080 static const SilcConfigTable table_admin[] = {
1081 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1082 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1083 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1084 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1085 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1086 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1087 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1091 static const SilcConfigTable table_deny[] = {
1092 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1093 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1097 static const SilcConfigTable table_serverconn[] = {
1098 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1099 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1100 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1101 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1102 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1106 static const SilcConfigTable table_routerconn[] = {
1107 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1108 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1109 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1110 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1111 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1112 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1113 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1114 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1115 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1119 static const SilcConfigTable table_main[] = {
1120 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1121 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1122 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1123 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1124 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1125 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1126 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1127 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1128 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1129 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1130 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1131 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1132 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1136 /* Set default values to stuff that was not configured. */
1138 static void silc_server_config_set_defaults(SilcServerConfig config)
1140 my_set_param_defaults(&config->param, NULL);
1142 config->channel_rekey_secs = (config->channel_rekey_secs ?
1143 config->channel_rekey_secs :
1144 SILC_SERVER_CHANNEL_REKEY);
1145 config->key_exchange_timeout = (config->key_exchange_timeout ?
1146 config->key_exchange_timeout :
1147 SILC_SERVER_SKE_TIMEOUT);
1148 config->conn_auth_timeout = (config->conn_auth_timeout ?
1149 config->conn_auth_timeout :
1150 SILC_SERVER_CONNAUTH_TIMEOUT);
1153 /* Allocates a new configuration object, opens configuration file and
1154 parses it. The parsed data is returned to the newly allocated
1155 configuration object. The SilcServerConfig must be freed by calling
1156 the silc_server_config_destroy function. */
1158 SilcServerConfig silc_server_config_alloc(const char *filename)
1160 SilcServerConfig config_new;
1161 SilcConfigEntity ent;
1162 SilcConfigFile *file;
1164 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1166 /* alloc a config object */
1167 config_new = silc_calloc(1, sizeof(*config_new));
1168 config_new->refcount = 1;
1172 /* obtain a config file object */
1173 file = silc_config_open(filename);
1175 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1180 /* obtain a SilcConfig entity, we can use it to start the parsing */
1181 ent = silc_config_init(file);
1183 /* load the known configuration options, give our empty object as context */
1184 silc_config_register_table(ent, table_main, (void *) config_new);
1186 /* enter the main parsing loop. When this returns, we have the parsing
1187 * result and the object filled (or partially, in case of errors). */
1188 ret = silc_config_main(ent);
1189 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1190 silc_config_strerror(ret)));
1192 /* Check if the parser returned errors */
1194 /* handle this special error return which asks to quietly return */
1195 if (ret != SILC_CONFIG_ESILENT) {
1196 char *linebuf, *filename = silc_config_get_filename(file);
1197 SilcUInt32 line = silc_config_get_line(file);
1198 if (ret != SILC_CONFIG_EPRINTLINE)
1199 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1200 silc_config_strerror(ret)));
1201 linebuf = silc_config_read_line(file, line);
1202 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1206 silc_server_config_destroy(config_new);
1210 /* close (destroy) the file object */
1211 silc_config_close(file);
1213 /* If config_new is incomplete, abort the object and return NULL */
1214 if (!config_new->server_info) {
1215 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1216 "`server_info'\n"));
1217 silc_server_config_destroy(config_new);
1221 /* XXX are there any other mandatory sections in the config file? */
1223 /* Set default to configuration parameters */
1224 silc_server_config_set_defaults(config_new);
1229 /* Increments the reference counter of a config object */
1231 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1236 ref->config = config;
1237 ref->ref_ptr = ref_ptr;
1238 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1239 config->refcount - 1, config->refcount));
1243 /* Decrements the reference counter of a config object. If the counter
1244 reaches 0, the config object is destroyed. */
1246 void silc_server_config_unref(SilcServerConfigRef *ref)
1249 silc_server_config_destroy(ref->config);
1252 /* Destroy a config object with all his children lists */
1254 void silc_server_config_destroy(SilcServerConfig config)
1259 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1260 config->refcount + 1, config->refcount));
1261 if (config->refcount > 0)
1264 SILC_LOG_DEBUG(("Freeing config context"));
1266 /* Destroy general config stuff */
1267 silc_free(config->module_path);
1268 silc_free(config->param.version_protocol);
1269 silc_free(config->param.version_software);
1270 silc_free(config->param.version_software_vendor);
1272 /* Destroy Logging channels */
1273 if (config->logging_info)
1274 silc_free(config->logging_info->file);
1275 if (config->logging_warnings)
1276 silc_free(config->logging_warnings->file);
1277 if (config->logging_errors)
1278 silc_free(config->logging_errors->file);
1279 if (config->logging_fatals)
1280 silc_free(config->logging_fatals->file);
1282 /* Destroy the ServerInfo struct */
1283 if (config->server_info) {
1284 register SilcServerConfigServerInfo *si = config->server_info;
1285 silc_free(si->server_name);
1286 silc_free(si->server_ip);
1287 silc_free(si->server_type);
1288 silc_free(si->location);
1289 silc_free(si->admin);
1290 silc_free(si->email);
1291 silc_free(si->user);
1292 silc_free(si->group);
1293 silc_free(si->motd_file);
1294 silc_free(si->pid_file);
1295 silc_pkcs_public_key_free(si->public_key);
1296 silc_pkcs_private_key_free(si->private_key);
1299 /* Now let's destroy the lists */
1301 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1303 silc_free(di->name);
1304 silc_free(di->module);
1307 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1308 silc_free(di->name);
1309 silc_free(di->module);
1312 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1313 silc_free(di->name);
1314 silc_free(di->hash);
1317 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1318 silc_free(di->name);
1321 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1322 config->conn_params)
1323 silc_free(di->name);
1324 silc_free(di->version_protocol);
1325 silc_free(di->version_software);
1326 silc_free(di->version_software_vendor);
1329 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1330 silc_free(di->host);
1331 CONFIG_FREE_AUTH(di);
1334 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1335 silc_free(di->host);
1336 silc_free(di->user);
1337 silc_free(di->nick);
1338 CONFIG_FREE_AUTH(di);
1341 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1342 silc_free(di->host);
1343 silc_free(di->reason);
1346 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1348 silc_free(di->host);
1349 CONFIG_FREE_AUTH(di);
1352 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1354 silc_free(di->host);
1355 silc_free(di->backup_replace_ip);
1356 CONFIG_FREE_AUTH(di);
1360 memset(config, 'F', sizeof(*config));
1364 /* Registers configured ciphers. These can then be allocated by the
1365 server when needed. */
1367 bool silc_server_config_register_ciphers(SilcServer server)
1369 SilcServerConfig config = server->config;
1370 SilcServerConfigCipher *cipher = config->cipher;
1371 char *module_path = config->module_path;
1373 SILC_LOG_DEBUG(("Registering configured ciphers"));
1375 if (!cipher) /* any cipher in the config file? */
1379 /* if there isn't a module_path OR there isn't a module sim name try to
1380 * use buil-in functions */
1381 if (!module_path || !cipher->module) {
1383 for (i = 0; silc_default_ciphers[i].name; i++)
1384 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1385 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1388 if (!silc_cipher_is_supported(cipher->name)) {
1389 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1390 silc_server_stop(server);
1395 /* Load (try at least) the crypto SIM module */
1396 char buf[1023], *alg_name;
1397 SilcCipherObject cipher_obj;
1400 memset(&cipher_obj, 0, sizeof(cipher_obj));
1401 cipher_obj.name = cipher->name;
1402 cipher_obj.block_len = cipher->block_length;
1403 cipher_obj.key_len = cipher->key_length * 8;
1405 /* build the libname */
1406 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1408 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1410 alg_name = strdup(cipher->name);
1411 if (strchr(alg_name, '-'))
1412 *strchr(alg_name, '-') = '\0';
1414 if (silc_sim_load(sim)) {
1415 cipher_obj.set_key =
1416 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1417 SILC_CIPHER_SIM_SET_KEY));
1418 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1419 cipher_obj.set_key_with_string =
1420 silc_sim_getsym(sim,
1421 silc_sim_symname(alg_name,
1422 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1423 SILC_LOG_DEBUG(("set_key_with_string=%p",
1424 cipher_obj.set_key_with_string));
1425 cipher_obj.encrypt =
1426 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1427 SILC_CIPHER_SIM_ENCRYPT_CBC));
1428 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1429 cipher_obj.decrypt =
1430 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1431 SILC_CIPHER_SIM_DECRYPT_CBC));
1432 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1433 cipher_obj.context_len =
1434 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1435 SILC_CIPHER_SIM_CONTEXT_LEN));
1436 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1438 /* Put the SIM to the list of all SIM's in server */
1439 silc_dlist_add(server->sim, sim);
1441 silc_free(alg_name);
1443 SILC_LOG_ERROR(("Error configuring ciphers"));
1444 silc_server_stop(server);
1448 /* Register the cipher */
1449 silc_cipher_register(&cipher_obj);
1451 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1452 "can't load modules!"));
1453 silc_server_stop(server);
1457 cipher = cipher->next;
1463 /* Registers configured hash functions. These can then be allocated by the
1464 server when needed. */
1466 bool silc_server_config_register_hashfuncs(SilcServer server)
1468 SilcServerConfig config = server->config;
1469 SilcServerConfigHash *hash = config->hash;
1470 char *module_path = config->module_path;
1472 SILC_LOG_DEBUG(("Registering configured hash functions"));
1474 if (!hash) /* any hash func in the config file? */
1478 /* if there isn't a module_path OR there isn't a module sim name try to
1479 * use buil-in functions */
1480 if (!module_path || !hash->module) {
1482 for (i = 0; silc_default_hash[i].name; i++)
1483 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1484 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1487 if (!silc_hash_is_supported(hash->name)) {
1488 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1489 silc_server_stop(server);
1494 /* Load (try at least) the hash SIM module */
1495 SilcHashObject hash_obj;
1498 memset(&hash_obj, 0, sizeof(hash_obj));
1499 hash_obj.name = hash->name;
1500 hash_obj.block_len = hash->block_length;
1501 hash_obj.hash_len = hash->digest_length;
1503 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1505 if ((silc_sim_load(sim))) {
1507 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1508 SILC_HASH_SIM_INIT));
1509 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1511 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1512 SILC_HASH_SIM_UPDATE));
1513 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1515 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1516 SILC_HASH_SIM_FINAL));
1517 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1518 hash_obj.context_len =
1519 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1520 SILC_HASH_SIM_CONTEXT_LEN));
1521 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1523 /* Put the SIM to the table of all SIM's in server */
1524 silc_dlist_add(server->sim, sim);
1526 SILC_LOG_ERROR(("Error configuring hash functions"));
1527 silc_server_stop(server);
1531 /* Register the hash function */
1532 silc_hash_register(&hash_obj);
1534 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1535 "can't load modules!"));
1536 silc_server_stop(server);
1546 /* Registers configure HMACs. These can then be allocated by the server
1549 bool silc_server_config_register_hmacs(SilcServer server)
1551 SilcServerConfig config = server->config;
1552 SilcServerConfigHmac *hmac = config->hmac;
1554 SILC_LOG_DEBUG(("Registering configured HMACs"));
1560 SilcHmacObject hmac_obj;
1561 if (!silc_hash_is_supported(hmac->hash)) {
1562 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1563 silc_server_stop(server);
1567 /* Register the HMAC */
1568 memset(&hmac_obj, 0, sizeof(hmac_obj));
1569 hmac_obj.name = hmac->name;
1570 hmac_obj.len = hmac->mac_length;
1571 silc_hmac_register(&hmac_obj);
1579 /* Registers configured PKCS's. */
1581 bool silc_server_config_register_pkcs(SilcServer server)
1583 SilcServerConfig config = server->config;
1584 SilcServerConfigPkcs *pkcs = config->pkcs;
1586 SILC_LOG_DEBUG(("Registering configured PKCS"));
1593 for (i = 0; silc_default_pkcs[i].name; i++)
1594 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1595 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1598 if (!silc_pkcs_is_supported(pkcs->name)) {
1599 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1600 silc_server_stop(server);
1609 /* Sets log files where log messages are saved by the server logger. */
1611 void silc_server_config_setlogfiles(SilcServer server)
1613 SilcServerConfig config = server->config;
1614 SilcServerConfigLogging *this;
1616 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1618 silc_log_quick = config->logging_quick;
1619 silc_log_flushdelay = (config->logging_flushdelay ?
1620 config->logging_flushdelay :
1621 SILC_SERVER_LOG_FLUSH_DELAY);
1623 if ((this = config->logging_fatals))
1624 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1626 if ((this = config->logging_errors))
1627 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1629 if ((this = config->logging_warnings))
1630 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1632 if ((this = config->logging_info))
1633 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1637 /* Returns client authentication information from configuration file by host
1640 SilcServerConfigClient *
1641 silc_server_config_find_client(SilcServer server, char *host)
1643 SilcServerConfig config = server->config;
1644 SilcServerConfigClient *client;
1646 if (!config || !host)
1649 for (client = config->clients; client; client = client->next) {
1650 if (client->host && !silc_string_compare(client->host, host))
1655 /* if none matched, then client is already NULL */
1659 /* Returns admin connection configuration by host, username and/or
1662 SilcServerConfigAdmin *
1663 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1666 SilcServerConfig config = server->config;
1667 SilcServerConfigAdmin *admin;
1669 /* make sure we have a value for the matching parameters */
1677 for (admin = config->admins; admin; admin = admin->next) {
1678 if (admin->host && !silc_string_compare(admin->host, host))
1680 if (admin->user && !silc_string_compare(admin->user, user))
1682 if (admin->nick && !silc_string_compare(admin->nick, nick))
1684 /* no checks failed -> this entry matches */
1688 /* if none matched, then admin is already NULL */
1692 /* Returns the denied connection configuration entry by host. */
1694 SilcServerConfigDeny *
1695 silc_server_config_find_denied(SilcServer server, char *host)
1697 SilcServerConfig config = server->config;
1698 SilcServerConfigDeny *deny;
1700 /* make sure we have a value for the matching parameters */
1701 if (!config || !host)
1704 for (deny = config->denied; deny; deny = deny->next) {
1705 if (deny->host && !silc_string_compare(deny->host, host))
1710 /* if none matched, then deny is already NULL */
1714 /* Returns server connection info from server configuartion by host
1717 SilcServerConfigServer *
1718 silc_server_config_find_server_conn(SilcServer server, char *host)
1720 SilcServerConfig config = server->config;
1721 SilcServerConfigServer *serv = NULL;
1726 if (!config->servers)
1729 for (serv = config->servers; serv; serv = serv->next) {
1730 if (!silc_string_compare(serv->host, host))
1738 /* Returns router connection info from server configuration by
1739 host (name or ip). */
1741 SilcServerConfigRouter *
1742 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1744 SilcServerConfig config = server->config;
1745 SilcServerConfigRouter *serv = NULL;
1750 if (!config->routers)
1753 for (serv = config->routers; serv; serv = serv->next) {
1754 if (!silc_string_compare(serv->host, host))
1756 if (port && serv->port && serv->port != port)
1764 /* Returns TRUE if configuration for a router connection that we are
1765 initiating exists. */
1767 bool silc_server_config_is_primary_route(SilcServer server)
1769 SilcServerConfig config = server->config;
1770 SilcServerConfigRouter *serv = NULL;
1774 serv = config->routers;
1775 for (i = 0; serv; i++) {
1776 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1787 /* Returns our primary connection configuration or NULL if we do not
1788 have primary router configured. */
1790 SilcServerConfigRouter *
1791 silc_server_config_get_primary_router(SilcServer server)
1793 SilcServerConfig config = server->config;
1794 SilcServerConfigRouter *serv = NULL;
1797 serv = config->routers;
1798 for (i = 0; serv; i++) {
1799 if (serv->initiator == TRUE && serv->backup_router == FALSE)