The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/silcd/packet_receive.c

  1 /*
  2 
  3   packet_receive.c
  4 
  5   Author: Pekka Riikonen <priikone@silcnet.org>
  6 
  7   Copyright (C) 1997 - 2005 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  * Server packet routines to handle received packets.
 22  */
 23 /* $Id: packet_receive.c,v 1.212 2005/04/23 13:32:24 priikone Exp $ */
 24 
 25 #include "serverincludes.h"
 26 #include "server_internal.h"
 27 
 28 /* Received notify packet. Server can receive notify packets from router.
 29    Server then relays the notify messages to clients if needed. */
 30 
 31 void silc_server_notify(SilcServer server,
 32                         SilcSocketConnection sock,
 33                         SilcPacketContext *packet)
 34 {
 35   SilcNotifyPayload payload;
 36   SilcNotifyType type;
 37   SilcArgumentPayload args;
 38   SilcChannelID *channel_id = NULL, *channel_id2;
 39   SilcClientID *client_id, *client_id2;
 40   SilcServerID *server_id;
 41   SilcIdType id_type;
 42   SilcChannelEntry channel = NULL;
 43   SilcClientEntry client = NULL, client2 = NULL;
 44   SilcServerEntry server_entry = NULL;
 45   SilcChannelClientEntry chl;
 46   SilcIDCacheEntry cache = NULL;
 47   SilcHashTableList htl;
 48   SilcUInt32 mode;
 49   unsigned char *tmp;
 50   SilcUInt32 tmp_len;
 51   bool local;
 52 
 53   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
 54       packet->src_id_type != SILC_ID_SERVER || !packet->dst_id) {
 55     SILC_LOG_DEBUG(("Bad notify packet received"));
 56     return;
 57   }
 58 
 59   /* If the packet is destined directly to a client then relay the packet
 60      before processing it. */
 61   if (packet->dst_id_type == SILC_ID_CLIENT) {
 62     SilcIDListData idata;
 63     SilcSocketConnection dst_sock;
 64 
 65     /* Get the route to the client */
 66     dst_sock = silc_server_get_client_route(server, packet->dst_id,
 67                                             packet->dst_id_len, NULL,
 68                                             &idata, NULL);
 69     if (dst_sock)
 70       /* Relay the packet */
 71       silc_server_relay_packet(server, dst_sock, idata->send_key,
 72                                idata->hmac_send, idata->psn_send++,
 73                                packet, TRUE);
 74   }
 75 
 76   /* Parse the Notify Payload */
 77   payload = silc_notify_payload_parse(packet->buffer->data,
 78                                       packet->buffer->len);
 79   if (!payload)
 80     return;
 81 
 82   /* If we are router and this packet is not already broadcast packet
 83      we will broadcast it. The sending socket really cannot be router or
 84      the router is buggy. If this packet is coming from router then it must
 85      have the broadcast flag set already and we won't do anything. */
 86   if (server->server_type == SILC_ROUTER &&
 87       sock->type == SILC_SOCKET_TYPE_SERVER &&
 88       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
 89     SILC_LOG_DEBUG(("Broadcasting received Notify packet"));
 90     if (packet->dst_id_type == SILC_ID_CHANNEL) {
 91       /* Packet is destined to channel */
 92       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
 93                                   packet->dst_id_type);
 94       if (!channel_id)
 95         goto out;
 96 
 97       silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server),
 98                                    packet->type, packet->flags |
 99                                    SILC_PACKET_FLAG_BROADCAST,
100                                    channel_id, SILC_ID_CHANNEL,
101                                    packet->buffer->data,
102                                    packet->buffer->len, FALSE);
103       silc_server_backup_send_dest(server, sock->user_data,
104                                    packet->type, packet->flags,
105                                    channel_id, SILC_ID_CHANNEL,
106                                    packet->buffer->data, packet->buffer->len,
107                                    FALSE, TRUE);
108     } else {
109       /* Packet is destined to client or server */
110       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
111                               packet->type,
112                               packet->flags | SILC_PACKET_FLAG_BROADCAST,
113                               packet->buffer->data, packet->buffer->len,
114                               FALSE);
115       silc_server_backup_send(server, sock->user_data,
116                               packet->type, packet->flags,
117                               packet->buffer->data, packet->buffer->len,
118                               FALSE, TRUE);
119     }
120   }
121 
122   type = silc_notify_get_type(payload);
123   args = silc_notify_get_args(payload);
124   if (!args)
125     goto out;
126 
127   switch(type) {
128   case SILC_NOTIFY_TYPE_JOIN:
129     /*
130      * Distribute the notify to local clients on the channel
131      */
132     SILC_LOG_DEBUG(("JOIN notify"));
133 
134     if (channel_id)
135       silc_free(channel_id);
136 
137     /* Get Channel ID */
138     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
139     if (!tmp)
140       goto out;
141     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
142     if (!channel_id)
143       goto out;
144 
145     /* Get channel entry */
146     channel = silc_idlist_find_channel_by_id(server->global_list,
147                                              channel_id, NULL);
148     if (!channel) {
149       channel = silc_idlist_find_channel_by_id(server->local_list,
150                                                channel_id, NULL);
151       if (!channel) {
152         SILC_LOG_DEBUG(("Notify for unknown channel"));
153         silc_free(channel_id);
154         goto out;
155       }
156     }
157     silc_free(channel_id);
158 
159     /* Get client ID */
160     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
161     if (!tmp)
162       goto out;
163     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
164     if (!client_id)
165       goto out;
166 
167     /* If the the client is not in local list we check global list (ie. the
168        channel will be global channel) and if it does not exist then create
169        entry for the client. */
170     client = silc_idlist_find_client_by_id(server->global_list,
171                                            client_id, server->server_type,
172                                            &cache);
173     if (!client) {
174       client = silc_idlist_find_client_by_id(server->local_list,
175                                              client_id, server->server_type,
176                                              &cache);
177       if (!client) {
178         /* If router did not find the client the it is bogus */
179         if (server->server_type != SILC_SERVER) {
180           silc_free(client_id);
181           goto out;
182         }
183 
184         client =
185           silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
186                                  silc_id_dup(client_id, SILC_ID_CLIENT),
187                                  sock->user_data, NULL, 0);
188         if (!client) {
189           SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
190           silc_free(client_id);
191           goto out;
192         }
193 
194         client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
195       }
196     }
197     silc_free(client_id);
198 
199     /* Do not process the notify if the client is not registered */
200     if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
201       break;
202 
203     /* Do not add client to channel if it is there already */
204     if (silc_server_client_on_channel(client, channel, NULL)) {
205       SILC_LOG_DEBUG(("Client already on channel %s",
206                       channel->channel_name));
207       break;
208     }
209 
210     /* Send to channel */
211     silc_server_packet_send_to_channel(server, sock, channel, packet->type,
212                                        FALSE, TRUE, packet->buffer->data,
213                                        packet->buffer->len, FALSE);
214 
215     if (server->server_type != SILC_ROUTER &&
216         sock->type == SILC_SOCKET_TYPE_ROUTER)
217       /* The channel is global now */
218       channel->global_users = TRUE;
219 
220     SILC_LOG_DEBUG(("Joining to channel %s", channel->channel_name));
221 
222     /* JOIN the global client to the channel (local clients (if router
223        created the channel) is joined in the pending JOIN command). */
224     chl = silc_calloc(1, sizeof(*chl));
225     chl->client = client;
226     chl->channel = channel;
227 
228     if (server->server_type != SILC_ROUTER ||
229         sock->type == SILC_SOCKET_TYPE_ROUTER) {
230       /* If founder auth is set, first client is not automatically founder. */
231       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
232         /* If this is the first one on the channel then it is the founder of
233            the channel. This is done on normal server and on router if this
234            notify is coming from router */
235         if (!silc_hash_table_count(channel->user_list)) {
236           SILC_LOG_DEBUG(("Client %s is founder on channel",
237                           silc_id_render(chl->client->id, SILC_ID_CLIENT)));
238           chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
239         }
240       }
241     }
242 
243     silc_hash_table_add(channel->user_list, client, chl);
244     silc_hash_table_add(client->channels, channel, chl);
245     channel->user_count++;
246     channel->disabled = FALSE;
247 
248     /* Make sure we don't expire clients that are on channel */
249     if (cache)
250       cache->expire = 0;
251 
252     /* Update statistics */
253     if (server->server_type == SILC_ROUTER) {
254       if (sock->type != SILC_SOCKET_TYPE_ROUTER)
255         server->stat.cell_chanclients++;
256       server->stat.chanclients++;
257     }
258 
259     break;
260 
261   case SILC_NOTIFY_TYPE_LEAVE:
262     /*
263      * Distribute the notify to local clients on the channel
264      */
265     SILC_LOG_DEBUG(("LEAVE notify"));
266 
267     if (!channel_id) {
268       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
269                                   packet->dst_id_type);
270       if (!channel_id)
271         goto out;
272     }
273 
274     /* Get channel entry */
275     channel = silc_idlist_find_channel_by_id(server->global_list,
276                                              channel_id, NULL);
277     if (!channel) {
278       channel = silc_idlist_find_channel_by_id(server->local_list,
279                                                channel_id, NULL);
280       if (!channel) {
281         SILC_LOG_DEBUG(("Notify for unknown channel"));
282         silc_free(channel_id);
283         goto out;
284       }
285     }
286 
287     /* Get client ID */
288     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
289     if (!tmp) {
290       silc_free(channel_id);
291       goto out;
292     }
293     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
294     if (!client_id) {
295       silc_free(channel_id);
296       goto out;
297     }
298 
299     /* Get client entry */
300     client = silc_idlist_find_client_by_id(server->global_list,
301                                            client_id, TRUE, NULL);
302     if (!client) {
303       client = silc_idlist_find_client_by_id(server->local_list,
304                                              client_id, TRUE, NULL);
305       if (!client) {
306         silc_free(client_id);
307         silc_free(channel_id);
308         goto out;
309       }
310     }
311     silc_free(client_id);
312     silc_free(channel_id);
313 
314     /* Check if on channel */
315     if (!silc_server_client_on_channel(client, channel, NULL))
316       break;
317 
318     /* Send the leave notify to channel */
319     silc_server_packet_send_to_channel(server, sock, channel, packet->type,
320                                        FALSE, TRUE, packet->buffer->data,
321                                        packet->buffer->len, FALSE);
322 
323     /* Remove the user from channel */
324     silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
325     break;
326 
327   case SILC_NOTIFY_TYPE_SIGNOFF:
328     /*
329      * Distribute the notify to local clients on the channel
330      */
331     SILC_LOG_DEBUG(("SIGNOFF notify"));
332 
333     /* Get client ID */
334     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
335     if (!tmp)
336       goto out;
337     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
338     if (!client_id)
339       goto out;
340 
341     /* Get client entry */
342     client = silc_idlist_find_client_by_id(server->global_list,
343                                            client_id, TRUE, &cache);
344     if (!client) {
345       client = silc_idlist_find_client_by_id(server->local_list,
346                                              client_id, TRUE, &cache);
347       if (!client) {
348         silc_free(client_id);
349         goto out;
350       }
351     }
352     silc_free(client_id);
353 
354     /* Get signoff message */
355     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
356     if (tmp_len > 128)
357       tmp = NULL;
358 
359     /* Update statistics */
360     server->stat.clients--;
361     if (server->stat.cell_clients)
362       server->stat.cell_clients--;
363     SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
364     SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
365     silc_schedule_task_del_by_context(server->schedule, client);
366 
367     /* Remove from public key hash table. */
368     if (client->data.public_key)
369       silc_hash_table_del_by_context(server->pk_hash, client->data.public_key,
370                                      client);
371 
372     /* Remove the client from all channels. */
373     silc_server_remove_from_channels(server, NULL, client, TRUE,
374                                      tmp, FALSE, FALSE);
375 
376     /* Check if anyone is watching this nickname */
377     if (server->server_type == SILC_ROUTER)
378       silc_server_check_watcher_list(server, client, NULL,
379                                      SILC_NOTIFY_TYPE_SIGNOFF);
380 
381     /* Remove this client from watcher list if it is */
382     silc_server_del_from_watcher_list(server, client);
383 
384     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
385     client->mode = 0;
386     client->router = NULL;
387     client->connection = NULL;
388     cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
389     break;
390 
391   case SILC_NOTIFY_TYPE_TOPIC_SET:
392     /*
393      * Distribute the notify to local clients on the channel
394      */
395 
396     SILC_LOG_DEBUG(("TOPIC SET notify"));
397 
398     /* Get client ID */
399     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
400     if (!tmp)
401       goto out;
402     client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
403     if (!client_id)
404       goto out;
405 
406     /* Get client entry */
407     if (id_type == SILC_ID_CLIENT) {
408       client = silc_idlist_find_client_by_id(server->global_list,
409                                              client_id, TRUE, &cache);
410       if (!client) {
411         client = silc_idlist_find_client_by_id(server->local_list,
412                                                client_id, TRUE, &cache);
413         if (!client) {
414           silc_free(client_id);
415           goto out;
416         }
417       }
418       silc_free(client_id);
419     }
420 
421     /* Get the topic */
422     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
423     if (!tmp) {
424       silc_free(channel_id);
425       goto out;
426     }
427 
428     if (!channel_id) {
429       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
430                                   packet->dst_id_type);
431       if (!channel_id)
432         goto out;
433     }
434 
435     /* Get channel entry */
436     channel = silc_idlist_find_channel_by_id(server->global_list,
437                                              channel_id, NULL);
438     if (!channel) {
439       channel = silc_idlist_find_channel_by_id(server->local_list,
440                                                channel_id, NULL);
441       if (!channel) {
442         SILC_LOG_DEBUG(("Notify for unknown channel"));
443         silc_free(channel_id);
444         goto out;
445       }
446     }
447     silc_free(channel_id);
448 
449     if (channel->topic && !strcmp(channel->topic, tmp)) {
450       SILC_LOG_DEBUG(("Topic is already set and same"));
451       goto out;
452     }
453 
454     if (client) {
455       /* Get user's channel entry and check that topic set is allowed. */
456       if (!silc_server_client_on_channel(client, channel, &chl))
457         goto out;
458       if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
459           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
460           !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
461         SILC_LOG_DEBUG(("Topic change is not allowed"));
462         goto out;
463       }
464     }
465 
466     /* Change the topic */
467     silc_free(channel->topic);
468     channel->topic = strdup(tmp);
469 
470     /* Send the same notify to the channel */
471     silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
472                                        FALSE, TRUE, packet->buffer->data,
473                                        packet->buffer->len, FALSE);
474     break;
475 
476   case SILC_NOTIFY_TYPE_NICK_CHANGE:
477     {
478       /*
479        * Distribute the notify to local clients on the channel
480        */
481       unsigned char *id, *id2;
482       char *nickname;
483       SilcUInt32 nickname_len;
484 
485       SILC_LOG_DEBUG(("NICK CHANGE notify"));
486 
487       /* Get old client ID */
488       id = silc_argument_get_arg_type(args, 1, &tmp_len);
489       if (!id)
490         goto out;
491       client_id = silc_id_payload_parse_id(id, tmp_len, NULL);
492       if (!client_id)
493         goto out;
494 
495       /* Get new client ID */
496       id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
497       if (!id2)
498         goto out;
499       client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
500       if (!client_id2) {
501         silc_free(client_id);
502         goto out;
503       }
504 
505       SILC_LOG_DEBUG(("Old Client ID id(%s)",
506                       silc_id_render(client_id, SILC_ID_CLIENT)));
507       SILC_LOG_DEBUG(("New Client ID id(%s)",
508                       silc_id_render(client_id2, SILC_ID_CLIENT)));
509 
510       /* From protocol version 1.1 we also get the new nickname */
511       nickname = silc_argument_get_arg_type(args, 3, &nickname_len);;
512 
513       /* Replace the Client ID */
514       client = silc_idlist_replace_client_id(server,
515                                              server->global_list, client_id,
516                                              client_id2, nickname);
517       if (!client)
518         client = silc_idlist_replace_client_id(server,
519                                                server->local_list, client_id,
520                                                client_id2, nickname);
521 
522       if (client) {
523         /* Send the NICK_CHANGE notify type to local clients on the channels
524            this client is joined to. */
525         silc_server_send_notify_on_channels(server, client, client,
526                                             SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
527                                             id, tmp_len, id2, tmp_len,
528                                             nickname, nickname ?
529                                             nickname_len : 0);
530       }
531 
532       silc_free(client_id);
533       if (!client)
534         silc_free(client_id2);
535       break;
536     }
537 
538   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
539     /*
540      * Distribute the notify to local clients on the channel
541      */
542 
543     SILC_LOG_DEBUG(("CMODE CHANGE notify"));
544 
545     /* Get client ID */
546     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
547     if (!tmp)
548       goto out;
549     client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
550     if (!client_id)
551       goto out;
552 
553     /* Get client entry */
554     if (id_type == SILC_ID_CLIENT) {
555       client = silc_idlist_find_client_by_id(server->global_list,
556                                              client_id, TRUE, &cache);
557       if (!client) {
558         client = silc_idlist_find_client_by_id(server->local_list,
559                                                client_id, TRUE, &cache);
560         if (!client) {
561           silc_free(client_id);
562           goto out;
563         }
564       }
565     }
566     silc_free(client_id);
567 
568     if (!channel_id) {
569       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
570                                   packet->dst_id_type);
571       if (!channel_id)
572         goto out;
573     }
574 
575     /* Get channel entry */
576     channel = silc_idlist_find_channel_by_id(server->global_list,
577                                              channel_id, NULL);
578     if (!channel) {
579       channel = silc_idlist_find_channel_by_id(server->local_list,
580                                                channel_id, NULL);
581       if (!channel) {
582         SILC_LOG_DEBUG(("Notify for unknown channel"));
583         silc_free(channel_id);
584         goto out;
585       }
586     }
587     silc_free(channel_id);
588 
589     /* Get the mode */
590     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
591     if (!tmp)
592       goto out;
593     SILC_GET32_MSB(mode, tmp);
594 
595     /* Check if mode changed */
596     if (channel->mode == mode) {
597       SILC_LOG_DEBUG(("Mode is changed already"));
598 
599       /* If this mode change has founder mode then we'll enforce the
600          change so that the server gets the real founder public key */
601       if (server->server_type != SILC_SERVER &&
602           sock != SILC_PRIMARY_ROUTE(server) &&
603           mode & SILC_CHANNEL_MODE_FOUNDER_AUTH && channel->founder_key) {
604         SILC_LOG_DEBUG(("Sending founder public key to server"));
605         silc_server_send_notify_cmode(server, sock, FALSE, channel,
606                                       channel->mode, server->id,
607                                       SILC_ID_SERVER, channel->cipher,
608                                       channel->hmac_name,
609                                       channel->passphrase,
610                                       channel->founder_key, NULL);
611       }
612 
613       /* If we received same mode from our primary check whether founder
614          mode and key in the notify is set.  We update the founder key
615          here since we may have wrong one */
616       if (server->server_type == SILC_SERVER &&
617           sock == SILC_PRIMARY_ROUTE(server) &&
618           mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
619         SILC_LOG_DEBUG(("Founder public key received from router"));
620         tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
621         if (!tmp)
622           break;
623 
624         if (channel->founder_key)
625           silc_pkcs_public_key_free(channel->founder_key);
626         channel->founder_key = NULL;
627         silc_pkcs_public_key_payload_decode(tmp, tmp_len,
628                                             &channel->founder_key);
629       }
630 
631       /* Check also for channel public key list */
632       if (server->server_type == SILC_SERVER &&
633           sock == SILC_PRIMARY_ROUTE(server) &&
634           mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
635         SilcBuffer chpklist;
636         SilcBuffer sidp;
637         unsigned char mask[4], ulimit[4];
638 
639         SILC_LOG_DEBUG(("Channel public key list received from router"));
640         tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
641         if (!tmp)
642           break;
643 
644         /* Set the router's list, and send the notify to channel too so that
645            channel gets the list */
646         silc_server_set_channel_pk_list(server, sock, channel, tmp, tmp_len);
647         chpklist = silc_server_get_channel_pk_list(server, channel,
648                                                    FALSE, FALSE);
649         if (!chpklist)
650           break;
651         sidp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
652         SILC_PUT32_MSB(channel->mode, mask);
653         if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
654           SILC_PUT32_MSB(channel->user_limit, ulimit);
655         silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
656                                            SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
657                                            sidp->data, sidp->len,
658                                            mask, 4,
659                                            channel->cipher,
660                                            channel->cipher ?
661                                            strlen(channel->cipher) : 0,
662                                            channel->hmac_name,
663                                            channel->hmac_name ?
664                                            strlen(channel->hmac_name) : 0,
665                                            channel->passphrase,
666                                            channel->passphrase ?
667                                            strlen(channel->passphrase) : 0,
668                                            NULL, 0,
669                                            chpklist->data, chpklist->len,
670                                            (channel->mode &
671                                             SILC_CHANNEL_MODE_ULIMIT ?
672                                             ulimit : NULL),
673                                            (channel->mode &
674                                             SILC_CHANNEL_MODE_ULIMIT ?
675                                             sizeof(ulimit) : 0));
676         silc_buffer_free(sidp);
677         silc_buffer_free(chpklist);
678         goto out;
679       }
680 
681       break;
682     }
683 
684     /* Get user's channel entry and check that mode change is allowed */
685     if (client) {
686       if (!silc_server_client_on_channel(client, channel, &chl))
687         goto out;
688       if (!silc_server_check_cmode_rights(server, channel, chl, mode)) {
689         SILC_LOG_DEBUG(("CMODE change is not allowed"));
690         silc_server_send_notify_cmode(server, sock, FALSE, channel,
691                                       channel->mode, server->id,
692                                       SILC_ID_SERVER, channel->cipher,
693                                       channel->hmac_name,
694                                       channel->passphrase,
695                                       channel->founder_key, NULL);
696         goto out;
697       }
698     } else {
699       /* Assure that server is not removing founder mode from us */
700       if (server->server_type == SILC_ROUTER &&
701           sock != SILC_PRIMARY_ROUTE(server) &&
702           channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH &&
703           !(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
704         SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
705         silc_server_send_notify_cmode(server, sock, FALSE, channel,
706                                       channel->mode, server->id,
707                                       SILC_ID_SERVER, channel->cipher,
708                                       channel->hmac_name,
709                                       channel->passphrase,
710                                       channel->founder_key, NULL);
711         goto out;
712       }
713 
714       /* If server is adding founder mode, check whether there is founder
715          on channel already and is not from this server */
716       if (server->server_type == SILC_ROUTER &&
717           sock != SILC_PRIMARY_ROUTE(server) &&
718           mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
719         silc_hash_table_list(channel->user_list, &htl);
720         while (silc_hash_table_get(&htl, NULL, (void *)&chl))
721           if (chl->mode & SILC_CHANNEL_UMODE_CHANFO &&
722               chl->client->router != sock->user_data) {
723             SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
724             silc_server_send_notify_cmode(server, sock, FALSE, channel,
725                                           channel->mode, server->id,
726                                           SILC_ID_SERVER, channel->cipher,
727                                           channel->hmac_name,
728                                           channel->passphrase,
729                                           channel->founder_key, NULL);
730             silc_hash_table_list_reset(&htl);
731             goto out;
732           }
733         silc_hash_table_list_reset(&htl);
734       }
735     }
736 
737     /* If the channel had private keys set and the mode was removed then
738        we must re-generate and re-distribute a new channel key */
739     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
740         !(mode & SILC_CHANNEL_MODE_PRIVKEY)) {
741       /* Re-generate channel key */
742       if (!silc_server_create_channel_key(server, channel, 0))
743         goto out;
744 
745       /* Send the channel key. This sends it to our local clients and if
746          we are normal server to our router as well. */
747       silc_server_send_channel_key(server, NULL, channel,
748                                    server->server_type == SILC_ROUTER ?
749                                    FALSE : !server->standalone);
750     }
751 
752     /* Get the hmac */
753     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
754     if (tmp) {
755       unsigned char hash[32];
756 
757       if (channel->hmac)
758         silc_hmac_free(channel->hmac);
759       if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
760         goto out;
761 
762       /* Set the HMAC key out of current channel key. The client must do
763          this locally. */
764       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
765                      channel->key_len / 8, hash);
766       silc_hmac_set_key(channel->hmac, hash,
767                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
768       memset(hash, 0, sizeof(hash));
769     }
770 
771     /* Get the passphrase */
772     tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
773     if (tmp) {
774       silc_free(channel->passphrase);
775       channel->passphrase = silc_memdup(tmp, tmp_len);
776     }
777 
778     /* Get founder public key */
779     tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
780     if (tmp && mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
781       if (channel->founder_key)
782         silc_pkcs_public_key_free(channel->founder_key);
783       channel->founder_key = NULL;
784       SILC_LOG_DEBUG(("Founder public key received"));
785       if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len,
786                                                &channel->founder_key)) {
787         SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
788         mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
789         silc_server_send_notify_cmode(server, sock, FALSE, channel,
790                                       mode, server->id, SILC_ID_SERVER,
791                                       channel->cipher,
792                                       channel->hmac_name,
793                                       channel->passphrase, NULL, NULL);
794         if (channel->founder_key)
795           silc_pkcs_public_key_free(channel->founder_key);
796         channel->founder_key = NULL;
797       }
798     }
799 
800     if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH && !channel->founder_key &&
801         server->server_type == SILC_ROUTER) {
802       SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
803       mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
804       silc_server_send_notify_cmode(server, sock, FALSE, channel,
805                                     mode, server->id, SILC_ID_SERVER,
806                                     channel->cipher,
807                                     channel->hmac_name,
808                                     channel->passphrase, NULL, NULL);
809     }
810 
811     /* Process channel public key(s). */
812     tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
813     if (tmp && mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
814       SilcStatus ret =
815         silc_server_set_channel_pk_list(server, sock, channel, tmp, tmp_len);
816 
817       /* If list was set already we will enforce the same list to server. */
818       if (ret == SILC_STATUS_ERR_OPERATION_ALLOWED) {
819         SilcBuffer chpklist = silc_server_get_channel_pk_list(server, channel,
820                                                               TRUE, FALSE);
821         silc_server_send_notify_cmode(server, sock, FALSE, channel,
822                                       mode, server->id, SILC_ID_SERVER,
823                                       channel->cipher,
824                                       channel->hmac_name,
825                                       channel->passphrase, NULL,
826                                       chpklist);
827         silc_buffer_free(chpklist);
828       }
829     }
830 
831     /* Get the user limit */
832     tmp = silc_argument_get_arg_type(args, 8, &tmp_len);
833     if (tmp && tmp_len == 4 && mode & SILC_CHANNEL_MODE_ULIMIT)
834       SILC_GET32_MSB(channel->user_limit, tmp);
835 
836     /* Send the same notify to the channel */
837     silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
838                                        FALSE, TRUE, packet->buffer->data,
839                                        packet->buffer->len, FALSE);
840 
841     /* Change mode */
842     channel->mode = mode;
843 
844     /* Cleanup if some modes are removed */
845 
846     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) &&
847         channel->founder_key) {
848       silc_pkcs_public_key_free(channel->founder_key);
849       channel->founder_key = NULL;
850     }
851 
852     if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) &&
853         channel->channel_pubkeys) {
854       silc_hash_table_free(channel->channel_pubkeys);
855       channel->channel_pubkeys = NULL;
856     }
857 
858     break;
859 
860   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
861     {
862       /*
863        * Distribute the notify to local clients on the channel
864        */
865       SilcChannelClientEntry chl2 = NULL;
866       bool notify_sent = FALSE;
867 
868       SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
869 
870       /* Get client ID */
871       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
872       if (!tmp)
873         goto out;
874       client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
875       if (!client_id)
876         goto out;
877 
878       /* Get client entry */
879       if (id_type == SILC_ID_CLIENT) {
880         client = silc_idlist_find_client_by_id(server->global_list,
881                                                client_id, TRUE, &cache);
882         if (!client) {
883           client = silc_idlist_find_client_by_id(server->local_list,
884                                                  client_id, TRUE, &cache);
885           if (!client) {
886             silc_free(client_id);
887             goto out;
888           }
889         }
890       }
891       silc_free(client_id);
892 
893       if (!channel_id) {
894         channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
895                                     packet->dst_id_type);
896         if (!channel_id)
897           goto out;
898       }
899 
900       /* Get channel entry */
901       channel = silc_idlist_find_channel_by_id(server->global_list,
902                                                channel_id, NULL);
903       if (!channel) {
904         channel = silc_idlist_find_channel_by_id(server->local_list,
905                                                  channel_id, NULL);
906         if (!channel) {
907           SILC_LOG_DEBUG(("Notify for unknown channel"));
908           silc_free(channel_id);
909           goto out;
910         }
911       }
912 
913       /* Get the mode */
914       tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
915       if (!tmp) {
916         silc_free(channel_id);
917         goto out;
918       }
919 
920       SILC_GET32_MSB(mode, tmp);
921 
922       /* Get target client */
923       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
924       if (!tmp)
925         goto out;
926       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
927       if (!client_id)
928         goto out;
929 
930       /* Get client entry */
931       client2 = silc_idlist_find_client_by_id(server->global_list,
932                                               client_id, TRUE, NULL);
933       if (!client2) {
934         client2 = silc_idlist_find_client_by_id(server->local_list,
935                                                 client_id, TRUE, NULL);
936         if (!client2) {
937           silc_free(client_id);
938           goto out;
939         }
940       }
941       silc_free(client_id);
942 
943       if (client) {
944         /* Check that sender is on channel */
945         if (!silc_server_client_on_channel(client, channel, &chl))
946           goto out;
947 
948         if (client != client2 && server->server_type == SILC_ROUTER) {
949           /* Sender must be operator */
950           if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
951               !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
952             SILC_LOG_DEBUG(("CUMODE change is not allowed"));
953             goto out;
954           }
955 
956           if (!silc_server_client_on_channel(client2, channel, &chl))
957             goto out;
958 
959           /* If target is founder mode change is not allowed. */
960           if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
961             SILC_LOG_DEBUG(("CUMODE change is not allowed"));
962             goto out;
963           }
964         }
965       }
966 
967       /* Get target channel user entry */
968       if (!silc_server_client_on_channel(client2, channel, &chl))
969         goto out;
970 
971       if (server->server_type == SILC_SERVER && chl->mode == mode) {
972         SILC_LOG_DEBUG(("Mode is changed already"));
973         break;
974       }
975 
976       /* Check whether to give founder rights to this user or not.  The
977          problem here is that we get only the public key of the client,
978          but no authentication data.  We must assume that server has
979          already authenticated the user (and thus we must trust the
980          server). */
981       if (mode & SILC_CHANNEL_UMODE_CHANFO &&
982           !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
983           server->server_type == SILC_ROUTER &&
984           sock != SILC_PRIMARY_ROUTE(server)) {
985         SilcPublicKey founder_key = NULL;
986 
987         /* If channel doesn't have founder auth mode then it's impossible
988            that someone would be getting founder rights with CUMODE command.
989            In that case there already either is founder or there isn't
990            founder at all on the channel (valid only when 'client' is
991            valid). */
992         if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
993           /* Force the mode to not have founder mode */
994           chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
995           silc_server_force_cumode_change(server, sock, channel, chl, mode);
996           notify_sent = TRUE;
997           break;
998         }