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"
25 #define SILC_CONFIG_SERVER_AUTH_METH_PASSWD "passwd"
26 #define SILC_CONFIG_SERVER_AUTH_METH_PUBKEY "pubkey"
29 #define SERVER_CONFIG_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
31 #define SERVER_CONFIG_DEBUG(fmt)
34 /* auto-declare needed variables for the common list parsing */
35 #define SILC_SERVER_CONFIG_SECTION_INIT(__type__) \
36 SilcServerConfig config = (SilcServerConfig) context; \
37 __type__ *findtmp, *tmp = (__type__ *) config->tmp; \
40 /* append the tmp field to the specified list */
41 #define SILC_SERVER_CONFIG_LIST_APPENDTMP(__list__) \
45 for (findtmp = __list__; findtmp->next; findtmp = findtmp->next); \
46 findtmp->next = tmp; \
49 /* loops all elements in a list and provides a di struct pointer of the
50 * specified type containing the current element */
51 #define SILC_SERVER_CONFIG_LIST_DESTROY(__type__, __list__) \
52 for (tmp = (void *) __list__; tmp;) { \
53 __type__ *di = (__type__ *) tmp; \
54 tmp = (void *) di->next;
56 /* free an authdata according to its auth method */
57 static void my_free_authdata(SilcAuthMethod auth_meth, void *auth_data)
59 if (auth_meth == SILC_AUTH_PASSWORD) {
61 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
62 silc_pkcs_public_key_free((SilcPublicKey) auth_data);
66 /* parse an authdata according to its auth method */
67 static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, uint32 line,
68 void **auth_data, uint32 *auth_data_len)
70 if (auth_meth == SILC_AUTH_PASSWORD) {
71 /* p is a plain text password */
72 *auth_data = (void *) strdup(p);
73 *auth_data_len = (uint32) strlen(p);
74 } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
75 /* p is a public key */
76 SilcPublicKey public_key;
78 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
79 if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
80 fprintf(stderr, "\nError while parsing config file at line %lu: "
81 "Could not load public key file!\n", line);
84 *auth_data = (void *) public_key;
87 fprintf(stderr, "\nError while parsing config file at line %lu: Specify "
88 "the AuthMethod before specifying the AuthData.\n", line);
96 SILC_CONFIG_CALLBACK(fetch_generic)
98 SilcServerConfig config = (SilcServerConfig) context;
100 if (!strcmp(name, "modulepath")) {
101 if (config->module_path) return SILC_CONFIG_EDOUBLE;
102 /* dup it only if non-empty, otherwise point it to NULL */
103 config->module_path = (*(char *)val ? strdup((char *) val) : NULL);
106 return SILC_CONFIG_EINTERNAL;
107 return SILC_CONFIG_OK;
110 SILC_CONFIG_CALLBACK(fetch_cipher)
112 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionCipher);
114 SERVER_CONFIG_DEBUG(("Received CIPHER type=%d name=\"%s\" (val=%x)", type, name, context));
115 if (type == SILC_CONFIG_ARG_BLOCK) {
116 /* check the temporary struct's fields */
117 if (!tmp) /* empty sub-block? */
118 return SILC_CONFIG_OK;
120 got_errno = SILC_CONFIG_EMISSFIELDS;
123 /* the temporary struct is ok, append it to the list */
124 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->cipher);
126 return SILC_CONFIG_OK;
128 /* if there isn't a temporary struct alloc one */
130 config->tmp = silc_calloc(1, sizeof(*findtmp));
131 tmp = (SilcServerConfigSectionCipher *) config->tmp;
134 /* Identify and save this value */
135 if (!strcmp(name, "name")) {
136 if (tmp->name) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
137 tmp->name = strdup((char *) val);
139 else if (!strcmp(name, "module")) { /* can be empty */
140 if (tmp->module) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
141 /* dup it only if non-empty, otherwise point it to NULL */
142 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
144 else if (!strcmp(name, "key_length"))
145 tmp->key_length = *(uint32 *)val;
146 else if (!strcmp(name, "block_length"))
147 tmp->block_length = *(uint32 *)val;
149 return SILC_CONFIG_EINTERNAL;
150 return SILC_CONFIG_OK;
153 silc_free(tmp->name);
154 silc_free(tmp->module);
160 SILC_CONFIG_CALLBACK(fetch_hash)
162 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionHash);
164 SERVER_CONFIG_DEBUG(("Received HASH type=%d name=%s (val=%x)", type, name, context));
165 if (type == SILC_CONFIG_ARG_BLOCK) {
166 /* check the temporary struct's fields */
167 if (!tmp) /* empty sub-block? */
168 return SILC_CONFIG_OK;
169 if (!tmp->name || (tmp->block_length == 0) || (tmp->digest_length == 0)) {
170 got_errno = SILC_CONFIG_EMISSFIELDS;
173 /* the temporary struct in tmp is ok */
174 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hash);
176 return SILC_CONFIG_OK;
178 /* if there isn't a temporary struct alloc one */
180 config->tmp = silc_calloc(1, sizeof(*findtmp));
181 tmp = (SilcServerConfigSectionHash *) config->tmp;
184 /* Identify and save this value */
185 if (!strcmp(name, "name")) {
186 if (tmp->name) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
187 tmp->name = strdup((char *) val);
189 else if (!strcmp(name, "module")) { /* can be empty */
190 if (tmp->module) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
191 /* dup it only if non-empty, otherwise point it to NULL */
192 tmp->module = (*(char *)val ? strdup((char *) val) : NULL);
194 else if (!strcmp(name, "block_length"))
195 tmp->block_length = *(int *)val;
196 else if (!strcmp(name, "digest_length"))
197 tmp->digest_length = *(int *)val;
199 return SILC_CONFIG_EINTERNAL;
200 return SILC_CONFIG_OK;
203 silc_free(tmp->name);
204 silc_free(tmp->module);
210 SILC_CONFIG_CALLBACK(fetch_hmac)
212 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionHmac);
214 SERVER_CONFIG_DEBUG(("Received HMAC type=%d name=\"%s\" (val=%x)", type, name, context));
215 if (type == SILC_CONFIG_ARG_BLOCK) {
216 /* check the temporary struct's fields */
217 if (!tmp) /* empty sub-block? */
218 return SILC_CONFIG_OK;
219 if (!tmp->name || !tmp->hash || (tmp->mac_length == 0)) {
220 got_errno = SILC_CONFIG_EMISSFIELDS;
223 /* the temporary struct is ok, append it to the list */
224 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->hmac);
226 return SILC_CONFIG_OK;
228 /* if there isn't a temporary struct alloc one */
230 config->tmp = silc_calloc(1, sizeof(*findtmp));
231 tmp = (SilcServerConfigSectionHmac *) config->tmp;
234 /* Identify and save this value */
235 if (!strcmp(name, "name")) {
236 if (tmp->name) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
237 tmp->name = strdup((char *) val);
239 else if (!strcmp(name, "hash")) {
240 if (tmp->hash) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
241 tmp->hash = strdup((char *) val);
243 else if (!strcmp(name, "mac_length"))
244 tmp->mac_length = *(int *)val;
246 return SILC_CONFIG_EINTERNAL;
247 return SILC_CONFIG_OK;
250 silc_free(tmp->name);
251 silc_free(tmp->hash);
257 SILC_CONFIG_CALLBACK(fetch_pkcs)
259 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionPkcs);
261 SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)", type, name, context));
262 if (type == SILC_CONFIG_ARG_BLOCK) {
263 /* check the temporary struct's fields */
264 if (!tmp) /* empty sub-block? */
265 return SILC_CONFIG_OK;
267 got_errno = SILC_CONFIG_EMISSFIELDS;
270 /* the temporary struct is ok, append it to the list */
271 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->pkcs);
273 return SILC_CONFIG_OK;
275 /* if there isn't a temporary struct alloc one */
277 config->tmp = silc_calloc(1, sizeof(*findtmp));
278 tmp = (SilcServerConfigSectionPkcs *) config->tmp;
281 /* Identify and save this value */
282 if (!strcmp(name, "name")) {
283 if (tmp->name) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
284 tmp->name = strdup((char *) val);
287 return SILC_CONFIG_EINTERNAL;
288 return SILC_CONFIG_OK;
291 silc_free(tmp->name);
297 SILC_CONFIG_CALLBACK(fetch_serverinfo)
299 SilcServerConfig config = (SilcServerConfig) context;
300 SilcServerConfigSectionServerInfo *server_info = config->server_info;
302 /* if there isn't the struct alloc it */
304 config->server_info = server_info = (SilcServerConfigSectionServerInfo *)
305 silc_calloc(1, sizeof(*server_info));
308 if (type == SILC_CONFIG_ARG_BLOCK) {
309 /* check for mandatory inputs */
310 return SILC_CONFIG_OK;
312 if (!strcmp(name, "hostname")) {
313 if (server_info->server_name) return SILC_CONFIG_EDOUBLE;
314 server_info->server_name = strdup((char *) val);
316 else if (!strcmp(name, "ip")) {
317 if (server_info->server_ip) return SILC_CONFIG_EDOUBLE;
318 server_info->server_ip = strdup((char *) val);
320 else if (!strcmp(name, "port")) {
321 int port = *(int *)val;
322 if ((port <= 0) || (port > 65535)) {
323 fprintf(stderr, "Invalid port number!\n");
324 return SILC_CONFIG_ESILENT;
326 server_info->port = (uint16) port;
328 else if (!strcmp(name, "servertype")) {
329 if (server_info->server_type) return SILC_CONFIG_EDOUBLE;
330 server_info->server_type = strdup((char *) val);
332 else if (!strcmp(name, "admin")) {
333 if (server_info->admin) return SILC_CONFIG_EDOUBLE;
334 server_info->admin = strdup((char *) val);
336 else if (!strcmp(name, "email")) {
337 if (server_info->email) return SILC_CONFIG_EDOUBLE;
338 server_info->email = strdup((char *) val);
340 else if (!strcmp(name, "location")) {
341 if (server_info->location) return SILC_CONFIG_EDOUBLE;
342 server_info->location = strdup((char *) val);
344 else if (!strcmp(name, "user")) {
345 if (server_info->user) return SILC_CONFIG_EDOUBLE;
346 server_info->user = strdup((char *) val);
348 else if (!strcmp(name, "group")) {
349 if (server_info->group) return SILC_CONFIG_EDOUBLE;
350 server_info->group = strdup((char *) val);
352 else if (!strcmp(name, "motdfile")) {
353 if (server_info->motd_file) return SILC_CONFIG_EDOUBLE;
354 server_info->motd_file = strdup((char *) val);
356 else if (!strcmp(name, "pidfile")) {
357 if (server_info->pid_file) return SILC_CONFIG_EDOUBLE;
358 server_info->pid_file = strdup((char *) val);
360 else if (!strcmp(name, "publickey")) {
361 char *tmp = (char *) val;
363 /* try to load specified file, if fail stop config parsing */
364 if (!silc_pkcs_load_public_key(tmp, &server_info->public_key,
366 if (!silc_pkcs_load_public_key(tmp, &server_info->public_key,
367 SILC_PKCS_FILE_BIN)) {
368 fprintf(stderr, "\nError: Could not load public key file.");
369 fprintf(stderr, "\n line %lu: file \"%s\"\n", line, tmp);
370 return SILC_CONFIG_ESILENT;
373 else if (!strcmp(name, "privatekey")) {
374 char *tmp = (char *) val;
376 /* try to load specified file, if fail stop config parsing */
377 if (!silc_pkcs_load_private_key(tmp, &server_info->private_key,
379 if (!silc_pkcs_load_private_key(tmp, &server_info->private_key,
380 SILC_PKCS_FILE_PEM)) {
381 fprintf(stderr, "\nError: Could not load private key file.");
382 fprintf(stderr, "\n line %lu: file \"%s\"\n", line, tmp);
383 return SILC_CONFIG_ESILENT;
387 return SILC_CONFIG_EINTERNAL;
388 return SILC_CONFIG_OK;
391 SILC_CONFIG_CALLBACK(fetch_logging)
393 SilcServerConfig config = (SilcServerConfig) context;
394 SilcServerConfigSectionLogging *tmp =
395 (SilcServerConfigSectionLogging *) config->tmp;
398 if (!strcmp(name, "quicklogs")) {
399 silc_log_quick = *(bool *)val;
401 else if (!strcmp(name, "flushdelay")) {
402 int flushdelay = *(int *)val;
403 if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
404 fprintf(stderr, "Error: line %lu: invalid flushdelay value, use "
405 "quicklogs if you want real-time logging.\n", line);
406 return SILC_CONFIG_ESILENT;
408 silc_log_flushdelay = (long) flushdelay;
410 #define FETCH_LOGGING_CHAN(__chan__, __member__) \
411 else if (!strcmp(name, __chan__)) { \
412 if (!tmp) return SILC_CONFIG_OK; \
414 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err; \
416 config->__member__ = tmp; \
417 config->tmp = NULL; \
419 FETCH_LOGGING_CHAN("info", logging_info)
420 FETCH_LOGGING_CHAN("warnings", logging_warnings)
421 FETCH_LOGGING_CHAN("errors", logging_errors)
422 FETCH_LOGGING_CHAN("fatals", logging_fatals)
423 #undef FETCH_LOGGING_CHAN
424 else if (!strcmp(name, "file")) {
425 if (!tmp) { /* FIXME: what the fuck is this? */
426 config->tmp = silc_calloc(1, sizeof(*tmp));
427 tmp = (SilcServerConfigSectionLogging *) config->tmp;
430 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
432 tmp->file = strdup((char *) val);
434 else if (!strcmp(name, "size")) {
436 config->tmp = silc_calloc(1, sizeof(*tmp));
437 tmp = (SilcServerConfigSectionLogging *) config->tmp;
439 tmp->maxsize = *(uint32 *) val;
442 return SILC_CONFIG_EINTERNAL;
443 return SILC_CONFIG_OK;
446 silc_free(tmp->file);
452 SILC_CONFIG_CALLBACK(fetch_client)
454 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionClient);
456 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)", type, name, context));
457 if (type == SILC_CONFIG_ARG_BLOCK) {
458 if (!tmp) /* empty sub-block? */
459 return SILC_CONFIG_OK;
460 if (tmp->auth_meth && !tmp->auth_data) {
461 fprintf(stderr, "\nError: line %lu: If you specify \"AuthMethod\" field "
462 "then you must also specify the \"AuthData\" field.\n", line);
463 got_errno = SILC_CONFIG_ESILENT;
466 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->clients);
468 return SILC_CONFIG_OK;
470 /* if there isn't a temporary struct alloc one */
472 config->tmp = silc_calloc(1, sizeof(*findtmp));
473 tmp = (SilcServerConfigSectionClient *) config->tmp;
476 /* Identify and save this value */
477 if (!strcmp(name, "host")) { /* any host (*) accepted */
478 if (tmp->host) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
479 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
481 /* get authentication method */
482 else if (!strcmp(name, "authmethod")) {
483 if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
484 tmp->auth_meth = SILC_AUTH_PASSWORD;
485 else if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
486 tmp->auth_meth = SILC_AUTH_PUBLIC_KEY;
488 got_errno = SILC_CONFIG_EINVALIDTEXT; goto got_err;
491 else if (!strcmp(name, "authdata")) {
492 if (!my_parse_authdata(tmp->auth_meth, (char *) val, line,
493 &tmp->auth_data, &tmp->auth_data_len)) {
494 got_errno = SILC_CONFIG_ESILENT;
495 goto got_err; /* error outputted in my_parse_authdata */
498 else if (!strcmp(name, "port")) {
499 int port = *(int *)val;
500 if ((port <= 0) || (port > 65535)) {
501 fprintf(stderr, "Invalid port number!\n");
502 got_errno = SILC_CONFIG_ESILENT; goto got_err;
504 tmp->port = (uint16) port;
506 /* FIXME: Improvement: use a direct class struct pointer instead of num */
507 else if (!strcmp(name, "class")) {
511 return SILC_CONFIG_EINTERNAL;
512 return SILC_CONFIG_OK;
515 silc_free(tmp->host);
516 my_free_authdata(tmp->auth_meth, tmp->auth_data);
521 SILC_CONFIG_CALLBACK(fetch_admin)
523 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionAdmin);
525 SERVER_CONFIG_DEBUG(("Received CLIENT type=%d name=\"%s\" (val=%x)", type, name, context));
526 if (type == SILC_CONFIG_ARG_BLOCK) {
527 /* check the temporary struct's fields */
528 if (!tmp) /* empty sub-block? */
529 return SILC_CONFIG_OK;
530 if (!tmp->auth_meth) {
531 got_errno = SILC_CONFIG_EMISSFIELDS; goto got_err;
533 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->admins);
535 return SILC_CONFIG_OK;
537 /* if there isn't a temporary struct alloc one */
539 config->tmp = silc_calloc(1, sizeof(*findtmp));
540 tmp = (SilcServerConfigSectionAdmin *) config->tmp;
543 /* Identify and save this value */
544 if (!strcmp(name, "host")) { /* any host (*) accepted */
545 if (tmp->host) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
546 tmp->host = (*(char *)val ? strdup((char *) val) : NULL);
548 else if (!strcmp(name, "user")) {
549 if (tmp->user) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
550 tmp->user = (*(char *)val ? strdup((char *) val) : NULL);
552 else if (!strcmp(name, "nick")) {
553 if (tmp->nick) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
554 tmp->nick = (*(char *)val ? strdup((char *) val) : NULL);
556 /* get authentication method */
557 else if (!strcmp(name, "authmethod")) {
558 if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
559 tmp->auth_meth = SILC_AUTH_PASSWORD;
560 else if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
561 tmp->auth_meth = SILC_AUTH_PUBLIC_KEY;
563 got_errno = SILC_CONFIG_EINVALIDTEXT; goto got_err;
566 else if (!strcmp(name, "authdata")) {
567 if (!my_parse_authdata(tmp->auth_meth, (char *) val, line,
568 &tmp->auth_data, &tmp->auth_data_len)) {
569 got_errno = SILC_CONFIG_ESILENT;
570 goto got_err; /* error outputted in my_parse_authdata */
574 return SILC_CONFIG_EINTERNAL;
575 return SILC_CONFIG_OK;
578 silc_free(tmp->host);
579 silc_free(tmp->user);
580 silc_free(tmp->nick);
581 my_free_authdata(tmp->auth_meth, tmp->auth_data);
586 SILC_CONFIG_CALLBACK(fetch_deny)
588 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionDeny);
590 SERVER_CONFIG_DEBUG(("Received DENY type=%d name=\"%s\" (val=%x)", type, name, context));
591 if (type == SILC_CONFIG_ARG_BLOCK) {
592 /* check the temporary struct's fields */
593 if (!tmp) /* empty sub-block? */
594 return SILC_CONFIG_OK;
596 got_errno = SILC_CONFIG_EMISSFIELDS;
599 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->denied);
601 return SILC_CONFIG_OK;
603 /* if there isn't a temporary struct alloc one */
605 config->tmp = silc_calloc(1, sizeof(*findtmp));
606 tmp = (SilcServerConfigSectionDeny *) config->tmp;
609 /* Identify and save this value */
610 if (!strcmp(name, "host")) { /* any host (*) accepted */
611 if (tmp->host) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
612 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
614 else if (!strcmp(name, "port")) {
615 int port = *(int *)val;
616 if ((port <= 0) || (port > 65535)) {
617 fprintf(stderr, "Invalid port number!\n");
618 got_errno = SILC_CONFIG_ESILENT; goto got_err;
620 tmp->port = (uint16) port;
622 else if (!strcmp(name, "reason")) {
623 if (tmp->reason) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
624 tmp->reason = strdup((char *) val);
627 return SILC_CONFIG_EINTERNAL;
628 return SILC_CONFIG_OK;
631 silc_free(tmp->host);
632 silc_free(tmp->reason);
637 SILC_CONFIG_CALLBACK(fetch_server)
639 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionServer);
641 SERVER_CONFIG_DEBUG(("Received SERVER type=%d name=\"%s\" (val=%x)", type, name, context));
642 if (type == SILC_CONFIG_ARG_BLOCK) {
643 /* check the temporary struct's fields */
644 if (!tmp) /* empty sub-block? */
645 return SILC_CONFIG_OK;
646 if (!tmp->auth_meth || !tmp->version) {
647 got_errno = SILC_CONFIG_EMISSFIELDS;
650 /* the temporary struct is ok, append it to the list */
651 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->servers);
653 return SILC_CONFIG_OK;
655 /* if there isn't a temporary struct alloc one */
657 config->tmp = silc_calloc(1, sizeof(*findtmp));
658 tmp = (SilcServerConfigSectionServer *) config->tmp;
661 /* Identify and save this value */
662 if (!strcmp(name, "host")) { /* any host (*) accepted */
663 if (tmp->host) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
664 tmp->host = (*(char *)val ? strdup((char *) val) : strdup("*"));
666 /* get authentication method */
667 else if (!strcmp(name, "authmethod")) {
668 if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
669 tmp->auth_meth = SILC_AUTH_PASSWORD;
670 else if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
671 tmp->auth_meth = SILC_AUTH_PUBLIC_KEY;
673 got_errno = SILC_CONFIG_EINVALIDTEXT; goto got_err;
676 else if (!strcmp(name, "authdata")) {
677 if (!my_parse_authdata(tmp->auth_meth, (char *) val, line,
678 &tmp->auth_data, &tmp->auth_data_len)) {
679 got_errno = SILC_CONFIG_ESILENT;
680 goto got_err; /* error outputted in my_parse_authdata */
683 else if (!strcmp(name, "port")) {
684 int port = *(int *)val;
685 if ((port <= 0) || (port > 65535)) {
686 fprintf(stderr, "Invalid port number!\n");
687 got_errno = SILC_CONFIG_ESILENT; goto got_err;
689 tmp->port = (uint16) port;
691 else if (!strcmp(name, "versionid")) {
692 if (tmp->version) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
693 tmp->version = strdup((char *) val);
695 /* FIXME: Improvement: use a direct class struct pointer instead of num */
696 else if (!strcmp(name, "class")) {
699 else if (!strcmp(name, "backup")) {
700 tmp->backup_router = *(bool *)val;
703 return SILC_CONFIG_EINTERNAL;
704 return SILC_CONFIG_OK;
707 silc_free(tmp->host);
708 silc_free(tmp->version);
709 my_free_authdata(tmp->auth_meth, tmp->auth_data);
714 SILC_CONFIG_CALLBACK(fetch_router)
716 SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigSectionRouter);
718 SERVER_CONFIG_DEBUG(("Received ROUTER type=%d name=\"%s\" (val=%x)", type, name, context));
719 if (type == SILC_CONFIG_ARG_BLOCK) {
720 if (!tmp) /* empty sub-block? */
721 return SILC_CONFIG_OK;
722 if (!tmp->auth_meth || !tmp->version) {
723 got_errno = SILC_CONFIG_EMISSFIELDS;
726 /* the temporary struct is ok, append it to the list */
727 SILC_SERVER_CONFIG_LIST_APPENDTMP(config->routers);
729 return SILC_CONFIG_OK;
731 /* if there isn't a temporary struct alloc one */
733 config->tmp = silc_calloc(1, sizeof(*findtmp));
734 tmp = (SilcServerConfigSectionRouter *) config->tmp;
737 /* Identify and save this value */
738 if (!strcmp(name, "host")) {
739 if (tmp->host) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
740 tmp->host = strdup((char *) val);
742 else if (!strcmp(name, "authmethod")) {
743 if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
744 tmp->auth_meth = SILC_AUTH_PASSWORD;
745 else if (!strcmp((char *) val, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
746 tmp->auth_meth = SILC_AUTH_PUBLIC_KEY;
748 got_errno = SILC_CONFIG_EINVALIDTEXT; goto got_err;
751 else if (!strcmp(name, "authdata")) {
752 if (!my_parse_authdata(tmp->auth_meth, (char *) val, line,
753 &tmp->auth_data, &tmp->auth_data_len)) {
754 got_errno = SILC_CONFIG_ESILENT;
755 goto got_err; /* error outputted in my_parse_authdata */
758 else if (!strcmp(name, "port")) {
759 int port = *(int *)val;
760 if ((port <= 0) || (port > 65535)) {
761 fprintf(stderr, "Invalid port number!\n");
762 got_errno = SILC_CONFIG_ESILENT; goto got_err;
764 tmp->port = (uint16) port;
766 else if (!strcmp(name, "versionid")) {
767 if (tmp->version) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
768 tmp->version = strdup((char *) val);
770 /* FIXME: Improvement: use a direct class struct pointer instead of num */
771 else if (!strcmp(name, "class")) {
774 else if (!strcmp(name, "initiator"))
775 tmp->initiator = *(bool *)val;
776 else if (!strcmp(name, "backuphost")) {
777 if (tmp->backup_replace_ip) { got_errno = SILC_CONFIG_EDOUBLE; goto got_err; }
778 tmp->backup_replace_ip = (*(char *)val ? strdup((char *) val) : strdup("*"));
781 return SILC_CONFIG_EINTERNAL;
782 return SILC_CONFIG_OK;
785 silc_free(tmp->host);
786 silc_free(tmp->version);
787 silc_free(tmp->backup_replace_ip);
788 my_free_authdata(tmp->auth_meth, tmp->auth_data);
793 /* known config options tables */
794 static const SilcConfigTable table_general[] = {
795 { "modulepath", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
799 static const SilcConfigTable table_cipher[] = {
800 { "name", SILC_CONFIG_ARG_STR, fetch_cipher, NULL },
801 { "module", SILC_CONFIG_ARG_STRE, fetch_cipher, NULL },
802 { "key_length", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
803 { "block_length", SILC_CONFIG_ARG_INT, fetch_cipher, NULL },
807 static const SilcConfigTable table_hash[] = {
808 { "name", SILC_CONFIG_ARG_STR, fetch_hash, NULL },
809 { "module", SILC_CONFIG_ARG_STRE, fetch_hash, NULL },
810 { "block_length", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
811 { "digest_length", SILC_CONFIG_ARG_INT, fetch_hash, NULL },
815 static const SilcConfigTable table_hmac[] = {
816 { "name", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
817 { "hash", SILC_CONFIG_ARG_STR, fetch_hmac, NULL },
818 { "mac_length", SILC_CONFIG_ARG_INT, fetch_hmac, NULL },
822 static const SilcConfigTable table_pkcs[] = {
823 { "name", SILC_CONFIG_ARG_STR, fetch_pkcs, NULL },
827 static const SilcConfigTable table_serverinfo[] = {
828 { "hostname", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
829 { "ip", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
830 { "port", SILC_CONFIG_ARG_INT, fetch_serverinfo, NULL},
831 { "servertype", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
832 { "location", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
833 { "admin", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
834 { "email", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
835 { "user", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
836 { "group", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
837 { "publickey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
838 { "privatekey", SILC_CONFIG_ARG_STR, fetch_serverinfo, NULL},
839 { "motdfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
840 { "pidfile", SILC_CONFIG_ARG_STRE, fetch_serverinfo, NULL},
844 static const SilcConfigTable table_logging_c[] = {
845 { "file", SILC_CONFIG_ARG_STR, fetch_logging, NULL },
846 { "size", SILC_CONFIG_ARG_SIZE, fetch_logging, NULL },
847 /*{ "quicklog", SILC_CONFIG_ARG_NONE, fetch_logging, NULL }, */
851 static const SilcConfigTable table_logging[] = {
852 { "quicklogs", SILC_CONFIG_ARG_TOGGLE, fetch_logging, NULL },
853 { "flushdelay", SILC_CONFIG_ARG_INT, fetch_logging, NULL },
854 { "info", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
855 { "warnings", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
856 { "errors", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
857 { "fatals", SILC_CONFIG_ARG_BLOCK, fetch_logging, table_logging_c },
862 static const SilcConfigTable table_class[] = {
863 { "name", SILC_CONFIG_ARG_STR, fetch_class, NULL },
864 { "ping", SILC_CONFIG_ARG_INT, fetch_class, NULL },
865 { "connect", SILC_CONFIG_ARG_INT, fetch_class, NULL },
866 { "links", SILC_CONFIG_ARG_INT, fetch_class, NULL },
870 static const SilcConfigTable table_client[] = {
871 { "host", SILC_CONFIG_ARG_STRE, fetch_client, NULL },
872 { "authmethod", SILC_CONFIG_ARG_STR, fetch_client, NULL },
873 { "authdata", SILC_CONFIG_ARG_STR, fetch_client, NULL },
874 { "port", SILC_CONFIG_ARG_INT, fetch_client, NULL },
875 { "class", SILC_CONFIG_ARG_STR, fetch_client, NULL },
879 static const SilcConfigTable table_admin[] = {
880 { "host", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
881 { "user", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
882 { "nick", SILC_CONFIG_ARG_STRE, fetch_admin, NULL },
883 { "authmethod", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
884 { "authdata", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
885 { "port", SILC_CONFIG_ARG_INT, fetch_admin, NULL },
886 { "class", SILC_CONFIG_ARG_STR, fetch_admin, NULL },
890 static const SilcConfigTable table_deny[] = {
891 { "host", SILC_CONFIG_ARG_STRE, fetch_deny, NULL },
892 { "port", SILC_CONFIG_ARG_INT, fetch_deny, NULL },
893 { "reason", SILC_CONFIG_ARG_STR, fetch_deny, NULL },
897 static const SilcConfigTable table_serverconn[] = {
898 { "host", SILC_CONFIG_ARG_STRE, fetch_server, NULL },
899 { "authmethod", SILC_CONFIG_ARG_STR, fetch_server, NULL },
900 { "authdata", SILC_CONFIG_ARG_STR, fetch_server, NULL },
901 { "port", SILC_CONFIG_ARG_INT, fetch_server, NULL },
902 { "versionid", SILC_CONFIG_ARG_STR, fetch_server, NULL },
903 { "class", SILC_CONFIG_ARG_STR, fetch_server, NULL },
904 { "backup", SILC_CONFIG_ARG_TOGGLE, fetch_server, NULL },
908 static const SilcConfigTable table_routerconn[] = {
909 { "host", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
910 { "authmethod", SILC_CONFIG_ARG_STR, fetch_router, NULL },
911 { "authdata", SILC_CONFIG_ARG_STR, fetch_router, NULL },
912 { "port", SILC_CONFIG_ARG_INT, fetch_router, NULL },
913 { "versionid", SILC_CONFIG_ARG_STR, fetch_router, NULL },
914 { "class", SILC_CONFIG_ARG_STR, fetch_router, NULL },
915 { "initiator", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
916 { "backuphost", SILC_CONFIG_ARG_STRE, fetch_router, NULL },
917 { "backupport", SILC_CONFIG_ARG_INT, fetch_router, NULL },
918 { "localbackup", SILC_CONFIG_ARG_TOGGLE, fetch_router, NULL },
922 static const SilcConfigTable table_main[] = {
923 { "general", SILC_CONFIG_ARG_BLOCK, NULL, table_general },
924 { "cipher", SILC_CONFIG_ARG_BLOCK, fetch_cipher, table_cipher },
925 { "hash", SILC_CONFIG_ARG_BLOCK, fetch_hash, table_hash },
926 { "hmac", SILC_CONFIG_ARG_BLOCK, fetch_hmac, table_hmac },
927 { "pkcs", SILC_CONFIG_ARG_BLOCK, fetch_pkcs, table_pkcs },
928 { "serverinfo", SILC_CONFIG_ARG_BLOCK, fetch_serverinfo, table_serverinfo },
929 { "logging", SILC_CONFIG_ARG_BLOCK, NULL, table_logging },
930 /*{ "class", SILC_CONFIG_ARG_BLOCK, fetch_class, table_class }, */
931 { "client", SILC_CONFIG_ARG_BLOCK, fetch_client, table_client },
932 { "admin", SILC_CONFIG_ARG_BLOCK, fetch_admin, table_admin },
933 { "deny", SILC_CONFIG_ARG_BLOCK, fetch_deny, table_deny },
934 { "serverconnection", SILC_CONFIG_ARG_BLOCK, fetch_server, table_serverconn },
935 { "routerconnection", SILC_CONFIG_ARG_BLOCK, fetch_router, table_routerconn },
939 /* Allocates a new configuration object, opens configuration file and
940 * parses it. The parsed data is returned to the newly allocated
941 * configuration object. */
943 SilcServerConfig silc_server_config_alloc(char *filename)
945 SilcServerConfig config;
946 SilcConfigEntity ent;
947 SilcConfigFile *file;
949 SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
951 /* alloc a config object */
952 config = (SilcServerConfig) silc_calloc(1, sizeof(*config));
953 /* obtain a config file object */
954 file = silc_config_open(filename);
956 fprintf(stderr, "\nError: can't open config file `%s'\n", filename);
959 /* obtain a SilcConfig entity, we can use it to start the parsing */
960 ent = silc_config_init(file);
961 /* load the known configuration options, give our empty object as context */
962 silc_config_register_table(ent, table_main, (void *) config);
963 /* enter the main parsing loop. When this returns, we have the parsing
964 * result and the object filled (or partially, in case of errors). */
965 ret = silc_config_main(ent);
966 SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret, silc_config_strerror(ret)));
968 /* Check if the parser returned errors */
970 /* handle this special error return which asks to quietly return */
971 if (ret != SILC_CONFIG_ESILENT) {
972 char *linebuf, *filename = silc_config_get_filename(file);
973 uint32 line = silc_config_get_line(file);
974 fprintf(stderr, "\nError while parsing config file: %s.\n",
975 silc_config_strerror(ret));
976 linebuf = silc_config_read_line(file, line);
977 fprintf(stderr, " file %s line %lu: %s\n\n", filename, line, linebuf);
982 /* close (destroy) the file object */
983 silc_config_close(file);
985 /* XXX FIXME: check for missing mandatory fields */
986 if (!config->server_info) {
987 fprintf(stderr, "\nError: Missing mandatory block `server_info'\n");
995 void silc_server_config_destroy(SilcServerConfig config)
998 silc_free(config->module_path);
1000 /* Destroy Logging channels */
1001 if (config->logging_info)
1002 silc_free(config->logging_info->file);
1003 if (config->logging_warnings)
1004 silc_free(config->logging_warnings->file);
1005 if (config->logging_errors)
1006 silc_free(config->logging_errors->file);
1007 if (config->logging_fatals)
1008 silc_free(config->logging_fatals->file);
1010 /* Destroy the ServerInfo struct */
1011 if (config->server_info) {
1012 register SilcServerConfigSectionServerInfo *si = config->server_info;
1013 silc_free(si->server_name);
1014 silc_free(si->server_ip);
1015 silc_free(si->server_type);
1016 silc_free(si->location);
1017 silc_free(si->admin);
1018 silc_free(si->email);
1019 silc_free(si->user);
1020 silc_free(si->group);
1021 silc_free(si->motd_file);
1022 silc_free(si->pid_file);
1025 /* Now let's destroy the lists */
1027 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionCipher,
1029 silc_free(di->name);
1030 silc_free(di->module);
1033 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionHash, config->hash)
1034 silc_free(di->name);
1035 silc_free(di->module);
1038 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionHmac, config->hmac)
1039 silc_free(di->name);
1040 silc_free(di->hash);
1043 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionPkcs, config->pkcs)
1044 silc_free(di->name);
1047 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionClient,
1049 silc_free(di->host);
1050 my_free_authdata(di->auth_meth, di->auth_data);
1053 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionAdmin, config->admins)
1054 silc_free(di->host);
1055 silc_free(di->user);
1056 silc_free(di->nick);
1057 my_free_authdata(di->auth_meth, di->auth_data);
1060 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionDeny, config->denied)
1061 silc_free(di->host);
1062 silc_free(di->reason);
1065 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionServer,
1067 silc_free(di->host);
1068 silc_free(di->version);
1069 my_free_authdata(di->auth_meth, di->auth_data);
1072 SILC_SERVER_CONFIG_LIST_DESTROY(SilcServerConfigSectionRouter,
1074 silc_free(di->host);
1075 silc_free(di->version);
1076 silc_free(di->backup_replace_ip);
1077 my_free_authdata(di->auth_meth, di->auth_data);
1082 /* Registers configured ciphers. These can then be allocated by the
1083 server when needed. */
1085 bool silc_server_config_register_ciphers(SilcServer server)
1087 SilcServerConfig config = server->config;
1088 SilcServerConfigSectionCipher *cipher = config->cipher;
1089 char *module_path = config->module_path;
1091 SILC_LOG_DEBUG(("Registering configured ciphers"));
1093 if (!cipher) /* any cipher in the config file? */
1097 /* if there isn't a module_path OR there isn't a module sim name try to
1098 * use buil-in functions */
1099 if (!module_path || !cipher->module) {
1101 for (i = 0; silc_default_ciphers[i].name; i++)
1102 if (!strcmp(silc_default_ciphers[i].name, cipher->name)) {
1103 silc_cipher_register(&silc_default_ciphers[i]);
1106 if (!silc_cipher_is_supported(cipher->name)) {
1107 SILC_LOG_ERROR(("Unknown cipher `%s'", cipher->name));
1108 silc_server_stop(server);
1113 /* Load (try at least) the crypto SIM module */
1114 char buf[1023], *alg_name;
1115 SilcCipherObject cipher_obj;
1116 SilcSimContext *sim;
1118 memset(&cipher_obj, 0, sizeof(cipher_obj));
1119 cipher_obj.name = cipher->name;
1120 cipher_obj.block_len = cipher->block_length;
1121 cipher_obj.key_len = cipher->key_length * 8;
1123 /* build the libname */
1124 snprintf(buf, sizeof(buf), "%s/%s", config->module_path,
1126 sim = silc_sim_alloc();
1127 sim->type = SILC_SIM_CIPHER;
1130 alg_name = strdup(cipher->name);
1131 if (strchr(alg_name, '-'))
1132 *strchr(alg_name, '-') = '\0';
1134 if (silc_sim_load(sim)) {
1135 cipher_obj.set_key =
1136 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1137 SILC_CIPHER_SIM_SET_KEY));
1138 SILC_LOG_DEBUG(("set_key=%p", cipher_obj.set_key));
1139 cipher_obj.set_key_with_string =
1140 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1141 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1142 SILC_LOG_DEBUG(("set_key_with_string=%p", cipher_obj.set_key_with_string));
1143 cipher_obj.encrypt =
1144 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1145 SILC_CIPHER_SIM_ENCRYPT_CBC));
1146 SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher_obj.encrypt));
1147 cipher_obj.decrypt =
1148 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1149 SILC_CIPHER_SIM_DECRYPT_CBC));
1150 SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher_obj.decrypt));
1151 cipher_obj.context_len =
1152 silc_sim_getsym(sim, silc_sim_symname(alg_name,
1153 SILC_CIPHER_SIM_CONTEXT_LEN));
1154 SILC_LOG_DEBUG(("context_len=%p", cipher_obj.context_len));
1156 /* Put the SIM to the list of all SIM's in server */
1157 silc_dlist_add(server->sim, sim);
1159 silc_free(alg_name);
1161 SILC_LOG_ERROR(("Error configuring ciphers"));
1162 silc_server_stop(server);
1166 /* Register the cipher */
1167 silc_cipher_register(&cipher_obj);
1169 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1170 "can't load modules!"));
1171 silc_server_stop(server);
1175 cipher = cipher->next;
1181 /* Registers configured hash functions. These can then be allocated by the
1182 server when needed. */
1184 bool silc_server_config_register_hashfuncs(SilcServer server)
1186 SilcServerConfig config = server->config;
1187 SilcServerConfigSectionHash *hash = config->hash;
1188 char *module_path = config->module_path;
1190 SILC_LOG_DEBUG(("Registering configured hash functions"));
1192 if (!hash) /* any hash func in the config file? */
1196 /* if there isn't a module_path OR there isn't a module sim name try to
1197 * use buil-in functions */
1198 if (!module_path || !hash->module) {
1200 for (i = 0; silc_default_hash[i].name; i++)
1201 if (!strcmp(silc_default_hash[i].name, hash->name)) {
1202 silc_hash_register(&silc_default_hash[i]);
1205 if (!silc_hash_is_supported(hash->name)) {
1206 SILC_LOG_ERROR(("Unknown hash funtion `%s'", hash->name));
1207 silc_server_stop(server);
1212 /* Load (try at least) the hash SIM module */
1213 SilcHashObject hash_obj;
1214 SilcSimContext *sim;
1216 memset(&hash_obj, 0, sizeof(hash_obj));
1217 hash_obj.name = hash->name;
1218 hash_obj.block_len = hash->block_length;
1219 hash_obj.hash_len = hash->digest_length;
1221 sim = silc_sim_alloc();
1222 sim->type = SILC_SIM_HASH;
1223 sim->libname = hash->module;
1225 if ((silc_sim_load(sim))) {
1227 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1228 SILC_HASH_SIM_INIT));
1229 SILC_LOG_DEBUG(("init=%p", hash_obj.init));
1231 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1232 SILC_HASH_SIM_UPDATE));
1233 SILC_LOG_DEBUG(("update=%p", hash_obj.update));
1235 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1236 SILC_HASH_SIM_FINAL));
1237 SILC_LOG_DEBUG(("final=%p", hash_obj.final));
1238 hash_obj.context_len =
1239 silc_sim_getsym(sim, silc_sim_symname(hash->name,
1240 SILC_HASH_SIM_CONTEXT_LEN));
1241 SILC_LOG_DEBUG(("context_len=%p", hash_obj.context_len));
1243 /* Put the SIM to the table of all SIM's in server */
1244 silc_dlist_add(server->sim, sim);
1246 SILC_LOG_ERROR(("Error configuring hash functions"));
1247 silc_server_stop(server);
1251 /* Register the hash function */
1252 silc_hash_register(&hash_obj);
1254 SILC_LOG_ERROR(("Dynamic module support not compiled, "
1255 "can't load modules!"));
1256 silc_server_stop(server);
1266 /* Registers configure HMACs. These can then be allocated by the server
1269 bool silc_server_config_register_hmacs(SilcServer server)
1271 SilcServerConfig config = server->config;
1272 SilcServerConfigSectionHmac *hmac = config->hmac;
1274 SILC_LOG_DEBUG(("Registering configured HMACs"));
1280 SilcHmacObject hmac_obj;
1281 if (!silc_hash_is_supported(hmac->hash)) {
1282 SILC_LOG_ERROR(("Unknown hash function `%s'", hmac->hash));
1283 silc_server_stop(server);
1286 /* Register the HMAC */
1287 memset(&hmac_obj, 0, sizeof(hmac_obj));
1288 hmac_obj.name = hmac->name;
1289 hmac_obj.len = hmac->mac_length;
1290 silc_hmac_register(&hmac_obj);
1298 /* Registers configured PKCS's. */
1300 bool silc_server_config_register_pkcs(SilcServer server)
1302 SilcServerConfig config = server->config;
1303 SilcServerConfigSectionPkcs *pkcs = config->pkcs;
1305 SILC_LOG_DEBUG(("Registering configured PKCS"));
1312 for (i = 0; silc_default_pkcs[i].name; i++)
1313 if (!strcmp(silc_default_pkcs[i].name, pkcs->name)) {
1314 silc_pkcs_register(&silc_default_pkcs[i]);
1317 if (!silc_pkcs_is_supported(pkcs->name)) {
1318 SILC_LOG_ERROR(("Unknown PKCS `%s'", pkcs->name));
1319 silc_server_stop(server);
1328 /* Sets log files where log messages are saved by the server logger. */
1330 void silc_server_config_setlogfiles(SilcServerConfig config,
1333 SilcServerConfigSectionLogging *this;
1335 SILC_LOG_DEBUG(("Setting configured log file names"));
1337 if ((this = config->logging_info))
1338 silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize, sked);
1339 if ((this = config->logging_warnings))
1340 silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize, sked);
1341 if ((this = config->logging_errors))
1342 silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize, sked);
1343 if ((this = config->logging_fatals))
1344 silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize, sked);
1347 /* Returns client authentication information from configuration file by host
1350 SilcServerConfigSectionClient *
1351 silc_server_config_find_client(SilcServerConfig config, char *host, int port)
1353 SilcServerConfigSectionClient *client;
1355 if (!config || !port) {
1356 SILC_LOG_WARNING(("Bogus: config_find_client(config=0x%08x, "
1357 "host=0x%08x \"%s\", port=%hu)",
1358 (uint32) config, (uint32) host, host, port));
1364 for (client = config->clients; client; client = client->next) {
1365 if (client->host && !silc_string_compare(client->host, host))
1367 if (client->port && (client->port != port))
1371 /* if none matched, then client is already NULL */
1375 /* Returns admin connection configuration by host, username and/or
1378 SilcServerConfigSectionAdmin *
1379 silc_server_config_find_admin(SilcServerConfig config,
1380 char *host, char *user, char *nick)
1382 SilcServerConfigSectionAdmin *admin;
1384 /* make sure we have a value for the matching parameters */
1392 for (admin = config->admins; admin; admin = admin->next) {
1393 if (admin->host && !silc_string_compare(admin->host, host))
1395 if (admin->user && !silc_string_compare(admin->user, user))
1397 if (admin->nick && !silc_string_compare(admin->nick, nick))
1399 /* no checks failed -> this entry matches */
1402 /* if none matched, then admin is already NULL */
1406 /* Returns the denied connection configuration entry by host and port. */
1408 SilcServerConfigSectionDeny *
1409 silc_server_config_find_denied(SilcServerConfig config,
1410 char *host, uint16 port)
1412 SilcServerConfigSectionDeny *deny;
1414 /* make sure we have a value for the matching parameters */
1415 if (!config || !port) {
1416 SILC_LOG_WARNING(("Bogus: config_find_denied(config=0x%08x, "
1417 "host=0x%08x \"%s\", port=%hu)",
1418 (uint32) config, (uint32) host, host, port));
1424 for (deny = config->denied; deny; deny = deny->next) {
1425 if (deny->host && !silc_string_compare(deny->host, host))
1429 /* if none matched, then deny is already NULL */
1433 /* Returns server connection info from server configuartion by host
1434 (name or ip). If `port' is non-null then both name or IP and the port
1437 SilcServerConfigSectionServer *
1438 silc_server_config_find_server_conn(SilcServerConfig config,
1439 char *host, int port)
1442 SilcServerConfigSectionServer *serv = NULL;
1448 if (!config->servers)
1451 serv = config->servers;
1452 for (i = 0; serv; i++) {
1453 if (silc_string_compare(serv->host, host))
1456 if (port && serv->port && serv->port != port)
1471 /* Returns router connection info from server configuration by
1472 host (name or ip). */
1474 SilcServerConfigSectionRouter *
1475 silc_server_config_find_router_conn(SilcServerConfig config,
1476 char *host, int port)
1479 SilcServerConfigSectionRouter *serv = NULL;
1485 if (!config->routers)
1488 serv = config->routers;
1489 for (i = 0; serv; i++) {
1490 if (silc_string_compare(serv->host, host))
1493 if (port && serv->port && serv->port != port)
1508 /* Returns TRUE if configuration for a router connection that we are
1509 initiating exists. */
1511 bool silc_server_config_is_primary_route(SilcServerConfig config)
1514 SilcServerConfigSectionRouter *serv = NULL;
1517 serv = config->routers;
1518 for (i = 0; serv; i++) {
1519 if (serv->initiator == TRUE && serv->backup_router == FALSE) {
1530 /* Returns our primary connection configuration or NULL if we do not
1531 have primary router configured. */
1533 SilcServerConfigSectionRouter *
1534 silc_server_config_get_primary_router(SilcServerConfig config)
1537 SilcServerConfigSectionRouter *serv = NULL;
1539 serv = config->routers;
1540 for (i = 0; serv; i++) {
1541 if (serv->initiator == TRUE && serv->backup_router == FALSE)