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