updates.
[silc.git] / apps / silcd / server_util.c
1 /*
2
3   server_util.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2001 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 /* Removes the client from channels and possibly removes the channels
25    as well.  After removing those channels that exist, their channel
26    keys are regnerated. This is called only by the function
27    silc_server_remove_clients_by_server. */
28
29 static void silc_server_remove_clients_channels(SilcServer server, 
30                                                 SilcSocketConnection sock,
31                                                 SilcClientEntry client,
32                                                 SilcHashTable channels)
33 {
34   SilcChannelEntry channel;
35   SilcChannelClientEntry chl;
36   SilcHashTableList htl;
37   SilcBuffer clidp;
38
39   SILC_LOG_DEBUG(("Start"));
40
41   if (!client || !client->id)
42     return;
43
44   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
45
46   /* Remove the client from all channels. The client is removed from
47      the channels' user list. */
48   silc_hash_table_list(client->channels, &htl);
49   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
50     channel = chl->channel;
51
52     /* Remove channel from client's channel list */
53     silc_hash_table_del(client->channels, channel);
54
55     /* Remove channel if there is no users anymore */
56     if (server->server_type == SILC_ROUTER &&
57         silc_hash_table_count(channel->user_list) < 2) {
58
59       if (silc_hash_table_find(channels, channel, NULL, NULL))
60         silc_hash_table_del(channels, channel);
61
62       if (channel->rekey)
63         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
64
65       if (silc_idlist_del_channel(server->local_list, channel))
66         server->stat.my_channels--;
67       else 
68         silc_idlist_del_channel(server->global_list, channel);
69       continue;
70     }
71
72     /* Remove client from channel's client list */
73     silc_hash_table_del(channel->user_list, chl->client);
74     channel->user_count--;
75
76     /* If there is no global users on the channel anymore mark the channel
77        as local channel. Do not check if the removed client is local client. */
78     if (server->server_type != SILC_ROUTER && channel->global_users && 
79         chl->client->router && !silc_server_channel_has_global(channel))
80       channel->global_users = FALSE;
81
82     silc_free(chl);
83     server->stat.my_chanclients--;
84
85     /* If there is not at least one local user on the channel then we don't
86        need the channel entry anymore, we can remove it safely. */
87     if (server->server_type != SILC_ROUTER &&
88         !silc_server_channel_has_local(channel)) {
89
90       if (silc_hash_table_find(channels, channel, NULL, NULL))
91         silc_hash_table_del(channels, channel);
92
93       if (channel->rekey)
94         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95
96       if (channel->founder_key) {
97         /* The founder auth data exists, do not remove the channel entry */
98         SilcChannelClientEntry chl2;
99         SilcHashTableList htl2;
100
101         channel->disabled = TRUE;
102
103         silc_hash_table_list(channel->user_list, &htl2);
104         while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
105           silc_hash_table_del(chl2->client->channels, channel);
106           silc_hash_table_del(channel->user_list, chl2->client);
107           channel->user_count--;
108           silc_free(chl2);
109         }
110         silc_hash_table_list_reset(&htl2);
111         continue;
112       }
113
114       /* Remove the channel entry */
115       if (silc_idlist_del_channel(server->local_list, channel))
116         server->stat.my_channels--;
117       else 
118         silc_idlist_del_channel(server->global_list, channel);
119       continue;
120     }
121
122     /* Add the channel to the the channels list to regenerate the 
123        channel key */
124     if (!silc_hash_table_find(channels, channel, NULL, NULL))
125       silc_hash_table_add(channels, channel, channel);
126   }
127   silc_hash_table_list_reset(&htl);
128
129   silc_buffer_free(clidp);
130 }
131
132 /* This function is used to remove all client entries by the server `entry'.
133    This is called when the connection is lost to the server. In this case
134    we must invalidate all the client entries owned by the server `entry'. 
135    If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
136    distributed to our local clients. */
137
138 bool silc_server_remove_clients_by_server(SilcServer server, 
139                                           SilcServerEntry entry,
140                                           bool server_signoff)
141 {
142   SilcIDCacheList list = NULL;
143   SilcIDCacheEntry id_cache = NULL;
144   SilcClientEntry client = NULL;
145   SilcBuffer idp;
146   SilcClientEntry *clients = NULL;
147   SilcUInt32 clients_c = 0;
148   unsigned char **argv = NULL;
149   SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
150   SilcHashTableList htl;
151   SilcChannelEntry channel;
152   SilcHashTable channels;
153   int i;
154
155   SILC_LOG_DEBUG(("Start"));
156
157   /* Allocate the hash table that holds the channels that require
158      channel key re-generation after we've removed this server's clients
159      from the channels. */
160   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
161                                    NULL, NULL, TRUE);
162
163   if (server_signoff) {
164     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
165     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
166     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
167     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
168     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
169     memcpy(argv[argc], idp->data, idp->len);
170     argv_lens[argc] = idp->len;
171     argv_types[argc] = argc + 1;
172     argc++;
173     silc_buffer_free(idp);
174   }
175
176   if (silc_idcache_get_all(server->local_list->clients, &list)) {
177
178     if (silc_idcache_list_first(list, &id_cache)) {
179       while (id_cache) {
180         client = (SilcClientEntry)id_cache->context;
181         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
182           if (!silc_idcache_list_next(list, &id_cache))
183             break;
184           else
185             continue;
186         }
187
188         if (client->router != entry) {
189           if (server_signoff) {
190             clients = silc_realloc(clients, 
191                                    sizeof(*clients) * (clients_c + 1));
192             clients[clients_c] = client;
193             clients_c++;
194           }
195
196           if (!silc_idcache_list_next(list, &id_cache))
197             break;
198           else
199             continue;
200         }
201
202         if (server_signoff) {
203           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
204           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
205           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
206                                    (argc + 1));
207           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
208                                     (argc + 1));
209           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
210           memcpy(argv[argc], idp->data, idp->len);
211           argv_lens[argc] = idp->len;
212           argv_types[argc] = argc + 1;
213           argc++;
214           silc_buffer_free(idp);
215         }
216
217         /* Update statistics */
218         server->stat.clients--;
219         if (server->server_type == SILC_ROUTER)
220           server->stat.cell_clients--;
221         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
222         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
223
224         /* Remove the client entry */
225         silc_server_remove_clients_channels(server, NULL, client, channels);
226         if (!server_signoff) {
227           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
228           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
229         } else {
230           silc_idlist_del_client(server->local_list, client);
231         }
232
233         if (!silc_idcache_list_next(list, &id_cache))
234           break;
235       }
236     }
237     silc_idcache_list_free(list);
238   }
239   
240   if (silc_idcache_get_all(server->global_list->clients, &list)) {
241
242     if (silc_idcache_list_first(list, &id_cache)) {
243       while (id_cache) {
244         client = (SilcClientEntry)id_cache->context;
245         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
246           if (!silc_idcache_list_next(list, &id_cache))
247             break;
248           else
249             continue;
250         }
251         
252         if (client->router != entry) {
253           if (server_signoff && client->connection) {
254             clients = silc_realloc(clients, 
255                                    sizeof(*clients) * (clients_c + 1));
256             clients[clients_c] = client;
257             clients_c++;
258           }
259
260           if (!silc_idcache_list_next(list, &id_cache))
261             break;
262           else
263             continue;
264         }
265
266         if (server_signoff) {
267           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
268           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
269           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
270                                    (argc + 1));
271           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
272                                     (argc + 1));
273           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
274           memcpy(argv[argc], idp->data, idp->len);
275           argv_lens[argc] = idp->len;
276           argv_types[argc] = argc + 1;
277           argc++;
278           silc_buffer_free(idp);
279         }
280
281         /* Update statistics */
282         server->stat.clients--;
283         if (server->server_type == SILC_ROUTER)
284           server->stat.cell_clients--;
285         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
286         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
287
288         /* Remove the client entry */
289         silc_server_remove_clients_channels(server, NULL, client, channels);
290         if (!server_signoff) {
291           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
292           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
293         } else {
294           silc_idlist_del_client(server->global_list, client);
295         }
296
297         if (!silc_idcache_list_next(list, &id_cache))
298           break;
299       }
300     }
301     silc_idcache_list_free(list);
302   }
303
304   /* Send the SERVER_SIGNOFF notify */
305   if (server_signoff) {
306     SilcBuffer args, not;
307
308     /* Send SERVER_SIGNOFF notify to our primary router */
309     if (!server->standalone && server->router &&
310         server->router != entry) {
311       args = silc_argument_payload_encode(1, argv, argv_lens,
312                                           argv_types);
313       silc_server_send_notify_args(server, 
314                                    server->router->connection,
315                                    server->server_type == SILC_SERVER ? 
316                                    FALSE : TRUE, 
317                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
318                                    argc, args);
319       silc_buffer_free(args);
320     }
321
322     /* Send to local clients. We also send the list of client ID's that
323        is to be removed for those servers that would like to use that list. */
324     args = silc_argument_payload_encode(argc, argv, argv_lens,
325                                         argv_types);
326     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
327                                           argc, args);
328     silc_server_packet_send_clients(server, clients, clients_c,
329                                     SILC_PACKET_NOTIFY, 0, FALSE,
330                                     not->data, not->len, FALSE);
331
332     silc_free(clients);
333     silc_buffer_free(args);
334     silc_buffer_free(not);
335     for (i = 0; i < argc; i++)
336       silc_free(argv[i]);
337     silc_free(argv);
338     silc_free(argv_lens);
339     silc_free(argv_types);
340   }
341
342   /* We must now re-generate the channel key for all channels that had
343      this server's client(s) on the channel. As they left the channel we
344      must re-generate the channel key. */
345   silc_hash_table_list(channels, &htl);
346   while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
347     if (!silc_server_create_channel_key(server, channel, 0)) {
348       silc_hash_table_list_reset(&htl);
349       silc_hash_table_free(channels);
350       return FALSE;
351     }
352
353     /* Do not send the channel key if private channel key mode is set */
354     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
355       continue;
356
357     silc_server_send_channel_key(server, NULL, channel, 
358                                  server->server_type == SILC_ROUTER ? 
359                                  FALSE : !server->standalone);
360   }
361   silc_hash_table_list_reset(&htl);
362   silc_hash_table_free(channels);
363
364   return TRUE;
365 }
366
367 static SilcServerEntry
368 silc_server_update_clients_by_real_server(SilcServer server,
369                                           SilcServerEntry from,
370                                           SilcClientEntry client,
371                                           bool local,
372                                           SilcIDCacheEntry client_cache)
373 {
374   SilcServerEntry server_entry;
375   SilcIDCacheEntry id_cache = NULL;
376   SilcIDCacheList list;
377
378   if (!silc_idcache_get_all(server->local_list->servers, &list))
379     return NULL;
380
381   if (silc_idcache_list_first(list, &id_cache)) {
382     while (id_cache) {
383       server_entry = (SilcServerEntry)id_cache->context;
384       if (server_entry != from &&
385           SILC_ID_COMPARE(server_entry->id, client->id, 
386                           client->id->ip.data_len)) {
387         SILC_LOG_DEBUG(("Found (local) %s",
388                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
389
390         if (!server_entry->data.send_key && server_entry->router) {
391           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
392           /* If the client is not marked as local then move it to local list
393              since the server is local. */
394           if (!local) {
395             SILC_LOG_DEBUG(("Moving client to local list"));
396             silc_idcache_add(server->local_list->clients, client_cache->name,
397                              client_cache->id, client_cache->context,
398                              client_cache->expire, NULL);
399             silc_idcache_del_by_context(server->global_list->clients, client);
400           }
401           server_entry = server_entry->router;
402         } else {
403           /* If the client is not marked as local then move it to local list
404              since the server is local. */
405           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
406             SILC_LOG_DEBUG(("Moving client to local list"));
407             silc_idcache_add(server->local_list->clients, client_cache->name,
408                              client_cache->id, client_cache->context,
409                              client_cache->expire, NULL);
410             silc_idcache_del_by_context(server->global_list->clients, client);
411           }
412         }
413
414         silc_idcache_list_free(list);
415         return server_entry;
416       }
417
418       if (!silc_idcache_list_next(list, &id_cache))
419         break;
420     }
421   }
422
423   silc_idcache_list_free(list);
424
425   if (!silc_idcache_get_all(server->global_list->servers, &list))
426     return NULL;
427
428   if (silc_idcache_list_first(list, &id_cache)) {
429     while (id_cache) {
430       server_entry = (SilcServerEntry)id_cache->context;
431       if (server_entry != from &&
432           SILC_ID_COMPARE(server_entry->id, client->id, 
433                           client->id->ip.data_len)) {
434         SILC_LOG_DEBUG(("Found (global) %s",
435                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
436
437         if (!server_entry->data.send_key && server_entry->router) {
438           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
439           /* If the client is marked as local then move it to global list
440              since the server is global. */
441           if (local) {
442             SILC_LOG_DEBUG(("Moving client to global list"));
443             silc_idcache_add(server->global_list->clients, client_cache->name,
444                              client_cache->id, client_cache->context,
445                              client_cache->expire, NULL);
446             silc_idcache_del_by_context(server->local_list->clients, client);
447           }
448           server_entry = server_entry->router;
449         } else {
450           /* If the client is marked as local then move it to global list
451              since the server is global. */
452           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
453             SILC_LOG_DEBUG(("Moving client to global list"));
454             silc_idcache_add(server->global_list->clients, client_cache->name,
455                              client_cache->id, client_cache->context,
456                              client_cache->expire, NULL);
457             silc_idcache_del_by_context(server->local_list->clients, client);
458           }
459         }
460
461         silc_idcache_list_free(list);
462         return server_entry;
463       }
464
465       if (!silc_idcache_list_next(list, &id_cache))
466         break;
467     }
468   }
469
470   silc_idcache_list_free(list);
471
472   return NULL;
473 }
474
475 /* Updates the clients that are originated from the `from' to be originated
476    from the `to'. If the `resolve_real_server' is TRUE then this will
477    attempt to figure out which clients really are originated from the
478    `from' and which are originated from a server that we have connection
479    to, when we've acting as backup router. If it is FALSE the `to' will
480    be the new source. This function also removes the clients that are
481    *really* originated from `from' if `remove_from' is TRUE. These are
482    clients that the `from' owns, and not just clients that are behind
483    the `from'. */
484
485 void silc_server_update_clients_by_server(SilcServer server, 
486                                           SilcServerEntry from,
487                                           SilcServerEntry to,
488                                           bool resolve_real_server,
489                                           bool remove_from)
490 {
491   SilcIDCacheList list = NULL;
492   SilcIDCacheEntry id_cache = NULL;
493   SilcClientEntry client = NULL;
494   bool local;
495
496   SILC_LOG_DEBUG(("Start"));
497
498   SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
499                                                 SILC_ID_SERVER)));
500   SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
501                                           SILC_ID_SERVER)));
502
503
504   local = FALSE;
505   if (silc_idcache_get_all(server->global_list->clients, &list)) {
506     if (silc_idcache_list_first(list, &id_cache)) {
507       while (id_cache) {
508         client = (SilcClientEntry)id_cache->context;
509         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
510           if (!silc_idcache_list_next(list, &id_cache))
511             break;
512           else
513             continue;
514         }
515
516         SILC_LOG_DEBUG(("Client (global) %s", 
517                         silc_id_render(client->id, SILC_ID_CLIENT)));
518         if (client->router)
519           SILC_LOG_DEBUG(("Client->router (global) %s", 
520                           silc_id_render(client->router->id, SILC_ID_SERVER)));
521
522         if (client->router == from) {
523           /* Skip clients that are *really* owned by the `from' */
524           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
525                                              client->id->ip.data_len)) {
526             SILC_LOG_DEBUG(("Found really owned client, skip it"));
527             if (!silc_idcache_list_next(list, &id_cache))
528               break;
529             else
530               continue;
531           }
532
533           if (resolve_real_server) {
534             client->router = 
535               silc_server_update_clients_by_real_server(server, from, client,
536                                                         local, id_cache);
537             if (!client->router)
538               client->router = to;
539           } else {
540             client->router = to;
541           }
542         }
543
544         if (!silc_idcache_list_next(list, &id_cache))
545           break;
546       }
547     }
548     silc_idcache_list_free(list);
549   }
550
551   local = TRUE;
552   if (silc_idcache_get_all(server->local_list->clients, &list)) {
553     if (silc_idcache_list_first(list, &id_cache)) {
554       while (id_cache) {
555         client = (SilcClientEntry)id_cache->context;
556         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
557           if (!silc_idcache_list_next(list, &id_cache))
558             break;
559           else
560             continue;
561         }
562
563         SILC_LOG_DEBUG(("Client (local) %s", 
564                         silc_id_render(client->id, SILC_ID_CLIENT)));
565         if (client->router)
566           SILC_LOG_DEBUG(("Client->router (local) %s", 
567                           silc_id_render(client->router->id, SILC_ID_SERVER)));
568
569         if (client->router == from) {
570           /* Skip clients that are *really* owned by the `from' */
571           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
572                                              client->id->ip.data_len)) {
573             SILC_LOG_DEBUG(("Found really owned client, skip it"));
574             if (!silc_idcache_list_next(list, &id_cache))
575               break;
576             else
577               continue;
578           }
579
580           if (resolve_real_server) {
581             client->router = 
582               silc_server_update_clients_by_real_server(server, from, client,
583                                                         local, id_cache);
584             if (!client->router)
585               client->router = from; /* on local list put old from */
586           } else {
587             client->router = to;
588           }
589         }
590
591         if (!silc_idcache_list_next(list, &id_cache))
592           break;
593       }
594     }
595     silc_idcache_list_free(list);
596   }
597
598   if (remove_from)
599     /* Now remove the clients that are still marked as orignated from the
600        `from'. These are the clients that really was owned by the `from' and
601        not just exist behind the `from'. */
602     silc_server_remove_clients_by_server(server, from, TRUE);
603 }
604
605 /* Updates servers that are from `from' to be originated from `to'.  This
606    will also update the server's connection to `to's connection. */
607
608 void silc_server_update_servers_by_server(SilcServer server, 
609                                           SilcServerEntry from,
610                                           SilcServerEntry to)
611 {
612   SilcIDCacheList list = NULL;
613   SilcIDCacheEntry id_cache = NULL;
614   SilcServerEntry server_entry = NULL;
615
616   SILC_LOG_DEBUG(("Start"));
617
618   if (silc_idcache_get_all(server->local_list->servers, &list)) {
619     if (silc_idcache_list_first(list, &id_cache)) {
620       while (id_cache) {
621         server_entry = (SilcServerEntry)id_cache->context;
622         if (server_entry->router == from) {
623           server_entry->router = to;
624           server_entry->connection = to->connection;
625         }
626         if (!silc_idcache_list_next(list, &id_cache))
627           break;
628       }
629     }
630     silc_idcache_list_free(list);
631   }
632
633   if (silc_idcache_get_all(server->global_list->servers, &list)) {
634     if (silc_idcache_list_first(list, &id_cache)) {
635       while (id_cache) {
636         server_entry = (SilcServerEntry)id_cache->context;
637         if (server_entry->router == from) {
638           server_entry->router = to;
639           server_entry->connection = to->connection;
640         }
641         if (!silc_idcache_list_next(list, &id_cache))
642           break;
643       }
644     }
645     silc_idcache_list_free(list);
646   }
647 }
648
649 /* Removes channels that are from `from. */
650
651 void silc_server_remove_channels_by_server(SilcServer server, 
652                                            SilcServerEntry from)
653 {
654   SilcIDCacheList list = NULL;
655   SilcIDCacheEntry id_cache = NULL;
656   SilcChannelEntry channel = NULL;
657
658   SILC_LOG_DEBUG(("Start"));
659
660   if (silc_idcache_get_all(server->global_list->channels, &list)) {
661     if (silc_idcache_list_first(list, &id_cache)) {
662       while (id_cache) {
663         channel = (SilcChannelEntry)id_cache->context;
664         if (channel->router == from)
665           silc_idlist_del_channel(server->global_list, channel);
666         if (!silc_idcache_list_next(list, &id_cache))
667           break;
668       }
669     }
670     silc_idcache_list_free(list);
671   }
672 }
673
674 /* Updates channels that are from `from' to be originated from `to'.  */
675
676 void silc_server_update_channels_by_server(SilcServer server, 
677                                            SilcServerEntry from,
678                                            SilcServerEntry to)
679 {
680   SilcIDCacheList list = NULL;
681   SilcIDCacheEntry id_cache = NULL;
682   SilcChannelEntry channel = NULL;
683
684   SILC_LOG_DEBUG(("Start"));
685
686   if (silc_idcache_get_all(server->global_list->channels, &list)) {
687     if (silc_idcache_list_first(list, &id_cache)) {
688       while (id_cache) {
689         channel = (SilcChannelEntry)id_cache->context;
690         if (channel->router == from)
691           channel->router = to;
692         if (!silc_idcache_list_next(list, &id_cache))
693           break;
694       }
695     }
696     silc_idcache_list_free(list);
697   }
698 }
699
700 /* Checks whether given channel has global users.  If it does this returns
701    TRUE and FALSE if there is only locally connected clients on the channel. */
702
703 bool silc_server_channel_has_global(SilcChannelEntry channel)
704 {
705   SilcChannelClientEntry chl;
706   SilcHashTableList htl;
707
708   silc_hash_table_list(channel->user_list, &htl);
709   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
710     if (chl->client->router) {
711       silc_hash_table_list_reset(&htl);
712       return TRUE;
713     }
714   }
715   silc_hash_table_list_reset(&htl);
716
717   return FALSE;
718 }
719
720 /* Checks whether given channel has locally connected users.  If it does this
721    returns TRUE and FALSE if there is not one locally connected client. */
722
723 bool silc_server_channel_has_local(SilcChannelEntry channel)
724 {
725   SilcChannelClientEntry chl;
726   SilcHashTableList htl;
727
728   silc_hash_table_list(channel->user_list, &htl);
729   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
730     if (!chl->client->router) {
731       silc_hash_table_list_reset(&htl);
732       return TRUE;
733     }
734   }
735   silc_hash_table_list_reset(&htl);
736
737   return FALSE;
738 }
739
740 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
741    This works because we assure that the user list on the channel is
742    always in up to date thus we can only check the channel list from 
743    `client' which is faster than checking the user list from `channel'. */
744
745 bool silc_server_client_on_channel(SilcClientEntry client,
746                                    SilcChannelEntry channel,
747                                    SilcChannelClientEntry *chl)
748 {
749   if (!client || !channel)
750     return FALSE;
751
752   return silc_hash_table_find(client->channels, channel, NULL, 
753                               (void **)chl);
754 }
755
756 /* Checks string for bad characters and returns TRUE if they are found. */
757
758 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
759 {
760   int i;
761
762   for (i = 0; i < name_len; i++) {
763     if (!isascii(name[i]))
764       return TRUE;
765     if (name[i] <= 32) return TRUE;
766     if (name[i] == ' ') return TRUE;
767     if (name[i] == '*') return TRUE;
768     if (name[i] == '?') return TRUE;
769     if (name[i] == ',') return TRUE;
770   }
771
772   return FALSE;
773 }
774
775 /* Modifies the `name' if it includes bad characters and returns new
776    allocated name that does not include bad characters. */
777
778 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
779 {
780   int i;
781   char *newname = strdup(name);
782
783   for (i = 0; i < name_len; i++) {
784     if (!isascii(newname[i])) newname[i] = '_';
785     if (newname[i] <= 32) newname[i] = '_';
786     if (newname[i] == ' ') newname[i] = '_';
787     if (newname[i] == '*') newname[i] = '_';
788     if (newname[i] == '?') newname[i] = '_';
789     if (newname[i] == ',') newname[i] = '_';
790   }
791
792   return newname;
793 }
794
795 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
796    socket connections with the IP address does not exist. */
797
798 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
799                                          SilcSocketType type)
800 {
801   int i, count;
802
803   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
804     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
805         server->sockets[i]->type == type)
806       count++;
807   }
808
809   return count;
810 }
811
812 /* Finds locally cached public key by the public key received in the SKE. 
813    If we have it locally cached then we trust it and will use it in the
814    authentication protocol.  Returns the locally cached public key or NULL
815    if we do not find the public key.  */
816
817 SilcPublicKey silc_server_find_public_key(SilcServer server, 
818                                           SilcHashTable local_public_keys,
819                                           SilcPublicKey remote_public_key)
820 {
821   SilcPublicKey cached_key;
822
823   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
824                   silc_hash_table_count(local_public_keys)));
825
826   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
827                                 (void **)&cached_key, NULL, 
828                                 silc_hash_public_key, NULL,
829                                 silc_hash_public_key_compare, NULL)) {
830     SILC_LOG_ERROR(("Public key not found"));
831     return NULL;
832   }
833
834   SILC_LOG_DEBUG(("Found public key"));
835
836   return cached_key;
837 }
838
839 /* This returns the first public key from the table of public keys.  This
840    is used only in cases where single public key exists in the table and
841    we want to get a pointer to it.  For public key tables that has multiple
842    keys in it the silc_server_find_public_key must be used. */
843
844 SilcPublicKey silc_server_get_public_key(SilcServer server,
845                                          SilcHashTable local_public_keys)
846 {
847   SilcPublicKey cached_key;
848   SilcHashTableList htl;
849
850   SILC_LOG_DEBUG(("Start"));
851
852   assert(silc_hash_table_count(local_public_keys) < 2);
853
854   silc_hash_table_list(local_public_keys, &htl);
855   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
856     return NULL;
857   silc_hash_table_list_reset(&htl);
858
859   return cached_key;
860 }
861
862 /* Check whether the connection `sock' is allowed to connect to us.  This
863    checks for example whether there is too much connections for this host,
864    and required version for the host etc. */
865
866 bool silc_server_connection_allowed(SilcServer server, 
867                                     SilcSocketConnection sock,
868                                     SilcSocketType type,
869                                     SilcServerConfigConnParams *global,
870                                     SilcServerConfigConnParams *params,
871                                     SilcSKE ske)
872 {
873   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
874                             server->stat.my_clients :
875                             type == SILC_SOCKET_TYPE_SERVER ?
876                             server->stat.my_servers :
877                             server->stat.my_routers);
878   SilcUInt32 num_sockets, max_hosts, max_per_host;
879   SilcUInt32 r_protocol_version, l_protocol_version;
880   SilcUInt32 r_software_version, l_software_version;
881   char *r_vendor_version = NULL, *l_vendor_version;
882
883   /* Check version */
884
885   l_protocol_version = 
886     silc_version_to_num(params && params->version_protocol ? 
887                         params->version_protocol : 
888                         global->version_protocol);
889   l_software_version = 
890     silc_version_to_num(params && params->version_software ? 
891                         params->version_software : 
892                         global->version_software);
893   l_vendor_version = (params && params->version_software_vendor ? 
894                       params->version_software_vendor : 
895                       global->version_software_vendor);
896   
897   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
898                                     &r_software_version, NULL,
899                                     &r_vendor_version)) {
900     /* Match protocol version */
901     if (l_protocol_version && r_protocol_version &&
902         r_protocol_version < l_protocol_version) {
903       SILC_LOG_INFO(("Connection %s (%s) is too old version",
904                      sock->hostname, sock->ip));
905       silc_server_disconnect_remote(server, sock, 
906                                     "Server closed connection: "
907                                     "You support too old protocol version");
908       return FALSE;
909     }
910
911     /* Math software version */
912     if (l_software_version && r_software_version &&
913         r_software_version < l_software_version) {
914       SILC_LOG_INFO(("Connection %s (%s) is too old version",
915                      sock->hostname, sock->ip));
916       silc_server_disconnect_remote(server, sock, 
917                                     "Server closed connection: "
918                                     "You support too old software version");
919       return FALSE;
920     }
921
922     /* Regex match vendor version */
923     if (l_vendor_version && r_vendor_version && 
924         !silc_string_match(l_vendor_version, r_vendor_version)) {
925       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
926                      sock->hostname, sock->ip));
927       silc_server_disconnect_remote(server, sock, 
928                                     "Server closed connection: "
929                                     "Your software is not supported");
930       return FALSE;
931     }
932   }
933   silc_free(r_vendor_version);
934
935   /* Check for maximum connections limit */
936
937   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
938   max_hosts = (params ? params->connections_max : global->connections_max);
939   max_per_host = (params ? params->connections_max_per_host :
940                   global->connections_max_per_host);
941
942   if (max_hosts && conn_number >= max_hosts) {
943     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
944                    sock->hostname, sock->ip));
945     silc_server_disconnect_remote(server, sock, 
946                                   "Server closed connection: "
947                                   "Server is full, try again later");
948     return FALSE;
949   }
950
951   if (num_sockets >= max_per_host) {
952     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
953                    sock->hostname, sock->ip));
954     silc_server_disconnect_remote(server, sock, 
955                                   "Server closed connection: "
956                                   "Too many connections from your host");
957     return FALSE;
958   }
959
960   return TRUE;
961 }
962
963 /* Checks that client has rights to add or remove channel modes. If any
964    of the checks fails FALSE is returned. */
965
966 bool silc_server_check_cmode_rights(SilcServer server,
967                                     SilcChannelEntry channel,
968                                     SilcChannelClientEntry client,
969                                     SilcUInt32 mode)
970 {
971   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
972   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
973
974   /* Check whether has rights to change anything */
975   if (!is_op && !is_fo)
976     return FALSE;
977
978   /* Check whether has rights to change everything */
979   if (is_op && is_fo)
980     return TRUE;
981
982   /* We know that client is channel operator, check that they are not
983      changing anything that requires channel founder rights. Rest of the
984      modes are available automatically for channel operator. */
985
986   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
987     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
988       if (is_op && !is_fo)
989         return FALSE;
990   } else {
991     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
992       if (is_op && !is_fo)
993         return FALSE;
994     }
995   }
996   
997   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
998     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
999       if (is_op && !is_fo)
1000         return FALSE;
1001   } else {
1002     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1003       if (is_op && !is_fo)
1004         return FALSE;
1005     }
1006   }
1007
1008   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1009     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
1010       if (is_op && !is_fo)
1011         return FALSE;
1012   } else {
1013     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1014       if (is_op && !is_fo)
1015         return FALSE;
1016     }
1017   }
1018   
1019   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1020     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
1021       if (is_op && !is_fo)
1022         return FALSE;
1023   } else {
1024     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1025       if (is_op && !is_fo)
1026         return FALSE;
1027     }
1028   }
1029   
1030   return TRUE;
1031 }
1032
1033 /* Check that the client has rights to change its user mode.  Returns
1034    FALSE if setting some mode is not allowed. */
1035
1036 bool silc_server_check_umode_rights(SilcServer server,
1037                                     SilcClientEntry client,
1038                                     SilcUInt32 mode)
1039 {
1040   bool server_op = FALSE, router_op = FALSE;
1041
1042   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1043     /* Cannot set server operator mode (must use OPER command) */
1044     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1045       return FALSE;
1046   } else {
1047     /* Remove the server operator rights */
1048     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1049       server_op = TRUE;
1050   }
1051
1052   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1053     /* Cannot set router operator mode (must use SILCOPER command) */
1054     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1055       return FALSE;
1056   } else {
1057     /* Remove the router operator rights */
1058     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1059       router_op = TRUE;
1060   }
1061
1062   if (server_op)
1063     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1064   if (router_op)
1065     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1066
1067   return TRUE;
1068 }