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\".", name));
116 /* parse an authdata according to its auth method */
117 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
118 void **auth_data, SilcUInt32 *auth_data_len)
120 if (auth_meth == SILC_AUTH_PASSWORD) {
121 /* p is a plain text password */
122 if (auth_data && auth_data_len) {
123 if (!silc_utf8_valid(p, strlen(p))) {
124 *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
125 SILC_STRING_LANGUAGE);
126 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
127 silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *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(("Error while parsing config file: "
141 "Could not load public key file!"));
145 /* The auth_data is a pointer to the hash table of public keys. */
147 if (*auth_data == NULL)
148 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
150 my_free_public_key, NULL,
152 silc_hash_table_add(*auth_data, public_key, public_key);
162 SILC_CONFIG_CALLBACK(fetch_generic)
164 SilcServerConfig config = (SilcServerConfig) context;
167 if (!strcmp(name, "module_path")) {
168 CONFIG_IS_DOUBLE(config->module_path);
169 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
171 else if (!strcmp(name, "prefer_passphrase_auth")) {
172 config->prefer_passphrase_auth = *(bool *)val;
174 else if (!strcmp(name, "require_reverse_lookup")) {
175 config->require_reverse_lookup = *(bool *)val;
177 else if (!strcmp(name, "connections_max")) {
178 config->param.connections_max = (SilcUInt32) *(int *)val;
180 else if (!strcmp(name, "connections_max_per_host")) {
181 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
183 else if (!strcmp(name, "keepalive_secs")) {
184 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
186 else if (!strcmp(name, "reconnect_count")) {
187 config->param.reconnect_count = (SilcUInt32) *(int *)val;
189 else if (!strcmp(name, "reconnect_interval")) {
190 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
192 else if (!strcmp(name, "reconnect_interval_max")) {
193 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
195 else if (!strcmp(name, "reconnect_keep_trying")) {
196 config->param.reconnect_keep_trying = *(bool *)val;
198 else if (!strcmp(name, "key_exchange_rekey")) {
199 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
201 else if (!strcmp(name, "key_exchange_pfs")) {
202 config->param.key_exchange_pfs = *(bool *)val;
204 else if (!strcmp(name, "channel_rekey_secs")) {
205 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
207 else if (!strcmp(name, "key_exchange_timeout")) {
208 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
210 else if (!strcmp(name, "conn_auth_timeout")) {
211 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
213 else if (!strcmp(name, "version_protocol")) {
214 CONFIG_IS_DOUBLE(config->param.version_protocol);
215 config->param.version_protocol =
216 (*(char *)val ? strdup((char *) val) : NULL);
218 else if (!strcmp(name, "version_software")) {
219 CONFIG_IS_DOUBLE(config->param.version_software);
220 config->param.version_software =
221 (*(char *)val ? strdup((char *) val) : NULL);
223 else if (!strcmp(name, "version_software_vendor")) {
224 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
225 config->param.version_software_vendor =
226 (*(char *)val ? strdup((char *) val) : NULL);
228 else if (!strcmp(name, "detach_disabled")) {
229 config->detach_disabled = *(bool *)val;
231 else if (!strcmp(name, "detach_timeout")) {
232 config->detach_timeout = (SilcUInt32) *(int *)val;
235 return SILC_CONFIG_EINTERNAL;
237 return SILC_CONFIG_OK;
243 SILC_CONFIG_CALLBACK(fetch_cipher)
245 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
247 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
248 type, name, context));
249 if (type == SILC_CONFIG_ARG_BLOCK) {
250 /* check the temporary struct's fields */
251 if (!tmp) /* discard empty sub-blocks */
252 return SILC_CONFIG_OK;
254 got_errno = SILC_CONFIG_EMISSFIELDS;
258 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
260 return SILC_CONFIG_OK;
262 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
264 /* Identify and save this value */
265 if (!strcmp(name, "name")) {
266 CONFIG_IS_DOUBLE(tmp->name);
267 tmp->name = strdup((char *) val);
269 else if (!strcmp(name, "module")) {
270 CONFIG_IS_DOUBLE(tmp->module);
271 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
273 else if (!strcmp(name, "keylength")) {
274 tmp->key_length = *(SilcUInt32 *)val;
276 else if (!strcmp(name, "blocklength")) {
277 tmp->block_length = *(SilcUInt32 *)val;
280 return SILC_CONFIG_EINTERNAL;
281 return SILC_CONFIG_OK;
284 silc_free(tmp->name);
285 silc_free(tmp->module);
291 SILC_CONFIG_CALLBACK(fetch_hash)
293 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
295 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
296 type, name, context));
297 if (type == SILC_CONFIG_ARG_BLOCK) {
298 /* check the temporary struct's fields */
299 if (!tmp) /* discard empty sub-blocks */
300 return SILC_CONFIG_OK;
301 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
302 got_errno = SILC_CONFIG_EMISSFIELDS;
306 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
308 return SILC_CONFIG_OK;
310 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
312 /* Identify and save this value */
313 if (!strcmp(name, "name")) {
314 CONFIG_IS_DOUBLE(tmp->name);
315 tmp->name = strdup((char *) val);
317 else if (!strcmp(name, "module")) {
318 CONFIG_IS_DOUBLE(tmp->module);
319 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
321 else if (!strcmp(name, "blocklength")) {
322 tmp->block_length = *(int *)val;
324 else if (!strcmp(name, "digestlength")) {
325 tmp->digest_length = *(int *)val;
328 return SILC_CONFIG_EINTERNAL;
329 return SILC_CONFIG_OK;
332 silc_free(tmp->name);
333 silc_free(tmp->module);
339 SILC_CONFIG_CALLBACK(fetch_hmac)
341 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
343 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
344 type, name, context));
345 if (type == SILC_CONFIG_ARG_BLOCK) {
346 /* check the temporary struct's fields */
347 if (!tmp) /* discard empty sub-blocks */
348 return SILC_CONFIG_OK;
349 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
350 got_errno = SILC_CONFIG_EMISSFIELDS;
354 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
356 return SILC_CONFIG_OK;
358 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
360 /* Identify and save this value */
361 if (!strcmp(name, "name")) {
362 CONFIG_IS_DOUBLE(tmp->name);
363 tmp->name = strdup((char *) val);
365 else if (!strcmp(name, "hash")) {
366 CONFIG_IS_DOUBLE(tmp->hash);
367 tmp->hash = strdup((char *) val);
369 else if (!strcmp(name, "maclength")) {
370 tmp->mac_length = *(int *)val;
373 return SILC_CONFIG_EINTERNAL;
374 return SILC_CONFIG_OK;
377 silc_free(tmp->name);
378 silc_free(tmp->hash);
384 SILC_CONFIG_CALLBACK(fetch_pkcs)
386 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
388 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
389 type, name, context));
390 if (type == SILC_CONFIG_ARG_BLOCK) {
391 /* check the temporary struct's fields */
392 if (!tmp) /* discard empty sub-blocks */
393 return SILC_CONFIG_OK;
395 got_errno = SILC_CONFIG_EMISSFIELDS;
399 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
401 return SILC_CONFIG_OK;
403 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
405 /* Identify and save this value */
406 if (!strcmp(name, "name")) {
407 CONFIG_IS_DOUBLE(tmp->name);
408 tmp->name = strdup((char *) val);
411 return SILC_CONFIG_EINTERNAL;
412 return SILC_CONFIG_OK;
415 silc_free(tmp->name);
421 SILC_CONFIG_CALLBACK(fetch_serverinfo)
423 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
424 SilcServerConfigServerInfo *server_info = config->server_info;
426 /* if there isn't the struct alloc it */
428 config->server_info = server_info = (SilcServerConfigServerInfo *)
429 silc_calloc(1, sizeof(*server_info));
431 if (type == SILC_CONFIG_ARG_BLOCK) {
432 if (!strcmp(name, "primary")) {
433 CONFIG_IS_DOUBLE(server_info->primary);
435 return SILC_CONFIG_OK;
436 server_info->primary = tmp;
438 return SILC_CONFIG_OK;
439 } else if (!strcmp(name, "secondary")) {
441 return SILC_CONFIG_OK;
442 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
444 return SILC_CONFIG_OK;
445 } else if (!server_info->public_key || !server_info->private_key) {
446 got_errno = SILC_CONFIG_EMISSFIELDS;
449 return SILC_CONFIG_OK;
451 if (!strcmp(name, "hostname")) {
452 CONFIG_IS_DOUBLE(server_info->server_name);
453 server_info->server_name = strdup((char *) val);
455 else if (!strcmp(name, "ip")) {
456 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
457 CONFIG_IS_DOUBLE(tmp->server_ip);
458 tmp->server_ip = strdup((char *) val);
460 else if (!strcmp(name, "port")) {
461 int port = *(int *)val;
462 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
463 if ((port <= 0) || (port > 65535)) {
464 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
465 "Invalid port number!"));
466 got_errno = SILC_CONFIG_EPRINTLINE;
469 tmp->port = (SilcUInt16) port;
471 else if (!strcmp(name, "servertype")) {
472 CONFIG_IS_DOUBLE(server_info->server_type);
473 server_info->server_type = strdup((char *) val);
475 else if (!strcmp(name, "admin")) {
476 CONFIG_IS_DOUBLE(server_info->admin);
477 server_info->admin = strdup((char *) val);
479 else if (!strcmp(name, "adminemail")) {
480 CONFIG_IS_DOUBLE(server_info->email);
481 server_info->email = strdup((char *) val);
483 else if (!strcmp(name, "location")) {
484 CONFIG_IS_DOUBLE(server_info->location);
485 server_info->location = strdup((char *) val);
487 else if (!strcmp(name, "user")) {
488 CONFIG_IS_DOUBLE(server_info->user);
489 server_info->user = strdup((char *) val);
491 else if (!strcmp(name, "group")) {
492 CONFIG_IS_DOUBLE(server_info->group);
493 server_info->group = strdup((char *) val);
495 else if (!strcmp(name, "motdfile")) {
496 CONFIG_IS_DOUBLE(server_info->motd_file);
497 server_info->motd_file = strdup((char *) val);
499 else if (!strcmp(name, "pidfile")) {
500 CONFIG_IS_DOUBLE(server_info->pid_file);
501 server_info->pid_file = strdup((char *) val);
503 else if (!strcmp(name, "publickey")) {
504 char *file_tmp = (char *) val;
506 /* try to load specified file, if fail stop config parsing */
507 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
509 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
510 SILC_PKCS_FILE_BIN)) {
511 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
512 return SILC_CONFIG_EPRINTLINE;
515 else if (!strcmp(name, "privatekey")) {
516 char *file_tmp = (char *) val;
518 /* try to load specified file, if fail stop config parsing */
519 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
521 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
522 SILC_PKCS_FILE_PEM)) {
523 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
524 return SILC_CONFIG_EPRINTLINE;
528 return SILC_CONFIG_EINTERNAL;
529 return SILC_CONFIG_OK;
533 silc_free(config->tmp);
538 SILC_CONFIG_CALLBACK(fetch_logging)
540 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
542 if (!strcmp(name, "timestamp")) {
543 config->logging_timestamp = *(bool *)val;
545 else if (!strcmp(name, "quicklogs")) {
546 config->logging_quick = *(bool *)val;
548 else if (!strcmp(name, "flushdelay")) {
549 int flushdelay = *(int *)val;
550 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
551 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
552 "Invalid flushdelay value, use quicklogs if you "
553 "want real-time logging."));
554 return SILC_CONFIG_EPRINTLINE;
556 config->logging_flushdelay = (long) flushdelay;
559 /* The following istances happens only in Logging's sub-blocks, a match
560 for the sub-block name means that you should store the filename/maxsize
561 temporary struct to the proper logging channel.
562 If we get a match for "file" or "maxsize" this means that we are inside
563 a sub-sub-block and it is safe to alloc a new tmp. */
564 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
565 else if (!strcmp(name, __chan__)) { \
566 if (!tmp) return SILC_CONFIG_OK; \
568 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
570 config->__member__ = tmp; \
571 config->tmp = NULL; \
573 FETCH_LOGGING_CHAN("info", logging_info)
574 FETCH_LOGGING_CHAN("warnings", logging_warnings)
575 FETCH_LOGGING_CHAN("errors", logging_errors)
576 FETCH_LOGGING_CHAN("fatals", logging_fatals)
577 #undef FETCH_LOGGING_CHAN
578 else if (!strcmp(name, "file")) {
579 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
580 CONFIG_IS_DOUBLE(tmp->file);
581 tmp->file = strdup((char *) val);
583 else if (!strcmp(name, "size")) {
585 config->tmp = silc_calloc(1, sizeof(*tmp));
586 tmp = (SilcServerConfigLogging *) config->tmp;
588 tmp->maxsize = *(SilcUInt32 *) val;
591 return SILC_CONFIG_EINTERNAL;
592 return SILC_CONFIG_OK;
595 silc_free(tmp->file);
601 SILC_CONFIG_CALLBACK(fetch_connparam)
603 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
605 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
606 type, name, context));
607 if (type == SILC_CONFIG_ARG_BLOCK) {
608 /* check the temporary struct's fields */
609 if (!tmp) /* discard empty sub-blocks */
610 return SILC_CONFIG_OK;
612 got_errno = SILC_CONFIG_EMISSFIELDS;
616 my_set_param_defaults(tmp, &config->param);
618 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
620 return SILC_CONFIG_OK;
622 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
624 if (!strcmp(name, "name")) {
625 CONFIG_IS_DOUBLE(tmp->name);
626 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
628 else if (!strcmp(name, "connections_max")) {
629 tmp->connections_max = *(SilcUInt32 *)val;
631 else if (!strcmp(name, "connections_max_per_host")) {
632 tmp->connections_max_per_host = *(SilcUInt32 *)val;
634 else if (!strcmp(name, "keepalive_secs")) {
635 tmp->keepalive_secs = *(SilcUInt32 *)val;
637 else if (!strcmp(name, "reconnect_count")) {
638 tmp->reconnect_count = *(SilcUInt32 *)val;
640 else if (!strcmp(name, "reconnect_interval")) {
641 tmp->reconnect_interval = *(SilcUInt32 *)val;
643 else if (!strcmp(name, "reconnect_interval_max")) {
644 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
646 else if (!strcmp(name, "reconnect_keep_trying")) {
647 tmp->reconnect_keep_trying = *(bool *)val;
649 else if (!strcmp(name, "key_exchange_rekey")) {
650 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
652 else if (!strcmp(name, "key_exchange_pfs")) {
653 tmp->key_exchange_pfs = *(bool *)val;
655 else if (!strcmp(name, "version_protocol")) {
656 CONFIG_IS_DOUBLE(tmp->version_protocol);
657 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
659 else if (!strcmp(name, "version_software")) {
660 CONFIG_IS_DOUBLE(tmp->version_software);
661 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
663 else if (!strcmp(name, "version_software_vendor")) {
664 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
665 tmp->version_software_vendor =
666 (*(char *)val ? strdup((char *) val) : NULL);
668 else if (!strcmp(name, "anonymous")) {
669 tmp->anonymous = *(bool *)val;
672 return SILC_CONFIG_EINTERNAL;
674 return SILC_CONFIG_OK;
677 silc_free(tmp->name);
683 SILC_CONFIG_CALLBACK(fetch_client)
685 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
687 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
688 type, name, context));
690 /* Alloc before block checking, because empty sub-blocks are welcome here */
691 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
693 if (type == SILC_CONFIG_ARG_BLOCK) {
694 /* empty sub-blocks are welcome */
695 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
697 return SILC_CONFIG_OK;
700 /* Identify and save this value */
701 if (!strcmp(name, "host")) {
702 CONFIG_IS_DOUBLE(tmp->host);
703 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
705 else if (!strcmp(name, "passphrase")) {
706 CONFIG_IS_DOUBLE(tmp->passphrase);
707 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
708 (void **)&tmp->passphrase,
709 &tmp->passphrase_len)) {
710 got_errno = SILC_CONFIG_EPRINTLINE;
714 else if (!strcmp(name, "publickey")) {
715 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
716 (void **)&tmp->publickeys, NULL)) {
717 got_errno = SILC_CONFIG_EPRINTLINE;
721 else if (!strcmp(name, "params")) {
722 CONFIG_IS_DOUBLE(tmp->param);
723 tmp->param = my_find_param(config, (char *) val);
724 if (!tmp->param) { /* error message already output */
725 got_errno = SILC_CONFIG_EPRINTLINE;
730 return SILC_CONFIG_EINTERNAL;
731 return SILC_CONFIG_OK;
734 silc_free(tmp->host);
735 CONFIG_FREE_AUTH(tmp);
741 SILC_CONFIG_CALLBACK(fetch_admin)
743 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
745 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
746 type, name, context));
747 if (type == SILC_CONFIG_ARG_BLOCK) {
748 /* check the temporary struct's fields */
749 if (!tmp) /* discard empty sub-blocks */
750 return SILC_CONFIG_OK;
752 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
754 return SILC_CONFIG_OK;
756 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
758 /* Identify and save this value */
759 if (!strcmp(name, "host")) {
760 CONFIG_IS_DOUBLE(tmp->host);
761 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
763 else if (!strcmp(name, "user")) {
764 CONFIG_IS_DOUBLE(tmp->user);
765 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
767 else if (!strcmp(name, "nick")) {
768 CONFIG_IS_DOUBLE(tmp->nick);
769 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
771 else if (!strcmp(name, "passphrase")) {
772 CONFIG_IS_DOUBLE(tmp->passphrase);
773 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
774 (void **)&tmp->passphrase,
775 &tmp->passphrase_len)) {
776 got_errno = SILC_CONFIG_EPRINTLINE;
780 else if (!strcmp(name, "publickey")) {
781 CONFIG_IS_DOUBLE(tmp->publickeys);
782 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
783 (void **)&tmp->publickeys, NULL)) {
784 got_errno = SILC_CONFIG_EPRINTLINE;
789 return SILC_CONFIG_EINTERNAL;
790 return SILC_CONFIG_OK;
793 silc_free(tmp->host);
794 silc_free(tmp->user);
795 silc_free(tmp->nick);
796 CONFIG_FREE_AUTH(tmp);
802 SILC_CONFIG_CALLBACK(fetch_deny)
804 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
806 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
807 type, name, context));
808 if (type == SILC_CONFIG_ARG_BLOCK) {
809 /* check the temporary struct's fields */
810 if (!tmp) /* discard empty sub-blocks */
811 return SILC_CONFIG_OK;
813 got_errno = SILC_CONFIG_EMISSFIELDS;
817 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
819 return SILC_CONFIG_OK;
821 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
823 /* Identify and save this value */
824 if (!strcmp(name, "host")) {
825 CONFIG_IS_DOUBLE(tmp->host);
826 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
828 else if (!strcmp(name, "reason")) {
829 CONFIG_IS_DOUBLE(tmp->reason);
830 tmp->reason = strdup((char *) val);
833 return SILC_CONFIG_EINTERNAL;
834 return SILC_CONFIG_OK;
837 silc_free(tmp->host);
838 silc_free(tmp->reason);
844 SILC_CONFIG_CALLBACK(fetch_server)
846 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
848 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
849 type, name, context));
850 if (type == SILC_CONFIG_ARG_BLOCK) {
851 /* check the temporary struct's fields */
852 if (!tmp) /* discard empty sub-blocks */
853 return SILC_CONFIG_OK;
855 /* the temporary struct is ok, append it to the list */
856 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
858 return SILC_CONFIG_OK;
860 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
862 /* Identify and save this value */
863 if (!strcmp(name, "host")) {
864 CONFIG_IS_DOUBLE(tmp->host);
865 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
867 else if (!strcmp(name, "passphrase")) {
868 CONFIG_IS_DOUBLE(tmp->passphrase);
869 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
870 (void **)&tmp->passphrase,
871 &tmp->passphrase_len)) {
872 got_errno = SILC_CONFIG_EPRINTLINE;
876 else if (!strcmp(name, "publickey")) {
877 CONFIG_IS_DOUBLE(tmp->publickeys);
878 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
879 (void **)&tmp->publickeys, NULL)) {
880 got_errno = SILC_CONFIG_EPRINTLINE;
884 else if (!strcmp(name, "params")) {
885 CONFIG_IS_DOUBLE(tmp->param);
886 tmp->param = my_find_param(config, (char *) val);
887 if (!tmp->param) { /* error message already output */
888 got_errno = SILC_CONFIG_EPRINTLINE;
892 else if (!strcmp(name, "backup")) {
893 tmp->backup_router = *(bool *)val;
896 return SILC_CONFIG_EINTERNAL;
898 return SILC_CONFIG_OK;
901 silc_free(tmp->host);
902 CONFIG_FREE_AUTH(tmp);
908 SILC_CONFIG_CALLBACK(fetch_router)
910 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
912 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
913 type, name, context));
914 if (type == SILC_CONFIG_ARG_BLOCK) {
915 if (!tmp) /* discard empty sub-blocks */
916 return SILC_CONFIG_OK;
918 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
920 return SILC_CONFIG_OK;
922 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
924 /* Identify and save this value */
925 if (!strcmp(name, "host")) {
926 CONFIG_IS_DOUBLE(tmp->host);
927 tmp->host = strdup((char *) val);
929 else if (!strcmp(name, "port")) {
930 int port = *(int *)val;
931 if ((port <= 0) || (port > 65535)) {
932 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
933 "Invalid port number!"));
934 got_errno = SILC_CONFIG_EPRINTLINE;
937 tmp->port = (SilcUInt16) port;
939 else if (!strcmp(name, "passphrase")) {
940 CONFIG_IS_DOUBLE(tmp->passphrase);
941 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
942 (void **)&tmp->passphrase,
943 &tmp->passphrase_len)) {
944 got_errno = SILC_CONFIG_EPRINTLINE;
948 else if (!strcmp(name, "publickey")) {
949 CONFIG_IS_DOUBLE(tmp->publickeys);
950 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
951 (void **)&tmp->publickeys, NULL)) {
952 got_errno = SILC_CONFIG_EPRINTLINE;
956 else if (!strcmp(name, "params")) {
957 CONFIG_IS_DOUBLE(tmp->param);
958 tmp->param = my_find_param(config, (char *) val);
959 if (!tmp->param) { /* error message already output */
960 got_errno = SILC_CONFIG_EPRINTLINE;
964 else if (!strcmp(name, "initiator")) {
965 tmp->initiator = *(bool *)val;
967 else if (!strcmp(name, "backuphost")) {
968 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
969 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
971 tmp->backup_router = TRUE;
973 else if (!strcmp(name, "backupport")) {
974 int port = *(int *)val;
975 if ((port <= 0) || (port > 65535)) {
976 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
977 "Invalid port number!"));
978 got_errno = SILC_CONFIG_EPRINTLINE;
981 tmp->backup_replace_port = (SilcUInt16) port;
983 else if (!strcmp(name, "backuplocal")) {
984 tmp->backup_local = *(bool *)val;
987 return SILC_CONFIG_EINTERNAL;
989 return SILC_CONFIG_OK;
992 silc_free(tmp->host);
993 silc_free(tmp->backup_replace_ip);
994 CONFIG_FREE_AUTH(tmp);
1000 /* known config options tables */
1001 static const SilcConfigTable table_general[] = {
1002 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1003 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1004 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1005 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1006 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1007 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1008 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1009 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1010 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1011 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1012 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1013 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1014 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1015 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1016 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1017 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1018 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1019 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1020 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1021 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1025 static const SilcConfigTable table_cipher[] = {
1026 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1027 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1028 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1029 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1033 static const SilcConfigTable table_hash[] = {
1034 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1035 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1036 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1037 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1041 static const SilcConfigTable table_hmac[] = {
1042 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1043 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1044 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1048 static const SilcConfigTable table_pkcs[] = {
1049 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1053 static const SilcConfigTable table_serverinfo_c[] = {
1054 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1055 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1059 static const SilcConfigTable table_serverinfo[] = {
1060 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1061 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1062 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1063 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1064 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1065 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1068 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1072 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1076 static const SilcConfigTable table_logging_c[] = {
1077 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1078 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1079 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1083 static const SilcConfigTable table_logging[] = {
1084 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1085 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1086 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1087 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1088 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1089 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1090 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1094 static const SilcConfigTable table_connparam[] = {
1095 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1096 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1097 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1098 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1099 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1100 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1101 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1103 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1104 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1106 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1107 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1108 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1109 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1113 static const SilcConfigTable table_client[] = {
1114 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1115 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1116 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1117 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1121 static const SilcConfigTable table_admin[] = {
1122 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1123 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1124 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1125 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1126 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1127 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1128 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1132 static const SilcConfigTable table_deny[] = {
1133 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1134 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1138 static const SilcConfigTable table_serverconn[] = {
1139 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1140 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1141 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1142 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1143 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1147 static const SilcConfigTable table_routerconn[] = {
1148 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1149 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1150 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1151 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1152 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1153 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1154 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1155 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1156 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1160 static const SilcConfigTable table_main[] = {
1161 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1162 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1163 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1164 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1165 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1166 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1167 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1168 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1169 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1170 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1171 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1172 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1173 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1177 /* Set default values to stuff that was not configured. */
1179 static void silc_server_config_set_defaults(SilcServerConfig config)
1181 my_set_param_defaults(&config->param, NULL);
1183 config->channel_rekey_secs = (config->channel_rekey_secs ?
1184 config->channel_rekey_secs :
1185 SILC_SERVER_CHANNEL_REKEY);
1186 config->key_exchange_timeout = (config->key_exchange_timeout ?
1187 config->key_exchange_timeout :
1188 SILC_SERVER_SKE_TIMEOUT);
1189 config->conn_auth_timeout = (config->conn_auth_timeout ?
1190 config->conn_auth_timeout :
1191 SILC_SERVER_CONNAUTH_TIMEOUT);
1194 /* Allocates a new configuration object, opens configuration file and
1195 parses it. The parsed data is returned to the newly allocated
1196 configuration object. The SilcServerConfig must be freed by calling
1197 the silc_server_config_destroy function. */
1199 SilcServerConfig silc_server_config_alloc(const char *filename)
1201 SilcServerConfig config_new;
1202 SilcConfigEntity ent;
1203 SilcConfigFile *file;
1205 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1207 /* alloc a config object */
1208 config_new = silc_calloc(1, sizeof(*config_new));
1209 config_new->refcount = 1;
1213 /* general config defaults */
1214 config_new->logging_timestamp = TRUE;
1216 /* obtain a config file object */
1217 file = silc_config_open(filename);
1219 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1224 /* obtain a SilcConfig entity, we can use it to start the parsing */
1225 ent = silc_config_init(file);
1227 /* load the known configuration options, give our empty object as context */
1228 silc_config_register_table(ent, table_main, (void *) config_new);
1230 /* enter the main parsing loop. When this returns, we have the parsing
1231 * result and the object filled (or partially, in case of errors). */
1232 ret = silc_config_main(ent);
1233 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1234 silc_config_strerror(ret)));
1236 /* Check if the parser returned errors */
1238 /* handle this special error return which asks to quietly return */
1239 if (ret != SILC_CONFIG_ESILENT) {
1240 char *linebuf, *filename = silc_config_get_filename(file);
1241 SilcUInt32 line = silc_config_get_line(file);
1242 if (ret != SILC_CONFIG_EPRINTLINE)
1243 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1244 silc_config_strerror(ret)));
1245 linebuf = silc_config_read_line(file, line);
1246 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1250 silc_server_config_destroy(config_new);
1254 /* close (destroy) the file object */
1255 silc_config_close(file);
1257 /* If config_new is incomplete, abort the object and return NULL */
1258 if (!config_new->server_info) {
1259 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1261 silc_server_config_destroy(config_new);
1265 /* Set default to configuration parameters */
1266 silc_server_config_set_defaults(config_new);
1271 /* Increments the reference counter of a config object */
1273 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1278 ref->config = config;
1279 ref->ref_ptr = ref_ptr;
1280 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1281 config->refcount - 1, config->refcount));
1285 /* Decrements the reference counter of a config object. If the counter
1286 reaches 0, the config object is destroyed. */
1288 void silc_server_config_unref(SilcServerConfigRef *ref)
1291 silc_server_config_destroy(ref->config);
1294 /* Destroy a config object with all his children lists */
1296 void silc_server_config_destroy(SilcServerConfig config)
1301 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1302 config->refcount + 1, config->refcount));
1303 if (config->refcount > 0)
1306 SILC_LOG_DEBUG(("Freeing config context"));
1308 /* Destroy general config stuff */
1309 silc_free(config->module_path);
1310 silc_free(config->param.version_protocol);
1311 silc_free(config->param.version_software);
1312 silc_free(config->param.version_software_vendor);
1314 /* Destroy Logging channels */
1315 if (config->logging_info)
1316 silc_free(config->logging_info->file);
1317 if (config->logging_warnings)
1318 silc_free(config->logging_warnings->file);
1319 if (config->logging_errors)
1320 silc_free(config->logging_errors->file);
1321 if (config->logging_fatals)
1322 silc_free(config->logging_fatals->file);
1323 silc_free(config->logging_info);
1324 silc_free(config->logging_warnings);
1325 silc_free(config->logging_errors);
1326 silc_free(config->logging_fatals);
1328 /* Destroy the ServerInfo struct */
1329 if (config->server_info) {
1330 register SilcServerConfigServerInfo *si = config->server_info;
1331 silc_free(si->server_name);
1333 silc_free(si->primary->server_ip);
1334 silc_free(si->primary);
1336 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1338 silc_free(di->server_ip);
1341 silc_free(si->server_type);
1342 silc_free(si->location);
1343 silc_free(si->admin);
1344 silc_free(si->email);
1345 silc_free(si->user);
1346 silc_free(si->group);
1347 silc_free(si->motd_file);
1348 silc_free(si->pid_file);
1349 silc_pkcs_public_key_free(si->public_key);
1350 silc_pkcs_private_key_free(si->private_key);
1354 /* Now let's destroy the lists */
1356 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1358 silc_free(di->name);
1359 silc_free(di->module);
1362 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1363 silc_free(di->name);
1364 silc_free(di->module);
1367 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1368 silc_free(di->name);
1369 silc_free(di->hash);
1372 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1373 silc_free(di->name);
1376 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1377 config->conn_params)
1378 silc_free(di->name);
1379 silc_free(di->version_protocol);
1380 silc_free(di->version_software);
1381 silc_free(di->version_software_vendor);
1384 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1385 silc_free(di->host);
1386 CONFIG_FREE_AUTH(di);
1389 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1390 silc_free(di->host);
1391 silc_free(di->user);
1392 silc_free(di->nick);
1393 CONFIG_FREE_AUTH(di);
1396 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1397 silc_free(di->host);
1398 silc_free(di->reason);
1401 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1403 silc_free(di->host);
1404 CONFIG_FREE_AUTH(di);
1407 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1409 silc_free(di->host);
1410 silc_free(di->backup_replace_ip);
1411 CONFIG_FREE_AUTH(di);
1415 memset(config, 'F', sizeof(*config));
1419 /* Registers configured ciphers. These can then be allocated by the
1420 server when needed. */
1422 bool silc_server_config_register_ciphers(SilcServer server)
1424 SilcServerConfig config = server->config;
1425 SilcServerConfigCipher *cipher = config->cipher;
1426 char *module_path = config->module_path;
1428 SILC_LOG_DEBUG(("Registering configured ciphers"));
1430 if (!cipher) /* any cipher in the config file? */
1434 /* if there isn't a module_path OR there isn't a module sim name try to
1435 * use buil-in functions */
1436 if (!module_path || !cipher->module) {
1438 for (i = 0; silc_default_ciphers[i].name; i++)
1439 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1440 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1443 if (!silc_cipher_is_supported(cipher->name)) {
1444 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1445 silc_server_stop(server);
1450 /* Load (try at least) the crypto SIM module */
1451 char buf[1023], *alg_name;
1452 SilcCipherObject cipher_obj;
1455 memset(&cipher_obj, 0, sizeof(cipher_obj));
1456 cipher_obj.name = cipher->name;
1457 cipher_obj.block_len = cipher->block_length;
1458 cipher_obj.key_len = cipher->key_length * 8;
1460 /* build the libname */
1461 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1463 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1465 alg_name = strdup(cipher->name);
1466 if (strchr(alg_name, '-'))
1467 *strchr(alg_name, '-') = '\0';
1469 if (silc_sim_load(sim)) {
1470 cipher_obj.set_key =
1471 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1472 SILC_CIPHER_SIM_SET_KEY));
1473 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1474 cipher_obj.set_key_with_string =
1475 silc_sim_getsym(sim,
1476 silc_sim_symname(alg_name,
1477 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1478 SILC_LOG_DEBUG(("set_key_with_string=%p",
1479 cipher_obj.set_key_with_string));
1480 cipher_obj.encrypt =
1481 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1482 SILC_CIPHER_SIM_ENCRYPT_CBC));
1483 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1484 cipher_obj.decrypt =
1485 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1486 SILC_CIPHER_SIM_DECRYPT_CBC));
1487 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1488 cipher_obj.context_len =
1489 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1490 SILC_CIPHER_SIM_CONTEXT_LEN));
1491 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1493 /* Put the SIM to the list of all SIM's in server */
1494 silc_dlist_add(server->sim, sim);
1496 silc_free(alg_name);
1498 SILC_LOG_ERROR(("Error configuring ciphers"));
1499 silc_server_stop(server);
1503 /* Register the cipher */
1504 silc_cipher_register(&cipher_obj);
1506 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1507 "can't load modules!"));
1508 silc_server_stop(server);
1512 cipher = cipher->next;
1518 /* Registers configured hash functions. These can then be allocated by the
1519 server when needed. */
1521 bool silc_server_config_register_hashfuncs(SilcServer server)
1523 SilcServerConfig config = server->config;
1524 SilcServerConfigHash *hash = config->hash;
1525 char *module_path = config->module_path;
1527 SILC_LOG_DEBUG(("Registering configured hash functions"));
1529 if (!hash) /* any hash func in the config file? */
1533 /* if there isn't a module_path OR there isn't a module sim name try to
1534 * use buil-in functions */
1535 if (!module_path || !hash->module) {
1537 for (i = 0; silc_default_hash[i].name; i++)
1538 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1539 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1542 if (!silc_hash_is_supported(hash->name)) {
1543 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1544 silc_server_stop(server);
1549 /* Load (try at least) the hash SIM module */
1550 SilcHashObject hash_obj;
1553 memset(&hash_obj, 0, sizeof(hash_obj));
1554 hash_obj.name = hash->name;
1555 hash_obj.block_len = hash->block_length;
1556 hash_obj.hash_len = hash->digest_length;
1558 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1560 if ((silc_sim_load(sim))) {
1562 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1563 SILC_HASH_SIM_INIT));
1564 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1566 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1567 SILC_HASH_SIM_UPDATE));
1568 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1570 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1571 SILC_HASH_SIM_FINAL));
1572 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1573 hash_obj.context_len =
1574 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1575 SILC_HASH_SIM_CONTEXT_LEN));
1576 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1578 /* Put the SIM to the table of all SIM's in server */
1579 silc_dlist_add(server->sim, sim);
1581 SILC_LOG_ERROR(("Error configuring hash functions"));
1582 silc_server_stop(server);
1586 /* Register the hash function */
1587 silc_hash_register(&hash_obj);
1589 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1590 "can't load modules!"));
1591 silc_server_stop(server);
1601 /* Registers configure HMACs. These can then be allocated by the server
1604 bool silc_server_config_register_hmacs(SilcServer server)
1606 SilcServerConfig config = server->config;
1607 SilcServerConfigHmac *hmac = config->hmac;
1609 SILC_LOG_DEBUG(("Registering configured HMACs"));
1615 SilcHmacObject hmac_obj;
1616 if (!silc_hash_is_supported(hmac->hash)) {
1617 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1618 silc_server_stop(server);
1622 /* Register the HMAC */
1623 memset(&hmac_obj, 0, sizeof(hmac_obj));
1624 hmac_obj.name = hmac->name;
1625 hmac_obj.len = hmac->mac_length;
1626 silc_hmac_register(&hmac_obj);
1634 /* Registers configured PKCS's. */
1636 bool silc_server_config_register_pkcs(SilcServer server)
1638 SilcServerConfig config = server->config;
1639 SilcServerConfigPkcs *pkcs = config->pkcs;
1641 SILC_LOG_DEBUG(("Registering configured PKCS"));
1648 for (i = 0; silc_default_pkcs[i].name; i++)
1649 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1650 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1653 if (!silc_pkcs_is_supported(pkcs->name)) {
1654 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1655 silc_server_stop(server);
1664 /* Sets log files where log messages are saved by the server logger. */
1666 void silc_server_config_setlogfiles(SilcServer server)
1668 SilcServerConfig config = server->config;
1669 SilcServerConfigLogging *this;
1671 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1673 silc_log_timestamp = config->logging_timestamp;
1674 silc_log_quick = config->logging_quick;
1675 silc_log_flushdelay = (config->logging_flushdelay ?
1676 config->logging_flushdelay :
1677 SILC_SERVER_LOG_FLUSH_DELAY);
1679 if ((this = config->logging_fatals))
1680 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1682 if ((this = config->logging_errors))
1683 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1685 if ((this = config->logging_warnings))
1686 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1688 if ((this = config->logging_info))
1689 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1693 /* Returns client authentication information from configuration file by host
1696 SilcServerConfigClient *
1697 silc_server_config_find_client(SilcServer server, char *host)
1699 SilcServerConfig config = server->config;
1700 SilcServerConfigClient *client;
1702 if (!config || !host)
1705 for (client = config->clients; client; client = client->next) {
1706 if (client->host && !silc_string_compare(client->host, host))
1711 /* if none matched, then client is already NULL */
1715 /* Returns admin connection configuration by host, username and/or
1718 SilcServerConfigAdmin *
1719 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1722 SilcServerConfig config = server->config;
1723 SilcServerConfigAdmin *admin;
1725 /* make sure we have a value for the matching parameters */
1733 for (admin = config->admins; admin; admin = admin->next) {
1734 if (admin->host && !silc_string_compare(admin->host, host))
1736 if (admin->user && !silc_string_compare(admin->user, user))
1738 if (admin->nick && !silc_string_compare(admin->nick, nick))
1740 /* no checks failed -> this entry matches */
1744 /* if none matched, then admin is already NULL */
1748 /* Returns the denied connection configuration entry by host. */
1750 SilcServerConfigDeny *
1751 silc_server_config_find_denied(SilcServer server, char *host)
1753 SilcServerConfig config = server->config;
1754 SilcServerConfigDeny *deny;
1756 /* make sure we have a value for the matching parameters */
1757 if (!config || !host)
1760 for (deny = config->denied; deny; deny = deny->next) {
1761 if (deny->host && !silc_string_compare(deny->host, host))
1766 /* if none matched, then deny is already NULL */
1770 /* Returns server connection info from server configuartion by host
1773 SilcServerConfigServer *
1774 silc_server_config_find_server_conn(SilcServer server, char *host)
1776 SilcServerConfig config = server->config;
1777 SilcServerConfigServer *serv = NULL;
1782 if (!config->servers)
1785 for (serv = config->servers; serv; serv = serv->next) {
1786 if (!silc_string_compare(serv->host, host))
1794 /* Returns router connection info from server configuration by
1795 host (name or ip). */
1797 SilcServerConfigRouter *
1798 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1800 SilcServerConfig config = server->config;
1801 SilcServerConfigRouter *serv = NULL;
1806 if (!config->routers)
1809 for (serv = config->routers; serv; serv = serv->next) {
1810 if (!silc_string_compare(serv->host, host))
1812 if (port && serv->port && serv->port != port)
1820 /* Find backup router connection by host (name or ip) */
1822 SilcServerConfigRouter *
1823 silc_server_config_find_backup_conn(SilcServer server, char *host)
1825 SilcServerConfig config = server->config;
1826 SilcServerConfigRouter *serv = NULL;
1831 if (!config->routers)
1834 for (serv = config->routers; serv; serv = serv->next) {
1835 if (!serv->backup_router)
1837 if (!silc_string_compare(serv->host, host))
1845 /* Returns TRUE if configuration for a router connection that we are
1846 initiating exists. */
1848 bool silc_server_config_is_primary_route(SilcServer server)
1850 SilcServerConfig config = server->config;
1851 SilcServerConfigRouter *serv = NULL;
1855 serv = config->routers;
1856 for (i = 0; serv; i++) {
1857 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1868 /* Returns our primary connection configuration or NULL if we do not
1869 have primary router configured. */
1871 SilcServerConfigRouter *
1872 silc_server_config_get_primary_router(SilcServer server)
1874 SilcServerConfig config = server->config;
1875 SilcServerConfigRouter *serv = NULL;
1878 serv = config->routers;
1879 for (i = 0; serv; i++) {
1880 if (serv->initiator == TRUE && serv->backup_router == FALSE)
1888 /* If we have backup router configured that is going to replace us this
1889 function returns it. */
1891 SilcServerConfigRouter *
1892 silc_server_config_get_backup_router(SilcServer server)
1894 SilcServerConfig config = server->config;
1895 SilcServerConfigRouter *serv = NULL;
1898 if (server->server_type != SILC_ROUTER)
1901 serv = config->routers;
1902 for (i = 0; serv; i++) {
1903 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1904 serv->backup_local == TRUE &&
1905 !strcmp(server->config->server_info->primary->server_ip,
1906 serv->backup_replace_ip) &&
1907 server->config->server_info->primary->port ==
1908 serv->backup_replace_port)