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 /* append the tmp field to the specified list */
38 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
42 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
43 findtmp->next = tmp; \
46 /* loops all elements in a list and provides a di struct pointer of the
47 * specified type containing the current element */
48 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
49 for (tmp = (void *) __list__; tmp;) { \
50 __type__ *di = (__type__ *) tmp; \
51 tmp = (void *) di->next;
53 /* Set EDOUBLE error value and bail out if necessary */
54 #define CONFIG_IS_DOUBLE(__x__) \
56 got_errno = SILC_CONFIG_EDOUBLE; \
60 /* Free the authentication fields in the specified struct
61 * Expands to two instructions */
62 #define CONFIG_FREE_AUTH(__section__) \
63 silc_free(__section__->passphrase); \
64 if (__section__->publickeys) \
65 silc_hash_table_free(__section__->publickeys);
67 static void my_free_public_key(void *key, void *context, void *user_data)
69 silc_pkcs_public_key_free(context);
72 /* Set default values to those parameters that have not been defined */
74 my_set_param_defaults(SilcServerConfigConnParams *params,
75 SilcServerConfigConnParams *defaults)
77 #define SET_PARAM_DEFAULT(p, d) params->p = \
78 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
80 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
81 SET_PARAM_DEFAULT(connections_max_per_host,
82 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
83 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
84 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
85 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
86 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
87 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
89 #undef SET_PARAM_DEFAULT
92 /* Find connection parameters by the parameter block name. */
93 static SilcServerConfigConnParams *
94 my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line)
96 SilcServerConfigConnParams *param;
98 for (param = config->conn_params; param; param = param->next) {
99 if (!strcasecmp(param->name, name))
103 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
104 "Cannot find Param \"%s\".\n", line, name));
109 /* parse an authdata according to its auth method */
110 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
111 SilcUInt32 line, void **auth_data,
112 SilcUInt32 *auth_data_len)
114 if (auth_meth == SILC_AUTH_PASSWORD) {
115 /* p is a plain text password */
116 if (auth_data && auth_data_len) {
117 if (!silc_utf8_valid(p, strlen(p))) {
118 *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0);
119 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
120 silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
123 *auth_data = (void *) strdup(p);
124 *auth_data_len = (SilcUInt32) strlen(p);
127 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
128 /* p is a public key file name */
129 SilcPublicKey public_key;
131 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
132 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
133 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
134 "%lu: Could not load public key file!\n",
139 /* The auth_data is a pointer to the hash table of public keys. */
141 if (*auth_data == NULL)
142 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
144 my_free_public_key, NULL,
146 silc_hash_table_add(*auth_data, public_key, public_key);
149 SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
150 "Unknown authentication method.\n", line));
158 SILC_CONFIG_CALLBACK(fetch_generic)
160 SilcServerConfig config = (SilcServerConfig) context;
163 if (!strcmp(name, "module_path")) {
164 CONFIG_IS_DOUBLE(config->module_path);
165 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
167 else if (!strcmp(name, "prefer_passphrase_auth")) {
168 config->prefer_passphrase_auth = *(bool *)val;
170 else if (!strcmp(name, "require_reverse_lookup")) {
171 config->require_reverse_lookup = *(bool *)val;
173 else if (!strcmp(name, "connections_max")) {
174 config->param.connections_max = (SilcUInt32) *(int *)val;
176 else if (!strcmp(name, "connections_max_per_host")) {
177 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
179 else if (!strcmp(name, "keepalive_secs")) {
180 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
182 else if (!strcmp(name, "reconnect_count")) {
183 config->param.reconnect_count = (SilcUInt32) *(int *)val;
185 else if (!strcmp(name, "reconnect_interval")) {
186 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
188 else if (!strcmp(name, "reconnect_interval_max")) {
189 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
191 else if (!strcmp(name, "reconnect_keep_trying")) {
192 config->param.reconnect_keep_trying = *(bool *)val;
194 else if (!strcmp(name, "key_exchange_rekey")) {
195 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
197 else if (!strcmp(name, "key_exchange_pfs")) {
198 config->param.key_exchange_pfs = *(bool *)val;
200 else if (!strcmp(name, "channel_rekey_secs")) {
201 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
203 else if (!strcmp(name, "key_exchange_timeout")) {
204 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
206 else if (!strcmp(name, "conn_auth_timeout")) {
207 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
209 else if (!strcmp(name, "version_protocol")) {
210 CONFIG_IS_DOUBLE(config->param.version_protocol);
211 config->param.version_protocol =
212 (*(char *)val ? strdup((char *) val) : NULL);
214 else if (!strcmp(name, "version_software")) {
215 CONFIG_IS_DOUBLE(config->param.version_software);
216 config->param.version_software =
217 (*(char *)val ? strdup((char *) val) : NULL);
219 else if (!strcmp(name, "version_software_vendor")) {
220 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
221 config->param.version_software_vendor =
222 (*(char *)val ? strdup((char *) val) : NULL);
225 return SILC_CONFIG_EINTERNAL;
227 return SILC_CONFIG_OK;
233 SILC_CONFIG_CALLBACK(fetch_cipher)
235 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
237 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
238 type, name, context));
239 if (type == SILC_CONFIG_ARG_BLOCK) {
240 /* check the temporary struct's fields */
241 if (!tmp) /* empty sub-block? */
242 return SILC_CONFIG_OK;
244 got_errno = SILC_CONFIG_EMISSFIELDS;
247 /* the temporary struct is ok, append it to the list */
248 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
250 return SILC_CONFIG_OK;
252 /* if there isn't a temporary struct alloc one */
254 config->tmp = silc_calloc(1, sizeof(*findtmp));
255 tmp = (SilcServerConfigCipher *) config->tmp;
258 /* Identify and save this value */
259 if (!strcmp(name, "name")) {
260 CONFIG_IS_DOUBLE(tmp->name);
261 tmp->name = strdup((char *) val);
263 else if (!strcmp(name, "module")) {
264 CONFIG_IS_DOUBLE(tmp->module);
265 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
267 else if (!strcmp(name, "keylength")) {
268 tmp->key_length = *(SilcUInt32 *)val;
270 else if (!strcmp(name, "blocklength")) {
271 tmp->block_length = *(SilcUInt32 *)val;
274 return SILC_CONFIG_EINTERNAL;
275 return SILC_CONFIG_OK;
278 silc_free(tmp->name);
279 silc_free(tmp->module);
285 SILC_CONFIG_CALLBACK(fetch_hash)
287 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
289 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
290 type, name, context));
291 if (type == SILC_CONFIG_ARG_BLOCK) {
292 /* check the temporary struct's fields */
293 if (!tmp) /* empty sub-block? */
294 return SILC_CONFIG_OK;
295 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
296 got_errno = SILC_CONFIG_EMISSFIELDS;
299 /* the temporary struct in tmp is ok */
300 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
302 return SILC_CONFIG_OK;
305 /* if there isn't a temporary struct alloc one */
307 config->tmp = silc_calloc(1, sizeof(*findtmp));
308 tmp = (SilcServerConfigHash *) config->tmp;
311 /* Identify and save this value */
312 if (!strcmp(name, "name")) {
313 CONFIG_IS_DOUBLE(tmp->name);
314 tmp->name = strdup((char *) val);
316 else if (!strcmp(name, "module")) {
317 CONFIG_IS_DOUBLE(tmp->module);
318 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
320 else if (!strcmp(name, "blocklength")) {
321 tmp->block_length = *(int *)val;
323 else if (!strcmp(name, "digestlength")) {
324 tmp->digest_length = *(int *)val;
327 return SILC_CONFIG_EINTERNAL;
328 return SILC_CONFIG_OK;
331 silc_free(tmp->name);
332 silc_free(tmp->module);
338 SILC_CONFIG_CALLBACK(fetch_hmac)
340 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
342 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
343 type, name, context));
344 if (type == SILC_CONFIG_ARG_BLOCK) {
345 /* check the temporary struct's fields */
346 if (!tmp) /* empty sub-block? */
347 return SILC_CONFIG_OK;
348 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
349 got_errno = SILC_CONFIG_EMISSFIELDS;
352 /* the temporary struct is ok, append it to the list */
353 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
355 return SILC_CONFIG_OK;
357 /* if there isn't a temporary struct alloc one */
359 config->tmp = silc_calloc(1, sizeof(*findtmp));
360 tmp = (SilcServerConfigHmac *) config->tmp;
363 /* Identify and save this value */
364 if (!strcmp(name, "name")) {
365 CONFIG_IS_DOUBLE(tmp->name);
366 tmp->name = strdup((char *) val);
368 else if (!strcmp(name, "hash")) {
369 CONFIG_IS_DOUBLE(tmp->hash);
370 tmp->hash = strdup((char *) val);
372 else if (!strcmp(name, "maclength")) {
373 tmp->mac_length = *(int *)val;
376 return SILC_CONFIG_EINTERNAL;
377 return SILC_CONFIG_OK;
380 silc_free(tmp->name);
381 silc_free(tmp->hash);
387 SILC_CONFIG_CALLBACK(fetch_pkcs)
389 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
391 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
392 type, name, context));
393 if (type == SILC_CONFIG_ARG_BLOCK) {
394 /* check the temporary struct's fields */
395 if (!tmp) /* empty sub-block? */
396 return SILC_CONFIG_OK;
398 got_errno = SILC_CONFIG_EMISSFIELDS;
401 /* the temporary struct is ok, append it to the list */
402 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
404 return SILC_CONFIG_OK;
406 /* if there isn't a temporary struct alloc one */
408 config->tmp = silc_calloc(1, sizeof(*findtmp));
409 tmp = (SilcServerConfigPkcs *) config->tmp;
412 /* Identify and save this value */
413 if (!strcmp(name, "name")) {
414 CONFIG_IS_DOUBLE(tmp->name);
415 tmp->name = strdup((char *) val);
418 return SILC_CONFIG_EINTERNAL;
419 return SILC_CONFIG_OK;
422 silc_free(tmp->name);
428 SILC_CONFIG_CALLBACK(fetch_serverinfo)
430 SilcServerConfig config = (SilcServerConfig) context;
431 SilcServerConfigServerInfo *server_info = config->server_info;
434 /* if there isn't the struct alloc it */
436 config->server_info = server_info = (SilcServerConfigServerInfo *)
437 silc_calloc(1, sizeof(*server_info));
439 if (type == SILC_CONFIG_ARG_BLOCK) {
440 /* check for mandatory inputs */
441 if (!server_info->public_key || !server_info->private_key) {
442 got_errno = SILC_CONFIG_EMISSFIELDS;
445 return SILC_CONFIG_OK;
447 if (!strcmp(name, "hostname")) {
448 CONFIG_IS_DOUBLE(server_info->server_name);
449 server_info->server_name = strdup((char *) val);
451 else if (!strcmp(name, "ip")) {
452 CONFIG_IS_DOUBLE(server_info->server_ip);
453 server_info->server_ip = strdup((char *) val);
455 else if (!strcmp(name, "port")) {
456 int port = *(int *)val;
457 if ((port <= 0) || (port > 65535)) {
458 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
459 return SILC_CONFIG_ESILENT;
461 server_info->port = (SilcUInt16) port;
463 else if (!strcmp(name, "servertype")) {
464 CONFIG_IS_DOUBLE(server_info->server_type);
465 server_info->server_type = strdup((char *) val);
467 else if (!strcmp(name, "admin")) {
468 CONFIG_IS_DOUBLE(server_info->admin);
469 server_info->admin = strdup((char *) val);
471 else if (!strcmp(name, "adminemail")) {
472 CONFIG_IS_DOUBLE(server_info->email);
473 server_info->email = strdup((char *) val);
475 else if (!strcmp(name, "location")) {
476 CONFIG_IS_DOUBLE(server_info->location);
477 server_info->location = strdup((char *) val);
479 else if (!strcmp(name, "user")) {
480 CONFIG_IS_DOUBLE(server_info->user);
481 server_info->user = strdup((char *) val);
483 else if (!strcmp(name, "group")) {
484 CONFIG_IS_DOUBLE(server_info->group);
485 server_info->group = strdup((char *) val);
487 else if (!strcmp(name, "motdfile")) {
488 CONFIG_IS_DOUBLE(server_info->motd_file);
489 server_info->motd_file = strdup((char *) val);
491 else if (!strcmp(name, "pidfile")) {
492 CONFIG_IS_DOUBLE(server_info->pid_file);
493 server_info->pid_file = strdup((char *) val);
495 else if (!strcmp(name, "publickey")) {
496 char *file_tmp = (char *) val;
498 /* try to load specified file, if fail stop config parsing */
499 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
501 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
502 SILC_PKCS_FILE_BIN)) {
503 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
504 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
505 return SILC_CONFIG_ESILENT;
508 else if (!strcmp(name, "privatekey")) {
509 char *file_tmp = (char *) val;
511 /* try to load specified file, if fail stop config parsing */
512 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
514 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
515 SILC_PKCS_FILE_PEM)) {
516 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
517 SILC_SERVER_LOG_ERROR((" line %lu: file \"%s\"\n", line, file_tmp));
518 return SILC_CONFIG_ESILENT;
522 return SILC_CONFIG_EINTERNAL;
523 return SILC_CONFIG_OK;
529 SILC_CONFIG_CALLBACK(fetch_logging)
531 SilcServerConfig config = (SilcServerConfig) context;
532 SilcServerConfigLogging *tmp =
533 (SilcServerConfigLogging *) config->tmp;
536 if (!strcmp(name, "quicklogs")) {
537 config->logging_quick = *(bool *)val;
539 else if (!strcmp(name, "flushdelay")) {
540 int flushdelay = *(int *)val;
541 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
542 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use "
543 "quicklogs if you want real-time logging.\n", line));
544 return SILC_CONFIG_ESILENT;
546 config->logging_flushdelay = (long) flushdelay;
548 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
549 else if (!strcmp(name, __chan__)) { \
550 if (!tmp) return SILC_CONFIG_OK; \
552 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
554 config->__member__ = tmp; \
555 config->tmp = NULL; \
557 FETCH_LOGGING_CHAN("info", logging_info)
558 FETCH_LOGGING_CHAN("warnings", logging_warnings)
559 FETCH_LOGGING_CHAN("errors", logging_errors)
560 FETCH_LOGGING_CHAN("fatals", logging_fatals)
561 #undef FETCH_LOGGING_CHAN
562 else if (!strcmp(name, "file")) {
563 if (!tmp) { /* FIXME: what the fuck is this? */
564 config->tmp = silc_calloc(1, sizeof(*tmp));
565 tmp = (SilcServerConfigLogging *) config->tmp;
568 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
570 tmp->file = strdup((char *) val);
572 else if (!strcmp(name, "size")) {
574 config->tmp = silc_calloc(1, sizeof(*tmp));
575 tmp = (SilcServerConfigLogging *) config->tmp;
577 tmp->maxsize = *(SilcUInt32 *) val;
580 return SILC_CONFIG_EINTERNAL;
581 return SILC_CONFIG_OK;
584 silc_free(tmp->file);
590 SILC_CONFIG_CALLBACK(fetch_connparam)
592 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
594 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
595 type, name, context));
597 if (type == SILC_CONFIG_ARG_BLOCK) {
599 return SILC_CONFIG_OK;
602 got_errno = SILC_CONFIG_EMISSFIELDS;
607 my_set_param_defaults(tmp, &config->param);
609 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
611 return SILC_CONFIG_OK;
614 /* if there isn't a temporary struct alloc one */
616 config->tmp = silc_calloc(1, sizeof(*findtmp));
617 tmp = (SilcServerConfigConnParams *) config->tmp;
620 if (!strcmp(name, "name")) {
621 CONFIG_IS_DOUBLE(tmp->name);
622 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
624 else if (!strcmp(name, "connections_max")) {
625 tmp->connections_max = *(SilcUInt32 *)val;
627 else if (!strcmp(name, "connections_max_per_host")) {
628 tmp->connections_max_per_host = *(SilcUInt32 *)val;
630 else if (!strcmp(name, "keepalive_secs")) {
631 tmp->keepalive_secs = *(SilcUInt32 *)val;
633 else if (!strcmp(name, "reconnect_count")) {
634 tmp->reconnect_count = *(SilcUInt32 *)val;
636 else if (!strcmp(name, "reconnect_interval")) {
637 tmp->reconnect_interval = *(SilcUInt32 *)val;
639 else if (!strcmp(name, "reconnect_interval_max")) {
640 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
642 else if (!strcmp(name, "reconnect_keep_trying")) {
643 tmp->reconnect_keep_trying = *(bool *)val;
645 else if (!strcmp(name, "key_exchange_rekey")) {
646 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
648 else if (!strcmp(name, "key_exchange_pfs")) {
649 tmp->key_exchange_pfs = *(bool *)val;
651 else if (!strcmp(name, "version_protocol")) {
652 CONFIG_IS_DOUBLE(tmp->version_protocol);
653 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
655 else if (!strcmp(name, "version_software")) {
656 CONFIG_IS_DOUBLE(tmp->version_software);
657 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
659 else if (!strcmp(name, "version_software_vendor")) {
660 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
661 tmp->version_software_vendor =
662 (*(char *)val ? strdup((char *) val) : NULL);
665 return SILC_CONFIG_EINTERNAL;
667 return SILC_CONFIG_OK;
670 silc_free(tmp->name);
676 SILC_CONFIG_CALLBACK(fetch_client)
678 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
680 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
681 type, name, context));
683 /* alloc tmp before block checking (empty sub-blocks are welcome here) */
685 config->tmp = silc_calloc(1, sizeof(*findtmp));
686 tmp = (SilcServerConfigClient *) config->tmp;
689 if (type == SILC_CONFIG_ARG_BLOCK) {
690 /* closing the block */
691 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
693 return SILC_CONFIG_OK;
696 /* Identify and save this value */
697 if (!strcmp(name, "host")) {
698 CONFIG_IS_DOUBLE(tmp->host);
699 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
701 else if (!strcmp(name, "passphrase")) {
702 CONFIG_IS_DOUBLE(tmp->passphrase);
703 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
704 (void **)&tmp->passphrase,
705 &tmp->passphrase_len)) {
706 got_errno = SILC_CONFIG_ESILENT;
710 else if (!strcmp(name, "publickey")) {
711 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
712 (void **)&tmp->publickeys, NULL)) {
713 got_errno = SILC_CONFIG_ESILENT;
717 else if (!strcmp(name, "params")) {
718 CONFIG_IS_DOUBLE(tmp->param);
719 tmp->param = my_find_param(config, (char *) val, line);
720 if (!tmp->param) { /* error already output */
721 got_errno = SILC_CONFIG_ESILENT;
726 return SILC_CONFIG_EINTERNAL;
727 return SILC_CONFIG_OK;
730 silc_free(tmp->host);
731 CONFIG_FREE_AUTH(tmp);
737 SILC_CONFIG_CALLBACK(fetch_admin)
739 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
741 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
742 type, name, context));
744 if (type == SILC_CONFIG_ARG_BLOCK) {
745 /* check the temporary struct's fields */
746 if (!tmp) /* empty sub-block? */
747 return SILC_CONFIG_OK;
749 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
751 return SILC_CONFIG_OK;
754 /* if there isn't a temporary struct alloc one */
756 config->tmp = silc_calloc(1, sizeof(*findtmp));
757 tmp = (SilcServerConfigAdmin *) config->tmp;
760 /* Identify and save this value */
761 if (!strcmp(name, "host")) {
762 CONFIG_IS_DOUBLE(tmp->host);
763 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
765 else if (!strcmp(name, "user")) {
766 CONFIG_IS_DOUBLE(tmp->user);
767 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
769 else if (!strcmp(name, "nick")) {
770 CONFIG_IS_DOUBLE(tmp->nick);
771 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
773 else if (!strcmp(name, "passphrase")) {
774 CONFIG_IS_DOUBLE(tmp->passphrase);
775 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
776 (void **)&tmp->passphrase,
777 &tmp->passphrase_len)) {
778 got_errno = SILC_CONFIG_ESILENT;
782 else if (!strcmp(name, "publickey")) {
783 CONFIG_IS_DOUBLE(tmp->publickeys);
784 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
785 (void **)&tmp->publickeys, NULL)) {
786 got_errno = SILC_CONFIG_ESILENT;
791 return SILC_CONFIG_EINTERNAL;
792 return SILC_CONFIG_OK;
795 silc_free(tmp->host);
796 silc_free(tmp->user);
797 silc_free(tmp->nick);
798 CONFIG_FREE_AUTH(tmp);
804 SILC_CONFIG_CALLBACK(fetch_deny)
806 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
808 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
809 type, name, context));
810 if (type == SILC_CONFIG_ARG_BLOCK) {
811 /* check the temporary struct's fields */
812 if (!tmp) /* empty sub-block? */
813 return SILC_CONFIG_OK;
815 got_errno = SILC_CONFIG_EMISSFIELDS;
818 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
820 return SILC_CONFIG_OK;
822 /* if there isn't a temporary struct alloc one */
824 config->tmp = silc_calloc(1, sizeof(*findtmp));
825 tmp = (SilcServerConfigDeny *) config->tmp;
828 /* Identify and save this value */
829 if (!strcmp(name, "host")) {
830 CONFIG_IS_DOUBLE(tmp->host);
831 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
833 else if (!strcmp(name, "reason")) {
834 CONFIG_IS_DOUBLE(tmp->reason);
835 tmp->reason = strdup((char *) val);
838 return SILC_CONFIG_EINTERNAL;
839 return SILC_CONFIG_OK;
842 silc_free(tmp->host);
843 silc_free(tmp->reason);
849 SILC_CONFIG_CALLBACK(fetch_server)
851 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
853 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
854 type, name, context));
856 if (type == SILC_CONFIG_ARG_BLOCK) {
857 /* check the temporary struct's fields */
858 if (!tmp) /* empty sub-block? */
859 return SILC_CONFIG_OK;
861 /* the temporary struct is ok, append it to the list */
862 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
864 return SILC_CONFIG_OK;
867 /* if there isn't a temporary struct alloc one */
869 config->tmp = silc_calloc(1, sizeof(*findtmp));
870 tmp = (SilcServerConfigServer *) config->tmp;
873 /* Identify and save this value */
874 if (!strcmp(name, "host")) {
875 CONFIG_IS_DOUBLE(tmp->host);
876 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
878 else if (!strcmp(name, "passphrase")) {
879 CONFIG_IS_DOUBLE(tmp->passphrase);
880 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
881 (void **)&tmp->passphrase,
882 &tmp->passphrase_len)) {
883 got_errno = SILC_CONFIG_ESILENT;
887 else if (!strcmp(name, "publickey")) {
888 CONFIG_IS_DOUBLE(tmp->publickeys);
889 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
890 (void **)&tmp->publickeys, NULL)) {
891 got_errno = SILC_CONFIG_ESILENT;
895 else if (!strcmp(name, "params")) {
896 CONFIG_IS_DOUBLE(tmp->param);
897 tmp->param = my_find_param(config, (char *) val, line);
898 if (!tmp->param) { /* error already output */
899 got_errno = SILC_CONFIG_ESILENT;
903 else if (!strcmp(name, "backup")) {
904 tmp->backup_router = *(bool *)val;
907 return SILC_CONFIG_EINTERNAL;
909 return SILC_CONFIG_OK;
912 silc_free(tmp->host);
913 CONFIG_FREE_AUTH(tmp);
919 SILC_CONFIG_CALLBACK(fetch_router)
921 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
923 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
924 type, name, context));
926 if (type == SILC_CONFIG_ARG_BLOCK) {
927 if (!tmp) /* empty sub-block? */
928 return SILC_CONFIG_OK;
930 /* the temporary struct is ok, append it to the list */
931 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
933 return SILC_CONFIG_OK;
936 /* if there isn't a temporary struct alloc one */
938 config->tmp = silc_calloc(1, sizeof(*findtmp));
939 tmp = (SilcServerConfigRouter *) config->tmp;
942 /* Identify and save this value */
943 if (!strcmp(name, "host")) {
944 CONFIG_IS_DOUBLE(tmp->host);
945 tmp->host = strdup((char *) val);
947 else if (!strcmp(name, "port")) {
948 int port = *(int *)val;
949 if ((port <= 0) || (port > 65535)) {
950 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
951 return SILC_CONFIG_ESILENT;
953 tmp->port = (SilcUInt16) port;
955 else if (!strcmp(name, "passphrase")) {
956 CONFIG_IS_DOUBLE(tmp->passphrase);
957 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val, line,
958 (void **)&tmp->passphrase,
959 &tmp->passphrase_len)) {
960 got_errno = SILC_CONFIG_ESILENT;
964 else if (!strcmp(name, "publickey")) {
965 CONFIG_IS_DOUBLE(tmp->publickeys);
966 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val, line,
967 (void **)&tmp->publickeys, NULL)) {
968 got_errno = SILC_CONFIG_ESILENT;
972 else if (!strcmp(name, "params")) {
973 CONFIG_IS_DOUBLE(tmp->param);
974 tmp->param = my_find_param(config, (char *) val, line);
975 if (!tmp->param) { /* error already output */
976 got_errno = SILC_CONFIG_ESILENT;
980 else if (!strcmp(name, "initiator")) {
981 tmp->initiator = *(bool *)val;
983 else if (!strcmp(name, "backuphost")) {
984 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
985 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
988 else if (!strcmp(name, "backupport")) {
989 int port = *(int *)val;
990 if ((port <= 0) || (port > 65535)) {
991 SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
992 return SILC_CONFIG_ESILENT;
994 tmp->backup_replace_port = (SilcUInt16) port;
996 else if (!strcmp(name, "backuplocal")) {
997 tmp->backup_local = *(bool *)val;
1000 return SILC_CONFIG_EINTERNAL;
1002 return SILC_CONFIG_OK;
1005 silc_free(tmp->host);
1006 silc_free(tmp->backup_replace_ip);
1007 CONFIG_FREE_AUTH(tmp);
1013 /* known config options tables */
1014 static const SilcConfigTable table_general[] = {
1015 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1016 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1017 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1018 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1019 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1020 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1021 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1022 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1023 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1024 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1025 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1026 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1027 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1028 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1029 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1030 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1031 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1032 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1036 static const SilcConfigTable table_cipher[] = {
1037 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1038 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1039 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1040 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1044 static const SilcConfigTable table_hash[] = {
1045 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1046 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1047 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1048 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1052 static const SilcConfigTable table_hmac[] = {
1053 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1054 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1055 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1059 static const SilcConfigTable table_pkcs[] = {
1060 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1064 static const SilcConfigTable table_serverinfo[] = {
1065 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1066 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1067 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1068 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1069 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1070 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1071 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1072 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1073 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1074 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1075 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1076 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1077 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1081 static const SilcConfigTable table_logging_c[] = {
1082 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1083 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1084 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1088 static const SilcConfigTable table_logging[] = {
1089 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1090 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1091 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1092 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1093 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1094 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1098 static const SilcConfigTable table_connparam[] = {
1099 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1100 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1101 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1102 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1103 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1104 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1105 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1106 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1107 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1108 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1109 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1110 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1111 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1112 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1116 static const SilcConfigTable table_client[] = {
1117 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1118 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1119 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1120 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1124 static const SilcConfigTable table_admin[] = {
1125 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1126 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1127 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1128 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1129 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1130 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1131 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1135 static const SilcConfigTable table_deny[] = {
1136 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1137 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1141 static const SilcConfigTable table_serverconn[] = {
1142 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1143 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1144 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1145 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1146 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1150 static const SilcConfigTable table_routerconn[] = {
1151 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1152 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1153 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1154 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1155 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1156 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1157 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1158 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1159 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1163 static const SilcConfigTable table_main[] = {
1164 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1165 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1166 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1167 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1168 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1169 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1170 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1171 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1172 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1173 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1174 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1175 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1176 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1180 /* Set default values to stuff that was not configured. */
1182 static void silc_server_config_set_defaults(SilcServerConfig config)
1184 my_set_param_defaults(&config->param, NULL);
1186 config->channel_rekey_secs = (config->channel_rekey_secs ?
1187 config->channel_rekey_secs :
1188 SILC_SERVER_CHANNEL_REKEY);
1189 config->key_exchange_timeout = (config->key_exchange_timeout ?
1190 config->key_exchange_timeout :
1191 SILC_SERVER_SKE_TIMEOUT);
1192 config->conn_auth_timeout = (config->conn_auth_timeout ?
1193 config->conn_auth_timeout :
1194 SILC_SERVER_CONNAUTH_TIMEOUT);
1197 /* Allocates a new configuration object, opens configuration file and
1198 parses it. The parsed data is returned to the newly allocated
1199 configuration object. The SilcServerConfig must be freed by calling
1200 the silc_server_config_destroy function. */
1202 SilcServerConfig silc_server_config_alloc(const char *filename)
1204 SilcServerConfig config_new;
1205 SilcConfigEntity ent;
1206 SilcConfigFile *file;
1208 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1210 /* alloc a config object */
1211 config_new = silc_calloc(1, sizeof(*config_new));
1212 config_new->refcount = 1;
1216 /* obtain a config file object */
1217 file = silc_config_open(filename);
1219 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n",
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 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
1243 silc_config_strerror(ret)));
1244 linebuf = silc_config_read_line(file, line);
1245 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1249 silc_server_config_destroy(config_new);
1253 /* close (destroy) the file object */
1254 silc_config_close(file);
1256 /* If config_new is incomplete, abort the object and return NULL */
1257 if (!config_new->server_info) {
1258 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1259 "`server_info'\n"));
1260 silc_server_config_destroy(config_new);
1264 /* XXX are there any other mandatory sections in the config file? */
1266 /* Set default to configuration parameters */
1267 silc_server_config_set_defaults(config_new);
1272 /* Increments the reference counter of a config object */
1274 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1279 ref->config = config;
1280 ref->ref_ptr = ref_ptr;
1281 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1282 config->refcount - 1, config->refcount));
1286 /* Decrements the reference counter of a config object. If the counter
1287 reaches 0, the config object is destroyed. */
1289 void silc_server_config_unref(SilcServerConfigRef *ref)
1292 silc_server_config_destroy(ref->config);
1295 /* Destroy a config object with all his children lists */
1297 void silc_server_config_destroy(SilcServerConfig config)
1302 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1303 config->refcount + 1, config->refcount));
1304 if (config->refcount > 0)
1307 SILC_LOG_DEBUG(("Freeing config context"));
1309 /* Destroy general config stuff */
1310 silc_free(config->module_path);
1311 silc_free(config->param.version_protocol);
1312 silc_free(config->param.version_software);
1313 silc_free(config->param.version_software_vendor);
1315 /* Destroy Logging channels */
1316 if (config->logging_info)
1317 silc_free(config->logging_info->file);
1318 if (config->logging_warnings)
1319 silc_free(config->logging_warnings->file);
1320 if (config->logging_errors)
1321 silc_free(config->logging_errors->file);
1322 if (config->logging_fatals)
1323 silc_free(config->logging_fatals->file);
1325 /* Destroy the ServerInfo struct */
1326 if (config->server_info) {
1327 register SilcServerConfigServerInfo *si = config->server_info;
1328 silc_free(si->server_name);
1329 silc_free(si->server_ip);
1330 silc_free(si->server_type);
1331 silc_free(si->location);
1332 silc_free(si->admin);
1333 silc_free(si->email);
1334 silc_free(si->user);
1335 silc_free(si->group);
1336 silc_free(si->motd_file);
1337 silc_free(si->pid_file);
1338 silc_pkcs_public_key_free(si->public_key);
1339 silc_pkcs_private_key_free(si->private_key);
1342 /* Now let's destroy the lists */
1344 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1346 silc_free(di->name);
1347 silc_free(di->module);
1350 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1351 silc_free(di->name);
1352 silc_free(di->module);
1355 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1356 silc_free(di->name);
1357 silc_free(di->hash);
1360 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1361 silc_free(di->name);
1364 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1365 config->conn_params)
1366 silc_free(di->name);
1367 silc_free(di->version_protocol);
1368 silc_free(di->version_software);
1369 silc_free(di->version_software_vendor);
1372 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1373 silc_free(di->host);
1374 CONFIG_FREE_AUTH(di);
1377 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1378 silc_free(di->host);
1379 silc_free(di->user);
1380 silc_free(di->nick);
1381 CONFIG_FREE_AUTH(di);
1384 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1385 silc_free(di->host);
1386 silc_free(di->reason);
1389 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1391 silc_free(di->host);
1392 CONFIG_FREE_AUTH(di);
1395 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1397 silc_free(di->host);
1398 silc_free(di->backup_replace_ip);
1399 CONFIG_FREE_AUTH(di);
1403 memset(config, 'F', sizeof(*config));
1407 /* Registers configured ciphers. These can then be allocated by the
1408 server when needed. */
1410 bool silc_server_config_register_ciphers(SilcServer server)
1412 SilcServerConfig config = server->config;
1413 SilcServerConfigCipher *cipher = config->cipher;
1414 char *module_path = config->module_path;
1416 SILC_LOG_DEBUG(("Registering configured ciphers"));
1418 if (!cipher) /* any cipher in the config file? */
1422 /* if there isn't a module_path OR there isn't a module sim name try to
1423 * use buil-in functions */
1424 if (!module_path || !cipher->module) {
1426 for (i = 0; silc_default_ciphers[i].name; i++)
1427 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1428 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1431 if (!silc_cipher_is_supported(cipher->name)) {
1432 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1433 silc_server_stop(server);
1438 /* Load (try at least) the crypto SIM module */
1439 char buf[1023], *alg_name;
1440 SilcCipherObject cipher_obj;
1443 memset(&cipher_obj, 0, sizeof(cipher_obj));
1444 cipher_obj.name = cipher->name;
1445 cipher_obj.block_len = cipher->block_length;
1446 cipher_obj.key_len = cipher->key_length * 8;
1448 /* build the libname */
1449 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1451 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1453 alg_name = strdup(cipher->name);
1454 if (strchr(alg_name, '-'))
1455 *strchr(alg_name, '-') = '\0';
1457 if (silc_sim_load(sim)) {
1458 cipher_obj.set_key =
1459 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1460 SILC_CIPHER_SIM_SET_KEY));
1461 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1462 cipher_obj.set_key_with_string =
1463 silc_sim_getsym(sim,
1464 silc_sim_symname(alg_name,
1465 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1466 SILC_LOG_DEBUG(("set_key_with_string=%p",
1467 cipher_obj.set_key_with_string));
1468 cipher_obj.encrypt =
1469 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1470 SILC_CIPHER_SIM_ENCRYPT_CBC));
1471 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1472 cipher_obj.decrypt =
1473 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1474 SILC_CIPHER_SIM_DECRYPT_CBC));
1475 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1476 cipher_obj.context_len =
1477 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1478 SILC_CIPHER_SIM_CONTEXT_LEN));
1479 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1481 /* Put the SIM to the list of all SIM's in server */
1482 silc_dlist_add(server->sim, sim);
1484 silc_free(alg_name);
1486 SILC_LOG_ERROR(("Error configuring ciphers"));
1487 silc_server_stop(server);
1491 /* Register the cipher */
1492 silc_cipher_register(&cipher_obj);
1494 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1495 "can't load modules!"));
1496 silc_server_stop(server);
1500 cipher = cipher->next;
1506 /* Registers configured hash functions. These can then be allocated by the
1507 server when needed. */
1509 bool silc_server_config_register_hashfuncs(SilcServer server)
1511 SilcServerConfig config = server->config;
1512 SilcServerConfigHash *hash = config->hash;
1513 char *module_path = config->module_path;
1515 SILC_LOG_DEBUG(("Registering configured hash functions"));
1517 if (!hash) /* any hash func in the config file? */
1521 /* if there isn't a module_path OR there isn't a module sim name try to
1522 * use buil-in functions */
1523 if (!module_path || !hash->module) {
1525 for (i = 0; silc_default_hash[i].name; i++)
1526 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1527 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1530 if (!silc_hash_is_supported(hash->name)) {
1531 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1532 silc_server_stop(server);
1537 /* Load (try at least) the hash SIM module */
1538 SilcHashObject hash_obj;
1541 memset(&hash_obj, 0, sizeof(hash_obj));
1542 hash_obj.name = hash->name;
1543 hash_obj.block_len = hash->block_length;
1544 hash_obj.hash_len = hash->digest_length;
1546 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1548 if ((silc_sim_load(sim))) {
1550 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1551 SILC_HASH_SIM_INIT));
1552 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1554 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1555 SILC_HASH_SIM_UPDATE));
1556 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1558 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1559 SILC_HASH_SIM_FINAL));
1560 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1561 hash_obj.context_len =
1562 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1563 SILC_HASH_SIM_CONTEXT_LEN));
1564 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1566 /* Put the SIM to the table of all SIM's in server */
1567 silc_dlist_add(server->sim, sim);
1569 SILC_LOG_ERROR(("Error configuring hash functions"));
1570 silc_server_stop(server);
1574 /* Register the hash function */
1575 silc_hash_register(&hash_obj);
1577 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1578 "can't load modules!"));
1579 silc_server_stop(server);
1589 /* Registers configure HMACs. These can then be allocated by the server
1592 bool silc_server_config_register_hmacs(SilcServer server)
1594 SilcServerConfig config = server->config;
1595 SilcServerConfigHmac *hmac = config->hmac;
1597 SILC_LOG_DEBUG(("Registering configured HMACs"));
1603 SilcHmacObject hmac_obj;
1604 if (!silc_hash_is_supported(hmac->hash)) {
1605 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1606 silc_server_stop(server);
1610 /* Register the HMAC */
1611 memset(&hmac_obj, 0, sizeof(hmac_obj));
1612 hmac_obj.name = hmac->name;
1613 hmac_obj.len = hmac->mac_length;
1614 silc_hmac_register(&hmac_obj);
1622 /* Registers configured PKCS's. */
1624 bool silc_server_config_register_pkcs(SilcServer server)
1626 SilcServerConfig config = server->config;
1627 SilcServerConfigPkcs *pkcs = config->pkcs;
1629 SILC_LOG_DEBUG(("Registering configured PKCS"));
1636 for (i = 0; silc_default_pkcs[i].name; i++)
1637 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1638 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1641 if (!silc_pkcs_is_supported(pkcs->name)) {
1642 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1643 silc_server_stop(server);
1652 /* Sets log files where log messages are saved by the server logger. */
1654 void silc_server_config_setlogfiles(SilcServer server)
1656 SilcServerConfig config = server->config;
1657 SilcServerConfigLogging *this;
1659 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1661 silc_log_quick = config->logging_quick;
1662 silc_log_flushdelay = (config->logging_flushdelay ?
1663 config->logging_flushdelay :
1664 SILC_SERVER_LOG_FLUSH_DELAY);
1666 if ((this = config->logging_fatals))
1667 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1669 if ((this = config->logging_errors))
1670 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1672 if ((this = config->logging_warnings))
1673 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1675 if ((this = config->logging_info))
1676 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1680 /* Returns client authentication information from configuration file by host
1683 SilcServerConfigClient *
1684 silc_server_config_find_client(SilcServer server, char *host)
1686 SilcServerConfig config = server->config;
1687 SilcServerConfigClient *client;
1689 if (!config || !host)
1692 for (client = config->clients; client; client = client->next) {
1693 if (client->host && !silc_string_compare(client->host, host))
1698 /* if none matched, then client is already NULL */
1702 /* Returns admin connection configuration by host, username and/or
1705 SilcServerConfigAdmin *
1706 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1709 SilcServerConfig config = server->config;
1710 SilcServerConfigAdmin *admin;
1712 /* make sure we have a value for the matching parameters */
1720 for (admin = config->admins; admin; admin = admin->next) {
1721 if (admin->host && !silc_string_compare(admin->host, host))
1723 if (admin->user && !silc_string_compare(admin->user, user))
1725 if (admin->nick && !silc_string_compare(admin->nick, nick))
1727 /* no checks failed -> this entry matches */
1731 /* if none matched, then admin is already NULL */
1735 /* Returns the denied connection configuration entry by host. */
1737 SilcServerConfigDeny *
1738 silc_server_config_find_denied(SilcServer server, char *host)
1740 SilcServerConfig config = server->config;
1741 SilcServerConfigDeny *deny;
1743 /* make sure we have a value for the matching parameters */
1744 if (!config || !host)
1747 for (deny = config->denied; deny; deny = deny->next) {
1748 if (deny->host && !silc_string_compare(deny->host, host))
1753 /* if none matched, then deny is already NULL */
1757 /* Returns server connection info from server configuartion by host
1760 SilcServerConfigServer *
1761 silc_server_config_find_server_conn(SilcServer server, char *host)
1763 SilcServerConfig config = server->config;
1764 SilcServerConfigServer *serv = NULL;
1769 if (!config->servers)
1772 for (serv = config->servers; serv; serv = serv->next) {
1773 if (!silc_string_compare(serv->host, host))
1781 /* Returns router connection info from server configuration by
1782 host (name or ip). */
1784 SilcServerConfigRouter *
1785 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1787 SilcServerConfig config = server->config;
1788 SilcServerConfigRouter *serv = NULL;
1793 if (!config->routers)
1796 for (serv = config->routers; serv; serv = serv->next) {
1797 if (!silc_string_compare(serv->host, host))
1799 if (port && serv->port && serv->port != port)
1807 /* Returns TRUE if configuration for a router connection that we are
1808 initiating exists. */
1810 bool silc_server_config_is_primary_route(SilcServer server)
1812 SilcServerConfig config = server->config;
1813 SilcServerConfigRouter *serv = NULL;
1817 serv = config->routers;
1818 for (i = 0; serv; i++) {
1819 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1830 /* Returns our primary connection configuration or NULL if we do not
1831 have primary router configured. */
1833 SilcServerConfigRouter *
1834 silc_server_config_get_primary_router(SilcServer server)
1836 SilcServerConfig config = server->config;
1837 SilcServerConfigRouter *serv = NULL;
1840 serv = config->routers;
1841 for (i = 0; serv; i++) {
1842 if (serv->initiator == TRUE && serv->backup_router == FALSE)