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;
234 else if (!strcmp(name, "qos")) {
235 config->param.qos = *(bool *)val;
237 else if (!strcmp(name, "qos_rate_limit")) {
238 config->param.qos_rate_limit = *(SilcUInt32 *)val;
240 else if (!strcmp(name, "qos_bytes_limit")) {
241 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
243 else if (!strcmp(name, "qos_limit_sec")) {
244 config->param.qos_limit_sec = *(SilcUInt32 *)val;
246 else if (!strcmp(name, "qos_limit_usec")) {
247 config->param.qos_limit_usec = *(SilcUInt32 *)val;
250 return SILC_CONFIG_EINTERNAL;
252 return SILC_CONFIG_OK;
258 SILC_CONFIG_CALLBACK(fetch_cipher)
260 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
262 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
263 type, name, context));
264 if (type == SILC_CONFIG_ARG_BLOCK) {
265 /* check the temporary struct's fields */
266 if (!tmp) /* discard empty sub-blocks */
267 return SILC_CONFIG_OK;
269 got_errno = SILC_CONFIG_EMISSFIELDS;
273 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
275 return SILC_CONFIG_OK;
277 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
279 /* Identify and save this value */
280 if (!strcmp(name, "name")) {
281 CONFIG_IS_DOUBLE(tmp->name);
282 tmp->name = strdup((char *) val);
284 else if (!strcmp(name, "module")) {
285 CONFIG_IS_DOUBLE(tmp->module);
286 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
288 else if (!strcmp(name, "keylength")) {
289 tmp->key_length = *(SilcUInt32 *)val;
291 else if (!strcmp(name, "blocklength")) {
292 tmp->block_length = *(SilcUInt32 *)val;
295 return SILC_CONFIG_EINTERNAL;
296 return SILC_CONFIG_OK;
299 silc_free(tmp->name);
300 silc_free(tmp->module);
306 SILC_CONFIG_CALLBACK(fetch_hash)
308 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
310 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
311 type, name, context));
312 if (type == SILC_CONFIG_ARG_BLOCK) {
313 /* check the temporary struct's fields */
314 if (!tmp) /* discard empty sub-blocks */
315 return SILC_CONFIG_OK;
316 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
317 got_errno = SILC_CONFIG_EMISSFIELDS;
321 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
323 return SILC_CONFIG_OK;
325 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
327 /* Identify and save this value */
328 if (!strcmp(name, "name")) {
329 CONFIG_IS_DOUBLE(tmp->name);
330 tmp->name = strdup((char *) val);
332 else if (!strcmp(name, "module")) {
333 CONFIG_IS_DOUBLE(tmp->module);
334 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
336 else if (!strcmp(name, "blocklength")) {
337 tmp->block_length = *(int *)val;
339 else if (!strcmp(name, "digestlength")) {
340 tmp->digest_length = *(int *)val;
343 return SILC_CONFIG_EINTERNAL;
344 return SILC_CONFIG_OK;
347 silc_free(tmp->name);
348 silc_free(tmp->module);
354 SILC_CONFIG_CALLBACK(fetch_hmac)
356 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
358 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
359 type, name, context));
360 if (type == SILC_CONFIG_ARG_BLOCK) {
361 /* check the temporary struct's fields */
362 if (!tmp) /* discard empty sub-blocks */
363 return SILC_CONFIG_OK;
364 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
365 got_errno = SILC_CONFIG_EMISSFIELDS;
369 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
371 return SILC_CONFIG_OK;
373 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
375 /* Identify and save this value */
376 if (!strcmp(name, "name")) {
377 CONFIG_IS_DOUBLE(tmp->name);
378 tmp->name = strdup((char *) val);
380 else if (!strcmp(name, "hash")) {
381 CONFIG_IS_DOUBLE(tmp->hash);
382 tmp->hash = strdup((char *) val);
384 else if (!strcmp(name, "maclength")) {
385 tmp->mac_length = *(int *)val;
388 return SILC_CONFIG_EINTERNAL;
389 return SILC_CONFIG_OK;
392 silc_free(tmp->name);
393 silc_free(tmp->hash);
399 SILC_CONFIG_CALLBACK(fetch_pkcs)
401 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
403 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
404 type, name, context));
405 if (type == SILC_CONFIG_ARG_BLOCK) {
406 /* check the temporary struct's fields */
407 if (!tmp) /* discard empty sub-blocks */
408 return SILC_CONFIG_OK;
410 got_errno = SILC_CONFIG_EMISSFIELDS;
414 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
416 return SILC_CONFIG_OK;
418 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
420 /* Identify and save this value */
421 if (!strcmp(name, "name")) {
422 CONFIG_IS_DOUBLE(tmp->name);
423 tmp->name = strdup((char *) val);
426 return SILC_CONFIG_EINTERNAL;
427 return SILC_CONFIG_OK;
430 silc_free(tmp->name);
436 SILC_CONFIG_CALLBACK(fetch_serverinfo)
438 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
439 SilcServerConfigServerInfo *server_info = config->server_info;
441 /* if there isn't the struct alloc it */
443 config->server_info = server_info = (SilcServerConfigServerInfo *)
444 silc_calloc(1, sizeof(*server_info));
446 if (type == SILC_CONFIG_ARG_BLOCK) {
447 if (!strcmp(name, "primary")) {
448 CONFIG_IS_DOUBLE(server_info->primary);
450 return SILC_CONFIG_OK;
451 server_info->primary = tmp;
453 return SILC_CONFIG_OK;
454 } else if (!strcmp(name, "secondary")) {
456 return SILC_CONFIG_OK;
457 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
459 return SILC_CONFIG_OK;
460 } else if (!server_info->public_key || !server_info->private_key) {
461 got_errno = SILC_CONFIG_EMISSFIELDS;
464 return SILC_CONFIG_OK;
466 if (!strcmp(name, "hostname")) {
467 CONFIG_IS_DOUBLE(server_info->server_name);
468 server_info->server_name = strdup((char *) val);
470 else if (!strcmp(name, "ip")) {
471 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
472 CONFIG_IS_DOUBLE(tmp->server_ip);
473 tmp->server_ip = strdup((char *) val);
475 else if (!strcmp(name, "port")) {
476 int port = *(int *)val;
477 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
478 if ((port <= 0) || (port > 65535)) {
479 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
480 "Invalid port number!"));
481 got_errno = SILC_CONFIG_EPRINTLINE;
484 tmp->port = (SilcUInt16) port;
486 else if (!strcmp(name, "servertype")) {
487 CONFIG_IS_DOUBLE(server_info->server_type);
488 server_info->server_type = strdup((char *) val);
490 else if (!strcmp(name, "admin")) {
491 CONFIG_IS_DOUBLE(server_info->admin);
492 server_info->admin = strdup((char *) val);
494 else if (!strcmp(name, "adminemail")) {
495 CONFIG_IS_DOUBLE(server_info->email);
496 server_info->email = strdup((char *) val);
498 else if (!strcmp(name, "location")) {
499 CONFIG_IS_DOUBLE(server_info->location);
500 server_info->location = strdup((char *) val);
502 else if (!strcmp(name, "user")) {
503 CONFIG_IS_DOUBLE(server_info->user);
504 server_info->user = strdup((char *) val);
506 else if (!strcmp(name, "group")) {
507 CONFIG_IS_DOUBLE(server_info->group);
508 server_info->group = strdup((char *) val);
510 else if (!strcmp(name, "motdfile")) {
511 CONFIG_IS_DOUBLE(server_info->motd_file);
512 server_info->motd_file = strdup((char *) val);
514 else if (!strcmp(name, "pidfile")) {
515 CONFIG_IS_DOUBLE(server_info->pid_file);
516 server_info->pid_file = strdup((char *) val);
518 else if (!strcmp(name, "publickey")) {
519 char *file_tmp = (char *) val;
521 /* try to load specified file, if fail stop config parsing */
522 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
524 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
525 SILC_PKCS_FILE_BIN)) {
526 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
527 return SILC_CONFIG_EPRINTLINE;
530 else if (!strcmp(name, "privatekey")) {
531 char *file_tmp = (char *) val;
533 /* try to load specified file, if fail stop config parsing */
534 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
536 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
537 SILC_PKCS_FILE_PEM)) {
538 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
539 return SILC_CONFIG_EPRINTLINE;
543 return SILC_CONFIG_EINTERNAL;
544 return SILC_CONFIG_OK;
548 silc_free(config->tmp);
553 SILC_CONFIG_CALLBACK(fetch_logging)
555 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
557 if (!strcmp(name, "timestamp")) {
558 config->logging_timestamp = *(bool *)val;
560 else if (!strcmp(name, "quicklogs")) {
561 config->logging_quick = *(bool *)val;
563 else if (!strcmp(name, "flushdelay")) {
564 int flushdelay = *(int *)val;
565 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
566 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
567 "Invalid flushdelay value, use quicklogs if you "
568 "want real-time logging."));
569 return SILC_CONFIG_EPRINTLINE;
571 config->logging_flushdelay = (long) flushdelay;
574 /* The following istances happens only in Logging's sub-blocks, a match
575 for the sub-block name means that you should store the filename/maxsize
576 temporary struct to the proper logging channel.
577 If we get a match for "file" or "maxsize" this means that we are inside
578 a sub-sub-block and it is safe to alloc a new tmp. */
579 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
580 else if (!strcmp(name, __chan__)) { \
581 if (!tmp) return SILC_CONFIG_OK; \
583 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
585 config->__member__ = tmp; \
586 config->tmp = NULL; \
588 FETCH_LOGGING_CHAN("info", logging_info)
589 FETCH_LOGGING_CHAN("warnings", logging_warnings)
590 FETCH_LOGGING_CHAN("errors", logging_errors)
591 FETCH_LOGGING_CHAN("fatals", logging_fatals)
592 #undef FETCH_LOGGING_CHAN
593 else if (!strcmp(name, "file")) {
594 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
595 CONFIG_IS_DOUBLE(tmp->file);
596 tmp->file = strdup((char *) val);
598 else if (!strcmp(name, "size")) {
600 config->tmp = silc_calloc(1, sizeof(*tmp));
601 tmp = (SilcServerConfigLogging *) config->tmp;
603 tmp->maxsize = *(SilcUInt32 *) val;
606 return SILC_CONFIG_EINTERNAL;
607 return SILC_CONFIG_OK;
610 silc_free(tmp->file);
616 SILC_CONFIG_CALLBACK(fetch_connparam)
618 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
620 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
621 type, name, context));
622 if (type == SILC_CONFIG_ARG_BLOCK) {
623 /* check the temporary struct's fields */
624 if (!tmp) /* discard empty sub-blocks */
625 return SILC_CONFIG_OK;
627 got_errno = SILC_CONFIG_EMISSFIELDS;
631 my_set_param_defaults(tmp, &config->param);
633 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
635 return SILC_CONFIG_OK;
637 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
639 if (!strcmp(name, "name")) {
640 CONFIG_IS_DOUBLE(tmp->name);
641 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
643 else if (!strcmp(name, "connections_max")) {
644 tmp->connections_max = *(SilcUInt32 *)val;
646 else if (!strcmp(name, "connections_max_per_host")) {
647 tmp->connections_max_per_host = *(SilcUInt32 *)val;
649 else if (!strcmp(name, "keepalive_secs")) {
650 tmp->keepalive_secs = *(SilcUInt32 *)val;
652 else if (!strcmp(name, "reconnect_count")) {
653 tmp->reconnect_count = *(SilcUInt32 *)val;
655 else if (!strcmp(name, "reconnect_interval")) {
656 tmp->reconnect_interval = *(SilcUInt32 *)val;
658 else if (!strcmp(name, "reconnect_interval_max")) {
659 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
661 else if (!strcmp(name, "reconnect_keep_trying")) {
662 tmp->reconnect_keep_trying = *(bool *)val;
664 else if (!strcmp(name, "key_exchange_rekey")) {
665 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
667 else if (!strcmp(name, "key_exchange_pfs")) {
668 tmp->key_exchange_pfs = *(bool *)val;
670 else if (!strcmp(name, "version_protocol")) {
671 CONFIG_IS_DOUBLE(tmp->version_protocol);
672 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
674 else if (!strcmp(name, "version_software")) {
675 CONFIG_IS_DOUBLE(tmp->version_software);
676 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
678 else if (!strcmp(name, "version_software_vendor")) {
679 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
680 tmp->version_software_vendor =
681 (*(char *)val ? strdup((char *) val) : NULL);
683 else if (!strcmp(name, "anonymous")) {
684 tmp->anonymous = *(bool *)val;
686 else if (!strcmp(name, "qos")) {
687 tmp->qos = *(bool *)val;
689 else if (!strcmp(name, "qos_rate_limit")) {
690 tmp->qos_rate_limit = *(SilcUInt32 *)val;
692 else if (!strcmp(name, "qos_bytes_limit")) {
693 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
695 else if (!strcmp(name, "qos_limit_sec")) {
696 tmp->qos_limit_sec = *(SilcUInt32 *)val;
698 else if (!strcmp(name, "qos_limit_usec")) {
699 tmp->qos_limit_usec = *(SilcUInt32 *)val;
702 return SILC_CONFIG_EINTERNAL;
704 return SILC_CONFIG_OK;
707 silc_free(tmp->name);
713 SILC_CONFIG_CALLBACK(fetch_client)
715 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
717 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
718 type, name, context));
720 /* Alloc before block checking, because empty sub-blocks are welcome here */
721 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
723 if (type == SILC_CONFIG_ARG_BLOCK) {
724 /* empty sub-blocks are welcome */
725 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
727 return SILC_CONFIG_OK;
730 /* Identify and save this value */
731 if (!strcmp(name, "host")) {
732 CONFIG_IS_DOUBLE(tmp->host);
733 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
735 else if (!strcmp(name, "passphrase")) {
736 CONFIG_IS_DOUBLE(tmp->passphrase);
737 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
738 (void **)&tmp->passphrase,
739 &tmp->passphrase_len)) {
740 got_errno = SILC_CONFIG_EPRINTLINE;
744 else if (!strcmp(name, "publickey")) {
745 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
746 (void **)&tmp->publickeys, NULL)) {
747 got_errno = SILC_CONFIG_EPRINTLINE;
751 else if (!strcmp(name, "params")) {
752 CONFIG_IS_DOUBLE(tmp->param);
753 tmp->param = my_find_param(config, (char *) val);
754 if (!tmp->param) { /* error message already output */
755 got_errno = SILC_CONFIG_EPRINTLINE;
760 return SILC_CONFIG_EINTERNAL;
761 return SILC_CONFIG_OK;
764 silc_free(tmp->host);
765 CONFIG_FREE_AUTH(tmp);
771 SILC_CONFIG_CALLBACK(fetch_admin)
773 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
775 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
776 type, name, context));
777 if (type == SILC_CONFIG_ARG_BLOCK) {
778 /* check the temporary struct's fields */
779 if (!tmp) /* discard empty sub-blocks */
780 return SILC_CONFIG_OK;
782 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
784 return SILC_CONFIG_OK;
786 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
788 /* Identify and save this value */
789 if (!strcmp(name, "host")) {
790 CONFIG_IS_DOUBLE(tmp->host);
791 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
793 else if (!strcmp(name, "user")) {
794 CONFIG_IS_DOUBLE(tmp->user);
795 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
797 else if (!strcmp(name, "nick")) {
798 CONFIG_IS_DOUBLE(tmp->nick);
799 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
801 else if (!strcmp(name, "passphrase")) {
802 CONFIG_IS_DOUBLE(tmp->passphrase);
803 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
804 (void **)&tmp->passphrase,
805 &tmp->passphrase_len)) {
806 got_errno = SILC_CONFIG_EPRINTLINE;
810 else if (!strcmp(name, "publickey")) {
811 CONFIG_IS_DOUBLE(tmp->publickeys);
812 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
813 (void **)&tmp->publickeys, NULL)) {
814 got_errno = SILC_CONFIG_EPRINTLINE;
819 return SILC_CONFIG_EINTERNAL;
820 return SILC_CONFIG_OK;
823 silc_free(tmp->host);
824 silc_free(tmp->user);
825 silc_free(tmp->nick);
826 CONFIG_FREE_AUTH(tmp);
832 SILC_CONFIG_CALLBACK(fetch_deny)
834 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
836 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
837 type, name, context));
838 if (type == SILC_CONFIG_ARG_BLOCK) {
839 /* check the temporary struct's fields */
840 if (!tmp) /* discard empty sub-blocks */
841 return SILC_CONFIG_OK;
843 got_errno = SILC_CONFIG_EMISSFIELDS;
847 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
849 return SILC_CONFIG_OK;
851 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
853 /* Identify and save this value */
854 if (!strcmp(name, "host")) {
855 CONFIG_IS_DOUBLE(tmp->host);
856 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
858 else if (!strcmp(name, "reason")) {
859 CONFIG_IS_DOUBLE(tmp->reason);
860 tmp->reason = strdup((char *) val);
863 return SILC_CONFIG_EINTERNAL;
864 return SILC_CONFIG_OK;
867 silc_free(tmp->host);
868 silc_free(tmp->reason);
874 SILC_CONFIG_CALLBACK(fetch_server)
876 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
878 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
879 type, name, context));
880 if (type == SILC_CONFIG_ARG_BLOCK) {
881 /* check the temporary struct's fields */
882 if (!tmp) /* discard empty sub-blocks */
883 return SILC_CONFIG_OK;
885 /* the temporary struct is ok, append it to the list */
886 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
888 return SILC_CONFIG_OK;
890 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
892 /* Identify and save this value */
893 if (!strcmp(name, "host")) {
894 CONFIG_IS_DOUBLE(tmp->host);
895 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
897 else if (!strcmp(name, "passphrase")) {
898 CONFIG_IS_DOUBLE(tmp->passphrase);
899 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
900 (void **)&tmp->passphrase,
901 &tmp->passphrase_len)) {
902 got_errno = SILC_CONFIG_EPRINTLINE;
906 else if (!strcmp(name, "publickey")) {
907 CONFIG_IS_DOUBLE(tmp->publickeys);
908 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
909 (void **)&tmp->publickeys, NULL)) {
910 got_errno = SILC_CONFIG_EPRINTLINE;
914 else if (!strcmp(name, "params")) {
915 CONFIG_IS_DOUBLE(tmp->param);
916 tmp->param = my_find_param(config, (char *) val);
917 if (!tmp->param) { /* error message already output */
918 got_errno = SILC_CONFIG_EPRINTLINE;
922 else if (!strcmp(name, "backup")) {
923 tmp->backup_router = *(bool *)val;
926 return SILC_CONFIG_EINTERNAL;
928 return SILC_CONFIG_OK;
931 silc_free(tmp->host);
932 CONFIG_FREE_AUTH(tmp);
938 SILC_CONFIG_CALLBACK(fetch_router)
940 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
942 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
943 type, name, context));
944 if (type == SILC_CONFIG_ARG_BLOCK) {
945 if (!tmp) /* discard empty sub-blocks */
946 return SILC_CONFIG_OK;
948 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
950 return SILC_CONFIG_OK;
952 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
954 /* Identify and save this value */
955 if (!strcmp(name, "host")) {
956 CONFIG_IS_DOUBLE(tmp->host);
957 tmp->host = strdup((char *) val);
959 else if (!strcmp(name, "port")) {
960 int port = *(int *)val;
961 if ((port <= 0) || (port > 65535)) {
962 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
963 "Invalid port number!"));
964 got_errno = SILC_CONFIG_EPRINTLINE;
967 tmp->port = (SilcUInt16) port;
969 else if (!strcmp(name, "passphrase")) {
970 CONFIG_IS_DOUBLE(tmp->passphrase);
971 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
972 (void **)&tmp->passphrase,
973 &tmp->passphrase_len)) {
974 got_errno = SILC_CONFIG_EPRINTLINE;
978 else if (!strcmp(name, "publickey")) {
979 CONFIG_IS_DOUBLE(tmp->publickeys);
980 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
981 (void **)&tmp->publickeys, NULL)) {
982 got_errno = SILC_CONFIG_EPRINTLINE;
986 else if (!strcmp(name, "params")) {
987 CONFIG_IS_DOUBLE(tmp->param);
988 tmp->param = my_find_param(config, (char *) val);
989 if (!tmp->param) { /* error message already output */
990 got_errno = SILC_CONFIG_EPRINTLINE;
994 else if (!strcmp(name, "initiator")) {
995 tmp->initiator = *(bool *)val;
997 else if (!strcmp(name, "backuphost")) {
998 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
999 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1001 tmp->backup_router = TRUE;
1003 else if (!strcmp(name, "backupport")) {
1004 int port = *(int *)val;
1005 if ((port <= 0) || (port > 65535)) {
1006 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1007 "Invalid port number!"));
1008 got_errno = SILC_CONFIG_EPRINTLINE;
1011 tmp->backup_replace_port = (SilcUInt16) port;
1013 else if (!strcmp(name, "backuplocal")) {
1014 tmp->backup_local = *(bool *)val;
1017 return SILC_CONFIG_EINTERNAL;
1019 return SILC_CONFIG_OK;
1022 silc_free(tmp->host);
1023 silc_free(tmp->backup_replace_ip);
1024 CONFIG_FREE_AUTH(tmp);
1030 /* known config options tables */
1031 static const SilcConfigTable table_general[] = {
1032 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1033 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1034 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1035 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1036 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1037 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1038 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1039 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1040 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1041 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1042 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1043 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1044 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1045 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1046 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1047 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1048 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1049 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1050 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1051 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1052 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1053 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1054 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1055 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1056 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1060 static const SilcConfigTable table_cipher[] = {
1061 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1062 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1063 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1064 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1068 static const SilcConfigTable table_hash[] = {
1069 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1070 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1071 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1072 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1076 static const SilcConfigTable table_hmac[] = {
1077 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1078 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1079 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1083 static const SilcConfigTable table_pkcs[] = {
1084 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1088 static const SilcConfigTable table_serverinfo_c[] = {
1089 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1090 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1094 static const SilcConfigTable table_serverinfo[] = {
1095 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1096 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1097 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1098 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1099 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1100 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1101 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1102 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1103 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1104 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1105 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1106 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1107 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1111 static const SilcConfigTable table_logging_c[] = {
1112 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1113 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1114 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1118 static const SilcConfigTable table_logging[] = {
1119 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1120 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1121 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1122 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1123 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1124 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1125 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1129 static const SilcConfigTable table_connparam[] = {
1130 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1131 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1132 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1133 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1134 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1135 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1136 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1137 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1138 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1139 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1140 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1141 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1142 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1143 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1144 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1145 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1146 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1147 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1148 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1149 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1153 static const SilcConfigTable table_client[] = {
1154 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1155 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1156 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1157 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1161 static const SilcConfigTable table_admin[] = {
1162 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1163 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1164 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1165 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1166 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1167 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1168 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1172 static const SilcConfigTable table_deny[] = {
1173 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1174 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1178 static const SilcConfigTable table_serverconn[] = {
1179 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1180 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1181 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1182 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1183 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1187 static const SilcConfigTable table_routerconn[] = {
1188 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1189 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1190 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1191 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1192 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1193 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1194 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1195 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1196 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1200 static const SilcConfigTable table_main[] = {
1201 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1202 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1203 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1204 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1205 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1206 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1207 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1208 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1209 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1210 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1211 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1212 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1213 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1217 /* Set default values to stuff that was not configured. */
1219 static void silc_server_config_set_defaults(SilcServerConfig config)
1221 my_set_param_defaults(&config->param, NULL);
1223 config->channel_rekey_secs = (config->channel_rekey_secs ?
1224 config->channel_rekey_secs :
1225 SILC_SERVER_CHANNEL_REKEY);
1226 config->key_exchange_timeout = (config->key_exchange_timeout ?
1227 config->key_exchange_timeout :
1228 SILC_SERVER_SKE_TIMEOUT);
1229 config->conn_auth_timeout = (config->conn_auth_timeout ?
1230 config->conn_auth_timeout :
1231 SILC_SERVER_CONNAUTH_TIMEOUT);
1234 /* Allocates a new configuration object, opens configuration file and
1235 parses it. The parsed data is returned to the newly allocated
1236 configuration object. The SilcServerConfig must be freed by calling
1237 the silc_server_config_destroy function. */
1239 SilcServerConfig silc_server_config_alloc(const char *filename)
1241 SilcServerConfig config_new;
1242 SilcConfigEntity ent;
1243 SilcConfigFile *file;
1245 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1247 /* alloc a config object */
1248 config_new = silc_calloc(1, sizeof(*config_new));
1249 config_new->refcount = 1;
1253 /* general config defaults */
1254 config_new->logging_timestamp = TRUE;
1256 /* obtain a config file object */
1257 file = silc_config_open(filename);
1259 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1264 /* obtain a SilcConfig entity, we can use it to start the parsing */
1265 ent = silc_config_init(file);
1267 /* load the known configuration options, give our empty object as context */
1268 silc_config_register_table(ent, table_main, (void *) config_new);
1270 /* enter the main parsing loop. When this returns, we have the parsing
1271 * result and the object filled (or partially, in case of errors). */
1272 ret = silc_config_main(ent);
1273 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1274 silc_config_strerror(ret)));
1276 /* Check if the parser returned errors */
1278 /* handle this special error return which asks to quietly return */
1279 if (ret != SILC_CONFIG_ESILENT) {
1280 char *linebuf, *filename = silc_config_get_filename(file);
1281 SilcUInt32 line = silc_config_get_line(file);
1282 if (ret != SILC_CONFIG_EPRINTLINE)
1283 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1284 silc_config_strerror(ret)));
1285 linebuf = silc_config_read_line(file, line);
1286 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1290 silc_server_config_destroy(config_new);
1294 /* close (destroy) the file object */
1295 silc_config_close(file);
1297 /* If config_new is incomplete, abort the object and return NULL */
1298 if (!config_new->server_info) {
1299 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1301 silc_server_config_destroy(config_new);
1305 /* Set default to configuration parameters */
1306 silc_server_config_set_defaults(config_new);
1311 /* Increments the reference counter of a config object */
1313 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1318 ref->config = config;
1319 ref->ref_ptr = ref_ptr;
1320 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1321 config->refcount - 1, config->refcount));
1325 /* Decrements the reference counter of a config object. If the counter
1326 reaches 0, the config object is destroyed. */
1328 void silc_server_config_unref(SilcServerConfigRef *ref)
1331 silc_server_config_destroy(ref->config);
1334 /* Destroy a config object with all his children lists */
1336 void silc_server_config_destroy(SilcServerConfig config)
1341 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1342 config->refcount + 1, config->refcount));
1343 if (config->refcount > 0)
1346 SILC_LOG_DEBUG(("Freeing config context"));
1348 /* Destroy general config stuff */
1349 silc_free(config->module_path);
1350 silc_free(config->param.version_protocol);
1351 silc_free(config->param.version_software);
1352 silc_free(config->param.version_software_vendor);
1354 /* Destroy Logging channels */
1355 if (config->logging_info)
1356 silc_free(config->logging_info->file);
1357 if (config->logging_warnings)
1358 silc_free(config->logging_warnings->file);
1359 if (config->logging_errors)
1360 silc_free(config->logging_errors->file);
1361 if (config->logging_fatals)
1362 silc_free(config->logging_fatals->file);
1363 silc_free(config->logging_info);
1364 silc_free(config->logging_warnings);
1365 silc_free(config->logging_errors);
1366 silc_free(config->logging_fatals);
1368 /* Destroy the ServerInfo struct */
1369 if (config->server_info) {
1370 register SilcServerConfigServerInfo *si = config->server_info;
1371 silc_free(si->server_name);
1373 silc_free(si->primary->server_ip);
1374 silc_free(si->primary);
1376 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1378 silc_free(di->server_ip);
1381 silc_free(si->server_type);
1382 silc_free(si->location);
1383 silc_free(si->admin);
1384 silc_free(si->email);
1385 silc_free(si->user);
1386 silc_free(si->group);
1387 silc_free(si->motd_file);
1388 silc_free(si->pid_file);
1389 silc_pkcs_public_key_free(si->public_key);
1390 silc_pkcs_private_key_free(si->private_key);
1394 /* Now let's destroy the lists */
1396 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1398 silc_free(di->name);
1399 silc_free(di->module);
1402 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1403 silc_free(di->name);
1404 silc_free(di->module);
1407 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1408 silc_free(di->name);
1409 silc_free(di->hash);
1412 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1413 silc_free(di->name);
1416 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1417 config->conn_params)
1418 silc_free(di->name);
1419 silc_free(di->version_protocol);
1420 silc_free(di->version_software);
1421 silc_free(di->version_software_vendor);
1424 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1425 silc_free(di->host);
1426 CONFIG_FREE_AUTH(di);
1429 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1430 silc_free(di->host);
1431 silc_free(di->user);
1432 silc_free(di->nick);
1433 CONFIG_FREE_AUTH(di);
1436 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1437 silc_free(di->host);
1438 silc_free(di->reason);
1441 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1443 silc_free(di->host);
1444 CONFIG_FREE_AUTH(di);
1447 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1449 silc_free(di->host);
1450 silc_free(di->backup_replace_ip);
1451 CONFIG_FREE_AUTH(di);
1455 memset(config, 'F', sizeof(*config));
1459 /* Registers configured ciphers. These can then be allocated by the
1460 server when needed. */
1462 bool silc_server_config_register_ciphers(SilcServer server)
1464 SilcServerConfig config = server->config;
1465 SilcServerConfigCipher *cipher = config->cipher;
1466 char *module_path = config->module_path;
1468 SILC_LOG_DEBUG(("Registering configured ciphers"));
1470 if (!cipher) /* any cipher in the config file? */
1474 /* if there isn't a module_path OR there isn't a module sim name try to
1475 * use buil-in functions */
1476 if (!module_path || !cipher->module) {
1478 for (i = 0; silc_default_ciphers[i].name; i++)
1479 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1480 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1483 if (!silc_cipher_is_supported(cipher->name)) {
1484 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1485 silc_server_stop(server);
1490 /* Load (try at least) the crypto SIM module */
1491 char buf[1023], *alg_name;
1492 SilcCipherObject cipher_obj;
1495 memset(&cipher_obj, 0, sizeof(cipher_obj));
1496 cipher_obj.name = cipher->name;
1497 cipher_obj.block_len = cipher->block_length;
1498 cipher_obj.key_len = cipher->key_length * 8;
1500 /* build the libname */
1501 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1503 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1505 alg_name = strdup(cipher->name);
1506 if (strchr(alg_name, '-'))
1507 *strchr(alg_name, '-') = '\0';
1509 if (silc_sim_load(sim)) {
1510 cipher_obj.set_key =
1511 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1512 SILC_CIPHER_SIM_SET_KEY));
1513 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1514 cipher_obj.set_key_with_string =
1515 silc_sim_getsym(sim,
1516 silc_sim_symname(alg_name,
1517 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1518 SILC_LOG_DEBUG(("set_key_with_string=%p",
1519 cipher_obj.set_key_with_string));
1520 cipher_obj.encrypt =
1521 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1522 SILC_CIPHER_SIM_ENCRYPT_CBC));
1523 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1524 cipher_obj.decrypt =
1525 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1526 SILC_CIPHER_SIM_DECRYPT_CBC));
1527 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1528 cipher_obj.context_len =
1529 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1530 SILC_CIPHER_SIM_CONTEXT_LEN));
1531 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1533 /* Put the SIM to the list of all SIM's in server */
1534 silc_dlist_add(server->sim, sim);
1536 silc_free(alg_name);
1538 SILC_LOG_ERROR(("Error configuring ciphers"));
1539 silc_server_stop(server);
1543 /* Register the cipher */
1544 silc_cipher_register(&cipher_obj);
1546 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1547 "can't load modules!"));
1548 silc_server_stop(server);
1552 cipher = cipher->next;
1558 /* Registers configured hash functions. These can then be allocated by the
1559 server when needed. */
1561 bool silc_server_config_register_hashfuncs(SilcServer server)
1563 SilcServerConfig config = server->config;
1564 SilcServerConfigHash *hash = config->hash;
1565 char *module_path = config->module_path;
1567 SILC_LOG_DEBUG(("Registering configured hash functions"));
1569 if (!hash) /* any hash func in the config file? */
1573 /* if there isn't a module_path OR there isn't a module sim name try to
1574 * use buil-in functions */
1575 if (!module_path || !hash->module) {
1577 for (i = 0; silc_default_hash[i].name; i++)
1578 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1579 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1582 if (!silc_hash_is_supported(hash->name)) {
1583 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1584 silc_server_stop(server);
1589 /* Load (try at least) the hash SIM module */
1590 SilcHashObject hash_obj;
1593 memset(&hash_obj, 0, sizeof(hash_obj));
1594 hash_obj.name = hash->name;
1595 hash_obj.block_len = hash->block_length;
1596 hash_obj.hash_len = hash->digest_length;
1598 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1600 if ((silc_sim_load(sim))) {
1602 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1603 SILC_HASH_SIM_INIT));
1604 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1606 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1607 SILC_HASH_SIM_UPDATE));
1608 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1610 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1611 SILC_HASH_SIM_FINAL));
1612 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1613 hash_obj.context_len =
1614 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1615 SILC_HASH_SIM_CONTEXT_LEN));
1616 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1618 /* Put the SIM to the table of all SIM's in server */
1619 silc_dlist_add(server->sim, sim);
1621 SILC_LOG_ERROR(("Error configuring hash functions"));
1622 silc_server_stop(server);
1626 /* Register the hash function */
1627 silc_hash_register(&hash_obj);
1629 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1630 "can't load modules!"));
1631 silc_server_stop(server);
1641 /* Registers configure HMACs. These can then be allocated by the server
1644 bool silc_server_config_register_hmacs(SilcServer server)
1646 SilcServerConfig config = server->config;
1647 SilcServerConfigHmac *hmac = config->hmac;
1649 SILC_LOG_DEBUG(("Registering configured HMACs"));
1655 SilcHmacObject hmac_obj;
1656 if (!silc_hash_is_supported(hmac->hash)) {
1657 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1658 silc_server_stop(server);
1662 /* Register the HMAC */
1663 memset(&hmac_obj, 0, sizeof(hmac_obj));
1664 hmac_obj.name = hmac->name;
1665 hmac_obj.len = hmac->mac_length;
1666 silc_hmac_register(&hmac_obj);
1674 /* Registers configured PKCS's. */
1676 bool silc_server_config_register_pkcs(SilcServer server)
1678 SilcServerConfig config = server->config;
1679 SilcServerConfigPkcs *pkcs = config->pkcs;
1681 SILC_LOG_DEBUG(("Registering configured PKCS"));
1688 for (i = 0; silc_default_pkcs[i].name; i++)
1689 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1690 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1693 if (!silc_pkcs_is_supported(pkcs->name)) {
1694 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1695 silc_server_stop(server);
1704 /* Sets log files where log messages are saved by the server logger. */
1706 void silc_server_config_setlogfiles(SilcServer server)
1708 SilcServerConfig config = server->config;
1709 SilcServerConfigLogging *this;
1711 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1713 silc_log_timestamp = config->logging_timestamp;
1714 silc_log_quick = config->logging_quick;
1715 silc_log_flushdelay = (config->logging_flushdelay ?
1716 config->logging_flushdelay :
1717 SILC_SERVER_LOG_FLUSH_DELAY);
1719 if ((this = config->logging_fatals))
1720 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1722 if ((this = config->logging_errors))
1723 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1725 if ((this = config->logging_warnings))
1726 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1728 if ((this = config->logging_info))
1729 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1733 /* Returns client authentication information from configuration file by host
1736 SilcServerConfigClient *
1737 silc_server_config_find_client(SilcServer server, char *host)
1739 SilcServerConfig config = server->config;
1740 SilcServerConfigClient *client;
1742 if (!config || !host)
1745 for (client = config->clients; client; client = client->next) {
1746 if (client->host && !silc_string_compare(client->host, host))
1751 /* if none matched, then client is already NULL */
1755 /* Returns admin connection configuration by host, username and/or
1758 SilcServerConfigAdmin *
1759 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1762 SilcServerConfig config = server->config;
1763 SilcServerConfigAdmin *admin;
1765 /* make sure we have a value for the matching parameters */
1773 for (admin = config->admins; admin; admin = admin->next) {
1774 if (admin->host && !silc_string_compare(admin->host, host))
1776 if (admin->user && !silc_string_compare(admin->user, user))
1778 if (admin->nick && !silc_string_compare(admin->nick, nick))
1780 /* no checks failed -> this entry matches */
1784 /* if none matched, then admin is already NULL */
1788 /* Returns the denied connection configuration entry by host. */
1790 SilcServerConfigDeny *
1791 silc_server_config_find_denied(SilcServer server, char *host)
1793 SilcServerConfig config = server->config;
1794 SilcServerConfigDeny *deny;
1796 /* make sure we have a value for the matching parameters */
1797 if (!config || !host)
1800 for (deny = config->denied; deny; deny = deny->next) {
1801 if (deny->host && !silc_string_compare(deny->host, host))
1806 /* if none matched, then deny is already NULL */
1810 /* Returns server connection info from server configuartion by host
1813 SilcServerConfigServer *
1814 silc_server_config_find_server_conn(SilcServer server, char *host)
1816 SilcServerConfig config = server->config;
1817 SilcServerConfigServer *serv = NULL;
1822 if (!config->servers)
1825 for (serv = config->servers; serv; serv = serv->next) {
1826 if (!silc_string_compare(serv->host, host))
1834 /* Returns router connection info from server configuration by
1835 host (name or ip). */
1837 SilcServerConfigRouter *
1838 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1840 SilcServerConfig config = server->config;
1841 SilcServerConfigRouter *serv = NULL;
1846 if (!config->routers)
1849 for (serv = config->routers; serv; serv = serv->next) {
1850 if (!silc_string_compare(serv->host, host))
1852 if (port && serv->port && serv->port != port)
1860 /* Find backup router connection by host (name or ip) */
1862 SilcServerConfigRouter *
1863 silc_server_config_find_backup_conn(SilcServer server, char *host)
1865 SilcServerConfig config = server->config;
1866 SilcServerConfigRouter *serv = NULL;
1871 if (!config->routers)
1874 for (serv = config->routers; serv; serv = serv->next) {
1875 if (!serv->backup_router)
1877 if (!silc_string_compare(serv->host, host))
1885 /* Returns TRUE if configuration for a router connection that we are
1886 initiating exists. */
1888 bool silc_server_config_is_primary_route(SilcServer server)
1890 SilcServerConfig config = server->config;
1891 SilcServerConfigRouter *serv = NULL;
1895 serv = config->routers;
1896 for (i = 0; serv; i++) {
1897 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1908 /* Returns our primary connection configuration or NULL if we do not
1909 have primary router configured. */
1911 SilcServerConfigRouter *
1912 silc_server_config_get_primary_router(SilcServer server)
1914 SilcServerConfig config = server->config;
1915 SilcServerConfigRouter *serv = NULL;
1918 serv = config->routers;
1919 for (i = 0; serv; i++) {
1920 if (serv->initiator == TRUE && serv->backup_router == FALSE)
1928 /* If we have backup router configured that is going to replace us this
1929 function returns it. */
1931 SilcServerConfigRouter *
1932 silc_server_config_get_backup_router(SilcServer server)
1934 SilcServerConfig config = server->config;
1935 SilcServerConfigRouter *serv = NULL;
1938 if (server->server_type != SILC_ROUTER)
1941 serv = config->routers;
1942 for (i = 0; serv; i++) {
1943 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
1944 serv->backup_local == TRUE &&
1945 !strcmp(server->config->server_info->primary->server_ip,
1946 serv->backup_replace_ip) &&
1947 server->config->server_info->primary->port ==
1948 serv->backup_replace_port)