1 /*
2
3 serverconfig.c
4
5 Author: Giovanni Giacobbi <giovanni@giacobbi.net>
6
7 Copyright (C) 1997 - 2004 Pekka Riikonen
8
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.
13
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.
18
19 */
20 /* $Id: serverconfig.c,v 1.73 2005/04/23 13:32:25 priikone Exp $ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include <dirent.h>
25
26 #if 0
27 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
28 #else
29 #define SERVER_CONFIG_DEBUG(fmt)
30 #endif
31
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; \
36 int got_errno = 0
37
38 /* allocate the tmp field for fetching data */
39 #define SILC_SERVER_CONFIG_ALLOCTMP(__type__) \
40 if (!tmp) { \
41 config->tmp = silc_calloc(1, sizeof(*findtmp)); \
42 tmp = (__type__ *) config->tmp; \
43 }
44
45 /* append the tmp field to the specified list */
46 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
47 if (!__list__) { \
48 __list__ = tmp; \
49 } else { \
50 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
51 findtmp->next = tmp; \
52 }
53
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;
60
61 /* Set EDOUBLE error value and bail out if necessary */
62 #define CONFIG_IS_DOUBLE(__x__) \
63 if ((__x__)) { \
64 got_errno = SILC_CONFIG_EDOUBLE; \
65 goto got_err; \
66 }
67
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);
74
75 static void my_free_public_key(void *key, void *context, void *user_data)
76 {
77 silc_pkcs_public_key_free(context);
78 }
79
80 /* Set default values to those parameters that have not been defined */
81 static void
82 my_set_param_defaults(SilcServerConfigConnParams *params,
83 SilcServerConfigConnParams *defaults)
84 {
85 #define SET_PARAM_DEFAULT(p, d) params->p = \
86 (params->p ? params->p : (defaults && defaults->p ? defaults->p : d))
87
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);
100
101 #undef SET_PARAM_DEFAULT
102 }
103
104 /* Find connection parameters by the parameter block name. */
105 static SilcServerConfigConnParams *
106 my_find_param(SilcServerConfig config, const char *name)
107 {
108 SilcServerConfigConnParams *param;
109
110 for (param = config->conn_params; param; param = param->next) {
111 if (!strcasecmp(param->name, name))
112 return param;
113 }
114
115 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
116 "Cannot find Params \"%s\".", name));
117
118 return NULL;
119 }
120
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)
124 {
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_LOCALE);
131 *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
132 silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
133 *auth_data_len);
134 } else {
135 *auth_data = (void *) strdup(p);
136 *auth_data_len = (SilcUInt32) strlen(p);
137 }
138 }
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;
143
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!"));
148 return FALSE;
149 }
150
151 if (*auth_data &&
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 */
159 }
160
161 /* The auth_data is a pointer to the hash table of public keys. */
162 if (auth_data) {
163 if (*auth_data == NULL)
164 *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
165 NULL, NULL,
166 my_free_public_key, NULL,
167 TRUE);
168 SILC_LOG_DEBUG(("Adding public key '%s' to authentication cache",
169 public_key->identifier));
170 silc_hash_table_add(*auth_data, public_key, public_key);
171 }
172 } else
173 abort();
174
175 return TRUE;
176 }
177
178 static bool my_parse_publickeydir(const char *dirname, void **auth_data)
179 {
180 int total = 0;
181 struct dirent *get_file;
182 DIR *dp;
183
184 if (!(dp = opendir(dirname))) {
185 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
186 "Could not open directory \"%s\"", dirname));
187 return FALSE;
188 }
189
190 /* errors are not considered fatal */
191 while ((get_file = readdir(dp))) {
192 const char *filename = get_file->d_name;
193 char buf[1024];
194 int dirname_len = strlen(dirname), filename_len = strlen(filename);
195 struct stat check_file;
196
197 /* Ignore "." and "..", and take files only with ".pub" suffix. */
198 if (!strcmp(filename, ".") || !strcmp(filename, "..") ||
199 (filename_len < 5) || strcmp(filename + filename_len - 4, ".pub"))
200 continue;
201
202 memset(buf, 0, sizeof(buf));
203 snprintf(buf, sizeof(buf) - 1, "%s%s%s", dirname,
204 (dirname[dirname_len - 1] == '/' ? "" : "/"), filename);
205
206 if (stat(buf, &check_file) < 0) {
207 SILC_SERVER_LOG_ERROR(("Error stating file %s: %s", buf,
208 strerror(errno)));
209 } else if (S_ISREG(check_file.st_mode)) {
210 my_parse_authdata(SILC_AUTH_PUBLIC_KEY, buf, auth_data, NULL);
211 total++;
212 }
213 }
214
215 SILC_LOG_DEBUG(("Tried to load %d public keys in \"%s\"", total, dirname));
216 return TRUE;
217 }
218
219 /* Callbacks */
220
221 SILC_CONFIG_CALLBACK(fetch_generic)
222 {
223 SilcServerConfig config = (SilcServerConfig) context;
224 int got_errno = 0;
225
226 if (!strcmp(name, "module_path")) {
227 CONFIG_IS_DOUBLE(config->module_path);
228 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
229 }
230 else if (!strcmp(name, "prefer_passphrase_auth")) {
231 config->prefer_passphrase_auth = *(bool *)val;
232 }
233 else if (!strcmp(name, "require_reverse_lookup")) {
234 config->require_reverse_lookup = *(bool *)val;
235 }
236 else if (!strcmp(name, "connections_max")) {
237 config->param.connections_max = (SilcUInt32) *(int *)val;
238 }
239 else if (!strcmp(name, "connections_max_per_host")) {
240 config->param.connections_max_per_host = (SilcUInt32) *(int *)val;
241 }
242 else if (!strcmp(name, "keepalive_secs")) {
243 config->param.keepalive_secs = (SilcUInt32) *(int *)val;
244 }
245 else if (!strcmp(name, "reconnect_count")) {
246 config->param.reconnect_count = (SilcUInt32) *(int *)val;
247 }
248 else if (!strcmp(name, "reconnect_interval")) {
249 config->param.reconnect_interval = (SilcUInt32) *(int *)val;
250 }
251 else if (!strcmp(name, "reconnect_interval_max")) {
252 config->param.reconnect_interval_max = (SilcUInt32) *(int *)val;
253 }
254 else if (!strcmp(name, "reconnect_keep_trying")) {
255 config->param.reconnect_keep_trying = *(bool *)val;
256 }
257 else if (!strcmp(name, "key_exchange_rekey")) {
258 config->param.key_exchange_rekey = (SilcUInt32) *(int *)val;
259 }
260 else if (!strcmp(name, "key_exchange_pfs")) {
261 config->param.key_exchange_pfs = *(bool *)val;
262 }
263 else if (!strcmp(name, "channel_rekey_secs")) {
264 config->channel_rekey_secs = (SilcUInt32) *(int *)val;
265 }
266 else if (!strcmp(name, "key_exchange_timeout")) {
267 config->key_exchange_timeout = (SilcUInt32) *(int *)val;
268 }
269 else if (!strcmp(name, "conn_auth_timeout")) {
270 config->conn_auth_timeout = (SilcUInt32) *(int *)val;
271 }
272 else if (!strcmp(name, "version_protocol")) {
273 CONFIG_IS_DOUBLE(config->param.version_protocol);
274 config->param.version_protocol =
275 (*(char *)val ? strdup((char *) val) : NULL);
276 }
277 else if (!strcmp(name, "version_software")) {
278 CONFIG_IS_DOUBLE(config->param.version_software);
279 config->param.version_software =
280 (*(char *)val ? strdup((char *) val) : NULL);
281 }
282 else if (!strcmp(name, "version_software_vendor")) {
283 CONFIG_IS_DOUBLE(config->param.version_software_vendor);;
284 config->param.version_software_vendor =
285 (*(char *)val ? strdup((char *) val) : NULL);
286 }
287 else if (!strcmp(name, "detach_disabled")) {
288 config->detach_disabled = *(bool *)val;
289 }
290 else if (!strcmp(name, "detach_timeout")) {
291 config->detach_timeout = (SilcUInt32) *(int *)val;
292 }
293 else if (!strcmp(name, "qos")) {
294 config->param.qos = *(bool *)val;
295 }
296 else if (!strcmp(name, "qos_rate_limit")) {
297 config->param.qos_rate_limit = *(SilcUInt32 *)val;
298 }
299 else if (!strcmp(name, "qos_bytes_limit")) {
300 config->param.qos_bytes_limit = *(SilcUInt32 *)val;
301 }
302 else if (!strcmp(name, "qos_limit_sec")) {
303 config->param.qos_limit_sec = *(SilcUInt32 *)val;
304 }
305 else if (!strcmp(name, "qos_limit_usec")) {
306 config->param.qos_limit_usec = *(SilcUInt32 *)val;
307 }
308 else if (!strcmp(name, "debug_string")) {
309 CONFIG_IS_DOUBLE(config->debug_string);
310 config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
311 }
312 else
313 return SILC_CONFIG_EINTERNAL;
314
315 return SILC_CONFIG_OK;
316
317 got_err:
318 return got_errno;
319 }
320
321 SILC_CONFIG_CALLBACK(fetch_cipher)
322 {
323 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigCipher);
324
325 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)",
326 type, name, context));
327 if (type == SILC_CONFIG_ARG_BLOCK) {
328 /* check the temporary struct's fields */
329 if (!tmp) /* discard empty sub-blocks */
330 return SILC_CONFIG_OK;
331 if (!tmp->name) {
332 got_errno = SILC_CONFIG_EMISSFIELDS;
333 goto got_err;
334 }
335
336 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
337 config->tmp = NULL;
338 return SILC_CONFIG_OK;
339 }
340 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigCipher);
341
342 /* Identify and save this value */
343 if (!strcmp(name, "name")) {
344 CONFIG_IS_DOUBLE(tmp->name);
345 tmp->name = strdup((char *) val);
346 }
347 else if (!strcmp(name, "module")) {
348 CONFIG_IS_DOUBLE(tmp->module);
349 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
350 }
351 else if (!strcmp(name, "keylength")) {
352 tmp->key_length = *(SilcUInt32 *)val;
353 }
354 else if (!strcmp(name, "blocklength")) {
355 tmp->block_length = *(SilcUInt32 *)val;
356 }
357 else
358 return SILC_CONFIG_EINTERNAL;
359 return SILC_CONFIG_OK;
360
361 got_err:
362 silc_free(tmp->name);
363 silc_free(tmp->module);
364 silc_free(tmp);
365 config->tmp = NULL;
366 return got_errno;
367 }
368
369 SILC_CONFIG_CALLBACK(fetch_hash)
370 {
371 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHash);
372
373 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)",
374 type, name, context));
375 if (type == SILC_CONFIG_ARG_BLOCK) {
376 /* check the temporary struct's fields */
377 if (!tmp) /* discard empty sub-blocks */
378 return SILC_CONFIG_OK;
379 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
380 got_errno = SILC_CONFIG_EMISSFIELDS;
381 goto got_err;
382 }
383
384 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
385 config->tmp = NULL;
386 return SILC_CONFIG_OK;
387 }
388 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHash);
389
390 /* Identify and save this value */
391 if (!strcmp(name, "name")) {
392 CONFIG_IS_DOUBLE(tmp->name);
393 tmp->name = strdup((char *) val);
394 }
395 else if (!strcmp(name, "module")) {
396 CONFIG_IS_DOUBLE(tmp->module);
397 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
398 }
399 else if (!strcmp(name, "blocklength")) {
400 tmp->block_length = *(int *)val;
401 }
402 else if (!strcmp(name, "digestlength")) {
403 tmp->digest_length = *(int *)val;
404 }
405 else
406 return SILC_CONFIG_EINTERNAL;
407 return SILC_CONFIG_OK;
408
409 got_err:
410 silc_free(tmp->name);
411 silc_free(tmp->module);
412 silc_free(tmp);
413 config->tmp = NULL;
414 return got_errno;
415 }
416
417 SILC_CONFIG_CALLBACK(fetch_hmac)
418 {
419 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigHmac);
420
421 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)",
422 type, name, context));
423 if (type == SILC_CONFIG_ARG_BLOCK) {
424 /* check the temporary struct's fields */
425 if (!tmp) /* discard empty sub-blocks */
426 return SILC_CONFIG_OK;
427 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
428 got_errno = SILC_CONFIG_EMISSFIELDS;
429 goto got_err;
430 }
431
432 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
433 config->tmp = NULL;
434 return SILC_CONFIG_OK;
435 }
436 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigHmac);
437
438 /* Identify and save this value */
439 if (!strcmp(name, "name")) {
440 CONFIG_IS_DOUBLE(tmp->name);
441 tmp->name = strdup((char *) val);
442 }
443 else if (!strcmp(name, "hash")) {
444 CONFIG_IS_DOUBLE(tmp->hash);
445 tmp->hash = strdup((char *) val);
446 }
447 else if (!strcmp(name, "maclength")) {
448 tmp->mac_length = *(int *)val;
449 }
450 else
451 return SILC_CONFIG_EINTERNAL;
452 return SILC_CONFIG_OK;
453
454 got_err:
455 silc_free(tmp->name);
456 silc_free(tmp->hash);
457 silc_free(tmp);
458 config->tmp = NULL;
459 return got_errno;
460 }
461
462 SILC_CONFIG_CALLBACK(fetch_pkcs)
463 {
464 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
465
466 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
467 type, name, context));
468 if (type == SILC_CONFIG_ARG_BLOCK) {
469 /* Check the temporary struct's fields */
470 if (!tmp) /* discard empty sub-blocks */
471 return SILC_CONFIG_OK;
472 if (!tmp->name) {
473 got_errno = SILC_CONFIG_EMISSFIELDS;
474 goto got_err;
475 }
476
477 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
478 config->tmp = NULL;
479 return SILC_CONFIG_OK;
480 }
481 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigPkcs);
482
483 /* Identify and save this value */
484 if (!strcmp(name, "name")) {
485 CONFIG_IS_DOUBLE(tmp->name);
486 tmp->name = strdup((char *) val);
487 }
488 else
489 return SILC_CONFIG_EINTERNAL;
490 return SILC_CONFIG_OK;
491
492 got_err:
493 silc_free(tmp->name);
494 silc_free(tmp);
495 config->tmp = NULL;
496 return got_errno;
497 }
498
499 SILC_CONFIG_CALLBACK(fetch_serverinfo)
500 {
501 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
502 SilcServerConfigServerInfo *server_info = config->server_info;
503
504 SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
505 type, name, context));
506
507 /* If there isn't the main struct alloc it */
508 if (!server_info)
509 config->server_info = server_info = (SilcServerConfigServerInfo *)
510 silc_calloc(1, sizeof(*server_info));
511
512 if (type == SILC_CONFIG_ARG_BLOCK) {
513 if (!strcmp(name, "primary")) {
514 if (server_info->primary) {
515 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
516 "Double primary specification."));
517 got_errno = SILC_CONFIG_EPRINTLINE;
518 goto got_err;
519 }
520 CONFIG_IS_DOUBLE(server_info->primary);
521
522 /* now check the temporary struct, don't accept empty block and
523 make sure all fields are there */
524 if (!tmp || !tmp->server_ip || !tmp->port) {
525 got_errno = SILC_CONFIG_EMISSFIELDS;
526 goto got_err;
527 }
528 server_info->primary = tmp;
529 config->tmp = NULL;
530 return SILC_CONFIG_OK;
531 } else if (!strcmp(name, "secondary")) {
532 if (!tmp)
533 return SILC_CONFIG_OK;
534 if (!tmp || !tmp->server_ip || !tmp->port) {
535 got_errno = SILC_CONFIG_EMISSFIELDS;
536 goto got_err;
537 }
538 SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
539 config->tmp = NULL;
540 return SILC_CONFIG_OK;
541 } else if (!server_info->public_key || !server_info->private_key) {
542 got_errno = SILC_CONFIG_EMISSFIELDS;
543 goto got_err;
544 }
545 return SILC_CONFIG_OK;
546 }
547 if (!strcmp(name, "hostname")) {
548 CONFIG_IS_DOUBLE(server_info->server_name);
549 server_info->server_name = strdup((char *) val);
550 }
551 else if (!strcmp(name, "ip")) {
552 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
553 CONFIG_IS_DOUBLE(tmp->server_ip);
554 tmp->server_ip = strdup((char *) val);
555 }
556 else if (!strcmp(name, "port")) {
557 int port = *(int *)val;
558 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServerInfoInterface);
559 if ((port <= 0) || (port > 65535)) {
560 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
561 "Invalid port number!"));
562 got_errno = SILC_CONFIG_EPRINTLINE;
563 goto got_err;
564 }
565 tmp->port = (SilcUInt16) port;
566 }
567 else if (!strcmp(name, "servertype")) {
568 CONFIG_IS_DOUBLE(server_info->server_type);
569 server_info->server_type = strdup((char *) val);
570 }
571 else if (!strcmp(name, "admin")) {
572 CONFIG_IS_DOUBLE(server_info->admin);
573 server_info->admin = strdup((char *) val);
574 }
575 else if (!strcmp(name, "adminemail")) {
576 CONFIG_IS_DOUBLE(server_info->email);
577 server_info->email = strdup((char *) val);
578 }
579 else if (!strcmp(name, "location")) {
580 CONFIG_IS_DOUBLE(server_info->location);
581 server_info->location = strdup((char *) val);
582 }
583 else if (!strcmp(name, "user")) {
584 CONFIG_IS_DOUBLE(server_info->user);
585 server_info->user = strdup((char *) val);
586 }
587 else if (!strcmp(name, "group")) {
588 CONFIG_IS_DOUBLE(server_info->group);
589 server_info->group = strdup((char *) val);
590 }
591 else if (!strcmp(name, "motdfile")) {
592 CONFIG_IS_DOUBLE(server_info->motd_file);
593 server_info->motd_file = strdup((char *) val);
594 }
595 else if (!strcmp(name, "pidfile")) {
596 CONFIG_IS_DOUBLE(server_info->pid_file);
597 server_info->pid_file = strdup((char *) val);
598 }
599 else if (!strcmp(name, "publickey")) {
600 char *file_tmp = (char *) val;
601 CONFIG_IS_DOUBLE(server_info->public_key);
602
603 /* Try to load specified file, if fail stop config parsing */
604 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
605 SILC_PKCS_FILE_PEM))
606 if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
607 SILC_PKCS_FILE_BIN)) {
608 SILC_SERVER_LOG_ERROR(("Error: Could not load public key file."));
609 return SILC_CONFIG_EPRINTLINE;
610 }
611 }
612 else if (!strcmp(name, "privatekey")) {
613 struct stat st;
614 char *file_tmp = (char *) val;
615 CONFIG_IS_DOUBLE(server_info->private_key);
616
617 /* Check the private key file permissions. */
618 if ((stat(file_tmp, &st)) != -1) {
619 if ((st.st_mode & 0777) != 0600) {
620 SILC_SERVER_LOG_ERROR(("Wrong permissions in private key "
621 "file \"%s\". The permissions must be "
622 "0600.", file_tmp));
623 return SILC_CONFIG_ESILENT;
624 }
625 }
626
627 /* Try to load specified file, if fail stop config parsing */
628 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
629 "", 0, SILC_PKCS_FILE_BIN))
630 if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
631 "", 0, SILC_PKCS_FILE_PEM)) {
632 SILC_SERVER_LOG_ERROR(("Error: Could not load private key file."));
633 return SILC_CONFIG_EPRINTLINE;
634 }
635 }
636 else
637 return SILC_CONFIG_EINTERNAL;
638 return SILC_CONFIG_OK;
639
640 got_err:
641 /* Here we need to check if tmp exists because this function handles
642 * misc data (multiple fields and single-only fields) */
643 if (tmp) {
644 silc_free(tmp->server_ip);
645 silc_free(tmp);
646 config->tmp = NULL;
647 }
648 return got_errno;
649 }
650
651 SILC_CONFIG_CALLBACK(fetch_logging)
652 {
653 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigLogging);
654
655 if (!strcmp(name, "timestamp")) {
656 config->logging_timestamp = *(bool *)val;
657 }
658 else if (!strcmp(name, "quicklogs")) {
659 config->logging_quick = *(bool *)val;
660 }
661 else if (!strcmp(name, "flushdelay")) {
662 int flushdelay = *(int *)val;
663 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
664 SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
665 "Invalid flushdelay value, use quicklogs if you "
666 "want real-time logging."));
667 return SILC_CONFIG_EPRINTLINE;
668 }
669 config->logging_flushdelay = (long) flushdelay;
670 }
671
672 /* The following istances happens only in Logging's sub-blocks, a match
673 for the sub-block name means that you should store the filename/maxsize
674 temporary struct to the proper logging channel.
675 If we get a match for "file" or "maxsize" this means that we are inside
676 a sub-sub-block and it is safe to alloc a new tmp. */
677 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
678 else if (!strcmp(name, __chan__)) { \
679 if (!tmp) return SILC_CONFIG_OK; \
680 if (!tmp->file) { \
681 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
682 } \
683 config->__member__ = tmp; \
684 config->tmp = NULL; \
685 }
686 FETCH_LOGGING_CHAN("info", logging_info)
687 FETCH_LOGGING_CHAN("warnings", logging_warnings)
688 FETCH_LOGGING_CHAN("errors", logging_errors)
689 FETCH_LOGGING_CHAN("fatals", logging_fatals)
690 #undef FETCH_LOGGING_CHAN
691 else if (!strcmp(name, "file")) {
692 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigLogging);
693 CONFIG_IS_DOUBLE(tmp->file);
694 tmp->file = strdup((char *) val);
695 }
696 else if (!strcmp(name, "size")) {
697 if (!tmp) {
698 config->tmp = silc_calloc(1, sizeof(*tmp));
699 tmp = (SilcServerConfigLogging *) config->tmp;
700 }
701 tmp->maxsize = *(SilcUInt32 *) val;
702 }
703 else
704 return SILC_CONFIG_EINTERNAL;
705 return SILC_CONFIG_OK;
706
707 got_err:
708 silc_free(tmp->file);
709 silc_free(tmp);
710 config->tmp = NULL;
711 return got_errno;
712 }
713
714 SILC_CONFIG_CALLBACK(fetch_connparam)
715 {
716 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigConnParams);
717
718 SERVER_CONFIG_DEBUG(("Received CONNPARAM type=%d name=\"%s\" (val=%x)",
719 type, name, context));
720 if (type == SILC_CONFIG_ARG_BLOCK) {
721 /* check the temporary struct's fields */
722 if (!tmp) /* discard empty sub-blocks */
723 return SILC_CONFIG_OK;
724 if (!tmp->name) {
725 got_errno = SILC_CONFIG_EMISSFIELDS;
726 goto got_err;
727 }
728 /* Set defaults */
729 my_set_param_defaults(tmp, &config->param);
730
731 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->conn_params);
732 config->tmp = NULL;
733 return SILC_CONFIG_OK;
734 }
735 if (!tmp) {
736 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
737 tmp->reconnect_keep_trying = TRUE;
738 }
739
740 if (!strcmp(name, "name")) {
741 CONFIG_IS_DOUBLE(tmp->name);
742 tmp->name = (*(char *)val ? strdup((char *) val) : NULL);
743 }
744 else if (!strcmp(name, "connections_max")) {
745 tmp->connections_max = *(SilcUInt32 *)val;
746 }
747 else if (!strcmp(name, "connections_max_per_host")) {
748 tmp->connections_max_per_host = *(SilcUInt32 *)val;
749 }
750 else if (!strcmp(name, "keepalive_secs")) {
751 tmp->keepalive_secs = *(SilcUInt32 *)val;
752 }
753 else if (!strcmp(name, "reconnect_count")) {
754 tmp->reconnect_count = *(SilcUInt32 *)val;
755 }
756 else if (!strcmp(name, "reconnect_interval")) {
757 tmp->reconnect_interval = *(SilcUInt32 *)val;
758 }
759 else if (!strcmp(name, "reconnect_interval_max")) {
760 tmp->reconnect_interval_max = *(SilcUInt32 *)val;
761 }
762 else if (!strcmp(name, "reconnect_keep_trying")) {
763 tmp->reconnect_keep_trying = *(bool *)val;
764 }
765 else if (!strcmp(name, "key_exchange_rekey")) {
766 tmp->key_exchange_rekey = *(SilcUInt32 *)val;
767 }
768 else if (!strcmp(name, "key_exchange_pfs")) {
769 tmp->key_exchange_pfs = *(bool *)val;
770 }
771 else if (!strcmp(name, "version_protocol")) {
772 CONFIG_IS_DOUBLE(tmp->version_protocol);
773 tmp->version_protocol = (*(char *)val ? strdup((char *) val) : NULL);
774 }
775 else if (!strcmp(name, "version_software")) {
776 CONFIG_IS_DOUBLE(tmp->version_software);
777 tmp->version_software = (*(char *)val ? strdup((char *) val) : NULL);
778 }
779 else if (!strcmp(name, "version_software_vendor")) {
780 CONFIG_IS_DOUBLE(tmp->version_software_vendor);;
781 tmp->version_software_vendor =
782 (*(char *)val ? strdup((char *) val) : NULL);
783 }
784 else if (!strcmp(name, "anonymous")) {
785 tmp->anonymous = *(bool *)val;
786 }
787 else if (!strcmp(name, "qos")) {
788 tmp->qos = *(bool *)val;
789 }
790 else if (!strcmp(name, "qos_rate_limit")) {
791 tmp->qos_rate_limit = *(SilcUInt32 *)val;
792 }
793 else if (!strcmp(name, "qos_bytes_limit")) {
794 tmp->qos_bytes_limit = *(SilcUInt32 *)val;
795 }
796 else if (!strcmp(name, "qos_limit_sec")) {
797 tmp->qos_limit_sec = *(SilcUInt32 *)val;
798 }
799 else if (!strcmp(name, "qos_limit_usec")) {
800 tmp->qos_limit_usec = *(SilcUInt32 *)val;
801 }
802 else
803 return SILC_CONFIG_EINTERNAL;
804
805 return SILC_CONFIG_OK;
806
807 got_err:
808 silc_free(tmp->name);
809 silc_free(tmp);
810 config->tmp = NULL;
811 return got_errno;
812 }
813
814 SILC_CONFIG_CALLBACK(fetch_client)
815 {
816 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigClient);
817
818 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
819 type, name, context));
820
821 /* Alloc before block checking, because empty sub-blocks are welcome here */
822 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigClient);
823
824 if (type == SILC_CONFIG_ARG_BLOCK) {
825 /* empty sub-blocks are welcome */
826 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
827 config->tmp = NULL;
828 return SILC_CONFIG_OK;
829 }
830
831 /* Identify and save this value */
832 if (!strcmp(name, "host")) {
833 CONFIG_IS_DOUBLE(tmp->host);
834 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
835 }
836 else if (!strcmp(name, "passphrase")) {
837 CONFIG_IS_DOUBLE(tmp->passphrase);
838 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
839 (void *)&tmp->passphrase,
840 &tmp->passphrase_len)) {
841 got_errno = SILC_CONFIG_EPRINTLINE;
842 goto got_err;
843 }
844 }
845 else if (!strcmp(name, "publickey")) {
846 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
847 (void *)&tmp->publickeys, NULL)) {
848 got_errno = SILC_CONFIG_EPRINTLINE;
849 goto got_err;
850 }
851 }
852 else if (!strcmp(name, "publickeydir")) {
853 if (!my_parse_publickeydir((char *) val, (void *)&tmp->publickeys)) {
854 got_errno = SILC_CONFIG_EPRINTLINE;
855 goto got_err;
856 }
857 }
858 else if (!strcmp(name, "params")) {
859 CONFIG_IS_DOUBLE(tmp->param);
860 tmp->param = my_find_param(config, (char *) val);
861 if (!tmp->param) { /* error message already output */
862 got_errno = SILC_CONFIG_EPRINTLINE;
863 goto got_err;
864 }
865 }
866 else
867 return SILC_CONFIG_EINTERNAL;
868 return SILC_CONFIG_OK;
869
870 got_err:
871 silc_free(tmp->host);
872 CONFIG_FREE_AUTH(tmp);
873 silc_free(tmp);
874 config->tmp = NULL;
875 return got_errno;
876 }
877
878 SILC_CONFIG_CALLBACK(fetch_admin)
879 {
880 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigAdmin);
881
882 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)",
883 type, name, context));
884 if (type == SILC_CONFIG_ARG_BLOCK) {
885 /* check the temporary struct's fields */
886 if (!tmp) /* discard empty sub-blocks */
887 return SILC_CONFIG_OK;
888
889 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
890 config->tmp = NULL;
891 return SILC_CONFIG_OK;
892 }
893 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigAdmin);
894
895 /* Identify and save this value */
896 if (!strcmp(name, "host")) {
897 CONFIG_IS_DOUBLE(tmp->host);
898 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
899 }
900 else if (!strcmp(name, "user")) {
901 CONFIG_IS_DOUBLE(tmp->user);
902 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
903 }
904 else if (!strcmp(name, "nick")) {
905 CONFIG_IS_DOUBLE(tmp->nick);
906 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
907 }
908 else if (!strcmp(name, "passphrase")) {
909 CONFIG_IS_DOUBLE(tmp->passphrase);
910 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
911 (void *)&tmp->passphrase,
912 &tmp->passphrase_len)) {
913 got_errno = SILC_CONFIG_EPRINTLINE;
914 goto got_err;
915 }
916 }
917 else if (!strcmp(name, "publickey")) {
918 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
919 (void *)&tmp->publickeys, NULL)) {
920 got_errno = SILC_CONFIG_EPRINTLINE;
921 goto got_err;
922 }
923 }
924 else
925 return SILC_CONFIG_EINTERNAL;
926 return SILC_CONFIG_OK;
927
928 got_err:
929 silc_free(tmp->host);
930 silc_free(tmp->user);
931 silc_free(tmp->nick);
932 CONFIG_FREE_AUTH(tmp);
933 silc_free(tmp);
934 config->tmp = NULL;
935 return got_errno;
936 }
937
938 SILC_CONFIG_CALLBACK(fetch_deny)
939 {
940 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigDeny);
941
942 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)",
943 type, name, context));
944 if (type == SILC_CONFIG_ARG_BLOCK) {
945 /* check the temporary struct's fields */
946 if (!tmp) /* discard empty sub-blocks */
947 return SILC_CONFIG_OK;
948 if (!tmp->reason) {
949 got_errno = SILC_CONFIG_EMISSFIELDS;
950 goto got_err;
951 }
952
953 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
954 config->tmp = NULL;
955 return SILC_CONFIG_OK;
956 }
957 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigDeny);
958
959 /* Identify and save this value */
960 if (!strcmp(name, "host")) {
961 CONFIG_IS_DOUBLE(tmp->host);
962 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
963 }
964 else if (!strcmp(name, "reason")) {
965 CONFIG_IS_DOUBLE(tmp->reason);
966 tmp->reason = strdup((char *) val);
967 }
968 else
969 return SILC_CONFIG_EINTERNAL;
970 return SILC_CONFIG_OK;
971
972 got_err:
973 silc_free(tmp->host);
974 silc_free(tmp->reason);
975 silc_free(tmp);
976 config->tmp = NULL;
977 return got_errno;
978 }
979
980 SILC_CONFIG_CALLBACK(fetch_server)
981 {
982 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServer);
983
984 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)",
985 type, name, context));
986 if (type == SILC_CONFIG_ARG_BLOCK) {
987 /* check the temporary struct's fields */
988 if (!tmp) /* discard empty sub-blocks */
989 return SILC_CONFIG_OK;
990 if (!tmp->host) {
991 got_errno = SILC_CONFIG_EMISSFIELDS;
992 goto got_err;
993 }
994
995 /* the temporary struct is ok, append it to the list */
996 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
997 config->tmp = NULL;
998 return SILC_CONFIG_OK;
999 }
1000 SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigServer);
1001
1002 /* Identify and save this value */
1003 if (!strcmp(name, "host")) {
1004 CONFIG_IS_DOUBLE(tmp->host);
1005 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
1006 }
1007 else if (!strcmp(name, "passphrase")) {
1008 CONFIG_IS_DOUBLE(tmp->passphrase);
1009 if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
1010 (void *)&tmp->passphrase,
1011 &tmp->passphrase_len)) {
1012 got_errno = SILC_CONFIG_EPRINTLINE;
1013 goto got_err;
1014 }
1015 }
1016 else if (!strcmp(name, "publickey")) {
1017 CONFIG_IS_DOUBLE(tmp->publickeys);
1018 if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
1019 (void *)&tmp->publickeys, NULL)) {
1020 got_errno = SILC_CONFIG_EPRINTLINE;
1021 goto got_err;
1022 }
1023 }
1024 else if (!strcmp(name, "params")) {
1025 CONFIG_IS_DOUBLE(tmp->param);
1026 tmp->param = my_find_param(config, (char *) val);
1027 if (!tmp->param) { /* error message already output */
1028 got_errno = SILC_CONFIG_EPRINTLINE;
1029 goto got_err;
1030 }
1031 }
1032 else if (!strcmp(name, "backup")) {
1033 tmp->backup_router = *(bool *)val;
1034 }
1035 else
1036 return SILC_CONFIG_EINTERNAL;
1037
1038 return SILC_CONFIG_OK;
1039
1040 got_err:
1041 silc_free(tmp->host);
1042 CONFIG_FREE_AUTH(tmp);
1043 silc_free(tmp);
1044 config->tmp = NULL;
1045 return got_errno;
1046 }
1047
1048 SILC_CONFIG_CALLBACK(fetch_router)
1049 {
1050 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigRouter);
1051
1052 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)",
1053 type, name, context));
1054 if (type == SILC_CONFIG_ARG_BLOCK) {
1055 if (!tmp) /* discard empty sub-blocks */