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 */
123 if (auth_data && auth_data_len) {
124 if (!silc_utf8_valid(p, strlen(p))) {
125 *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0);
126 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127 silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
130 *auth_data = (void *) strdup(p);
131 *auth_data_len = (SilcUInt32) strlen(p);
134 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
135 /* p is a public key file name */
136 SilcPublicKey public_key;
138 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
139 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
140 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
141 "%lu: Could not load public key file!\n",
146 /* The auth_data is a pointer to the hash table of public keys. */
148 if (*auth_data == NULL)
149 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
151 my_free_public_key, NULL,
153 silc_hash_table_add(*auth_data, public_key, public_key);
156 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
157 "Unknown authentication method.\n", line));
165 SILC_CONFIG_CALLBACK(fetch_generic)
167 SilcServerConfig config = (SilcServerConfig) context;
170 if (!strcmp(name, "module_path")) {
171 CONFIG_IS_DOUBLE(config->module_path);
172 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
174 else if (!strcmp(name, "prefer_passphrase_auth")) {
175 config->prefer_passphrase_auth = *(bool *)val;
177 else if (!strcmp(name, "require_reverse_lookup")) {
178 config->require_reverse_lookup = *(bool *)val;
180 else if (!strcmp(name, "connections_max")) {
181 config->param.connections_max = (SilcUInt32) *(int *)val;
183 else if (!strcmp(name, "connections_max_per_host")) {
184 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
186 else if (!strcmp(name, "keepalive_secs")) {
187 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
189 else if (!strcmp(name, "reconnect_count")) {
190 config->param.reconnect_count = (SilcUInt32) *(int *)val;
192 else if (!strcmp(name, "reconnect_interval")) {
193 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
195 else if (!strcmp(name, "reconnect_interval_max")) {
196 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
198 else if (!strcmp(name, "reconnect_keep_trying")) {
199 config->param.reconnect_keep_trying = *(bool *)val;
201 else if (!strcmp(name, "key_exchange_rekey")) {
202 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
204 else if (!strcmp(name, "key_exchange_pfs")) {
205 config->param.key_exchange_pfs = *(bool *)val;
207 else if (!strcmp(name, "channel_rekey_secs")) {
208 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
210 else if (!strcmp(name, "key_exchange_timeout")) {
211 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
213 else if (!strcmp(name, "conn_auth_timeout")) {
214 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
216 else if (!strcmp(name, "version_protocol")) {
217 CONFIG_IS_DOUBLE(config->param.version_protocol);
218 config->param.version_protocol =
219 (*(char *)val ? strdup((char *) val) : NULL);
221 else if (!strcmp(name, "version_software")) {
222 CONFIG_IS_DOUBLE(config->param.version_software);
223 config->param.version_software =
224 (*(char *)val ? strdup((char *) val) : NULL);
226 else if (!strcmp(name, "version_software_vendor")) {
227 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
228 config->param.version_software_vendor =
229 (*(char *)val ? strdup((char *) val) : NULL);
231 else if (!strcmp(name, "detach_disabled")) {
232 config->detach_disabled = *(bool *)val;
234 else if (!strcmp(name, "detach_timeout")) {
235 config->detach_timeout = (SilcUInt32) *(int *)val;
238 return SILC_CONFIG_EINTERNAL;
240 return SILC_CONFIG_OK;
246 SILC_CONFIG_CALLBACK(fetch_cipher)
248 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
250 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
251 type, name, context));
252 if (type == SILC_CONFIG_ARG_BLOCK) {
253 /* check the temporary struct's fields */
254 if (!tmp) /* discard empty sub-blocks */
255 return SILC_CONFIG_OK;
257 got_errno = SILC_CONFIG_EMISSFIELDS;
261 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
263 return SILC_CONFIG_OK;
265 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
267 /* Identify and save this value */
268 if (!strcmp(name, "name")) {
269 CONFIG_IS_DOUBLE(tmp->name);
270 tmp->name = strdup((char *) val);
272 else if (!strcmp(name, "module")) {
273 CONFIG_IS_DOUBLE(tmp->module);
274 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
276 else if (!strcmp(name, "keylength")) {
277 tmp->key_length = *(SilcUInt32 *)val;
279 else if (!strcmp(name, "blocklength")) {
280 tmp->block_length = *(SilcUInt32 *)val;
283 return SILC_CONFIG_EINTERNAL;
284 return SILC_CONFIG_OK;
287 silc_free(tmp->name);
288 silc_free(tmp->module);
294 SILC_CONFIG_CALLBACK(fetch_hash)
296 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
298 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
299 type, name, context));
300 if (type == SILC_CONFIG_ARG_BLOCK) {
301 /* check the temporary struct's fields */
302 if (!tmp) /* discard empty sub-blocks */
303 return SILC_CONFIG_OK;
304 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
305 got_errno = SILC_CONFIG_EMISSFIELDS;
309 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
311 return SILC_CONFIG_OK;
313 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
315 /* Identify and save this value */
316 if (!strcmp(name, "name")) {
317 CONFIG_IS_DOUBLE(tmp->name);
318 tmp->name = strdup((char *) val);
320 else if (!strcmp(name, "module")) {
321 CONFIG_IS_DOUBLE(tmp->module);
322 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
324 else if (!strcmp(name, "blocklength")) {
325 tmp->block_length = *(int *)val;
327 else if (!strcmp(name, "digestlength")) {
328 tmp->digest_length = *(int *)val;
331 return SILC_CONFIG_EINTERNAL;
332 return SILC_CONFIG_OK;
335 silc_free(tmp->name);
336 silc_free(tmp->module);
342 SILC_CONFIG_CALLBACK(fetch_hmac)
344 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
346 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
347 type, name, context));
348 if (type == SILC_CONFIG_ARG_BLOCK) {
349 /* check the temporary struct's fields */
350 if (!tmp) /* discard empty sub-blocks */
351 return SILC_CONFIG_OK;
352 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
353 got_errno = SILC_CONFIG_EMISSFIELDS;
357 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
359 return SILC_CONFIG_OK;
361 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
363 /* Identify and save this value */
364 if (!strcmp(name, "name")) {
365 CONFIG_IS_DOUBLE(tmp->name);
366 tmp->name = strdup((char *) val);
368 else if (!strcmp(name, "hash")) {
369 CONFIG_IS_DOUBLE(tmp->hash);
370 tmp->hash = strdup((char *) val);
372 else if (!strcmp(name, "maclength")) {
373 tmp->mac_length = *(int *)val;
376 return SILC_CONFIG_EINTERNAL;
377 return SILC_CONFIG_OK;
380 silc_free(tmp->name);
381 silc_free(tmp->hash);
387 SILC_CONFIG_CALLBACK(fetch_pkcs)
389 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
391 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
392 type, name, context));
393 if (type == SILC_CONFIG_ARG_BLOCK) {
394 /* check the temporary struct's fields */
395 if (!tmp) /* discard empty sub-blocks */
396 return SILC_CONFIG_OK;
398 got_errno = SILC_CONFIG_EMISSFIELDS;
402 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
404 return SILC_CONFIG_OK;
406 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
408 /* Identify and save this value */
409 if (!strcmp(name, "name")) {
410 CONFIG_IS_DOUBLE(tmp->name);
411 tmp->name = strdup((char *) val);
414 return SILC_CONFIG_EINTERNAL;
415 return SILC_CONFIG_OK;
418 silc_free(tmp->name);
424 SILC_CONFIG_CALLBACK(fetch_serverinfo)
426 SilcServerConfig config = (SilcServerConfig) context;
427 SilcServerConfigServerInfo *server_info = config->server_info;
430 /* if there isn't the struct alloc it */
432 config->server_info = server_info = (SilcServerConfigServerInfo *)
433 silc_calloc(1, sizeof(*server_info));
435 if (type == SILC_CONFIG_ARG_BLOCK) {
436 /* check for mandatory inputs */
437 if (!server_info->public_key || !server_info->private_key) {
438 got_errno = SILC_CONFIG_EMISSFIELDS;
441 return SILC_CONFIG_OK;
443 if (!strcmp(name, "hostname")) {
444 CONFIG_IS_DOUBLE(server_info->server_name);
445 server_info->server_name = strdup((char *) val);
447 else if (!strcmp(name, "ip")) {
448 CONFIG_IS_DOUBLE(server_info->server_ip);
449 server_info->server_ip = strdup((char *) val);
451 else if (!strcmp(name, "port")) {
452 int port = *(int *)val;
453 if ((port <= 0) || (port > 65535)) {
454 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
455 "Invalid port number!\n"));
456 got_errno = SILC_CONFIG_EPRINTLINE;
459 server_info->port = (SilcUInt16) port;
461 else if (!strcmp(name, "servertype")) {
462 CONFIG_IS_DOUBLE(server_info->server_type);
463 server_info->server_type = strdup((char *) val);
465 else if (!strcmp(name, "admin")) {
466 CONFIG_IS_DOUBLE(server_info->admin);
467 server_info->admin = strdup((char *) val);
469 else if (!strcmp(name, "adminemail")) {
470 CONFIG_IS_DOUBLE(server_info->email);
471 server_info->email = strdup((char *) val);
473 else if (!strcmp(name, "location")) {
474 CONFIG_IS_DOUBLE(server_info->location);
475 server_info->location = strdup((char *) val);
477 else if (!strcmp(name, "user")) {
478 CONFIG_IS_DOUBLE(server_info->user);
479 server_info->user = strdup((char *) val);
481 else if (!strcmp(name, "group")) {
482 CONFIG_IS_DOUBLE(server_info->group);
483 server_info->group = strdup((char *) val);
485 else if (!strcmp(name, "motdfile")) {
486 CONFIG_IS_DOUBLE(server_info->motd_file);
487 server_info->motd_file = strdup((char *) val);
489 else if (!strcmp(name, "pidfile")) {
490 CONFIG_IS_DOUBLE(server_info->pid_file);
491 server_info->pid_file = strdup((char *) val);
493 else if (!strcmp(name, "publickey")) {
494 char *file_tmp = (char *) val;
496 /* try to load specified file, if fail stop config parsing */
497 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
499 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
500 SILC_PKCS_FILE_BIN)) {
501 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
502 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
503 return SILC_CONFIG_ESILENT;
506 else if (!strcmp(name, "privatekey")) {
507 char *file_tmp = (char *) val;
509 /* try to load specified file, if fail stop config parsing */
510 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
512 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
513 SILC_PKCS_FILE_PEM)) {
514 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
515 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
516 return SILC_CONFIG_ESILENT;
520 return SILC_CONFIG_EINTERNAL;
521 return SILC_CONFIG_OK;
527 SILC_CONFIG_CALLBACK(fetch_logging)
529 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
531 if (!strcmp(name, "quicklogs")) {
532 config->logging_quick = *(bool *)val;
534 else if (!strcmp(name, "flushdelay")) {
535 int flushdelay = *(int *)val;
536 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
537 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
538 "Invalid flushdelay value, use quicklogs if you "
539 "want real-time logging.\n"));
540 return SILC_CONFIG_EPRINTLINE;
542 config->logging_flushdelay = (long) flushdelay;
545 /* The following istances happens only in Logging's sub-blocks, a match
546 for the sub-block name means that you should store the filename/maxsize
547 temporary struct to the proper logging channel.
548 If we get a match for "file" or "maxsize" this means that we are inside
549 a sub-sub-block and it is safe to alloc a new tmp. */
550 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
551 else if (!strcmp(name, __chan__)) { \
552 if (!tmp) return SILC_CONFIG_OK; \
554 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
556 config->__member__ = tmp; \
557 config->tmp = NULL; \
559 FETCH_LOGGING_CHAN("info", logging_info)
560 FETCH_LOGGING_CHAN("warnings", logging_warnings)
561 FETCH_LOGGING_CHAN("errors", logging_errors)
562 FETCH_LOGGING_CHAN("fatals", logging_fatals)
563 #undef FETCH_LOGGING_CHAN
564 else if (!strcmp(name, "file")) {
565 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
566 CONFIG_IS_DOUBLE(tmp->file);
567 tmp->file = strdup((char *) val);
569 else if (!strcmp(name, "size")) {
571 config->tmp = silc_calloc(1, sizeof(*tmp));
572 tmp = (SilcServerConfigLogging *) config->tmp;
574 tmp->maxsize = *(SilcUInt32 *) val;
577 return SILC_CONFIG_EINTERNAL;
578 return SILC_CONFIG_OK;
581 silc_free(tmp->file);
587 SILC_CONFIG_CALLBACK(fetch_connparam)
589 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
591 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
592 type, name, context));
593 if (type == SILC_CONFIG_ARG_BLOCK) {
594 /* check the temporary struct's fields */
595 if (!tmp) /* discard empty sub-blocks */
596 return SILC_CONFIG_OK;
598 got_errno = SILC_CONFIG_EMISSFIELDS;
602 my_set_param_defaults(tmp, &config->param);
604 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
606 return SILC_CONFIG_OK;
608 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
610 if (!strcmp(name, "name")) {
611 CONFIG_IS_DOUBLE(tmp->name);
612 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
614 else if (!strcmp(name, "connections_max")) {
615 tmp->connections_max = *(SilcUInt32 *)val;
617 else if (!strcmp(name, "connections_max_per_host")) {
618 tmp->connections_max_per_host = *(SilcUInt32 *)val;
620 else if (!strcmp(name, "keepalive_secs")) {
621 tmp->keepalive_secs = *(SilcUInt32 *)val;
623 else if (!strcmp(name, "reconnect_count")) {
624 tmp->reconnect_count = *(SilcUInt32 *)val;
626 else if (!strcmp(name, "reconnect_interval")) {
627 tmp->reconnect_interval = *(SilcUInt32 *)val;
629 else if (!strcmp(name, "reconnect_interval_max")) {
630 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
632 else if (!strcmp(name, "reconnect_keep_trying")) {
633 tmp->reconnect_keep_trying = *(bool *)val;
635 else if (!strcmp(name, "key_exchange_rekey")) {
636 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
638 else if (!strcmp(name, "key_exchange_pfs")) {
639 tmp->key_exchange_pfs = *(bool *)val;
641 else if (!strcmp(name, "version_protocol")) {
642 CONFIG_IS_DOUBLE(tmp->version_protocol);
643 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
645 else if (!strcmp(name, "version_software")) {
646 CONFIG_IS_DOUBLE(tmp->version_software);
647 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
649 else if (!strcmp(name, "version_software_vendor")) {
650 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
651 tmp->version_software_vendor =
652 (*(char *)val ? strdup((char *) val) : NULL);
655 return SILC_CONFIG_EINTERNAL;
657 return SILC_CONFIG_OK;
660 silc_free(tmp->name);
666 SILC_CONFIG_CALLBACK(fetch_client)
668 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
670 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
671 type, name, context));
673 /* Alloc before block checking, because empty sub-blocks are welcome here */
674 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
676 if (type == SILC_CONFIG_ARG_BLOCK) {
677 /* empty sub-blocks are welcome */
678 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
680 return SILC_CONFIG_OK;
683 /* Identify and save this value */
684 if (!strcmp(name, "host")) {
685 CONFIG_IS_DOUBLE(tmp->host);
686 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
688 else if (!strcmp(name, "passphrase")) {
689 CONFIG_IS_DOUBLE(tmp->passphrase);
690 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
691 (void **)&tmp->passphrase,
692 &tmp->passphrase_len)) {
693 got_errno = SILC_CONFIG_ESILENT;
697 else if (!strcmp(name, "publickey")) {
698 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
699 (void **)&tmp->publickeys, NULL)) {
700 got_errno = SILC_CONFIG_ESILENT;
704 else if (!strcmp(name, "params")) {
705 CONFIG_IS_DOUBLE(tmp->param);
706 tmp->param = my_find_param(config, (char *) val);
707 if (!tmp->param) { /* error message already output */
708 got_errno = SILC_CONFIG_EPRINTLINE;
713 return SILC_CONFIG_EINTERNAL;
714 return SILC_CONFIG_OK;
717 silc_free(tmp->host);
718 CONFIG_FREE_AUTH(tmp);
724 SILC_CONFIG_CALLBACK(fetch_admin)
726 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
728 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
729 type, name, context));
730 if (type == SILC_CONFIG_ARG_BLOCK) {
731 /* check the temporary struct's fields */
732 if (!tmp) /* discard empty sub-blocks */
733 return SILC_CONFIG_OK;
735 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
737 return SILC_CONFIG_OK;
739 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
741 /* Identify and save this value */
742 if (!strcmp(name, "host")) {
743 CONFIG_IS_DOUBLE(tmp->host);
744 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
746 else if (!strcmp(name, "user")) {
747 CONFIG_IS_DOUBLE(tmp->user);
748 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
750 else if (!strcmp(name, "nick")) {
751 CONFIG_IS_DOUBLE(tmp->nick);
752 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
754 else if (!strcmp(name, "passphrase")) {
755 CONFIG_IS_DOUBLE(tmp->passphrase);
756 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
757 (void **)&tmp->passphrase,
758 &tmp->passphrase_len)) {
759 got_errno = SILC_CONFIG_ESILENT;
763 else if (!strcmp(name, "publickey")) {
764 CONFIG_IS_DOUBLE(tmp->publickeys);
765 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
766 (void **)&tmp->publickeys, NULL)) {
767 got_errno = SILC_CONFIG_ESILENT;
772 return SILC_CONFIG_EINTERNAL;
773 return SILC_CONFIG_OK;
776 silc_free(tmp->host);
777 silc_free(tmp->user);
778 silc_free(tmp->nick);
779 CONFIG_FREE_AUTH(tmp);
785 SILC_CONFIG_CALLBACK(fetch_deny)
787 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
789 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
790 type, name, context));
791 if (type == SILC_CONFIG_ARG_BLOCK) {
792 /* check the temporary struct's fields */
793 if (!tmp) /* discard empty sub-blocks */
794 return SILC_CONFIG_OK;
796 got_errno = SILC_CONFIG_EMISSFIELDS;
800 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
802 return SILC_CONFIG_OK;
804 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
806 /* Identify and save this value */
807 if (!strcmp(name, "host")) {
808 CONFIG_IS_DOUBLE(tmp->host);
809 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
811 else if (!strcmp(name, "reason")) {
812 CONFIG_IS_DOUBLE(tmp->reason);
813 tmp->reason = strdup((char *) val);
816 return SILC_CONFIG_EINTERNAL;
817 return SILC_CONFIG_OK;
820 silc_free(tmp->host);
821 silc_free(tmp->reason);
827 SILC_CONFIG_CALLBACK(fetch_server)
829 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
831 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
832 type, name, context));
833 if (type == SILC_CONFIG_ARG_BLOCK) {
834 /* check the temporary struct's fields */
835 if (!tmp) /* discard empty sub-blocks */
836 return SILC_CONFIG_OK;
838 /* the temporary struct is ok, append it to the list */
839 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
841 return SILC_CONFIG_OK;
843 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
845 /* Identify and save this value */
846 if (!strcmp(name, "host")) {
847 CONFIG_IS_DOUBLE(tmp->host);
848 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
850 else if (!strcmp(name, "passphrase")) {
851 CONFIG_IS_DOUBLE(tmp->passphrase);
852 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
853 (void **)&tmp->passphrase,
854 &tmp->passphrase_len)) {
855 got_errno = SILC_CONFIG_ESILENT;
859 else if (!strcmp(name, "publickey")) {
860 CONFIG_IS_DOUBLE(tmp->publickeys);
861 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
862 (void **)&tmp->publickeys, NULL)) {
863 got_errno = SILC_CONFIG_ESILENT;
867 else if (!strcmp(name, "params")) {
868 CONFIG_IS_DOUBLE(tmp->param);
869 tmp->param = my_find_param(config, (char *) val);
870 if (!tmp->param) { /* error message already output */
871 got_errno = SILC_CONFIG_EPRINTLINE;
875 else if (!strcmp(name, "backup")) {
876 tmp->backup_router = *(bool *)val;
879 return SILC_CONFIG_EINTERNAL;
881 return SILC_CONFIG_OK;
884 silc_free(tmp->host);
885 CONFIG_FREE_AUTH(tmp);
891 SILC_CONFIG_CALLBACK(fetch_router)
893 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
895 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
896 type, name, context));
897 if (type == SILC_CONFIG_ARG_BLOCK) {
898 if (!tmp) /* discard empty sub-blocks */
899 return SILC_CONFIG_OK;
901 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
903 return SILC_CONFIG_OK;
905 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
907 /* Identify and save this value */
908 if (!strcmp(name, "host")) {
909 CONFIG_IS_DOUBLE(tmp->host);
910 tmp->host = strdup((char *) val);
912 else if (!strcmp(name, "port")) {
913 int port = *(int *)val;
914 if ((port <= 0) || (port > 65535)) {
915 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
916 "Invalid port number!\n"));
917 got_errno = SILC_CONFIG_EPRINTLINE;
920 tmp->port = (SilcUInt16) port;
922 else if (!strcmp(name, "passphrase")) {
923 CONFIG_IS_DOUBLE(tmp->passphrase);
924 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
925 (void **)&tmp->passphrase,
926 &tmp->passphrase_len)) {
927 got_errno = SILC_CONFIG_ESILENT;
931 else if (!strcmp(name, "publickey")) {
932 CONFIG_IS_DOUBLE(tmp->publickeys);
933 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
934 (void **)&tmp->publickeys, NULL)) {
935 got_errno = SILC_CONFIG_ESILENT;
939 else if (!strcmp(name, "params")) {
940 CONFIG_IS_DOUBLE(tmp->param);
941 tmp->param = my_find_param(config, (char *) val);
942 if (!tmp->param) { /* error message already output */
943 got_errno = SILC_CONFIG_EPRINTLINE;
947 else if (!strcmp(name, "initiator")) {
948 tmp->initiator = *(bool *)val;
950 else if (!strcmp(name, "backuphost")) {
951 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
952 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
955 else if (!strcmp(name, "backupport")) {
956 int port = *(int *)val;
957 if ((port <= 0) || (port > 65535)) {
958 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
959 "Invalid port number!\n"));
960 got_errno = SILC_CONFIG_EPRINTLINE;
963 tmp->backup_replace_port = (SilcUInt16) port;
965 else if (!strcmp(name, "backuplocal")) {
966 tmp->backup_local = *(bool *)val;
969 return SILC_CONFIG_EINTERNAL;
971 return SILC_CONFIG_OK;
974 silc_free(tmp->host);
975 silc_free(tmp->backup_replace_ip);
976 CONFIG_FREE_AUTH(tmp);
982 /* known config options tables */
983 static const SilcConfigTable table_general[] = {
984 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
985 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
986 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
987 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
988 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
989 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
990 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
991 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
992 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
993 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
994 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
995 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
996 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
997 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
998 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
999 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1000 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1001 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1002 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1003 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1007 static const SilcConfigTable table_cipher[] = {
1008 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1009 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1010 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1011 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1015 static const SilcConfigTable table_hash[] = {
1016 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1017 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1018 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1019 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1023 static const SilcConfigTable table_hmac[] = {
1024 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1025 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1026 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1030 static const SilcConfigTable table_pkcs[] = {
1031 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1035 static const SilcConfigTable table_serverinfo[] = {
1036 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1037 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1038 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1039 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1040 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1041 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1042 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1043 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1044 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1045 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1046 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1047 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1048 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1052 static const SilcConfigTable table_logging_c[] = {
1053 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1054 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1055 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1059 static const SilcConfigTable table_logging[] = {
1060 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1061 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1062 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1063 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1064 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1065 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1069 static const SilcConfigTable table_connparam[] = {
1070 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1071 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1072 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1073 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1074 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1075 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1076 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1077 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1078 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1079 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1080 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1081 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1082 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1083 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1087 static const SilcConfigTable table_client[] = {
1088 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1089 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1090 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1091 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1095 static const SilcConfigTable table_admin[] = {
1096 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1097 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1098 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1099 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1100 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1101 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1102 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1106 static const SilcConfigTable table_deny[] = {
1107 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1108 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1112 static const SilcConfigTable table_serverconn[] = {
1113 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1114 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1115 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1116 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1117 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1121 static const SilcConfigTable table_routerconn[] = {
1122 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1123 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1124 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1125 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1126 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1127 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1128 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1129 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1130 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1134 static const SilcConfigTable table_main[] = {
1135 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1136 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1137 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1138 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1139 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1140 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1141 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1142 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1143 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1144 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1145 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1146 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1147 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1151 /* Set default values to stuff that was not configured. */
1153 static void silc_server_config_set_defaults(SilcServerConfig config)
1155 my_set_param_defaults(&config->param, NULL);
1157 config->channel_rekey_secs = (config->channel_rekey_secs ?
1158 config->channel_rekey_secs :
1159 SILC_SERVER_CHANNEL_REKEY);
1160 config->key_exchange_timeout = (config->key_exchange_timeout ?
1161 config->key_exchange_timeout :
1162 SILC_SERVER_SKE_TIMEOUT);
1163 config->conn_auth_timeout = (config->conn_auth_timeout ?
1164 config->conn_auth_timeout :
1165 SILC_SERVER_CONNAUTH_TIMEOUT);
1168 /* Allocates a new configuration object, opens configuration file and
1169 parses it. The parsed data is returned to the newly allocated
1170 configuration object. The SilcServerConfig must be freed by calling
1171 the silc_server_config_destroy function. */
1173 SilcServerConfig silc_server_config_alloc(const char *filename)
1175 SilcServerConfig config_new;
1176 SilcConfigEntity ent;
1177 SilcConfigFile *file;
1179 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1181 /* alloc a config object */
1182 config_new = silc_calloc(1, sizeof(*config_new));
1183 config_new->refcount = 1;
1187 /* obtain a config file object */
1188 file = silc_config_open(filename);
1190 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1195 /* obtain a SilcConfig entity, we can use it to start the parsing */
1196 ent = silc_config_init(file);
1198 /* load the known configuration options, give our empty object as context */
1199 silc_config_register_table(ent, table_main, (void *) config_new);
1201 /* enter the main parsing loop. When this returns, we have the parsing
1202 * result and the object filled (or partially, in case of errors). */
1203 ret = silc_config_main(ent);
1204 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1205 silc_config_strerror(ret)));
1207 /* Check if the parser returned errors */
1209 /* handle this special error return which asks to quietly return */
1210 if (ret != SILC_CONFIG_ESILENT) {
1211 char *linebuf, *filename = silc_config_get_filename(file);
1212 SilcUInt32 line = silc_config_get_line(file);
1213 if (ret != SILC_CONFIG_EPRINTLINE)
1214 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1215 silc_config_strerror(ret)));
1216 linebuf = silc_config_read_line(file, line);
1217 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1221 silc_server_config_destroy(config_new);
1225 /* close (destroy) the file object */
1226 silc_config_close(file);
1228 /* If config_new is incomplete, abort the object and return NULL */
1229 if (!config_new->server_info) {
1230 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1231 "`server_info'\n"));
1232 silc_server_config_destroy(config_new);
1236 /* XXX are there any other mandatory sections in the config file? */
1238 /* Set default to configuration parameters */
1239 silc_server_config_set_defaults(config_new);
1244 /* Increments the reference counter of a config object */
1246 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1251 ref->config = config;
1252 ref->ref_ptr = ref_ptr;
1253 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1254 config->refcount - 1, config->refcount));
1258 /* Decrements the reference counter of a config object. If the counter
1259 reaches 0, the config object is destroyed. */
1261 void silc_server_config_unref(SilcServerConfigRef *ref)
1264 silc_server_config_destroy(ref->config);
1267 /* Destroy a config object with all his children lists */
1269 void silc_server_config_destroy(SilcServerConfig config)
1274 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1275 config->refcount + 1, config->refcount));
1276 if (config->refcount > 0)
1279 SILC_LOG_DEBUG(("Freeing config context"));
1281 /* Destroy general config stuff */
1282 silc_free(config->module_path);
1283 silc_free(config->param.version_protocol);
1284 silc_free(config->param.version_software);
1285 silc_free(config->param.version_software_vendor);
1287 /* Destroy Logging channels */
1288 if (config->logging_info)
1289 silc_free(config->logging_info->file);
1290 if (config->logging_warnings)
1291 silc_free(config->logging_warnings->file);
1292 if (config->logging_errors)
1293 silc_free(config->logging_errors->file);
1294 if (config->logging_fatals)
1295 silc_free(config->logging_fatals->file);
1297 /* Destroy the ServerInfo struct */
1298 if (config->server_info) {
1299 register SilcServerConfigServerInfo *si = config->server_info;
1300 silc_free(si->server_name);
1301 silc_free(si->server_ip);
1302 silc_free(si->server_type);
1303 silc_free(si->location);
1304 silc_free(si->admin);
1305 silc_free(si->email);
1306 silc_free(si->user);
1307 silc_free(si->group);
1308 silc_free(si->motd_file);
1309 silc_free(si->pid_file);
1310 silc_pkcs_public_key_free(si->public_key);
1311 silc_pkcs_private_key_free(si->private_key);
1314 /* Now let's destroy the lists */
1316 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1318 silc_free(di->name);
1319 silc_free(di->module);
1322 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1323 silc_free(di->name);
1324 silc_free(di->module);
1327 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1328 silc_free(di->name);
1329 silc_free(di->hash);
1332 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1333 silc_free(di->name);
1336 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1337 config->conn_params)
1338 silc_free(di->name);
1339 silc_free(di->version_protocol);
1340 silc_free(di->version_software);
1341 silc_free(di->version_software_vendor);
1344 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1345 silc_free(di->host);
1346 CONFIG_FREE_AUTH(di);
1349 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1350 silc_free(di->host);
1351 silc_free(di->user);
1352 silc_free(di->nick);
1353 CONFIG_FREE_AUTH(di);
1356 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1357 silc_free(di->host);
1358 silc_free(di->reason);
1361 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1363 silc_free(di->host);
1364 CONFIG_FREE_AUTH(di);
1367 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1369 silc_free(di->host);
1370 silc_free(di->backup_replace_ip);
1371 CONFIG_FREE_AUTH(di);
1375 memset(config, 'F', sizeof(*config));
1379 /* Registers configured ciphers. These can then be allocated by the
1380 server when needed. */
1382 bool silc_server_config_register_ciphers(SilcServer server)
1384 SilcServerConfig config = server->config;
1385 SilcServerConfigCipher *cipher = config->cipher;
1386 char *module_path = config->module_path;
1388 SILC_LOG_DEBUG(("Registering configured ciphers"));
1390 if (!cipher) /* any cipher in the config file? */
1394 /* if there isn't a module_path OR there isn't a module sim name try to
1395 * use buil-in functions */
1396 if (!module_path || !cipher->module) {
1398 for (i = 0; silc_default_ciphers[i].name; i++)
1399 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1400 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1403 if (!silc_cipher_is_supported(cipher->name)) {
1404 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1405 silc_server_stop(server);
1410 /* Load (try at least) the crypto SIM module */
1411 char buf[1023], *alg_name;
1412 SilcCipherObject cipher_obj;
1415 memset(&cipher_obj, 0, sizeof(cipher_obj));
1416 cipher_obj.name = cipher->name;
1417 cipher_obj.block_len = cipher->block_length;
1418 cipher_obj.key_len = cipher->key_length * 8;
1420 /* build the libname */
1421 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1423 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1425 alg_name = strdup(cipher->name);
1426 if (strchr(alg_name, '-'))
1427 *strchr(alg_name, '-') = '\0';
1429 if (silc_sim_load(sim)) {
1430 cipher_obj.set_key =
1431 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1432 SILC_CIPHER_SIM_SET_KEY));
1433 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1434 cipher_obj.set_key_with_string =
1435 silc_sim_getsym(sim,
1436 silc_sim_symname(alg_name,
1437 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1438 SILC_LOG_DEBUG(("set_key_with_string=%p",
1439 cipher_obj.set_key_with_string));
1440 cipher_obj.encrypt =
1441 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1442 SILC_CIPHER_SIM_ENCRYPT_CBC));
1443 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1444 cipher_obj.decrypt =
1445 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1446 SILC_CIPHER_SIM_DECRYPT_CBC));
1447 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1448 cipher_obj.context_len =
1449 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1450 SILC_CIPHER_SIM_CONTEXT_LEN));
1451 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1453 /* Put the SIM to the list of all SIM's in server */
1454 silc_dlist_add(server->sim, sim);
1456 silc_free(alg_name);
1458 SILC_LOG_ERROR(("Error configuring ciphers"));
1459 silc_server_stop(server);
1463 /* Register the cipher */
1464 silc_cipher_register(&cipher_obj);
1466 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1467 "can't load modules!"));
1468 silc_server_stop(server);
1472 cipher = cipher->next;
1478 /* Registers configured hash functions. These can then be allocated by the
1479 server when needed. */
1481 bool silc_server_config_register_hashfuncs(SilcServer server)
1483 SilcServerConfig config = server->config;
1484 SilcServerConfigHash *hash = config->hash;
1485 char *module_path = config->module_path;
1487 SILC_LOG_DEBUG(("Registering configured hash functions"));
1489 if (!hash) /* any hash func in the config file? */
1493 /* if there isn't a module_path OR there isn't a module sim name try to
1494 * use buil-in functions */
1495 if (!module_path || !hash->module) {
1497 for (i = 0; silc_default_hash[i].name; i++)
1498 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1499 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1502 if (!silc_hash_is_supported(hash->name)) {
1503 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1504 silc_server_stop(server);
1509 /* Load (try at least) the hash SIM module */
1510 SilcHashObject hash_obj;
1513 memset(&hash_obj, 0, sizeof(hash_obj));
1514 hash_obj.name = hash->name;
1515 hash_obj.block_len = hash->block_length;
1516 hash_obj.hash_len = hash->digest_length;
1518 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1520 if ((silc_sim_load(sim))) {
1522 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1523 SILC_HASH_SIM_INIT));
1524 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1526 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1527 SILC_HASH_SIM_UPDATE));
1528 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1530 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1531 SILC_HASH_SIM_FINAL));
1532 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1533 hash_obj.context_len =
1534 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1535 SILC_HASH_SIM_CONTEXT_LEN));
1536 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1538 /* Put the SIM to the table of all SIM's in server */
1539 silc_dlist_add(server->sim, sim);
1541 SILC_LOG_ERROR(("Error configuring hash functions"));
1542 silc_server_stop(server);
1546 /* Register the hash function */
1547 silc_hash_register(&hash_obj);
1549 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1550 "can't load modules!"));
1551 silc_server_stop(server);
1561 /* Registers configure HMACs. These can then be allocated by the server
1564 bool silc_server_config_register_hmacs(SilcServer server)
1566 SilcServerConfig config = server->config;
1567 SilcServerConfigHmac *hmac = config->hmac;
1569 SILC_LOG_DEBUG(("Registering configured HMACs"));
1575 SilcHmacObject hmac_obj;
1576 if (!silc_hash_is_supported(hmac->hash)) {
1577 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1578 silc_server_stop(server);
1582 /* Register the HMAC */
1583 memset(&hmac_obj, 0, sizeof(hmac_obj));
1584 hmac_obj.name = hmac->name;
1585 hmac_obj.len = hmac->mac_length;
1586 silc_hmac_register(&hmac_obj);
1594 /* Registers configured PKCS's. */
1596 bool silc_server_config_register_pkcs(SilcServer server)
1598 SilcServerConfig config = server->config;
1599 SilcServerConfigPkcs *pkcs = config->pkcs;
1601 SILC_LOG_DEBUG(("Registering configured PKCS"));
1608 for (i = 0; silc_default_pkcs[i].name; i++)
1609 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1610 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1613 if (!silc_pkcs_is_supported(pkcs->name)) {
1614 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1615 silc_server_stop(server);
1624 /* Sets log files where log messages are saved by the server logger. */
1626 void silc_server_config_setlogfiles(SilcServer server)
1628 SilcServerConfig config = server->config;
1629 SilcServerConfigLogging *this;
1631 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1633 silc_log_quick = config->logging_quick;
1634 silc_log_flushdelay = (config->logging_flushdelay ?
1635 config->logging_flushdelay :
1636 SILC_SERVER_LOG_FLUSH_DELAY);
1638 if ((this = config->logging_fatals))
1639 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1641 if ((this = config->logging_errors))
1642 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1644 if ((this = config->logging_warnings))
1645 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1647 if ((this = config->logging_info))
1648 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1652 /* Returns client authentication information from configuration file by host
1655 SilcServerConfigClient *
1656 silc_server_config_find_client(SilcServer server, char *host)
1658 SilcServerConfig config = server->config;
1659 SilcServerConfigClient *client;
1661 if (!config || !host)
1664 for (client = config->clients; client; client = client->next) {
1665 if (client->host && !silc_string_compare(client->host, host))
1670 /* if none matched, then client is already NULL */
1674 /* Returns admin connection configuration by host, username and/or
1677 SilcServerConfigAdmin *
1678 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1681 SilcServerConfig config = server->config;
1682 SilcServerConfigAdmin *admin;
1684 /* make sure we have a value for the matching parameters */
1692 for (admin = config->admins; admin; admin = admin->next) {
1693 if (admin->host && !silc_string_compare(admin->host, host))
1695 if (admin->user && !silc_string_compare(admin->user, user))
1697 if (admin->nick && !silc_string_compare(admin->nick, nick))
1699 /* no checks failed -> this entry matches */
1703 /* if none matched, then admin is already NULL */
1707 /* Returns the denied connection configuration entry by host. */
1709 SilcServerConfigDeny *
1710 silc_server_config_find_denied(SilcServer server, char *host)
1712 SilcServerConfig config = server->config;
1713 SilcServerConfigDeny *deny;
1715 /* make sure we have a value for the matching parameters */
1716 if (!config || !host)
1719 for (deny = config->denied; deny; deny = deny->next) {
1720 if (deny->host && !silc_string_compare(deny->host, host))
1725 /* if none matched, then deny is already NULL */
1729 /* Returns server connection info from server configuartion by host
1732 SilcServerConfigServer *
1733 silc_server_config_find_server_conn(SilcServer server, char *host)
1735 SilcServerConfig config = server->config;
1736 SilcServerConfigServer *serv = NULL;
1741 if (!config->servers)
1744 for (serv = config->servers; serv; serv = serv->next) {
1745 if (!silc_string_compare(serv->host, host))
1753 /* Returns router connection info from server configuration by
1754 host (name or ip). */
1756 SilcServerConfigRouter *
1757 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1759 SilcServerConfig config = server->config;
1760 SilcServerConfigRouter *serv = NULL;
1765 if (!config->routers)
1768 for (serv = config->routers; serv; serv = serv->next) {
1769 if (!silc_string_compare(serv->host, host))
1771 if (port && serv->port && serv->port != port)
1779 /* Returns TRUE if configuration for a router connection that we are
1780 initiating exists. */
1782 bool silc_server_config_is_primary_route(SilcServer server)
1784 SilcServerConfig config = server->config;
1785 SilcServerConfigRouter *serv = NULL;
1789 serv = config->routers;
1790 for (i = 0; serv; i++) {
1791 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1802 /* Returns our primary connection configuration or NULL if we do not
1803 have primary router configured. */
1805 SilcServerConfigRouter *
1806 silc_server_config_get_primary_router(SilcServer server)
1808 SilcServerConfig config = server->config;
1809 SilcServerConfigRouter *serv = NULL;
1812 serv = config->routers;
1813 for (i = 0; serv; i++) {
1814 if (serv->initiator == TRUE && serv->backup_router == FALSE)