Some bugfixes.
[silc.git] / apps / silcd / serverconfig.c
1 /*
2
3   serverconfig.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 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 /*
21  * $Id$
22  * $Log$
23  * Revision 1.5  2000/11/02 22:15:23  priikone
24  *      Some bugfixes.
25  *      Changed server->sim to SilcDList and code accordingly.
26  *      Changes SilcClientEntry->channel to SilcList and added
27  *      back-pointer to SilcChannelClientEntry which is now used by both
28  *      client entry and channel entry
29  *
30  * Revision 1.4  2000/10/06 08:10:23  priikone
31  *      Added WHOIS to send multiple replies if multiple nicknames are
32  *      found.
33  *      Added MOTD command and [motd] config section and server also sends
34  *      motd to client on connection now.
35  *      Fixed TOPIC command some more.
36  *
37  * Revision 1.3  2000/07/10 05:41:20  priikone
38  *      Added missing token to administrative information.
39  *
40  * Revision 1.2  2000/07/05 06:14:01  priikone
41  *      Global costemic changes.
42  *
43  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
44  *      Imported from internal CVS/Added Log headers.
45  *
46  *
47  */
48
49 #include "serverincludes.h"
50 #include "server_internal.h"
51
52 /*  XXX
53    All possible configuration sections for SILC server. 
54
55    <Cipher>
56
57        Format:
58
59        +<Cipher name>:<SIM path>
60
61    <PKCS>
62
63        Format:
64
65        +<PKCS name>:<key length>
66
67    <HashFunction>
68
69        Format:
70
71        +<Hash function name>:<SIM path>
72
73    <ServerInfo>
74
75        This section is used to set the server informations.
76
77        Format:
78
79        +<Server DNS name>:<Server IP>:<Geographic location>:<Port>
80
81    <AdminInfo>
82
83        This section is used to set the server's administrative information.
84
85        Format:
86
87        +<Location>:<Server type>:<Admin's name>:<Admin's email address>
88
89    <ListenPort>
90
91        This section is used to set ports the server is listenning.
92
93        Format:
94
95        +<Local IP/UNIX socket path>:<Remote IP>:<Port>
96
97    <Logging>
98
99        This section is used to set various logging files, their paths
100        and maximum sizes. All the other directives except those defined
101        below are ignored in this section. Log files are purged after they
102        reach the maximum set byte size.
103
104        Format:
105
106        +infologfile:<path>:<max byte size>
107        +errorlogfile:<path>:<max byte size>
108
109    <ConnectionClass>
110
111        This section is used to define connection classes. These can be
112        used to optimize the server and the connections.
113
114        Format:
115
116        +<Class number>:<Ping freq>:<Connect freq>:<Max links>
117
118    <ClientAuth>
119
120        This section is used to define client authentications.
121
122        Format:
123
124        +<Remote address or name>:<auth method>:<password/cert/key/???>:<Port>:<Class>
125
126    <AdminAuth>
127
128        This section is used to define the server's administration 
129        authentications.
130
131        Format:
132
133        +<Hostname>:<auth method>:<password/cert/key/???>:<Nickname hash>:<Class>
134
135    <ServerConnection>
136
137        This section is used to define the server connections to this
138        server/router. Only routers can have normal server connections.
139        Normal servers leave this section epmty. The remote server cannot be
140        older than specified Version ID.
141
142        Format:
143
144        +<Remote address or name>:<auth method>:<password/key/???>:<Port>:<Version ID>:<Class>
145
146    <RouterConnection>
147
148        This section is used to define the router connections to this
149        server/router. Both normal server and router can have router
150        connections. Normal server usually has only one connection while
151        a router can have multiple. The remote server cannot be older than
152        specified Version ID.
153
154        Format:
155
156        +<Remote address or name>:<auth method>:<password/key/???>:<Port>:<Version ID>:<Class>
157
158    <DenyConnection>
159
160        This section is used to deny specific connections to your server. This
161        can be used to deny both clients and servers.
162
163        Format:
164
165        +<Remote address or name or nickname>:<Time interval>:<Comment>:<Port>
166
167    <RedirectClient>
168
169        This section is used to set the alternate servers that clients will be
170        redirected to when our server is full.
171
172        Format:
173
174        +<Remote address or name>:<Port>
175
176 */
177 SilcConfigServerSection silc_config_server_sections[] = {
178   { "[Cipher]", 
179     SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
180   { "[PKCS]", 
181     SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 2 },
182   { "[HashFunction]", 
183     SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
184   { "[ServerInfo]", 
185     SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, 4 },
186   { "[AdminInfo]", 
187     SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, 4 },
188   { "[ListenPort]", 
189     SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, 3 },
190   { "[Logging]", 
191     SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, 3 },
192   { "[ConnectionClass]", 
193     SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS, 4 },
194   { "[ClientConnection]", 
195     SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION, 5 },
196   { "[ServerConnection]", 
197     SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION, 6 },
198   { "[RouterConnection]", 
199     SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION, 6 },
200   { "[AdminConnection]", 
201     SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION, 5 },
202   { "[DenyConnection]", 
203     SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION, 4 },
204   { "[RedirectClient]", 
205     SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT, 2 },
206   { "[motd]", 
207     SILC_CONFIG_SERVER_SECTION_TYPE_MOTD, 1 },
208   
209   { NULL, SILC_CONFIG_SERVER_SECTION_TYPE_NONE, 0 }
210 };
211
212 /* Allocates a new configuration object, opens configuration file and
213    parses the file. The parsed data is returned to the newly allocated
214    configuration object. */
215
216 SilcConfigServer silc_config_server_alloc(char *filename)
217 {
218   SilcConfigServer new;
219   SilcBuffer buffer;
220   SilcConfigServerParse config_parse;
221
222   SILC_LOG_DEBUG(("Allocating new configuration object"));
223
224   new = silc_calloc(1, sizeof(*new));
225   if (!new) {
226     fprintf(stderr, "Could not allocate new configuration object");
227     return NULL;
228   }
229
230   new->filename = filename;
231
232   /* Open configuration file and parse it */
233   config_parse = NULL;
234   buffer = NULL;
235   silc_config_open(filename, &buffer);
236   if (!buffer)
237     goto fail;
238   if ((silc_config_server_parse(new, buffer, &config_parse)) == FALSE)
239     goto fail;
240   if ((silc_config_server_parse_lines(new, config_parse)) == FALSE)
241     goto fail;
242
243   silc_free(buffer);
244
245   return new;
246
247  fail:
248   silc_free(new);
249   return NULL;
250 }
251
252 /* Free's a configuration object. */
253
254 void silc_config_server_free(SilcConfigServer config)
255 {
256   if (config) {
257     silc_free(config->filename);
258     silc_free(config->server_info);
259     silc_free(config->admin_info);
260     silc_free(config->listen_port);
261     silc_free(config->conn_class);
262     silc_free(config->clients);
263     silc_free(config->admins);
264     silc_free(config->servers);
265     silc_free(config->routers);
266     silc_free(config->denied);
267     silc_free(config->redirect);
268     silc_free(config->motd);
269     silc_free(config);
270   }
271 }
272
273 /* Parses the the buffer and returns the parsed lines into return_config
274    argument. The return_config argument doesn't have to be initialized 
275    before calling this. It will be initialized during the parsing. The
276    buffer sent as argument can be safely free'd after this function has
277    succesfully returned. */
278
279 int silc_config_server_parse(SilcConfigServer config, SilcBuffer buffer, 
280                              SilcConfigServerParse *return_config)
281 {
282   int i, begin;
283   unsigned int linenum;
284   char line[1024], *cp;
285   SilcConfigServerSection *cptr = NULL;
286   SilcConfigServerParse parse = *return_config, first = NULL;
287
288   SILC_LOG_DEBUG(("Parsing configuration file"));
289
290   begin = 0;
291   linenum = 0;
292   while((begin = silc_gets(line, sizeof(line), 
293                            buffer->data, buffer->len, begin)) != EOF) {
294     cp = line;
295     linenum++;
296
297     /* Check for bad line */
298     if (silc_check_line(cp))
299       continue;
300
301     /* Remove tabs and whitespaces from the line */
302     if (strchr(cp, '\t')) {
303       i = 0;
304       while(strchr(cp + i, '\t')) {
305         *strchr(cp + i, '\t') = ' ';
306         i++;
307       }
308     }
309     for (i = 0; i < strlen(cp); i++) {
310       if (cp[i] != ' ') {
311         if (i)
312           cp++;
313         break;
314       }
315       cp++;
316     }
317
318     /* Parse line */
319     switch(cp[0]) {
320     case '[':
321       /*
322        * Start of a section
323        */
324
325       /* Remove new line sign */
326       if (strchr(cp, '\n'))
327         *strchr(cp, '\n') = '\0';
328       
329       /* Check for matching sections */
330       for (cptr = silc_config_server_sections; cptr->section; cptr++)
331         if (!strncasecmp(cp, cptr->section, strlen(cptr->section)))
332           break;
333
334       if (!cptr->section) {
335         fprintf(stderr, "%s:%d: Unknown section `%s'\n", 
336                         config->filename, linenum, cp);
337         return FALSE;
338       }
339
340       break;
341     default:
342       /*
343        * Start of a configuration line
344        */
345
346       if (cptr->type != SILC_CONFIG_SERVER_SECTION_TYPE_NONE) {
347         
348         if (strchr(cp, '\n'))
349             *strchr(cp, '\n') = ':';
350
351         if (parse == NULL) {
352           parse = silc_calloc(1, sizeof(*parse));
353           parse->line = NULL;
354           parse->section = NULL;
355           parse->next = NULL;
356           parse->prev = NULL;
357         } else {
358           if (parse->next == NULL) {
359             parse->next = silc_calloc(1, sizeof(*parse->next));
360             parse->next->line = NULL;
361             parse->next->section = NULL;
362             parse->next->next = NULL;
363             parse->next->prev = parse;
364             parse = parse->next;
365           }
366         }
367         
368         if (first == NULL)
369           first = parse;
370
371         /* Add the line to parsing structure for further parsing. */
372         if (parse) {
373           parse->section = cptr;
374           parse->line = silc_buffer_alloc(strlen(cp) + 1);
375           parse->linenum = linenum;
376           silc_buffer_pull_tail(parse->line, strlen(cp));
377           silc_buffer_put(parse->line, cp, strlen(cp));
378         }
379       }
380       break;
381     }
382   }
383   
384   /* Set the return_config argument to its first value so that further
385      parsing can be started from the first line. */
386   *return_config = first;
387
388   return TRUE;
389 }
390
391 /* Parses the lines earlier read from configuration file. The config object
392    must not be initialized, it will be initialized in this function. The
393    parse_config argument is uninitialized automatically during this
394    function. */
395
396 int silc_config_server_parse_lines(SilcConfigServer config, 
397                                    SilcConfigServerParse parse_config)
398 {
399   int ret, check = FALSE;
400   unsigned int checkmask;
401   char *tmp;
402   SilcConfigServerParse pc = parse_config;
403   SilcBuffer line;
404
405   SILC_LOG_DEBUG(("Parsing configuration lines"));
406   
407   if (!config)
408     return FALSE;
409   
410   checkmask = 0;
411   while(pc) {
412     check = FALSE;
413     line = pc->line;
414
415     /* Get number of tokens in line */
416     ret = silc_config_check_num_token(line);
417     if (ret != pc->section->maxfields) {
418       /* Bad line */
419       fprintf(stderr, "%s:%d: Missing tokens, %d tokens (should be %d)\n",
420               config->filename, pc->linenum, ret, 
421               pc->section->maxfields);
422       break;
423     }
424
425     /* Parse the line */
426     switch(pc->section->type) {
427     case SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER:
428
429       SILC_SERVER_CONFIG_LIST_ALLOC(config->cipher);
430
431       /* Get cipher name */
432       ret = silc_config_get_token(line, &config->cipher->alg_name);
433       if (ret < 0)
434         break;
435       if (ret == 0) {
436         fprintf(stderr, "%s:%d: Cipher name not defined\n",
437                 config->filename, pc->linenum);
438         break;
439       }
440
441       /* Get module name */
442       config->cipher->sim_name = NULL;
443       ret = silc_config_get_token(line, &config->cipher->sim_name);
444       if (ret < 0)
445         break;
446
447       /* Get block length */
448       ret = silc_config_get_token(line, &tmp);
449       if (ret < 0)
450         break;
451       if (ret == 0) {
452         fprintf(stderr, "%s:%d: Cipher block length not defined\n",
453                 config->filename, pc->linenum);
454         break;
455       }
456       config->cipher->block_len = atoi(tmp);
457       silc_free(tmp);
458
459       /* Get key length */
460       ret = silc_config_get_token(line, &tmp);
461       if (ret < 0)
462         break;
463       if (ret == 0) {
464         fprintf(stderr, "%s:%d: Cipher key length not defined\n",
465                 config->filename, pc->linenum);
466         break;
467       }
468       config->cipher->key_len = atoi(tmp);
469       silc_free(tmp);
470
471       check = TRUE;
472       checkmask |= (1L << pc->section->type);
473       break;
474
475     case SILC_CONFIG_SERVER_SECTION_TYPE_PKCS:
476
477       SILC_SERVER_CONFIG_LIST_ALLOC(config->pkcs);
478
479       /* Get PKCS name */
480       ret = silc_config_get_token(line, &config->pkcs->alg_name);
481       if (ret < 0)
482         break;
483       if (ret == 0) {
484         fprintf(stderr, "%s:%d: PKCS name not defined\n",
485                 config->filename, pc->linenum);
486         break;
487       }
488
489       /* Get key length */
490       ret = silc_config_get_token(line, &tmp);
491       if (ret < 0)
492         break;
493       if (ret == 0) {
494         fprintf(stderr, "%s:%d: PKCS key length not defined\n",
495                 config->filename, pc->linenum);
496         break;
497       }
498       config->pkcs->key_len = atoi(tmp);
499       silc_free(tmp);
500
501       check = TRUE;
502       checkmask |= (1L << pc->section->type);
503       break;
504
505     case SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION:
506
507       SILC_SERVER_CONFIG_LIST_ALLOC(config->hash_func);
508
509       /* Get Hash function name */
510       ret = silc_config_get_token(line, &config->hash_func->alg_name);
511       if (ret < 0)
512         break;
513       if (ret == 0) {
514         fprintf(stderr, "%s:%d: Hash function name not defined\n",
515                 config->filename, pc->linenum);
516         break;
517       }
518       
519       /* Get Hash function module name */
520       config->hash_func->sim_name = NULL;
521       ret = silc_config_get_token(line, &config->hash_func->sim_name);
522       if (ret < 0)
523         break;
524
525       /* Get block length */
526       ret = silc_config_get_token(line, &tmp);
527       if (ret < 0)
528         break;
529       if (ret == 0) {
530         fprintf(stderr, "%s:%d: Hash function block length not defined\n",
531                 config->filename, pc->linenum);
532         break;
533       }
534       config->hash_func->block_len = atoi(tmp);
535       silc_free(tmp);
536
537       /* Get hash length */
538       ret = silc_config_get_token(line, &tmp);
539       if (ret < 0)
540         break;
541       if (ret == 0) {
542         fprintf(stderr, "%s:%d: Hash function hash length not defined\n",
543                 config->filename, pc->linenum);
544         break;
545       }
546       config->hash_func->key_len = atoi(tmp);
547       silc_free(tmp);
548
549       check = TRUE;
550       checkmask |= (1L << pc->section->type);
551       break;
552
553     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO:
554
555       if (!config->server_info)
556         config->server_info = silc_calloc(1, sizeof(*config->server_info));
557
558       /* Get server name */
559       ret = silc_config_get_token(line, &config->server_info->server_name);
560       if (ret < 0)
561         break;
562       if (ret == 0) {
563         /* Server name not defined */
564
565       }
566       
567       /* Get server IP */
568       ret = silc_config_get_token(line, &config->server_info->server_ip);
569       if (ret < 0)
570         break;
571       if (ret == 0) {
572         /* Server IP not defined */
573
574       }
575
576       /* Get server location */
577       ret = silc_config_get_token(line, &config->server_info->location);
578       if (ret < 0)
579         break;
580
581       /* Get server port */
582       /* XXX: Need port here??? */
583       ret = silc_config_get_token(line, &tmp);
584       if (ret < 0)
585         break;
586       if (ret == 0) {
587         /* Port not defined */
588
589       }
590       config->server_info->port = atoi(tmp);
591       silc_free(tmp);
592
593       check = TRUE;
594       checkmask |= (1L << pc->section->type);
595       break;
596
597     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO:
598
599       if (!config->admin_info)
600         config->admin_info = silc_calloc(1, sizeof(*config->admin_info));
601
602       /* Get location */
603       ret = silc_config_get_token(line, &config->admin_info->location);
604       if (ret < 0)
605         break;
606
607       /* Get server type */
608       ret = silc_config_get_token(line, &config->admin_info->server_type);
609       if (ret < 0)
610         break;
611
612       /* Get admins name */
613       ret = silc_config_get_token(line, &config->admin_info->admin_name);
614       if (ret < 0)
615         break;
616
617       /* Get admins email address */
618       ret = silc_config_get_token(line, &config->admin_info->admin_email);
619       if (ret < 0)
620         break;
621
622       check = TRUE;
623       checkmask |= (1L << pc->section->type);
624       break;
625
626     case SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT:
627
628       SILC_SERVER_CONFIG_LIST_ALLOC(config->listen_port);
629
630       /* Get host */
631       ret = silc_config_get_token(line, &config->listen_port->host);
632       if (ret < 0)
633         break;
634
635       /* Get remote IP */
636       ret = silc_config_get_token(line, &config->listen_port->remote_ip);
637       if (ret < 0)
638         break;
639
640       /* Get port */
641       ret = silc_config_get_token(line, &tmp);
642       if (ret < 0)
643         break;
644       if (ret == 0) {
645         /* Any port */
646         config->listen_port->port = 0;
647       } else {
648         config->listen_port->port = atoi(tmp);
649         silc_free(tmp);
650       }
651
652       check = TRUE;
653       checkmask |= (1L << pc->section->type);
654       break;
655
656     case SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS:
657
658       SILC_SERVER_CONFIG_LIST_ALLOC(config->conn_class);
659
660       /* Get class number */
661       ret = silc_config_get_token(line, &tmp);
662       if (ret < 0)
663         break;
664       if (ret == 0) {
665         /* Class number not defined */
666
667       }
668       config->conn_class->class = atoi(tmp);
669       silc_free(tmp);
670
671       /* Get ping frequency */
672       ret = silc_config_get_token(line, &tmp);
673       if (ret < 0)
674         break;
675       config->conn_class->ping_freq = atoi(tmp);
676       silc_free(tmp);
677
678       /* Get connect frequency */
679       ret = silc_config_get_token(line, &tmp);
680       if (ret < 0)
681         break;
682       config->conn_class->connect_freq = atoi(tmp);
683       silc_free(tmp);
684
685       /* Get max links */
686       ret = silc_config_get_token(line, &tmp);
687       if (ret < 0)
688         break;
689       config->conn_class->max_links = atoi(tmp);
690       silc_free(tmp);
691
692       check = TRUE;
693       checkmask |= (1L << pc->section->type);
694       break;
695
696     case SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING:
697
698       SILC_SERVER_CONFIG_LIST_ALLOC(config->logging);
699
700       /* Get log section type and check it */
701       ret = silc_config_get_token(line, &config->logging->logtype);
702       if (ret < 0)
703         break;
704       if (ret == 0) {
705         fprintf(stderr, "%s:%d: Log file section not defined\n", 
706                 config->filename, pc->linenum);
707         break;
708       }
709       if (strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_INFO)
710           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_WARNING)
711           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_ERROR)
712           && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
713         fprintf(stderr, "%s:%d: Unknown log file section '%s'\n",
714                 config->filename, pc->linenum, config->logging->logtype);
715         break;
716       }
717
718       /* Get log filename */
719       ret = silc_config_get_token(line, &config->logging->filename);
720       if (ret < 0)
721         break;
722       if (ret == 0) {
723         fprintf(stderr, "%s:%d: Log file name not defined\n",
724                 config->filename, pc->linenum);
725         break;
726       }
727
728       /* Get max byte size */
729       ret = silc_config_get_token(line, &tmp);
730       if (ret < 0)
731         break;
732       if (ret) {
733         config->logging->maxsize = atoi(tmp);
734         silc_free(tmp);
735       }
736
737       check = TRUE;
738       checkmask |= (1L << pc->section->type);
739       break;
740
741     case SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION:
742
743       SILC_SERVER_CONFIG_LIST_ALLOC(config->clients);
744
745       /* Get host */
746       ret = silc_config_get_token(line, &config->clients->host);
747       if (ret < 0)
748         break;
749       if (ret == 0)
750         /* Any host */
751         config->clients->host = strdup("*");
752
753       /* Get authentication method */
754       ret = silc_config_get_token(line, &tmp);
755       if (ret < 0)
756         break;
757       if (ret) {
758         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
759             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
760           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
761                   config->filename, pc->linenum, tmp);
762           break;
763         }
764
765         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
766           config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
767
768         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
769           config->clients->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
770
771         silc_free(tmp);
772       }
773
774       /* Get authentication data */
775       ret = silc_config_get_token(line, &config->clients->auth_data);
776       if (ret < 0)
777         break;
778       if (ret == 0)
779         /* Any host */
780         config->clients->host = strdup("*");
781
782       /* Get port */
783       ret = silc_config_get_token(line, &tmp);
784       if (ret < 0)
785         break;
786       if (ret == 0) {
787         config->clients->port = atoi(tmp);
788         silc_free(tmp);
789       }
790
791       /* Get class number */
792       ret = silc_config_get_token(line, &tmp);
793       if (ret < 0)
794         break;
795       if (ret) {
796         config->clients->class = atoi(tmp);
797         silc_free(tmp);
798       }
799
800       check = TRUE;
801       checkmask |= (1L << pc->section->type);
802       break;
803
804     case SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION:
805
806       SILC_SERVER_CONFIG_LIST_ALLOC(config->servers);
807
808       /* Get host */
809       ret = silc_config_get_token(line, &config->servers->host);
810       if (ret < 0)
811         break;
812       if (ret == 0)
813         /* Any host */
814         config->servers->host = strdup("*");
815
816       /* Get authentication method */
817       ret = silc_config_get_token(line, &tmp);
818       if (ret < 0)
819         break;
820       if (ret) {
821         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
822             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
823           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
824                   config->filename, pc->linenum, tmp);
825           break;
826         }
827
828         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
829           config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
830
831         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
832           config->servers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
833
834         silc_free(tmp);
835       }
836
837       /* Get authentication data */
838       ret = silc_config_get_token(line, &config->servers->auth_data);
839       if (ret < 0)
840         break;
841
842       /* Get port */
843       ret = silc_config_get_token(line, &tmp);
844       if (ret < 0)
845         break;
846       if (ret) {
847         config->servers->port = atoi(tmp);
848         silc_free(tmp);
849       }
850
851       /* Get version */
852       ret = silc_config_get_token(line, &config->servers->version);
853       if (ret < 0)
854         break;
855
856       /* Get class number */
857       ret = silc_config_get_token(line, &tmp);
858       if (ret < 0)
859         break;
860       if (ret) {
861         config->servers->class = atoi(tmp);
862         silc_free(tmp);
863       }
864
865       check = TRUE;
866       checkmask |= (1L << pc->section->type);
867       break;
868
869     case SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION:
870
871       SILC_SERVER_CONFIG_LIST_ALLOC(config->routers);
872
873       /* Get host */
874       ret = silc_config_get_token(line, &config->routers->host);
875       if (ret < 0)
876         break;
877       //      if (ret == 0)
878       ///* Any host */
879       //        config->routers->host = strdup("*");
880
881       /* Get authentication method */
882       ret = silc_config_get_token(line, &tmp);
883       if (ret < 0)
884         break;
885       if (ret) {
886         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
887             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
888           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
889                   config->filename, pc->linenum, tmp);
890           break;
891         }
892
893         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
894           config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
895
896         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
897           config->routers->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
898
899         silc_free(tmp);
900       }
901
902       /* Get authentication data */
903       ret = silc_config_get_token(line, &config->routers->auth_data);
904       if (ret < 0)
905         break;
906
907       /* Get port */
908       ret = silc_config_get_token(line, &tmp);
909       if (ret < 0)
910         break;
911       if (ret) {
912         config->routers->port = atoi(tmp);
913         silc_free(tmp);
914       }
915
916       /* Get version */
917       ret = silc_config_get_token(line, &config->routers->version);
918       if (ret < 0)
919         break;
920
921       /* Get class number */
922       ret = silc_config_get_token(line, &tmp);
923       if (ret < 0)
924         break;
925       if (ret) {
926         config->routers->class = atoi(tmp);
927         silc_free(tmp);
928       }
929
930       check = TRUE;
931       checkmask |= (1L << pc->section->type);
932       break;
933
934     case SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION:
935
936       SILC_SERVER_CONFIG_LIST_ALLOC(config->admins);
937
938       /* Get host */
939       ret = silc_config_get_token(line, &config->admins->host);
940       if (ret < 0)
941         break;
942       if (ret == 0)
943         /* Any host */
944         config->admins->host = strdup("*");
945
946       /* Get authentication method */
947       ret = silc_config_get_token(line, &tmp);
948       if (ret < 0)
949         break;
950       if (ret) {
951         if (strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD) &&
952             strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY)) {
953           fprintf(stderr, "%s:%d: Unknown authentication method '%s'\n",
954                   config->filename, pc->linenum, tmp);
955           break;
956         }
957
958         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PASSWD))
959           config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
960
961         if (!strcmp(tmp, SILC_CONFIG_SERVER_AUTH_METH_PUBKEY))
962           config->admins->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
963
964         silc_free(tmp);
965       }
966
967       /* Get authentication data */
968       ret = silc_config_get_token(line, &config->admins->auth_data);
969       if (ret < 0)
970         break;
971
972       /* Get nickname */
973       ret = silc_config_get_token(line, &config->admins->nickname);
974       if (ret < 0)
975         break;
976
977       /* Get class number */
978       ret = silc_config_get_token(line, &tmp);
979       if (ret < 0)
980         break;
981       if (ret) {
982         config->admins->class = atoi(tmp);
983         silc_free(tmp);
984       }
985
986       check = TRUE;
987       checkmask |= (1L << pc->section->type);
988       break;
989
990     case SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION:
991       /* Not implemented yet */
992       check = TRUE;
993       break;
994
995     case SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT:
996       /* Not implemented yet */
997       check = TRUE;
998       break;
999
1000     case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
1001
1002       if (!config->motd)
1003         config->motd = silc_calloc(1, sizeof(*config->motd));
1004
1005       /* Get motd file */
1006       ret = silc_config_get_token(line, &config->motd->motd_file);
1007       if (ret < 0)
1008         break;
1009
1010       check = TRUE;
1011       checkmask |= (1L << pc->section->type);
1012       break;
1013
1014     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
1015     default:
1016       /* Error */
1017       break;
1018     }
1019
1020     /* Check for error */
1021     if (check == FALSE) {
1022       /* Line could not be parsed */
1023       fprintf(stderr, "%s:%d: Parse error\n", config->filename, pc->linenum);
1024       break;
1025     }
1026
1027     pc = pc->next;
1028     /* XXXX */
1029     //    silc_free(pc->prev);
1030     //    pc->prev = NULL;
1031   }
1032
1033   if (check == FALSE)
1034     return FALSE;;
1035
1036   /* Check that all mandatory sections really were found. If not, the server
1037      cannot function and we return error. */
1038   ret = silc_config_server_check_sections(checkmask);
1039   if (ret == FALSE) {
1040     /* XXX */
1041
1042   }
1043   
1044   /* Before returning all the lists in the config object must be set
1045      to their first values (the last value is first here). */
1046   while (config->cipher && config->cipher->prev)
1047     config->cipher = config->cipher->prev;
1048   while (config->pkcs && config->pkcs->prev)
1049     config->pkcs = config->pkcs->prev;
1050   while (config->hash_func && config->hash_func->prev)
1051     config->hash_func = config->hash_func->prev;
1052   while (config->listen_port && config->listen_port->prev)
1053     config->listen_port = config->listen_port->prev;
1054   while (config->logging && config->logging->prev)
1055     config->logging = config->logging->prev;
1056   while (config->conn_class && config->conn_class->prev)
1057     config->conn_class = config->conn_class->prev;
1058   while (config->clients && config->clients->prev)
1059     config->clients = config->clients->prev;
1060   while (config->servers && config->servers->prev)
1061     config->servers = config->servers->prev;
1062   while (config->routers && config->routers->prev)
1063     config->routers = config->routers->prev;
1064   
1065   SILC_LOG_DEBUG(("Done"));
1066   
1067   return TRUE;
1068 }
1069
1070 /* This function checks that the mask sent as argument includes all the 
1071    sections that are mandatory in SILC server. */
1072
1073 int silc_config_server_check_sections(unsigned int checkmask)
1074 {
1075   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO))) {
1076     
1077     return FALSE;
1078   }
1079   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO))) {
1080     
1081     return FALSE;
1082   }
1083   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT))) {
1084     
1085     return FALSE;
1086   }
1087   if (!(checkmask & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_CLIENT_CONNECTION))) {
1088     
1089     return FALSE;
1090   }
1091   if (!(checkmask 
1092         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION))) {
1093     
1094     return FALSE;
1095   }
1096   if (!(checkmask 
1097         & (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
1098     
1099     return FALSE;
1100   }
1101
1102   return TRUE;
1103 }
1104
1105 /* Sets log files where log messages is saved by the server. */
1106
1107 void silc_config_server_setlogfiles(SilcConfigServer config)
1108 {
1109   SilcConfigServerSectionLogging *log;
1110   char *info, *warning, *error, *fatal;
1111   unsigned int info_size, warning_size, error_size, fatal_size;
1112
1113   SILC_LOG_DEBUG(("Setting configured log file names"));
1114
1115   /* Set default files before checking configuration */
1116   info = SILC_LOG_FILE_INFO;
1117   warning = SILC_LOG_FILE_WARNING;
1118   error = SILC_LOG_FILE_ERROR;
1119   fatal = SILC_LOG_FILE_FATAL;
1120   info_size = 0;
1121   warning_size = 0;
1122   error_size = 0;
1123   fatal_size = 0;
1124
1125   log = config->logging;
1126   while(log) {
1127     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
1128       info = log->filename;
1129       info_size = log->maxsize;
1130     }
1131     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
1132       warning = log->filename;
1133       warning_size = log->maxsize;
1134     }
1135     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
1136       error = log->filename;
1137       error_size = log->maxsize;
1138     }
1139     if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
1140       fatal = log->filename;
1141       fatal_size = log->maxsize;
1142     }
1143
1144     log = log->next;
1145   }
1146
1147   silc_log_set_files(info, info_size, warning, warning_size,
1148                      error, error_size, fatal, fatal_size);
1149 }
1150
1151 /* Registers configured ciphers. These can then be allocated by the
1152    server when needed. */
1153
1154 void silc_config_server_register_ciphers(SilcConfigServer config)
1155 {
1156   SilcConfigServerSectionAlg *alg;
1157   SilcServer server = (SilcServer)config->server;
1158
1159   SILC_LOG_DEBUG(("Registering configured ciphers"));
1160
1161   alg = config->cipher;
1162   while(alg) {
1163
1164     if (!alg->sim_name) {
1165       /* Crypto module is supposed to be built in. Nothing to be done
1166          here except to test that the cipher really is built in. */
1167       SilcCipher tmp = NULL;
1168
1169       if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
1170         SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
1171         silc_server_stop(server);
1172         exit(1);
1173       }
1174       silc_cipher_free(tmp);
1175
1176 #ifdef SILC_SIM
1177     } else {
1178       /* Load (try at least) the crypto SIM module */
1179       SilcCipherObject cipher;
1180       SilcSimContext *sim;
1181
1182       memset(&cipher, 0, sizeof(cipher));
1183       cipher.name = alg->alg_name;
1184       cipher.block_len = alg->block_len;
1185       cipher.key_len = alg->key_len * 8;
1186
1187       sim = silc_sim_alloc();
1188       sim->type = SILC_SIM_CIPHER;
1189       sim->libname = alg->sim_name;
1190
1191       if ((silc_sim_load(sim))) {
1192         cipher.set_key = 
1193           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1194                                                 SILC_CIPHER_SIM_SET_KEY));
1195         SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
1196         cipher.set_key_with_string = 
1197           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1198                                                 SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
1199         SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
1200         cipher.encrypt = 
1201           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1202                                                 SILC_CIPHER_SIM_ENCRYPT_CBC));
1203         SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
1204         cipher.decrypt = 
1205           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1206                                                 SILC_CIPHER_SIM_DECRYPT_CBC));
1207         SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
1208         cipher.context_len = 
1209           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1210                                                 SILC_CIPHER_SIM_CONTEXT_LEN));
1211         SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
1212
1213         /* Put the SIM to the list of all SIM's in server */
1214         silc_dlist_add(server->sim, sim);
1215       } else {
1216         SILC_LOG_ERROR(("Error configuring ciphers"));
1217         silc_server_stop(server);
1218         exit(1);
1219       }
1220
1221       /* Register the cipher */
1222       silc_cipher_register(&cipher);
1223 #endif
1224     }
1225
1226     alg = alg->next;
1227   }
1228 }
1229
1230 /* Registers configured PKCS's. */
1231 /* XXX: This really doesn't do anything now since we have statically
1232    registered our PKCS's. This should be implemented when PKCS works
1233    as SIM's. This checks now only that the PKCS user requested is 
1234    really out there. */
1235
1236 void silc_config_server_register_pkcs(SilcConfigServer config)
1237 {
1238   SilcConfigServerSectionAlg *alg = config->pkcs;
1239   SilcServer server = (SilcServer)config->server;
1240   SilcPKCS tmp = NULL;
1241
1242   SILC_LOG_DEBUG(("Registering configured PKCS"));
1243
1244   while(alg) {
1245
1246     if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
1247       SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
1248       silc_server_stop(server);
1249       exit(1);
1250     }
1251     silc_free(tmp);
1252
1253     alg = alg->next;
1254   }
1255 }
1256
1257 /* Registers configured hash functions. These can then be allocated by the
1258    server when needed. */
1259
1260 void silc_config_server_register_hashfuncs(SilcConfigServer config)
1261 {
1262   SilcConfigServerSectionAlg *alg;
1263   SilcServer server = (SilcServer)config->server;
1264
1265   SILC_LOG_DEBUG(("Registering configured hash functions"));
1266
1267   alg = config->hash_func;
1268   while(alg) {
1269
1270     if (!alg->sim_name) {
1271       /* Hash module is supposed to be built in. Nothing to be done
1272          here except to test that the hash function really is built in. */
1273       SilcHash tmp = NULL;
1274
1275       if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
1276         SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
1277         silc_server_stop(server);
1278         exit(1);
1279       }
1280       silc_free(tmp);
1281
1282 #ifdef SILC_SIM
1283     } else {
1284       /* Load (try at least) the hash SIM module */
1285       SilcHashObject hash;
1286       SilcSimContext *sim;
1287
1288       memset(&hash, 0, sizeof(hash));
1289       hash.name = alg->alg_name;
1290       hash.block_len = alg->block_len;
1291       hash.hash_len = alg->key_len;
1292
1293       sim = silc_sim_alloc();
1294       sim->type = SILC_SIM_HASH;
1295       sim->libname = alg->sim_name;
1296
1297       if ((silc_sim_load(sim))) {
1298         hash.init = 
1299           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
1300                                                 SILC_HASH_SIM_INIT));
1301         SILC_LOG_DEBUG(("init=%p", hash.init));
1302         hash.update = 
1303           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1304                                                 SILC_HASH_SIM_UPDATE));
1305         SILC_LOG_DEBUG(("update=%p", hash.update));
1306         hash.final = 
1307           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1308                                                 SILC_HASH_SIM_FINAL));
1309         SILC_LOG_DEBUG(("final=%p", hash.final));
1310         hash.context_len = 
1311           silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
1312                                                 SILC_HASH_SIM_CONTEXT_LEN));
1313         SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
1314
1315         /* Put the SIM to the table of all SIM's in server */
1316         silc_dlist_add(server->sim, sim);
1317       } else {
1318         SILC_LOG_ERROR(("Error configuring hash functions"));
1319         silc_server_stop(server);
1320         exit(1);
1321       }
1322
1323       /* Register the cipher */
1324       silc_hash_register(&hash);
1325 #endif
1326     }
1327
1328     alg = alg->next;
1329   }
1330 }
1331
1332 /* Returns client authentication information from server configuration
1333    by host (name or ip). */
1334
1335 SilcConfigServerSectionClientConnection *
1336 silc_config_server_find_client_conn(SilcConfigServer config, 
1337                                     char *host, int port)
1338 {
1339   int i;
1340   SilcConfigServerSectionClientConnection *client = NULL;
1341
1342   if (!host)
1343     return NULL;
1344
1345   if (!config->clients)
1346     return NULL;
1347
1348   client = config->clients;
1349
1350   for (i = 0; client; i++) {
1351     if (silc_string_compare(client->host, host))
1352       break;
1353     client = client->next;
1354   }
1355
1356   if (!client)
1357     return NULL;
1358
1359   return client;
1360 }
1361
1362 /* Returns server connection info from server configuartion by host 
1363    (name or ip). */
1364
1365 SilcConfigServerSectionServerConnection *
1366 silc_config_server_find_server_conn(SilcConfigServer config, 
1367                                     char *host, int port)
1368 {
1369   int i;
1370   SilcConfigServerSectionServerConnection *serv = NULL;
1371
1372   if (!host)
1373     return NULL;
1374
1375   if (!config->servers)
1376     return NULL;
1377
1378   serv = config->servers;
1379   for (i = 0; serv; i++) {
1380     if (silc_string_compare(serv->host, host))
1381       break;
1382     serv = serv->next;
1383   }
1384
1385   if (!serv)
1386     return NULL;
1387
1388   return serv;
1389 }
1390
1391 /* Returns router connection info from server configuartion by
1392    host (name or ip). */
1393
1394 SilcConfigServerSectionServerConnection *
1395 silc_config_server_find_router_conn(SilcConfigServer config, 
1396                                     char *host, int port)
1397 {
1398   int i;
1399   SilcConfigServerSectionServerConnection *serv = NULL;
1400
1401   if (!host)
1402     return NULL;
1403
1404   if (!config->routers)
1405     return NULL;
1406
1407   serv = config->routers;
1408   for (i = 0; serv; i++) {
1409     if (silc_string_compare(serv->host, host))
1410       break;
1411     serv = serv->next;
1412   }
1413
1414   if (!serv)
1415     return NULL;
1416
1417   return serv;
1418 }
1419
1420 /* Prints out example configuration file with default built in
1421    configuration values. */
1422
1423 void silc_config_server_print()
1424 {
1425   char *buf;
1426
1427   buf = "\
1428 #\n\
1429 # Automatically generated example SILCd configuration file with default\n\
1430 # built in values. Use this as a guide to configure your SILCd configuration\n\
1431 # file for your system. For detailed description of different configuration\n\
1432 # sections refer to silcd(8) manual page.\n\
1433 #\n";
1434   /*
1435 #<Cipher>
1436 #+blowfish
1437 #+twofish
1438 #+rc5
1439 #+rc6
1440 #+3des
1441
1442 #<HashFunction>
1443 #+md5
1444 #+sha1
1445
1446 <ServerInfo>
1447 +lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:1333
1448
1449 <AdminInfo>
1450 +Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
1451
1452 <ListenPort>
1453 +10.2.1.6:10.2.1.6:1333
1454
1455 <Logging>
1456 +infologfile:silcd.log:10000
1457 #+warninglogfile:/var/log/silcd_warning.log:10000
1458 #+errorlogfile:ERROR.log:10000
1459 #+fatallogfile:/var/log/silcd_error.log:
1460
1461 <ConnectionClass>
1462                 +1:100:100:100
1463                         +2:200:300:400
1464
1465 <ClientAuth>
1466 +10.2.1.199:priikone:333:1
1467
1468 <AdminAuth>
1469 +10.2.1.199:priikone:priikone:1
1470
1471 <ServerConnection>
1472
1473 <RouterConnection>
1474
1475 <DenyConnection>
1476 <RedirectClient>
1477   */
1478
1479   fprintf(stdout, "%s\n", buf);
1480 }