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 }