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"
27 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
29 #define SERVER_CONFIG_DEBUG(fmt)
32 /* auto-declare needed variables for the common list parsing */
33 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__) \
34 SilcServerConfig config = (SilcServerConfig) context; \
35 __type__ *findtmp, *tmp = (__type__ *) config->tmp; \
38 /* allocate the tmp field for fetching data */
39 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
41 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
42 tmp = (__type__ *) config->tmp; \
45 /* append the tmp field to the specified list */
46 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
50 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
51 findtmp->next = tmp; \
54 /* loops all elements in a list and provides a di struct pointer of the
55 * specified type containing the current element */
56 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
57 for (tmp = (void *) __list__; tmp;) { \
58 __type__ *di = (__type__ *) tmp; \
59 tmp = (void *) di->next;
61 /* Set EDOUBLE error value and bail out if necessary */
62 #define CONFIG_IS_DOUBLE(__x__) \
64 got_errno = SILC_CONFIG_EDOUBLE; \
68 /* Free the authentication fields in the specified struct
69 * Expands to two instructions */
70 #define CONFIG_FREE_AUTH(__section__) \
71 silc_free(__section__->passphrase); \
72 if (__section__->publickeys) \
73 silc_hash_table_free(__section__->publickeys);
75 static void my_free_public_key(void *key, void *context, void *user_data)
77 silc_pkcs_public_key_free(context);
80 /* Set default values to those parameters that have not been defined */
82 my_set_param_defaults(SilcServerConfigConnParams *params,
83 SilcServerConfigConnParams *defaults)
85 #define SET_PARAM_DEFAULT(p, d) params->p = \
86 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
88 SET_PARAM_DEFAULT(connections_max, SILC_SERVER_MAX_CONNECTIONS);
89 SET_PARAM_DEFAULT(connections_max_per_host,
90 SILC_SERVER_MAX_CONNECTIONS_SINGLE);
91 SET_PARAM_DEFAULT(keepalive_secs, SILC_SERVER_KEEPALIVE);
92 SET_PARAM_DEFAULT(reconnect_count, SILC_SERVER_RETRY_COUNT);
93 SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
94 SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
95 SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
96 SET_PARAM_DEFAULT(qos_rate_limit, SILC_SERVER_QOS_RATE_LIMIT);
97 SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
98 SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
99 SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
101 #undef SET_PARAM_DEFAULT
104 /* Find connection parameters by the parameter block name. */
105 static SilcServerConfigConnParams *
106 my_find_param(SilcServerConfig config, const char *name)
108 SilcServerConfigConnParams *param;
110 for (param = config->conn_params; param; param = param->next) {
111 if (!strcasecmp(param->name, name))
115 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
116 "Cannot find Params \"%s\".", name));
121 /* parse an authdata according to its auth method */
122 static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
123 void **auth_data, SilcUInt32 *auth_data_len)
125 if (auth_meth == SILC_AUTH_PASSWORD) {
126 /* p is a plain text password */
127 if (auth_data && auth_data_len) {
128 if (!silc_utf8_valid(p, strlen(p))) {
129 *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
130 SILC_STRING_LANGUAGE);
131 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
132 silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
135 *auth_data = (void *) strdup(p);
136 *auth_data_len = (SilcUInt32) strlen(p);
139 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
140 /* p is a public key file name */
141 SilcPublicKey public_key;
142 SilcPublicKey cached_key;
144 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
145 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
146 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
147 "Could not load public key file!"));
152 silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key,
153 NULL, silc_hash_public_key, NULL,
154 silc_hash_public_key_compare, NULL)) {
155 silc_pkcs_public_key_free(public_key);
156 SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
157 "configured, ignoring this key", p));
158 return TRUE; /* non fatal error */
161 /* The auth_data is a pointer to the hash table of public keys. */
163 if (*auth_data == NULL)
164 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
166 my_free_public_key, NULL,
168 silc_hash_table_add(*auth_data, public_key, public_key);
176 static bool my_parse_publickeydir(const char *dirname, void **auth_data)
179 struct dirent *get_file;
182 if (!(dp = opendir(dirname))) {
183 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
184 "Could not open directory \"%s\"", dirname));
188 /* errors are not considered fatal */
189 while ((get_file = readdir(dp))) {
190 const char *filename = get_file->d_name;
192 int dirname_len = strlen(dirname), filename_len = strlen(filename);
193 struct stat check_file;
195 /* Ignore "." and "..", and take files only with ".pub" suffix. */
196 if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
197 (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
200 memset(buf, 0, sizeof(buf));
201 snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
202 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
204 if (stat(buf, &check_file) < 0) {
205 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
207 } else if (S_ISREG(check_file.st_mode)) {
208 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
213 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
219 SILC_CONFIG_CALLBACK(fetch_generic)
221 SilcServerConfig config = (SilcServerConfig) context;
224 if (!strcmp(name, "module_path")) {
225 CONFIG_IS_DOUBLE(config->module_path);
226 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
228 else if (!strcmp(name, "prefer_passphrase_auth")) {
229 config->prefer_passphrase_auth = *(bool *)val;
231 else if (!strcmp(name, "require_reverse_lookup")) {
232 config->require_reverse_lookup = *(bool *)val;
234 else if (!strcmp(name, "connections_max")) {
235 config->param.connections_max = (SilcUInt32) *(int *)val;
237 else if (!strcmp(name, "connections_max_per_host")) {
238 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
240 else if (!strcmp(name, "keepalive_secs")) {
241 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
243 else if (!strcmp(name, "reconnect_count")) {
244 config->param.reconnect_count = (SilcUInt32) *(int *)val;
246 else if (!strcmp(name, "reconnect_interval")) {
247 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
249 else if (!strcmp(name, "reconnect_interval_max")) {
250 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
252 else if (!strcmp(name, "reconnect_keep_trying")) {
253 config->param.reconnect_keep_trying = *(bool *)val;
255 else if (!strcmp(name, "key_exchange_rekey")) {
256 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
258 else if (!strcmp(name, "key_exchange_pfs")) {
259 config->param.key_exchange_pfs = *(bool *)val;
261 else if (!strcmp(name, "channel_rekey_secs")) {
262 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
264 else if (!strcmp(name, "key_exchange_timeout")) {
265 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
267 else if (!strcmp(name, "conn_auth_timeout")) {
268 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
270 else if (!strcmp(name, "version_protocol")) {
271 CONFIG_IS_DOUBLE(config->param.version_protocol);
272 config->param.version_protocol =
273 (*(char *)val ? strdup((char *) val) : NULL);
275 else if (!strcmp(name, "version_software")) {
276 CONFIG_IS_DOUBLE(config->param.version_software);
277 config->param.version_software =
278 (*(char *)val ? strdup((char *) val) : NULL);
280 else if (!strcmp(name, "version_software_vendor")) {
281 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
282 config->param.version_software_vendor =
283 (*(char *)val ? strdup((char *) val) : NULL);
285 else if (!strcmp(name, "detach_disabled")) {
286 config->detach_disabled = *(bool *)val;
288 else if (!strcmp(name, "detach_timeout")) {
289 config->detach_timeout = (SilcUInt32) *(int *)val;
291 else if (!strcmp(name, "qos")) {
292 config->param.qos = *(bool *)val;
294 else if (!strcmp(name, "qos_rate_limit")) {
295 config->param.qos_rate_limit = *(SilcUInt32 *)val;
297 else if (!strcmp(name, "qos_bytes_limit")) {
298 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
300 else if (!strcmp(name, "qos_limit_sec")) {
301 config->param.qos_limit_sec = *(SilcUInt32 *)val;
303 else if (!strcmp(name, "qos_limit_usec")) {
304 config->param.qos_limit_usec = *(SilcUInt32 *)val;
307 return SILC_CONFIG_EINTERNAL;
309 return SILC_CONFIG_OK;
315 SILC_CONFIG_CALLBACK(fetch_cipher)
317 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
319 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
320 type, name, context));
321 if (type == SILC_CONFIG_ARG_BLOCK) {
322 /* check the temporary struct's fields */
323 if (!tmp) /* discard empty sub-blocks */
324 return SILC_CONFIG_OK;
326 got_errno = SILC_CONFIG_EMISSFIELDS;
330 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
332 return SILC_CONFIG_OK;
334 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
336 /* Identify and save this value */
337 if (!strcmp(name, "name")) {
338 CONFIG_IS_DOUBLE(tmp->name);
339 tmp->name = strdup((char *) val);
341 else if (!strcmp(name, "module")) {
342 CONFIG_IS_DOUBLE(tmp->module);
343 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
345 else if (!strcmp(name, "keylength")) {
346 tmp->key_length = *(SilcUInt32 *)val;
348 else if (!strcmp(name, "blocklength")) {
349 tmp->block_length = *(SilcUInt32 *)val;
352 return SILC_CONFIG_EINTERNAL;
353 return SILC_CONFIG_OK;
356 silc_free(tmp->name);
357 silc_free(tmp->module);
363 SILC_CONFIG_CALLBACK(fetch_hash)
365 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
367 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
368 type, name, context));
369 if (type == SILC_CONFIG_ARG_BLOCK) {
370 /* check the temporary struct's fields */
371 if (!tmp) /* discard empty sub-blocks */
372 return SILC_CONFIG_OK;
373 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
374 got_errno = SILC_CONFIG_EMISSFIELDS;
378 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
380 return SILC_CONFIG_OK;
382 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
384 /* Identify and save this value */
385 if (!strcmp(name, "name")) {
386 CONFIG_IS_DOUBLE(tmp->name);
387 tmp->name = strdup((char *) val);
389 else if (!strcmp(name, "module")) {
390 CONFIG_IS_DOUBLE(tmp->module);
391 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
393 else if (!strcmp(name, "blocklength")) {
394 tmp->block_length = *(int *)val;
396 else if (!strcmp(name, "digestlength")) {
397 tmp->digest_length = *(int *)val;
400 return SILC_CONFIG_EINTERNAL;
401 return SILC_CONFIG_OK;
404 silc_free(tmp->name);
405 silc_free(tmp->module);
411 SILC_CONFIG_CALLBACK(fetch_hmac)
413 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
415 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
416 type, name, context));
417 if (type == SILC_CONFIG_ARG_BLOCK) {
418 /* check the temporary struct's fields */
419 if (!tmp) /* discard empty sub-blocks */
420 return SILC_CONFIG_OK;
421 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
422 got_errno = SILC_CONFIG_EMISSFIELDS;
426 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
428 return SILC_CONFIG_OK;
430 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
432 /* Identify and save this value */
433 if (!strcmp(name, "name")) {
434 CONFIG_IS_DOUBLE(tmp->name);
435 tmp->name = strdup((char *) val);
437 else if (!strcmp(name, "hash")) {
438 CONFIG_IS_DOUBLE(tmp->hash);
439 tmp->hash = strdup((char *) val);
441 else if (!strcmp(name, "maclength")) {
442 tmp->mac_length = *(int *)val;
445 return SILC_CONFIG_EINTERNAL;
446 return SILC_CONFIG_OK;
449 silc_free(tmp->name);
450 silc_free(tmp->hash);
456 SILC_CONFIG_CALLBACK(fetch_pkcs)
458 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
460 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
461 type, name, context));
462 if (type == SILC_CONFIG_ARG_BLOCK) {
463 /* check the temporary struct's fields */
464 if (!tmp) /* discard empty sub-blocks */
465 return SILC_CONFIG_OK;
467 got_errno = SILC_CONFIG_EMISSFIELDS;
471 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
473 return SILC_CONFIG_OK;
475 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
477 /* Identify and save this value */
478 if (!strcmp(name, "name")) {
479 CONFIG_IS_DOUBLE(tmp->name);
480 tmp->name = strdup((char *) val);
483 return SILC_CONFIG_EINTERNAL;
484 return SILC_CONFIG_OK;
487 silc_free(tmp->name);
493 SILC_CONFIG_CALLBACK(fetch_serverinfo)
495 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
496 SilcServerConfigServerInfo *server_info = config->server_info;
498 /* if there isn't the struct alloc it */
500 config->server_info = server_info = (SilcServerConfigServerInfo *)
501 silc_calloc(1, sizeof(*server_info));
503 if (type == SILC_CONFIG_ARG_BLOCK) {
504 if (!strcmp(name, "primary")) {
505 CONFIG_IS_DOUBLE(server_info->primary);
507 return SILC_CONFIG_OK;
508 server_info->primary = tmp;
510 return SILC_CONFIG_OK;
511 } else if (!strcmp(name, "secondary")) {
513 return SILC_CONFIG_OK;
514 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
516 return SILC_CONFIG_OK;
517 } else if (!server_info->public_key || !server_info->private_key) {
518 got_errno = SILC_CONFIG_EMISSFIELDS;
521 return SILC_CONFIG_OK;
523 if (!strcmp(name, "hostname")) {
524 CONFIG_IS_DOUBLE(server_info->server_name);
525 server_info->server_name = strdup((char *) val);
527 else if (!strcmp(name, "ip")) {
528 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
529 CONFIG_IS_DOUBLE(tmp->server_ip);
530 tmp->server_ip = strdup((char *) val);
532 else if (!strcmp(name, "port")) {
533 int port = *(int *)val;
534 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
535 if ((port <= 0) || (port > 65535)) {
536 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
537 "Invalid port number!"));
538 got_errno = SILC_CONFIG_EPRINTLINE;
541 tmp->port = (SilcUInt16) port;
543 else if (!strcmp(name, "servertype")) {
544 CONFIG_IS_DOUBLE(server_info->server_type);
545 server_info->server_type = strdup((char *) val);
547 else if (!strcmp(name, "admin")) {
548 CONFIG_IS_DOUBLE(server_info->admin);
549 server_info->admin = strdup((char *) val);
551 else if (!strcmp(name, "adminemail")) {
552 CONFIG_IS_DOUBLE(server_info->email);
553 server_info->email = strdup((char *) val);
555 else if (!strcmp(name, "location")) {
556 CONFIG_IS_DOUBLE(server_info->location);
557 server_info->location = strdup((char *) val);
559 else if (!strcmp(name, "user")) {
560 CONFIG_IS_DOUBLE(server_info->user);
561 server_info->user = strdup((char *) val);
563 else if (!strcmp(name, "group")) {
564 CONFIG_IS_DOUBLE(server_info->group);
565 server_info->group = strdup((char *) val);
567 else if (!strcmp(name, "motdfile")) {
568 CONFIG_IS_DOUBLE(server_info->motd_file);
569 server_info->motd_file = strdup((char *) val);
571 else if (!strcmp(name, "pidfile")) {
572 CONFIG_IS_DOUBLE(server_info->pid_file);
573 server_info->pid_file = strdup((char *) val);
575 else if (!strcmp(name, "publickey")) {
576 char *file_tmp = (char *) val;
577 CONFIG_IS_DOUBLE(server_info->public_key);
579 /* try to load specified file, if fail stop config parsing */
580 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
582 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
583 SILC_PKCS_FILE_BIN)) {
584 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
585 return SILC_CONFIG_EPRINTLINE;
588 else if (!strcmp(name, "privatekey")) {
589 char *file_tmp = (char *) val;
590 CONFIG_IS_DOUBLE(server_info->private_key);
592 /* try to load specified file, if fail stop config parsing */
593 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
594 "", 0, SILC_PKCS_FILE_BIN))
595 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
596 "", 0, SILC_PKCS_FILE_PEM)) {
597 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
598 return SILC_CONFIG_EPRINTLINE;
602 return SILC_CONFIG_EINTERNAL;
603 return SILC_CONFIG_OK;
607 silc_free(config->tmp);
612 SILC_CONFIG_CALLBACK(fetch_logging)
614 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
616 if (!strcmp(name, "timestamp")) {
617 config->logging_timestamp = *(bool *)val;
619 else if (!strcmp(name, "quicklogs")) {
620 config->logging_quick = *(bool *)val;
622 else if (!strcmp(name, "flushdelay")) {
623 int flushdelay = *(int *)val;
624 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
625 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
626 "Invalid flushdelay value, use quicklogs if you "
627 "want real-time logging."));
628 return SILC_CONFIG_EPRINTLINE;
630 config->logging_flushdelay = (long) flushdelay;
633 /* The following istances happens only in Logging's sub-blocks, a match
634 for the sub-block name means that you should store the filename/maxsize
635 temporary struct to the proper logging channel.
636 If we get a match for "file" or "maxsize" this means that we are inside
637 a sub-sub-block and it is safe to alloc a new tmp. */
638 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
639 else if (!strcmp(name, __chan__)) { \
640 if (!tmp) return SILC_CONFIG_OK; \
642 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
644 config->__member__ = tmp; \
645 config->tmp = NULL; \
647 FETCH_LOGGING_CHAN("info", logging_info)
648 FETCH_LOGGING_CHAN("warnings", logging_warnings)
649 FETCH_LOGGING_CHAN("errors", logging_errors)
650 FETCH_LOGGING_CHAN("fatals", logging_fatals)
651 #undef FETCH_LOGGING_CHAN
652 else if (!strcmp(name, "file")) {
653 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
654 CONFIG_IS_DOUBLE(tmp->file);
655 tmp->file = strdup((char *) val);
657 else if (!strcmp(name, "size")) {
659 config->tmp = silc_calloc(1, sizeof(*tmp));
660 tmp = (SilcServerConfigLogging *) config->tmp;
662 tmp->maxsize = *(SilcUInt32 *) val;
665 return SILC_CONFIG_EINTERNAL;
666 return SILC_CONFIG_OK;
669 silc_free(tmp->file);
675 SILC_CONFIG_CALLBACK(fetch_connparam)
677 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
679 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
680 type, name, context));
681 if (type == SILC_CONFIG_ARG_BLOCK) {
682 /* check the temporary struct's fields */
683 if (!tmp) /* discard empty sub-blocks */
684 return SILC_CONFIG_OK;
686 got_errno = SILC_CONFIG_EMISSFIELDS;
690 my_set_param_defaults(tmp, &config->param);
692 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
694 return SILC_CONFIG_OK;
696 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
698 if (!strcmp(name, "name")) {
699 CONFIG_IS_DOUBLE(tmp->name);
700 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
702 else if (!strcmp(name, "connections_max")) {
703 tmp->connections_max = *(SilcUInt32 *)val;
705 else if (!strcmp(name, "connections_max_per_host")) {
706 tmp->connections_max_per_host = *(SilcUInt32 *)val;
708 else if (!strcmp(name, "keepalive_secs")) {
709 tmp->keepalive_secs = *(SilcUInt32 *)val;
711 else if (!strcmp(name, "reconnect_count")) {
712 tmp->reconnect_count = *(SilcUInt32 *)val;
714 else if (!strcmp(name, "reconnect_interval")) {
715 tmp->reconnect_interval = *(SilcUInt32 *)val;
717 else if (!strcmp(name, "reconnect_interval_max")) {
718 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
720 else if (!strcmp(name, "reconnect_keep_trying")) {
721 tmp->reconnect_keep_trying = *(bool *)val;
723 else if (!strcmp(name, "key_exchange_rekey")) {
724 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
726 else if (!strcmp(name, "key_exchange_pfs")) {
727 tmp->key_exchange_pfs = *(bool *)val;
729 else if (!strcmp(name, "version_protocol")) {
730 CONFIG_IS_DOUBLE(tmp->version_protocol);
731 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
733 else if (!strcmp(name, "version_software")) {
734 CONFIG_IS_DOUBLE(tmp->version_software);
735 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
737 else if (!strcmp(name, "version_software_vendor")) {
738 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
739 tmp->version_software_vendor =
740 (*(char *)val ? strdup((char *) val) : NULL);
742 else if (!strcmp(name, "anonymous")) {
743 tmp->anonymous = *(bool *)val;
745 else if (!strcmp(name, "qos")) {
746 tmp->qos = *(bool *)val;
748 else if (!strcmp(name, "qos_rate_limit")) {
749 tmp->qos_rate_limit = *(SilcUInt32 *)val;
751 else if (!strcmp(name, "qos_bytes_limit")) {
752 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
754 else if (!strcmp(name, "qos_limit_sec")) {
755 tmp->qos_limit_sec = *(SilcUInt32 *)val;
757 else if (!strcmp(name, "qos_limit_usec")) {
758 tmp->qos_limit_usec = *(SilcUInt32 *)val;
761 return SILC_CONFIG_EINTERNAL;
763 return SILC_CONFIG_OK;
766 silc_free(tmp->name);
772 SILC_CONFIG_CALLBACK(fetch_client)
774 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
776 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
777 type, name, context));
779 /* Alloc before block checking, because empty sub-blocks are welcome here */
780 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
782 if (type == SILC_CONFIG_ARG_BLOCK) {
783 /* empty sub-blocks are welcome */
784 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
786 return SILC_CONFIG_OK;
789 /* Identify and save this value */
790 if (!strcmp(name, "host")) {
791 CONFIG_IS_DOUBLE(tmp->host);
792 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
794 else if (!strcmp(name, "passphrase")) {
795 CONFIG_IS_DOUBLE(tmp->passphrase);
796 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
797 (void **)&tmp->passphrase,
798 &tmp->passphrase_len)) {
799 got_errno = SILC_CONFIG_EPRINTLINE;
803 else if (!strcmp(name, "publickey")) {
804 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
805 (void **)&tmp->publickeys, NULL)) {
806 got_errno = SILC_CONFIG_EPRINTLINE;
810 else if (!strcmp(name, "publickeydir")) {
811 if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
812 got_errno = SILC_CONFIG_EPRINTLINE;
816 else if (!strcmp(name, "params")) {
817 CONFIG_IS_DOUBLE(tmp->param);
818 tmp->param = my_find_param(config, (char *) val);
819 if (!tmp->param) { /* error message already output */
820 got_errno = SILC_CONFIG_EPRINTLINE;
825 return SILC_CONFIG_EINTERNAL;
826 return SILC_CONFIG_OK;
829 silc_free(tmp->host);
830 CONFIG_FREE_AUTH(tmp);
836 SILC_CONFIG_CALLBACK(fetch_admin)
838 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
840 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
841 type, name, context));
842 if (type == SILC_CONFIG_ARG_BLOCK) {
843 /* check the temporary struct's fields */
844 if (!tmp) /* discard empty sub-blocks */
845 return SILC_CONFIG_OK;
847 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
849 return SILC_CONFIG_OK;
851 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
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) : NULL);
858 else if (!strcmp(name, "user")) {
859 CONFIG_IS_DOUBLE(tmp->user);
860 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
862 else if (!strcmp(name, "nick")) {
863 CONFIG_IS_DOUBLE(tmp->nick);
864 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
866 else if (!strcmp(name, "passphrase")) {
867 CONFIG_IS_DOUBLE(tmp->passphrase);
868 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
869 (void **)&tmp->passphrase,
870 &tmp->passphrase_len)) {
871 got_errno = SILC_CONFIG_EPRINTLINE;
875 else if (!strcmp(name, "publickey")) {
876 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
877 (void **)&tmp->publickeys, NULL)) {
878 got_errno = SILC_CONFIG_EPRINTLINE;
882 else if (!strcmp(name, "publickeydir")) {
883 if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
884 got_errno = SILC_CONFIG_EPRINTLINE;
889 return SILC_CONFIG_EINTERNAL;
890 return SILC_CONFIG_OK;
893 silc_free(tmp->host);
894 silc_free(tmp->user);
895 silc_free(tmp->nick);
896 CONFIG_FREE_AUTH(tmp);
902 SILC_CONFIG_CALLBACK(fetch_deny)
904 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
906 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
907 type, name, context));
908 if (type == SILC_CONFIG_ARG_BLOCK) {
909 /* check the temporary struct's fields */
910 if (!tmp) /* discard empty sub-blocks */
911 return SILC_CONFIG_OK;
913 got_errno = SILC_CONFIG_EMISSFIELDS;
917 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
919 return SILC_CONFIG_OK;
921 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
923 /* Identify and save this value */
924 if (!strcmp(name, "host")) {
925 CONFIG_IS_DOUBLE(tmp->host);
926 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
928 else if (!strcmp(name, "reason")) {
929 CONFIG_IS_DOUBLE(tmp->reason);
930 tmp->reason = strdup((char *) val);
933 return SILC_CONFIG_EINTERNAL;
934 return SILC_CONFIG_OK;
937 silc_free(tmp->host);
938 silc_free(tmp->reason);
944 SILC_CONFIG_CALLBACK(fetch_server)
946 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
948 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
949 type, name, context));
950 if (type == SILC_CONFIG_ARG_BLOCK) {
951 /* check the temporary struct's fields */
952 if (!tmp) /* discard empty sub-blocks */
953 return SILC_CONFIG_OK;
955 /* the temporary struct is ok, append it to the list */
956 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
958 return SILC_CONFIG_OK;
960 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
962 /* Identify and save this value */
963 if (!strcmp(name, "host")) {
964 CONFIG_IS_DOUBLE(tmp->host);
965 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
967 else if (!strcmp(name, "passphrase")) {
968 CONFIG_IS_DOUBLE(tmp->passphrase);
969 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
970 (void **)&tmp->passphrase,
971 &tmp->passphrase_len)) {
972 got_errno = SILC_CONFIG_EPRINTLINE;
976 else if (!strcmp(name, "publickey")) {
977 CONFIG_IS_DOUBLE(tmp->publickeys);
978 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
979 (void **)&tmp->publickeys, NULL)) {
980 got_errno = SILC_CONFIG_EPRINTLINE;
984 else if (!strcmp(name, "params")) {
985 CONFIG_IS_DOUBLE(tmp->param);
986 tmp->param = my_find_param(config, (char *) val);
987 if (!tmp->param) { /* error message already output */
988 got_errno = SILC_CONFIG_EPRINTLINE;
992 else if (!strcmp(name, "backup")) {
993 tmp->backup_router = *(bool *)val;
996 return SILC_CONFIG_EINTERNAL;
998 return SILC_CONFIG_OK;
1001 silc_free(tmp->host);
1002 CONFIG_FREE_AUTH(tmp);
1008 SILC_CONFIG_CALLBACK(fetch_router)
1010 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1012 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1013 type, name, context));
1014 if (type == SILC_CONFIG_ARG_BLOCK) {
1015 if (!tmp) /* discard empty sub-blocks */
1016 return SILC_CONFIG_OK;
1018 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
1020 return SILC_CONFIG_OK;
1022 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigRouter);
1024 /* Identify and save this value */
1025 if (!strcmp(name, "host")) {
1026 CONFIG_IS_DOUBLE(tmp->host);
1027 tmp->host = strdup((char *) val);
1029 else if (!strcmp(name, "port")) {
1030 int port = *(int *)val;
1031 if ((port <= 0) || (port > 65535)) {
1032 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1033 "Invalid port number!"));
1034 got_errno = SILC_CONFIG_EPRINTLINE;
1037 tmp->port = (SilcUInt16) port;
1039 else if (!strcmp(name, "passphrase")) {
1040 CONFIG_IS_DOUBLE(tmp->passphrase);
1041 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1042 (void **)&tmp->passphrase,
1043 &tmp->passphrase_len)) {
1044 got_errno = SILC_CONFIG_EPRINTLINE;
1048 else if (!strcmp(name, "publickey")) {
1049 CONFIG_IS_DOUBLE(tmp->publickeys);
1050 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1051 (void **)&tmp->publickeys, NULL)) {
1052 got_errno = SILC_CONFIG_EPRINTLINE;
1056 else if (!strcmp(name, "params")) {
1057 CONFIG_IS_DOUBLE(tmp->param);
1058 tmp->param = my_find_param(config, (char *) val);
1059 if (!tmp->param) { /* error message already output */
1060 got_errno = SILC_CONFIG_EPRINTLINE;
1064 else if (!strcmp(name, "initiator")) {
1065 tmp->initiator = *(bool *)val;
1067 else if (!strcmp(name, "backuphost")) {
1068 CONFIG_IS_DOUBLE(tmp->backup_replace_ip);
1069 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) :
1071 tmp->backup_router = TRUE;
1073 else if (!strcmp(name, "backupport")) {
1074 int port = *(int *)val;
1075 if ((port <= 0) || (port > 65535)) {
1076 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
1077 "Invalid port number!"));
1078 got_errno = SILC_CONFIG_EPRINTLINE;
1081 tmp->backup_replace_port = (SilcUInt16) port;
1083 else if (!strcmp(name, "backuplocal")) {
1084 tmp->backup_local = *(bool *)val;
1087 return SILC_CONFIG_EINTERNAL;
1089 return SILC_CONFIG_OK;
1092 silc_free(tmp->host);
1093 silc_free(tmp->backup_replace_ip);
1094 CONFIG_FREE_AUTH(tmp);
1100 /* known config options tables */
1101 static const SilcConfigTable table_general[] = {
1102 { "module_path", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
1103 { "prefer_passphrase_auth", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1104 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1105 { "connections_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1106 { "connections_max_per_host", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1107 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1108 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1109 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1110 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1111 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1112 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1113 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1114 { "channel_rekey_secs", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1115 { "key_exchange_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1116 { "conn_auth_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1117 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1118 { "version_software", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1119 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
1120 { "detach_disabled", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1121 { "detach_timeout", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1122 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1123 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1124 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1125 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1126 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1130 static const SilcConfigTable table_cipher[] = {
1131 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
1132 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
1133 { "keylength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1134 { "blocklength", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
1138 static const SilcConfigTable table_hash[] = {
1139 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
1140 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
1141 { "blocklength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1142 { "digestlength", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
1146 static const SilcConfigTable table_hmac[] = {
1147 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1148 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
1149 { "maclength", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
1153 static const SilcConfigTable table_pkcs[] = {
1154 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
1158 static const SilcConfigTable table_serverinfo_c[] = {
1159 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1160 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
1164 static const SilcConfigTable table_serverinfo[] = {
1165 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1166 { "primary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1167 { "secondary", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo_c},
1168 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1169 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1170 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1171 { "adminemail", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1172 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1173 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1174 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1175 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
1176 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1177 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
1181 static const SilcConfigTable table_logging_c[] = {
1182 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
1183 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
1184 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
1188 static const SilcConfigTable table_logging[] = {
1189 { "timestamp", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1190 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
1191 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
1192 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1193 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1194 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1195 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
1199 static const SilcConfigTable table_connparam[] = {
1200 { "name", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1201 { "require_reverse_lookup", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1202 { "connections_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1203 { "connections_max_per_host",SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1204 { "keepalive_secs", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1205 { "reconnect_count", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1206 { "reconnect_interval", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1207 { "reconnect_interval_max", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1208 { "reconnect_keep_trying", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1209 { "key_exchange_rekey", SILC_CONFIG_ARG_INT, fetch_connparam, NULL },
1210 { "key_exchange_pfs", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1211 { "version_protocol", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1212 { "version_software", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1213 { "version_software_vendor", SILC_CONFIG_ARG_STR, fetch_connparam, NULL },
1214 { "anonymous", SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
1215 { "qos", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
1216 { "qos_rate_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1217 { "qos_bytes_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1218 { "qos_limit_sec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1219 { "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
1223 static const SilcConfigTable table_client[] = {
1224 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
1225 { "passphrase", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1226 { "publickey", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1227 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1228 { "params", SILC_CONFIG_ARG_STR, fetch_client, NULL },
1232 static const SilcConfigTable table_admin[] = {
1233 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1234 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1235 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
1236 { "passphrase", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1237 { "publickey", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1238 { "publickeydir", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1239 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
1240 { "params", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
1244 static const SilcConfigTable table_deny[] = {
1245 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
1246 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
1250 static const SilcConfigTable table_serverconn[] = {
1251 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
1252 { "passphrase", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1253 { "publickey", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1254 { "params", SILC_CONFIG_ARG_STR, fetch_server, NULL },
1255 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
1259 static const SilcConfigTable table_routerconn[] = {
1260 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1261 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1262 { "passphrase", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1263 { "publickey", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1264 { "params", SILC_CONFIG_ARG_STR, fetch_router, NULL },
1265 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1266 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
1267 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
1268 { "backuplocal", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
1272 static const SilcConfigTable table_main[] = {
1273 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
1274 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
1275 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
1276 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
1277 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
1278 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
1279 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
1280 { "connectionparams", SILC_CONFIG_ARG_BLOCK, fetch_connparam, table_connparam },
1281 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
1282 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
1283 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
1284 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
1285 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
1289 /* Set default values to stuff that was not configured. */
1291 static void silc_server_config_set_defaults(SilcServerConfig config)
1293 my_set_param_defaults(&config->param, NULL);
1295 config->channel_rekey_secs = (config->channel_rekey_secs ?
1296 config->channel_rekey_secs :
1297 SILC_SERVER_CHANNEL_REKEY);
1298 config->key_exchange_timeout = (config->key_exchange_timeout ?
1299 config->key_exchange_timeout :
1300 SILC_SERVER_SKE_TIMEOUT);
1301 config->conn_auth_timeout = (config->conn_auth_timeout ?
1302 config->conn_auth_timeout :
1303 SILC_SERVER_CONNAUTH_TIMEOUT);
1306 /* Allocates a new configuration object, opens configuration file and
1307 parses it. The parsed data is returned to the newly allocated
1308 configuration object. The SilcServerConfig must be freed by calling
1309 the silc_server_config_destroy function. */
1311 SilcServerConfig silc_server_config_alloc(const char *filename)
1313 SilcServerConfig config_new;
1314 SilcConfigEntity ent;
1315 SilcConfigFile *file;
1317 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
1319 /* alloc a config object */
1320 config_new = silc_calloc(1, sizeof(*config_new));
1324 /* general config defaults */
1325 config_new->refcount = 1;
1326 config_new->logging_timestamp = TRUE;
1328 /* obtain a config file object */
1329 file = silc_config_open(filename);
1331 SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'",
1336 /* obtain a SilcConfig entity, we can use it to start the parsing */
1337 ent = silc_config_init(file);
1339 /* load the known configuration options, give our empty object as context */
1340 silc_config_register_table(ent, table_main, (void *) config_new);
1342 /* enter the main parsing loop. When this returns, we have the parsing
1343 * result and the object filled (or partially, in case of errors). */
1344 ret = silc_config_main(ent);
1345 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
1346 silc_config_strerror(ret)));
1348 /* Check if the parser returned errors */
1350 /* handle this special error return which asks to quietly return */
1351 if (ret != SILC_CONFIG_ESILENT) {
1352 char *linebuf, *filename = silc_config_get_filename(file);
1353 SilcUInt32 line = silc_config_get_line(file);
1354 if (ret != SILC_CONFIG_EPRINTLINE)
1355 SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.",
1356 silc_config_strerror(ret)));
1357 linebuf = silc_config_read_line(file, line);
1358 SILC_SERVER_LOG_ERROR((" file %s line %lu: %s\n", filename,
1362 silc_server_config_destroy(config_new);
1366 /* close (destroy) the file object */
1367 silc_config_close(file);
1369 /* If config_new is incomplete, abort the object and return NULL */
1370 if (!config_new->server_info) {
1371 SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
1373 silc_server_config_destroy(config_new);
1377 /* Set default to configuration parameters */
1378 silc_server_config_set_defaults(config_new);
1383 /* Increments the reference counter of a config object */
1385 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
1390 ref->config = config;
1391 ref->ref_ptr = ref_ptr;
1392 SILC_LOG_DEBUG(("Referencing config [%p] refcnt %d->%d", config,
1393 config->refcount - 1, config->refcount));
1397 /* Decrements the reference counter of a config object. If the counter
1398 reaches 0, the config object is destroyed. */
1400 void silc_server_config_unref(SilcServerConfigRef *ref)
1403 silc_server_config_destroy(ref->config);
1406 /* Destroy a config object with all his children lists */
1408 void silc_server_config_destroy(SilcServerConfig config)
1413 SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %d->%d", config,
1414 config->refcount + 1, config->refcount));
1415 if (config->refcount > 0)
1418 SILC_LOG_DEBUG(("Freeing config context"));
1420 /* Destroy general config stuff */
1421 silc_free(config->module_path);
1422 silc_free(config->param.version_protocol);
1423 silc_free(config->param.version_software);
1424 silc_free(config->param.version_software_vendor);
1426 /* Destroy Logging channels */
1427 if (config->logging_info)
1428 silc_free(config->logging_info->file);
1429 if (config->logging_warnings)
1430 silc_free(config->logging_warnings->file);
1431 if (config->logging_errors)
1432 silc_free(config->logging_errors->file);
1433 if (config->logging_fatals)
1434 silc_free(config->logging_fatals->file);
1435 silc_free(config->logging_info);
1436 silc_free(config->logging_warnings);
1437 silc_free(config->logging_errors);
1438 silc_free(config->logging_fatals);
1440 /* Destroy the ServerInfo struct */
1441 if (config->server_info) {
1442 register SilcServerConfigServerInfo *si = config->server_info;
1443 silc_free(si->server_name);
1445 silc_free(si->primary->server_ip);
1446 silc_free(si->primary);
1448 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServerInfoInterface,
1450 silc_free(di->server_ip);
1453 silc_free(si->server_type);
1454 silc_free(si->location);
1455 silc_free(si->admin);
1456 silc_free(si->email);
1457 silc_free(si->user);
1458 silc_free(si->group);
1459 silc_free(si->motd_file);
1460 silc_free(si->pid_file);
1461 silc_pkcs_public_key_free(si->public_key);
1462 silc_pkcs_private_key_free(si->private_key);
1466 /* Now let's destroy the lists */
1468 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigCipher,
1470 silc_free(di->name);
1471 silc_free(di->module);
1474 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHash, config->hash)
1475 silc_free(di->name);
1476 silc_free(di->module);
1479 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigHmac, config->hmac)
1480 silc_free(di->name);
1481 silc_free(di->hash);
1484 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigPkcs, config->pkcs)
1485 silc_free(di->name);
1488 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigConnParams,
1489 config->conn_params)
1490 silc_free(di->name);
1491 silc_free(di->version_protocol);
1492 silc_free(di->version_software);
1493 silc_free(di->version_software_vendor);
1496 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigClient, config->clients)
1497 silc_free(di->host);
1498 CONFIG_FREE_AUTH(di);
1501 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigAdmin, config->admins)
1502 silc_free(di->host);
1503 silc_free(di->user);
1504 silc_free(di->nick);
1505 CONFIG_FREE_AUTH(di);
1508 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigDeny, config->denied)
1509 silc_free(di->host);
1510 silc_free(di->reason);
1513 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigServer,
1515 silc_free(di->host);
1516 CONFIG_FREE_AUTH(di);
1519 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigRouter,
1521 silc_free(di->host);
1522 silc_free(di->backup_replace_ip);
1523 CONFIG_FREE_AUTH(di);
1527 memset(config, 'F', sizeof(*config));
1531 /* Registers configured ciphers. These can then be allocated by the
1532 server when needed. */
1534 bool silc_server_config_register_ciphers(SilcServer server)
1536 SilcServerConfig config = server->config;
1537 SilcServerConfigCipher *cipher = config->cipher;
1538 char *module_path = config->module_path;
1540 SILC_LOG_DEBUG(("Registering configured ciphers"));
1542 if (!cipher) /* any cipher in the config file? */
1546 /* if there isn't a module_path OR there isn't a module sim name try to
1547 * use buil-in functions */
1548 if (!module_path || !cipher->module) {
1550 for (i = 0; silc_default_ciphers[i].name; i++)
1551 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1552 silc_cipher_register((SilcCipherObject *)&silc_default_ciphers[i]);
1555 if (!silc_cipher_is_supported(cipher->name)) {
1556 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1557 silc_server_stop(server);
1562 /* Load (try at least) the crypto SIM module */
1563 char buf[1023], *alg_name;
1564 SilcCipherObject cipher_obj;
1567 memset(&cipher_obj, 0, sizeof(cipher_obj));
1568 cipher_obj.name = cipher->name;
1569 cipher_obj.block_len = cipher->block_length;
1570 cipher_obj.key_len = cipher->key_length * 8;
1572 /* build the libname */
1573 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1575 sim = silc_sim_alloc(SILC_SIM_CIPHER, buf, 0);
1577 alg_name = strdup(cipher->name);
1578 if (strchr(alg_name, '-'))
1579 *strchr(alg_name, '-') = '\0';
1581 if (silc_sim_load(sim)) {
1582 cipher_obj.set_key =
1583 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1584 SILC_CIPHER_SIM_SET_KEY));
1585 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1586 cipher_obj.set_key_with_string =
1587 silc_sim_getsym(sim,
1588 silc_sim_symname(alg_name,
1589 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1590 SILC_LOG_DEBUG(("set_key_with_string=%p",
1591 cipher_obj.set_key_with_string));
1592 cipher_obj.encrypt =
1593 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1594 SILC_CIPHER_SIM_ENCRYPT_CBC));
1595 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1596 cipher_obj.decrypt =
1597 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1598 SILC_CIPHER_SIM_DECRYPT_CBC));
1599 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1600 cipher_obj.context_len =
1601 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1602 SILC_CIPHER_SIM_CONTEXT_LEN));
1603 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1605 /* Put the SIM to the list of all SIM's in server */
1606 silc_dlist_add(server->sim, sim);
1608 silc_free(alg_name);
1610 SILC_LOG_ERROR(("Error configuring ciphers"));
1612 silc_server_stop(server);
1616 /* Register the cipher */
1617 silc_cipher_register(&cipher_obj);
1619 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1620 "can't load modules!"));
1621 silc_server_stop(server);
1625 cipher = cipher->next;
1631 /* Registers configured hash functions. These can then be allocated by the
1632 server when needed. */
1634 bool silc_server_config_register_hashfuncs(SilcServer server)
1636 SilcServerConfig config = server->config;
1637 SilcServerConfigHash *hash = config->hash;
1638 char *module_path = config->module_path;
1640 SILC_LOG_DEBUG(("Registering configured hash functions"));
1642 if (!hash) /* any hash func in the config file? */
1646 /* if there isn't a module_path OR there isn't a module sim name try to
1647 * use buil-in functions */
1648 if (!module_path || !hash->module) {
1650 for (i = 0; silc_default_hash[i].name; i++)
1651 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1652 silc_hash_register((SilcHashObject *)&silc_default_hash[i]);
1655 if (!silc_hash_is_supported(hash->name)) {
1656 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1657 silc_server_stop(server);
1662 /* Load (try at least) the hash SIM module */
1663 SilcHashObject hash_obj;
1666 memset(&hash_obj, 0, sizeof(hash_obj));
1667 hash_obj.name = hash->name;
1668 hash_obj.block_len = hash->block_length;
1669 hash_obj.hash_len = hash->digest_length;
1671 sim = silc_sim_alloc(SILC_SIM_HASH, hash->module, 0);
1673 if ((silc_sim_load(sim))) {
1675 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1676 SILC_HASH_SIM_INIT));
1677 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1679 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1680 SILC_HASH_SIM_UPDATE));
1681 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1683 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1684 SILC_HASH_SIM_FINAL));
1685 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1686 hash_obj.context_len =
1687 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1688 SILC_HASH_SIM_CONTEXT_LEN));
1689 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1691 /* Put the SIM to the table of all SIM's in server */
1692 silc_dlist_add(server->sim, sim);
1694 SILC_LOG_ERROR(("Error configuring hash functions"));
1696 silc_server_stop(server);
1700 /* Register the hash function */
1701 silc_hash_register(&hash_obj);
1703 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1704 "can't load modules!"));
1705 silc_server_stop(server);
1715 /* Registers configure HMACs. These can then be allocated by the server
1718 bool silc_server_config_register_hmacs(SilcServer server)
1720 SilcServerConfig config = server->config;
1721 SilcServerConfigHmac *hmac = config->hmac;
1723 SILC_LOG_DEBUG(("Registering configured HMACs"));
1729 SilcHmacObject hmac_obj;
1730 if (!silc_hash_is_supported(hmac->hash)) {
1731 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1732 silc_server_stop(server);
1736 /* Register the HMAC */
1737 memset(&hmac_obj, 0, sizeof(hmac_obj));
1738 hmac_obj.name = hmac->name;
1739 hmac_obj.len = hmac->mac_length;
1740 silc_hmac_register(&hmac_obj);
1748 /* Registers configured PKCS's. */
1750 bool silc_server_config_register_pkcs(SilcServer server)
1752 SilcServerConfig config = server->config;
1753 SilcServerConfigPkcs *pkcs = config->pkcs;
1755 SILC_LOG_DEBUG(("Registering configured PKCS"));
1762 for (i = 0; silc_default_pkcs[i].name; i++)
1763 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1764 silc_pkcs_register((SilcPKCSObject *)&silc_default_pkcs[i]);
1767 if (!silc_pkcs_is_supported(pkcs->name)) {
1768 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1769 silc_server_stop(server);
1778 /* Sets log files where log messages are saved by the server logger. */
1780 void silc_server_config_setlogfiles(SilcServer server)
1782 SilcServerConfig config = server->config;
1783 SilcServerConfigLogging *this;
1785 SILC_LOG_DEBUG(("Setting configured log file names and options"));
1787 silc_log_timestamp = config->logging_timestamp;
1788 silc_log_quick = config->logging_quick;
1789 silc_log_flushdelay = (config->logging_flushdelay ?
1790 config->logging_flushdelay :
1791 SILC_SERVER_LOG_FLUSH_DELAY);
1793 if ((this = config->logging_fatals))
1794 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
1796 if ((this = config->logging_errors))
1797 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
1799 if ((this = config->logging_warnings))
1800 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
1802 if ((this = config->logging_info))
1803 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
1807 /* Returns client authentication information from configuration file by host
1810 SilcServerConfigClient *
1811 silc_server_config_find_client(SilcServer server, char *host)
1813 SilcServerConfig config = server->config;
1814 SilcServerConfigClient *client;
1816 if (!config || !host)
1819 for (client = config->clients; client; client = client->next) {
1820 if (client->host && !silc_string_compare(client->host, host))
1825 /* if none matched, then client is already NULL */
1829 /* Returns admin connection configuration by host, username and/or
1832 SilcServerConfigAdmin *
1833 silc_server_config_find_admin(SilcServer server, char *host, char *user,
1836 SilcServerConfig config = server->config;
1837 SilcServerConfigAdmin *admin;
1839 /* make sure we have a value for the matching parameters */
1847 for (admin = config->admins; admin; admin = admin->next) {
1848 if (admin->host && !silc_string_compare(admin->host, host))
1850 if (admin->user && !silc_string_compare(admin->user, user))
1852 if (admin->nick && !silc_string_compare(admin->nick, nick))
1854 /* no checks failed -> this entry matches */
1858 /* if none matched, then admin is already NULL */
1862 /* Returns the denied connection configuration entry by host. */
1864 SilcServerConfigDeny *
1865 silc_server_config_find_denied(SilcServer server, char *host)
1867 SilcServerConfig config = server->config;
1868 SilcServerConfigDeny *deny;
1870 /* make sure we have a value for the matching parameters */
1871 if (!config || !host)
1874 for (deny = config->denied; deny; deny = deny->next) {
1875 if (deny->host && !silc_string_compare(deny->host, host))
1880 /* if none matched, then deny is already NULL */
1884 /* Returns server connection info from server configuartion by host
1887 SilcServerConfigServer *
1888 silc_server_config_find_server_conn(SilcServer server, char *host)
1890 SilcServerConfig config = server->config;
1891 SilcServerConfigServer *serv = NULL;
1896 if (!config->servers)
1899 for (serv = config->servers; serv; serv = serv->next) {
1900 if (!silc_string_compare(serv->host, host))
1908 /* Returns router connection info from server configuration by
1909 host (name or ip). */
1911 SilcServerConfigRouter *
1912 silc_server_config_find_router_conn(SilcServer server, char *host, int port)
1914 SilcServerConfig config = server->config;
1915 SilcServerConfigRouter *serv = NULL;
1920 if (!config->routers)
1923 for (serv = config->routers; serv; serv = serv->next) {
1924 if (!silc_string_compare(serv->host, host))
1926 if (port && serv->port && serv->port != port)
1934 /* Find backup router connection by host (name or ip) */
1936 SilcServerConfigRouter *
1937 silc_server_config_find_backup_conn(SilcServer server, char *host)
1939 SilcServerConfig config = server->config;
1940 SilcServerConfigRouter *serv = NULL;
1945 if (!config->routers)
1948 for (serv = config->routers; serv; serv = serv->next) {
1949 if (!serv->backup_router)
1951 if (!silc_string_compare(serv->host, host))
1959 /* Returns TRUE if configuration for a router connection that we are
1960 initiating exists. */
1962 bool silc_server_config_is_primary_route(SilcServer server)
1964 SilcServerConfig config = server->config;
1965 SilcServerConfigRouter *serv = NULL;
1969 serv = config->routers;
1970 for (i = 0; serv; i++) {
1971 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1982 /* Returns our primary connection configuration or NULL if we do not
1983 have primary router configured. */
1985 SilcServerConfigRouter *
1986 silc_server_config_get_primary_router(SilcServer server)
1988 SilcServerConfig config = server->config;
1989 SilcServerConfigRouter *serv = NULL;
1992 serv = config->routers;
1993 for (i = 0; serv; i++) {
1994 if (serv->initiator == TRUE && serv->backup_router == FALSE)
2002 /* If we have backup router configured that is going to replace us this
2003 function returns it. */
2005 SilcServerConfigRouter *
2006 silc_server_config_get_backup_router(SilcServer server)
2008 SilcServerConfig config = server->config;
2009 SilcServerConfigRouter *serv = NULL;
2012 if (server->server_type != SILC_ROUTER)
2015 serv = config->routers;
2016 for (i = 0; serv; i++) {
2017 if (serv->initiator == FALSE && serv->backup_router == TRUE &&
2018 serv->backup_local == TRUE &&
2019 !strcmp(server->config->server_info->primary->server_ip,
2020 serv->backup_replace_ip) &&
2021 server->config->server_info->primary->port ==
2022 serv->backup_replace_port)