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),
126 SILC_STRING_LANGUAGE);
127 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
128 silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
131 *auth_data = (void *) strdup(p);
132 *auth_data_len = (SilcUInt32) strlen(p);
135 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
136 /* p is a public key file name */
137 SilcPublicKey public_key;
139 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
140 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
141 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
142 "%lu: Could not load public key file!\n",
147 /* The auth_data is a pointer to the hash table of public keys. */
149 if (*auth_data == NULL)
150 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
152 my_free_public_key, NULL,
154 silc_hash_table_add(*auth_data, public_key, public_key);
157 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
158 "Unknown authentication method.\n", line));
166 SILC_CONFIG_CALLBACK(fetch_generic)
168 SilcServerConfig config = (SilcServerConfig) context;
171 if (!strcmp(name, "module_path")) {
172 CONFIG_IS_DOUBLE(config->module_path);
173 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
175 else if (!strcmp(name, "prefer_passphrase_auth")) {
176 config->prefer_passphrase_auth = *(bool *)val;
178 else if (!strcmp(name, "require_reverse_lookup")) {
179 config->require_reverse_lookup = *(bool *)val;
181 else if (!strcmp(name, "connections_max")) {
182 config->param.connections_max = (SilcUInt32) *(int *)val;
184 else if (!strcmp(name, "connections_max_per_host")) {
185 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
187 else if (!strcmp(name, "keepalive_secs")) {
188 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
190 else if (!strcmp(name, "reconnect_count")) {
191 config->param.reconnect_count = (SilcUInt32) *(int *)val;
193 else if (!strcmp(name, "reconnect_interval")) {
194 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
196 else if (!strcmp(name, "reconnect_interval_max")) {
197 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
199 else if (!strcmp(name, "reconnect_keep_trying")) {
200 config->param.reconnect_keep_trying = *(bool *)val;
202 else if (!strcmp(name, "key_exchange_rekey")) {
203 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
205 else if (!strcmp(name, "key_exchange_pfs")) {
206 config->param.key_exchange_pfs = *(bool *)val;
208 else if (!strcmp(name, "channel_rekey_secs")) {
209 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
211 else if (!strcmp(name, "key_exchange_timeout")) {
212 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
214 else if (!strcmp(name, "conn_auth_timeout")) {
215 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
217 else if (!strcmp(name, "version_protocol")) {
218 CONFIG_IS_DOUBLE(config->param.version_protocol);
219 config->param.version_protocol =
220 (*(char *)val ? strdup((char *) val) : NULL);
222 else if (!strcmp(name, "version_software")) {
223 CONFIG_IS_DOUBLE(config->param.version_software);
224 config->param.version_software =
225 (*(char *)val ? strdup((char *) val) : NULL);
227 else if (!strcmp(name, "version_software_vendor")) {
228 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
229 config->param.version_software_vendor =
230 (*(char *)val ? strdup((char *) val) : NULL);
232 else if (!strcmp(name, "detach_disabled")) {
233 config->detach_disabled = *(bool *)val;
235 else if (!strcmp(name, "detach_timeout")) {
236 config->detach_timeout = (SilcUInt32) *(int *)val;
239 return SILC_CONFIG_EINTERNAL;
241 return SILC_CONFIG_OK;
247 SILC_CONFIG_CALLBACK(fetch_cipher)
249 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
251 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
252 type, name, context));
253 if (type == SILC_CONFIG_ARG_BLOCK) {
254 /* check the temporary struct's fields */
255 if (!tmp) /* discard empty sub-blocks */
256 return SILC_CONFIG_OK;
258 got_errno = SILC_CONFIG_EMISSFIELDS;
262 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
264 return SILC_CONFIG_OK;
266 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
268 /* Identify and save this value */
269 if (!strcmp(name, "name")) {
270 CONFIG_IS_DOUBLE(tmp->name);
271 tmp->name = strdup((char *) val);
273 else if (!strcmp(name, "module")) {
274 CONFIG_IS_DOUBLE(tmp->module);
275 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
277 else if (!strcmp(name, "keylength")) {
278 tmp->key_length = *(SilcUInt32 *)val;
280 else if (!strcmp(name, "blocklength")) {
281 tmp->block_length = *(SilcUInt32 *)val;
284 return SILC_CONFIG_EINTERNAL;
285 return SILC_CONFIG_OK;
288 silc_free(tmp->name);
289 silc_free(tmp->module);
295 SILC_CONFIG_CALLBACK(fetch_hash)
297 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
299 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
300 type, name, context));
301 if (type == SILC_CONFIG_ARG_BLOCK) {
302 /* check the temporary struct's fields */
303 if (!tmp) /* discard empty sub-blocks */
304 return SILC_CONFIG_OK;
305 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
306 got_errno = SILC_CONFIG_EMISSFIELDS;
310 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
312 return SILC_CONFIG_OK;
314 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
316 /* Identify and save this value */
317 if (!strcmp(name, "name")) {
318 CONFIG_IS_DOUBLE(tmp->name);
319 tmp->name = strdup((char *) val);
321 else if (!strcmp(name, "module")) {
322 CONFIG_IS_DOUBLE(tmp->module);
323 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
325 else if (!strcmp(name, "blocklength")) {
326 tmp->block_length = *(int *)val;
328 else if (!strcmp(name, "digestlength")) {
329 tmp->digest_length = *(int *)val;
332 return SILC_CONFIG_EINTERNAL;
333 return SILC_CONFIG_OK;
336 silc_free(tmp->name);
337 silc_free(tmp->module);
343 SILC_CONFIG_CALLBACK(fetch_hmac)
345 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
347 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
348 type, name, context));
349 if (type == SILC_CONFIG_ARG_BLOCK) {
350 /* check the temporary struct's fields */
351 if (!tmp) /* discard empty sub-blocks */
352 return SILC_CONFIG_OK;
353 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
354 got_errno = SILC_CONFIG_EMISSFIELDS;
358 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
360 return SILC_CONFIG_OK;
362 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
364 /* Identify and save this value */
365 if (!strcmp(name, "name")) {
366 CONFIG_IS_DOUBLE(tmp->name);
367 tmp->name = strdup((char *) val);
369 else if (!strcmp(name, "hash")) {
370 CONFIG_IS_DOUBLE(tmp->hash);
371 tmp->hash = strdup((char *) val);
373 else if (!strcmp(name, "maclength")) {
374 tmp->mac_length = *(int *)val;
377 return SILC_CONFIG_EINTERNAL;
378 return SILC_CONFIG_OK;
381 silc_free(tmp->name);
382 silc_free(tmp->hash);
388 SILC_CONFIG_CALLBACK(fetch_pkcs)
390 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
392 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
393 type, name, context));
394 if (type == SILC_CONFIG_ARG_BLOCK) {
395 /* check the temporary struct's fields */
396 if (!tmp) /* discard empty sub-blocks */
397 return SILC_CONFIG_OK;
399 got_errno = SILC_CONFIG_EMISSFIELDS;
403 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
405 return SILC_CONFIG_OK;
407 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
409 /* Identify and save this value */
410 if (!strcmp(name, "name")) {
411 CONFIG_IS_DOUBLE(tmp->name);
412 tmp->name = strdup((char *) val);
415 return SILC_CONFIG_EINTERNAL;
416 return SILC_CONFIG_OK;
419 silc_free(tmp->name);
425 SILC_CONFIG_CALLBACK(fetch_serverinfo)
427 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
428 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 if (!strcmp(name, "primary")) {
437 CONFIG_IS_DOUBLE(server_info->primary);
439 return SILC_CONFIG_OK;
440 server_info->primary = tmp;
442 return SILC_CONFIG_OK;
443 } else if (!strcmp(name, "secondary")) {
445 return SILC_CONFIG_OK;
446 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
448 return SILC_CONFIG_OK;
449 } else if (!server_info->public_key || !server_info->private_key) {
450 got_errno = SILC_CONFIG_EMISSFIELDS;
453 return SILC_CONFIG_OK;
455 if (!strcmp(name, "hostname")) {
456 CONFIG_IS_DOUBLE(server_info->server_name);
457 server_info->server_name = strdup((char *) val);
459 else if (!strcmp(name, "ip")) {
460 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
461 CONFIG_IS_DOUBLE(tmp->server_ip);
462 tmp->server_ip = strdup((char *) val);
464 else if (!strcmp(name, "port")) {
465 int port = *(int *)val;
466 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
467 if ((port <= 0) || (port > 65535)) {
468 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
469 "Invalid port number!\n"));
470 got_errno = SILC_CONFIG_EPRINTLINE;
473 tmp->port = (SilcUInt16) port;
475 else if (!strcmp(name, "servertype")) {
476 CONFIG_IS_DOUBLE(server_info->server_type);
477 server_info->server_type = strdup((char *) val);
479 else if (!strcmp(name, "admin")) {
480 CONFIG_IS_DOUBLE(server_info->admin);
481 server_info->admin = strdup((char *) val);
483 else if (!strcmp(name, "adminemail")) {
484 CONFIG_IS_DOUBLE(server_info->email);
485 server_info->email = strdup((char *) val);
487 else if (!strcmp(name, "location")) {
488 CONFIG_IS_DOUBLE(server_info->location);
489 server_info->location = strdup((char *) val);
491 else if (!strcmp(name, "user")) {
492 CONFIG_IS_DOUBLE(server_info->user);
493 server_info->user = strdup((char *) val);
495 else if (!strcmp(name, "group")) {
496 CONFIG_IS_DOUBLE(server_info->group);
497 server_info->group = strdup((char *) val);
499 else if (!strcmp(name, "motdfile")) {
500 CONFIG_IS_DOUBLE(server_info->motd_file);
501 server_info->motd_file = strdup((char *) val);
503 else if (!strcmp(name, "pidfile")) {
504 CONFIG_IS_DOUBLE(server_info->pid_file);
505 server_info->pid_file = strdup((char *) val);
507 else if (!strcmp(name, "publickey")) {
508 char *file_tmp = (char *) val;
510 /* try to load specified file, if fail stop config parsing */
511 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
513 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
514 SILC_PKCS_FILE_BIN)) {
515 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
516 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
517 return SILC_CONFIG_ESILENT;
520 else if (!strcmp(name, "privatekey")) {
521 char *file_tmp = (char *) val;
523 /* try to load specified file, if fail stop config parsing */
524 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
526 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
527 SILC_PKCS_FILE_PEM)) {
528 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
529 SILC_SERVER_LOG_ERROR((" line %lu, file \"%s\"\n", line, file_tmp));
530 return SILC_CONFIG_ESILENT;
534 return SILC_CONFIG_EINTERNAL;
535 return SILC_CONFIG_OK;
539 silc_free(config->tmp);
544 SILC_CONFIG_CALLBACK(fetch_logging)
546 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
548 if (!strcmp(name, "timestamp")) {
549 config->logging_timestamp = *(bool *)val;
551 else if (!strcmp(name, "quicklogs")) {
552 config->logging_quick = *(bool *)val;
554 else if (!strcmp(name, "flushdelay")) {
555 int flushdelay = *(int *)val;
556 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
557 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
558 "Invalid flushdelay value, use quicklogs if you "
559 "want real-time logging.\n"));
560 return SILC_CONFIG_EPRINTLINE;
562 config->logging_flushdelay = (long) flushdelay;
565 /* The following istances happens only in Logging's sub-blocks, a match
566 for the sub-block name means that you should store the filename/maxsize
567 temporary struct to the proper logging channel.
568 If we get a match for "file" or "maxsize" this means that we are inside
569 a sub-sub-block and it is safe to alloc a new tmp. */
570 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
571 else if (!strcmp(name, __chan__)) { \
572 if (!tmp) return SILC_CONFIG_OK; \
574 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
576 config->__member__ = tmp; \
577 config->tmp = NULL; \
579 FETCH_LOGGING_CHAN("info", logging_info)
580 FETCH_LOGGING_CHAN("warnings", logging_warnings)
581 FETCH_LOGGING_CHAN("errors", logging_errors)
582 FETCH_LOGGING_CHAN("fatals", logging_fatals)
583 #undef FETCH_LOGGING_CHAN
584 else if (!strcmp(name, "file")) {
585 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
586 CONFIG_IS_DOUBLE(tmp->file);
587 tmp->file = strdup((char *) val);
589 else if (!strcmp(name, "size")) {
591 config->tmp = silc_calloc(1, sizeof(*tmp));
592 tmp = (SilcServerConfigLogging *) config->tmp;
594 tmp->maxsize = *(SilcUInt32 *) val;
597 return SILC_CONFIG_EINTERNAL;
598 return SILC_CONFIG_OK;
601 silc_free(tmp->file);
607 SILC_CONFIG_CALLBACK(fetch_connparam)
609 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
611 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
612 type, name, context));
613 if (type == SILC_CONFIG_ARG_BLOCK) {
614 /* check the temporary struct's fields */
615 if (!tmp) /* discard empty sub-blocks */
616 return SILC_CONFIG_OK;
618 got_errno = SILC_CONFIG_EMISSFIELDS;
622 my_set_param_defaults(tmp, &config->param);
624 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
626 return SILC_CONFIG_OK;
628 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
630 if (!strcmp(name, "name")) {
631 CONFIG_IS_DOUBLE(tmp->name);
632 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
634 else if (!strcmp(name, "connections_max")) {
635 tmp->connections_max = *(SilcUInt32 *)val;
637 else if (!strcmp(name, "connections_max_per_host")) {
638 tmp->connections_max_per_host = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "keepalive_secs")) {
641 tmp->keepalive_secs = *(SilcUInt32 *)val;
643 else if (!strcmp(name, "reconnect_count")) {
644 tmp->reconnect_count = *(SilcUInt32 *)val;
646 else if (!strcmp(name, "reconnect_interval")) {
647 tmp->reconnect_interval = *(SilcUInt32 *)val;
649 else if (!strcmp(name, "reconnect_interval_max")) {
650 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
652 else if (!strcmp(name, "reconnect_keep_trying")) {
653 tmp->reconnect_keep_trying = *(bool *)val;
655 else if (!strcmp(name, "key_exchange_rekey")) {
656 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
658 else if (!strcmp(name, "key_exchange_pfs")) {
659 tmp->key_exchange_pfs = *(bool *)val;
661 else if (!strcmp(name, "version_protocol")) {
662 CONFIG_IS_DOUBLE(tmp->version_protocol);
663 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
665 else if (!strcmp(name, "version_software")) {
666 CONFIG_IS_DOUBLE(tmp->version_software);
667 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
669 else if (!strcmp(name, "version_software_vendor")) {
670 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
671 tmp->version_software_vendor =
672 (*(char *)val ? strdup((char *) val) : NULL);
675 return SILC_CONFIG_EINTERNAL;
677 return SILC_CONFIG_OK;
680 silc_free(tmp->name);
686 SILC_CONFIG_CALLBACK(fetch_client)
688 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
690 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
691 type, name, context));
693 /* Alloc before block checking, because empty sub-blocks are welcome here */
694 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
696 if (type == SILC_CONFIG_ARG_BLOCK) {
697 /* empty sub-blocks are welcome */
698 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
700 return SILC_CONFIG_OK;
703 /* Identify and save this value */
704 if (!strcmp(name, "host")) {
705 CONFIG_IS_DOUBLE(tmp->host);
706 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
708 else if (!strcmp(name, "passphrase")) {
709 CONFIG_IS_DOUBLE(tmp->passphrase);
710 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
711 (void **)&tmp->passphrase,
712 &tmp->passphrase_len)) {
713 got_errno = SILC_CONFIG_ESILENT;
717 else if (!strcmp(name, "publickey")) {
718 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
719 (void **)&tmp->publickeys, NULL)) {
720 got_errno = SILC_CONFIG_ESILENT;
724 else if (!strcmp(name, "params")) {
725 CONFIG_IS_DOUBLE(tmp->param);
726 tmp->param = my_find_param(config, (char *) val);
727 if (!tmp->param) { /* error message already output */
728 got_errno = SILC_CONFIG_EPRINTLINE;
733 return SILC_CONFIG_EINTERNAL;
734 return SILC_CONFIG_OK;
737 silc_free(tmp->host);
738 CONFIG_FREE_AUTH(tmp);
744 SILC_CONFIG_CALLBACK(fetch_admin)
746 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
748 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
749 type, name, context));
750 if (type == SILC_CONFIG_ARG_BLOCK) {
751 /* check the temporary struct's fields */
752 if (!tmp) /* discard empty sub-blocks */
753 return SILC_CONFIG_OK;
755 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
757 return SILC_CONFIG_OK;
759 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
761 /* Identify and save this value */
762 if (!strcmp(name, "host")) {
763 CONFIG_IS_DOUBLE(tmp->host);
764 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
766 else if (!strcmp(name, "user")) {
767 CONFIG_IS_DOUBLE(tmp->user);
768 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
770 else if (!strcmp(name, "nick")) {
771 CONFIG_IS_DOUBLE(tmp->nick);
772 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
774 else if (!strcmp(name, "passphrase")) {
775 CONFIG_IS_DOUBLE(tmp->passphrase);
776 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
777 (void **)&tmp->passphrase,
778 &tmp->passphrase_len)) {
779 got_errno = SILC_CONFIG_ESILENT;
783 else if (!strcmp(name, "publickey")) {
784 CONFIG_IS_DOUBLE(tmp->publickeys);
785 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
786 (void **)&tmp->publickeys, NULL)) {
787 got_errno = SILC_CONFIG_ESILENT;
792 return SILC_CONFIG_EINTERNAL;
793 return SILC_CONFIG_OK;
796 silc_free(tmp->host);
797 silc_free(tmp->user);
798 silc_free(tmp->nick);
799 CONFIG_FREE_AUTH(tmp);
805 SILC_CONFIG_CALLBACK(fetch_deny)
807 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
809 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
810 type, name, context));
811 if (type == SILC_CONFIG_ARG_BLOCK) {
812 /* check the temporary struct's fields */
813 if (!tmp) /* discard empty sub-blocks */
814 return SILC_CONFIG_OK;
816 got_errno = SILC_CONFIG_EMISSFIELDS;
820 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
822 return SILC_CONFIG_OK;
824 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
826 /* Identify and save this value */
827 if (!strcmp(name, "host")) {
828 CONFIG_IS_DOUBLE(tmp->host);
829 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
831 else if (!strcmp(name, "reason")) {
832 CONFIG_IS_DOUBLE(tmp->reason);
833 tmp->reason = strdup((char *) val);
836 return SILC_CONFIG_EINTERNAL;
837 return SILC_CONFIG_OK;
840 silc_free(tmp->host);
841 silc_free(tmp->reason);
847 SILC_CONFIG_CALLBACK(fetch_server)
849 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
851 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
852 type, name, context));
853 if (type == SILC_CONFIG_ARG_BLOCK) {
854 /* check the temporary struct's fields */
855 if (!tmp) /* discard empty sub-blocks */
856 return SILC_CONFIG_OK;
858 /* the temporary struct is ok, append it to the list */
859 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
861 return SILC_CONFIG_OK;
863 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
865 /* Identify and save this value */
866 if (!strcmp(name, "host")) {
867 CONFIG_IS_DOUBLE(tmp->host);
868 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
870 else if (!strcmp(name, "passphrase")) {
871 CONFIG_IS_DOUBLE(tmp->passphrase);
872 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
873 (void **)&tmp->passphrase,
874 &tmp->passphrase_len)) {
875 got_errno = SILC_CONFIG_ESILENT;
879 else if (!strcmp(name, "publickey")) {
880 CONFIG_IS_DOUBLE(tmp->publickeys);
881 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
882 (void **)&tmp->publickeys, NULL)) {
883 got_errno = SILC_CONFIG_ESILENT;
887 else if (!strcmp(name, "params")) {
888 CONFIG_IS_DOUBLE(tmp->param);
889 tmp->param = my_find_param(config, (char *) val);
890 if (!tmp->param) { /* error message already output */
891 got_errno = SILC_CONFIG_EPRINTLINE;
895 else if (!strcmp(name, "backup")) {
896 tmp->backup_router = *(bool *)val;
899 return SILC_CONFIG_EINTERNAL;
901 return SILC_CONFIG_OK;
904 silc_free(tmp->host);
905 CONFIG_FREE_AUTH(tmp);
911 SILC_CONFIG_CALLBACK(fetch_router)
913 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
915 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
916 type, name, context));
917 if (type == SILC_CONFIG_ARG_BLOCK) {
918 if (!tmp) /* discard empty sub-blocks */
919 return SILC_CONFIG_OK;
921 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
923 return SILC_CONFIG_OK;
925 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
927 /* Identify and save this value */
928 if (!strcmp(name, "host")) {
929 CONFIG_IS_DOUBLE(tmp->host);
930 tmp->host = strdup((char *) val);
932 else if (!strcmp(name, "port")) {
933 int port = *(int *)val;
934 if ((port <= 0) || (port > 65535)) {
935 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
936 "Invalid port number!\n"));
937 got_errno = SILC_CONFIG_EPRINTLINE;
940 tmp->port = (SilcUInt16) port;
942 else if (!strcmp(name, "passphrase")) {
943 CONFIG_IS_DOUBLE(tmp->passphrase);
944 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
945 (void **)&tmp->passphrase,
946 &tmp->passphrase_len)) {
947 got_errno = SILC_CONFIG_ESILENT;
951 else if (!strcmp(name, "publickey")) {
952 CONFIG_IS_DOUBLE(tmp->publickeys);
953 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
954 (void **)&tmp->publickeys, NULL)) {
955 got_errno = SILC_CONFIG_ESILENT;
959 else if (!strcmp(name, "params")) {
960 CONFIG_IS_DOUBLE(tmp->param);
961 tmp->param = my_find_param(config, (char *) val);
962 if (!tmp->param) { /* error message already output */
963 got_errno = SILC_CONFIG_EPRINTLINE;
967 else if (!strcmp(name, "initiator")) {
968 tmp->initiator = *(bool *)val;
970 else if (!strcmp(name, "backuphost")) {
971 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
972 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
974 tmp->backup_router = TRUE;
976 else if (!strcmp(name, "backupport")) {
977 int port = *(int *)val;
978 if ((port <= 0) || (port > 65535)) {
979 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
980 "Invalid port number!\n"));
981 got_errno = SILC_CONFIG_EPRINTLINE;
984 tmp->backup_replace_port = (SilcUInt16) port;
986 else if (!strcmp(name, "backuplocal")) {
987 tmp->backup_local = *(bool *)val;
990 return SILC_CONFIG_EINTERNAL;
992 return SILC_CONFIG_OK;
995 silc_free(tmp->host);
996 silc_free(tmp->backup_replace_ip);
997 CONFIG_FREE_AUTH(tmp);
1003 /* known config options tables */
1004 static const SilcConfigTable table_general[] = {
1005 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1006 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1007 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1008 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1009 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1010 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1011 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1012 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1014 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1015 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1017 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1018 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1019 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1020 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1021 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1022 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1023 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1024 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1028 static const SilcConfigTable table_cipher[] = {
1029 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1030 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1031 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1032 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1036 static const SilcConfigTable table_hash[] = {
1037 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1038 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1039 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1040 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1044 static const SilcConfigTable table_hmac[] = {
1045 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1046 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1047 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1051 static const SilcConfigTable table_pkcs[] = {
1052 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1056 static const SilcConfigTable table_serverinfo_c[] = {
1057 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1058 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1062 static const SilcConfigTable table_serverinfo[] = {
1063 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1065 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1066 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1072 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1073 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1074 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1075 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1079 static const SilcConfigTable table_logging_c[] = {
1080 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1081 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1082 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1086 static const SilcConfigTable table_logging[] = {
1087 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1088 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1089 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1090 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1091 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1092 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1093 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1097 static const SilcConfigTable table_connparam[] = {
1098 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1099 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1100 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1103 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1106 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1107 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1108 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1109 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1110 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1111 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1115 static const SilcConfigTable table_client[] = {
1116 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1117 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1118 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1119 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1123 static const SilcConfigTable table_admin[] = {
1124 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1125 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1126 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1127 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1128 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1129 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1130 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1134 static const SilcConfigTable table_deny[] = {
1135 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1136 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1140 static const SilcConfigTable table_serverconn[] = {
1141 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1142 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1143 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1144 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1145 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1149 static const SilcConfigTable table_routerconn[] = {
1150 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1151 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1152 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1153 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1154 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1155 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1156 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1157 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1158 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1162 static const SilcConfigTable table_main[] = {
1163 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1164 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1165 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1166 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1167 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1168 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1169 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1170 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1171 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1172 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1173 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1174 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1175 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1179 /* Set default values to stuff that was not configured. */
1181 static void silc_server_config_set_defaults(SilcServerConfig config)
1183 my_set_param_defaults(&config->param, NULL);
1185 config->channel_rekey_secs = (config->channel_rekey_secs ?
1186 config->channel_rekey_secs :
1187 SILC_SERVER_CHANNEL_REKEY);
1188 config->key_exchange_timeout = (config->key_exchange_timeout ?
1189 config->key_exchange_timeout :
1190 SILC_SERVER_SKE_TIMEOUT);
1191 config->conn_auth_timeout = (config->conn_auth_timeout ?
1192 config->conn_auth_timeout :
1193 SILC_SERVER_CONNAUTH_TIMEOUT);
1196 /* Allocates a new configuration object, opens configuration file and
1197 parses it. The parsed data is returned to the newly allocated
1198 configuration object. The SilcServerConfig must be freed by calling
1199 the silc_server_config_destroy function. */
1201 SilcServerConfig silc_server_config_alloc(const char *filename)
1203 SilcServerConfig config_new;
1204 SilcConfigEntity ent;
1205 SilcConfigFile *file;
1207 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1209 /* alloc a config object */
1210 config_new = silc_calloc(1, sizeof(*config_new));
1211 config_new->refcount = 1;
1215 /* general config defaults */
1216 config_new->logging_timestamp = TRUE;
1218 /* obtain a config file object */
1219 file = silc_config_open(filename);
1221 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
1226 /* obtain a SilcConfig entity, we can use it to start the parsing */
1227 ent = silc_config_init(file);
1229 /* load the known configuration options, give our empty object as context */
1230 silc_config_register_table(ent, table_main, (void *) config_new);
1232 /* enter the main parsing loop. When this returns, we have the parsing
1233 * result and the object filled (or partially, in case of errors). */
1234 ret = silc_config_main(ent);
1235 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1236 silc_config_strerror(ret)));
1238 /* Check if the parser returned errors */
1240 /* handle this special error return which asks to quietly return */
1241 if (ret != SILC_CONFIG_ESILENT) {
1242 char *linebuf, *filename = silc_config_get_filename(file);
1243 SilcUInt32 line = silc_config_get_line(file);
1244 if (ret != SILC_CONFIG_EPRINTLINE)
1245 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1246 silc_config_strerror(ret)));
1247 linebuf = silc_config_read_line(file, line);
1248 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n\n", filename,
1252 silc_server_config_destroy(config_new);
1256 /* close (destroy) the file object */
1257 silc_config_close(file);
1259 /* If config_new is incomplete, abort the object and return NULL */
1260 if (!config_new->server_info) {
1261 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1262 "`server_info'\n"));
1263 silc_server_config_destroy(config_new);
1267 /* Set default to configuration parameters */
1268 silc_server_config_set_defaults(config_new);
1273 /* Increments the reference counter of a config object */
1275 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1280 ref->config = config;
1281 ref->ref_ptr = ref_ptr;
1282 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1283 config->refcount - 1, config->refcount));
1287 /* Decrements the reference counter of a config object. If the counter
1288 reaches 0, the config object is destroyed. */
1290 void silc_server_config_unref(SilcServerConfigRef *ref)
1293 silc_server_config_destroy(ref->config);
1296 /* Destroy a config object with all his children lists */
1298 void silc_server_config_destroy(SilcServerConfig config)
1303 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1304 config->refcount + 1, config->refcount));
1305 if (config->refcount > 0)
1308 SILC_LOG_DEBUG(("Freeing config context"));
1310 /* Destroy general config stuff */
1311 silc_free(config->module_path);
1312 silc_free(config->param.version_protocol);
1313 silc_free(config->param.version_software);
1314 silc_free(config->param.version_software_vendor);
1316 /* Destroy Logging channels */
1317 if (config->logging_info)
1318 silc_free(config->logging_info->file);
1319 if (config->logging_warnings)
1320 silc_free(config->logging_warnings->file);
1321 if (config->logging_errors)
1322 silc_free(config->logging_errors->file);
1323 if (config->logging_fatals)
1324 silc_free(config->logging_fatals->file);
1325 silc_free(config->logging_info);
1326 silc_free(config->logging_warnings);
1327 silc_free(config->logging_errors);
1328 silc_free(config->logging_fatals);
1330 /* Destroy the ServerInfo struct */
1331 if (config->server_info) {
1332 register SilcServerConfigServerInfo *si = config->server_info;
1333 silc_free(si->server_name);
1335 silc_free(si->primary->server_ip);
1336 silc_free(si->primary);
1338 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1340 silc_free(di->server_ip);
1343 silc_free(si->server_type);
1344 silc_free(si->location);
1345 silc_free(si->admin);
1346 silc_free(si->email);
1347 silc_free(si->user);
1348 silc_free(si->group);
1349 silc_free(si->motd_file);
1350 silc_free(si->pid_file);
1351 silc_pkcs_public_key_free(si->public_key);
1352 silc_pkcs_private_key_free(si->private_key);
1356 /* Now let's destroy the lists */
1358 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1360 silc_free(di->name);
1361 silc_free(di->module);
1364 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1365 silc_free(di->name);
1366 silc_free(di->module);
1369 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1370 silc_free(di->name);
1371 silc_free(di->hash);
1374 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1375 silc_free(di->name);
1378 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1379 config->conn_params)
1380 silc_free(di->name);
1381 silc_free(di->version_protocol);
1382 silc_free(di->version_software);
1383 silc_free(di->version_software_vendor);
1386 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1387 silc_free(di->host);
1388 CONFIG_FREE_AUTH(di);
1391 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1392 silc_free(di->host);
1393 silc_free(di->user);
1394 silc_free(di->nick);
1395 CONFIG_FREE_AUTH(di);
1398 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1399 silc_free(di->host);
1400 silc_free(di->reason);
1403 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1405 silc_free(di->host);
1406 CONFIG_FREE_AUTH(di);
1409 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1411 silc_free(di->host);
1412 silc_free(di->backup_replace_ip);
1413 CONFIG_FREE_AUTH(di);
1417 memset(config, 'F', sizeof(*config));
1421 /* Registers configured ciphers. These can then be allocated by the
1422 server when needed. */
1424 bool silc_server_config_register_ciphers(SilcServer server)
1426 SilcServerConfig config = server->config;
1427 SilcServerConfigCipher *cipher = config->cipher;
1428 char *module_path = config->module_path;
1430 SILC_LOG_DEBUG(("Registering configured ciphers"));
1432 if (!cipher) /* any cipher in the config file? */
1436 /* if there isn't a module_path OR there isn't a module sim name try to
1437 * use buil-in functions */
1438 if (!module_path || !cipher->module) {
1440 for (i = 0; silc_default_ciphers[i].name; i++)
1441 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1442 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1445 if (!silc_cipher_is_supported(cipher->name)) {
1446 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1447 silc_server_stop(server);
1452 /* Load (try at least) the crypto SIM module */
1453 char buf[1023], *alg_name;
1454 SilcCipherObject cipher_obj;
1457 memset(&cipher_obj, 0, sizeof(cipher_obj));
1458 cipher_obj.name = cipher->name;
1459 cipher_obj.block_len = cipher->block_length;
1460 cipher_obj.key_len = cipher->key_length * 8;
1462 /* build the libname */
1463 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1465 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1467 alg_name = strdup(cipher->name);
1468 if (strchr(alg_name, '-'))
1469 *strchr(alg_name, '-') = '\0';
1471 if (silc_sim_load(sim)) {
1472 cipher_obj.set_key =
1473 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1474 SILC_CIPHER_SIM_SET_KEY));
1475 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1476 cipher_obj.set_key_with_string =
1477 silc_sim_getsym(sim,
1478 silc_sim_symname(alg_name,
1479 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1480 SILC_LOG_DEBUG(("set_key_with_string=%p",
1481 cipher_obj.set_key_with_string));
1482 cipher_obj.encrypt =
1483 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1484 SILC_CIPHER_SIM_ENCRYPT_CBC));
1485 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1486 cipher_obj.decrypt =
1487 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1488 SILC_CIPHER_SIM_DECRYPT_CBC));
1489 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1490 cipher_obj.context_len =
1491 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1492 SILC_CIPHER_SIM_CONTEXT_LEN));
1493 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1495 /* Put the SIM to the list of all SIM's in server */
1496 silc_dlist_add(server->sim, sim);
1498 silc_free(alg_name);
1500 SILC_LOG_ERROR(("Error configuring ciphers"));
1501 silc_server_stop(server);
1505 /* Register the cipher */
1506 silc_cipher_register(&cipher_obj);
1508 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1509 "can't load modules!"));
1510 silc_server_stop(server);
1514 cipher = cipher->next;
1520 /* Registers configured hash functions. These can then be allocated by the
1521 server when needed. */
1523 bool silc_server_config_register_hashfuncs(SilcServer server)
1525 SilcServerConfig config = server->config;
1526 SilcServerConfigHash *hash = config->hash;
1527 char *module_path = config->module_path;
1529 SILC_LOG_DEBUG(("Registering configured hash functions"));
1531 if (!hash) /* any hash func in the config file? */
1535 /* if there isn't a module_path OR there isn't a module sim name try to
1536 * use buil-in functions */
1537 if (!module_path || !hash->module) {
1539 for (i = 0; silc_default_hash[i].name; i++)
1540 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1541 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1544 if (!silc_hash_is_supported(hash->name)) {
1545 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1546 silc_server_stop(server);
1551 /* Load (try at least) the hash SIM module */
1552 SilcHashObject hash_obj;
1555 memset(&hash_obj, 0, sizeof(hash_obj));
1556 hash_obj.name = hash->name;
1557 hash_obj.block_len = hash->block_length;
1558 hash_obj.hash_len = hash->digest_length;
1560 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1562 if ((silc_sim_load(sim))) {
1564 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1565 SILC_HASH_SIM_INIT));
1566 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1568 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1569 SILC_HASH_SIM_UPDATE));
1570 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1572 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1573 SILC_HASH_SIM_FINAL));
1574 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1575 hash_obj.context_len =
1576 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1577 SILC_HASH_SIM_CONTEXT_LEN));
1578 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1580 /* Put the SIM to the table of all SIM's in server */
1581 silc_dlist_add(server->sim, sim);
1583 SILC_LOG_ERROR(("Error configuring hash functions"));
1584 silc_server_stop(server);
1588 /* Register the hash function */
1589 silc_hash_register(&hash_obj);
1591 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1592 "can't load modules!"));
1593 silc_server_stop(server);
1603 /* Registers configure HMACs. These can then be allocated by the server
1606 bool silc_server_config_register_hmacs(SilcServer server)
1608 SilcServerConfig config = server->config;
1609 SilcServerConfigHmac *hmac = config->hmac;
1611 SILC_LOG_DEBUG(("Registering configured HMACs"));
1617 SilcHmacObject hmac_obj;
1618 if (!silc_hash_is_supported(hmac->hash)) {
1619 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1620 silc_server_stop(server);
1624 /* Register the HMAC */
1625 memset(&hmac_obj, 0, sizeof(hmac_obj));
1626 hmac_obj.name = hmac->name;
1627 hmac_obj.len = hmac->mac_length;
1628 silc_hmac_register(&hmac_obj);
1636 /* Registers configured PKCS's. */
1638 bool silc_server_config_register_pkcs(SilcServer server)
1640 SilcServerConfig config = server->config;
1641 SilcServerConfigPkcs *pkcs = config->pkcs;
1643 SILC_LOG_DEBUG(("Registering configured PKCS"));
1650 for (i = 0; silc_default_pkcs[i].name; i++)
1651 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1652 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1655 if (!silc_pkcs_is_supported(pkcs->name)) {
1656 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1657 silc_server_stop(server);
1666 /* Sets log files where log messages are saved by the server logger. */
1668 void silc_server_config_setlogfiles(SilcServer server)
1670 SilcServerConfig config = server->config;
1671 SilcServerConfigLogging *this;
1673 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1675 silc_log_timestamp = config->logging_timestamp;
1676 silc_log_quick = config->logging_quick;
1677 silc_log_flushdelay = (config->logging_flushdelay ?
1678 config->logging_flushdelay :
1679 SILC_SERVER_LOG_FLUSH_DELAY);
1681 if ((this = config->logging_fatals))
1682 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1684 if ((this = config->logging_errors))
1685 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1687 if ((this = config->logging_warnings))
1688 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1690 if ((this = config->logging_info))
1691 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1695 /* Returns client authentication information from configuration file by host
1698 SilcServerConfigClient *
1699 silc_server_config_find_client(SilcServer server, char *host)
1701 SilcServerConfig config = server->config;
1702 SilcServerConfigClient *client;
1704 if (!config || !host)
1707 for (client = config->clients; client; client = client->next) {
1708 if (client->host && !silc_string_compare(client->host, host))
1713 /* if none matched, then client is already NULL */
1717 /* Returns admin connection configuration by host, username and/or
1720 SilcServerConfigAdmin *
1721 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1724 SilcServerConfig config = server->config;
1725 SilcServerConfigAdmin *admin;
1727 /* make sure we have a value for the matching parameters */
1735 for (admin = config->admins; admin; admin = admin->next) {
1736 if (admin->host && !silc_string_compare(admin->host, host))
1738 if (admin->user && !silc_string_compare(admin->user, user))
1740 if (admin->nick && !silc_string_compare(admin->nick, nick))
1742 /* no checks failed -> this entry matches */
1746 /* if none matched, then admin is already NULL */
1750 /* Returns the denied connection configuration entry by host. */
1752 SilcServerConfigDeny *
1753 silc_server_config_find_denied(SilcServer server, char *host)
1755 SilcServerConfig config = server->config;
1756 SilcServerConfigDeny *deny;
1758 /* make sure we have a value for the matching parameters */
1759 if (!config || !host)
1762 for (deny = config->denied; deny; deny = deny->next) {
1763 if (deny->host && !silc_string_compare(deny->host, host))
1768 /* if none matched, then deny is already NULL */
1772 /* Returns server connection info from server configuartion by host
1775 SilcServerConfigServer *
1776 silc_server_config_find_server_conn(SilcServer server, char *host)
1778 SilcServerConfig config = server->config;
1779 SilcServerConfigServer *serv = NULL;
1784 if (!config->servers)
1787 for (serv = config->servers; serv; serv = serv->next) {
1788 if (!silc_string_compare(serv->host, host))
1796 /* Returns router connection info from server configuration by
1797 host (name or ip). */
1799 SilcServerConfigRouter *
1800 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1802 SilcServerConfig config = server->config;
1803 SilcServerConfigRouter *serv = NULL;
1808 if (!config->routers)
1811 for (serv = config->routers; serv; serv = serv->next) {
1812 if (!silc_string_compare(serv->host, host))
1814 if (port && serv->port && serv->port != port)
1822 /* Find backup router connection by host (name or ip) */
1824 SilcServerConfigRouter *
1825 silc_server_config_find_backup_conn(SilcServer server, char *host)
1827 SilcServerConfig config = server->config;
1828 SilcServerConfigRouter *serv = NULL;
1833 if (!config->routers)
1836 for (serv = config->routers; serv; serv = serv->next) {
1837 if (!serv->backup_router)
1839 if (!silc_string_compare(serv->host, host))
1847 /* Returns TRUE if configuration for a router connection that we are
1848 initiating exists. */
1850 bool silc_server_config_is_primary_route(SilcServer server)
1852 SilcServerConfig config = server->config;
1853 SilcServerConfigRouter *serv = NULL;
1857 serv = config->routers;
1858 for (i = 0; serv; i++) {
1859 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1870 /* Returns our primary connection configuration or NULL if we do not
1871 have primary router configured. */
1873 SilcServerConfigRouter *
1874 silc_server_config_get_primary_router(SilcServer server)
1876 SilcServerConfig config = server->config;
1877 SilcServerConfigRouter *serv = NULL;
1880 serv = config->routers;
1881 for (i = 0; serv; i++) {
1882 if (serv->initiator == TRUE && serv->backup_router == FALSE)
1890 /* If we have backup router configured that is going to replace us this
1891 function returns it. */
1893 SilcServerConfigRouter *
1894 silc_server_config_get_backup_router(SilcServer server)
1896 SilcServerConfig config = server->config;
1897 SilcServerConfigRouter *serv = NULL;
1900 if (server->server_type != SILC_ROUTER)
1903 serv = config->routers;
1904 for (i = 0; serv; i++) {
1905 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1906 serv->backup_local == TRUE &&
1907 !strcmp(server->config->server_info->primary->server_ip,
1908 serv->backup_replace_ip) &&
1909 server->config->server_info->primary->port ==
1910 serv->backup_replace_port)