updates
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      unsigned int arg_type,
38                                      unsigned char *arg,
39                                      unsigned int arg_len);
40 static void silc_server_command_free(SilcServerCommandContext cmd);
41
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
44 {
45   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
49   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
50   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
54   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(connect, CONNECT, 
56                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
60   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(restart, RESTART, 
66                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67   SILC_SERVER_CMD(close, CLOSE,
68                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69   SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70   SILC_SERVER_CMD(silcoper, SILCOPER,
71                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
73   SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
74
75   { NULL, 0 },
76 };
77
78 /* List of pending commands. */
79 SilcDList silc_command_pending;
80
81 /* Returns TRUE if the connection is registered. Unregistered connections
82    usually cannot send commands hence the check. */
83
84 static int silc_server_is_registered(SilcServer server,
85                                      SilcSocketConnection sock,
86                                      SilcServerCommandContext cmd,
87                                      SilcCommand command)
88 {
89   SilcIDListData idata = (SilcIDListData)sock->user_data;
90   if (idata->registered)
91     return TRUE;
92
93   silc_server_command_send_status_reply(cmd, command,
94                                         SILC_STATUS_ERR_NOT_REGISTERED);
95   silc_server_command_free(cmd);
96   return FALSE;
97 }
98
99 /* Processes received command packet. */
100
101 void silc_server_command_process(SilcServer server,
102                                  SilcSocketConnection sock,
103                                  SilcPacketContext *packet)
104 {
105   SilcServerCommandContext ctx;
106   SilcServerCommand *cmd;
107
108 #if 0
109   /* XXX allow commands in but do not execute them more than once per
110      two seconds. */
111
112   /* Check whether it is allowed for this connection to execute any
113      command. */
114   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
115     time_t curtime;
116     SilcClientEntry client = (SilcClientEntry)sock->user_data;
117
118     if (!client)
119       goto out;
120
121     /* Allow only one command executed in 2 seconds. */
122     curtime = time(NULL);
123     if (client->last_command && (curtime - client->last_command) < 2)
124       goto out;
125
126     /* Update access time */
127     client->last_command = curtime;
128   }
129 #endif
130   
131   /* Allocate command context. This must be free'd by the
132      command routine receiving it. */
133   ctx = silc_calloc(1, sizeof(*ctx));
134   ctx->server = server;
135   ctx->sock = sock;
136   ctx->packet = packet; /* Save original packet */
137   
138   /* Parse the command payload in the packet */
139   ctx->payload = silc_command_payload_parse(packet->buffer);
140   if (!ctx->payload) {
141     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
142     silc_buffer_free(packet->buffer);
143     silc_free(ctx);
144     return;
145   }
146   ctx->args = silc_command_get_args(ctx->payload);
147   
148   /* Execute command. If this fails the packet is dropped. */
149   for (cmd = silc_command_list; cmd->cb; cmd++)
150     if (cmd->cmd == silc_command_get(ctx->payload)) {
151
152       if (!(cmd->flags & SILC_CF_REG)) {
153         cmd->cb(ctx);
154         break;
155       }
156       
157       if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
158         cmd->cb(ctx);
159         break;
160       }
161     }
162
163   if (cmd == NULL) {
164     SILC_LOG_ERROR(("Unknown command, packet dropped"));
165     silc_free(ctx);
166     goto out;
167   }
168
169  out:
170   silc_buffer_free(packet->buffer);
171 }
172
173 /* Add new pending command to be executed when reply to a command has been
174    received. The `reply_cmd' is the command that will call the `callback'
175    with `context' when reply has been received.  If `ident' is non-zero
176    the `callback' will be executed when received reply with command
177    identifier `ident'. */
178
179 void silc_server_command_pending(SilcCommand reply_cmd,
180                                  unsigned short ident,
181                                  SilcCommandCb callback,
182                                  void *context)
183 {
184   SilcServerCommandPending *reply;
185
186   reply = silc_calloc(1, sizeof(*reply));
187   reply->reply_cmd = reply_cmd;
188   reply->ident = ident;
189   reply->context = context;
190   reply->callback = callback;
191   silc_dlist_add(silc_command_pending, reply);
192 }
193
194 /* Deletes pending command by reply command type. */
195
196 void silc_server_command_pending_del(SilcCommand reply_cmd,
197                                      unsigned short ident)
198 {
199   SilcServerCommandPending *r;
200
201   while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
202     if (r->reply_cmd == reply_cmd && r->ident == ident) {
203       silc_dlist_del(silc_command_pending, r);
204       break;
205     }
206   }
207 }
208
209 /* Checks for pending commands and marks callbacks to be called from
210    the command reply function. Returns TRUE if there were pending command. */
211
212 int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
213                                       SilcCommand command, 
214                                       unsigned short ident)
215 {
216   SilcServerCommandPending *r;
217
218   while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
219     if (r->reply_cmd == command && r->ident == ident) {
220       ctx->context = r->context;
221       ctx->callback = r->callback;
222       ctx->ident = ident;
223       return TRUE;
224     }
225   }
226
227   return FALSE;
228 }
229
230 /* Free's the command context allocated before executing the command */
231
232 static void silc_server_command_free(SilcServerCommandContext cmd)
233 {
234   if (cmd) {
235     silc_command_free_payload(cmd->payload);
236     silc_free(cmd);
237   }
238 }
239
240 /* Sends simple status message as command reply packet */
241
242 static void 
243 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
244                                       SilcCommand command,
245                                       SilcCommandStatus status)
246 {
247   SilcBuffer buffer;
248
249   SILC_LOG_DEBUG(("Sending command status %d", status));
250
251   buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
252   silc_server_packet_send(cmd->server, cmd->sock,
253                           SILC_PACKET_COMMAND_REPLY, 0, 
254                           buffer->data, buffer->len, FALSE);
255   silc_buffer_free(buffer);
256 }
257
258 /* Sends command status reply with one extra argument. The argument
259    type must be sent as argument. */
260
261 static void 
262 silc_server_command_send_status_data(SilcServerCommandContext cmd,
263                                      SilcCommand command,
264                                      SilcCommandStatus status,
265                                      unsigned int arg_type,
266                                      unsigned char *arg,
267                                      unsigned int arg_len)
268 {
269   SilcBuffer buffer;
270
271   SILC_LOG_DEBUG(("Sending command status %d", status));
272
273   buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
274                                                 arg_type, arg, arg_len);
275   silc_server_packet_send(cmd->server, cmd->sock,
276                           SILC_PACKET_COMMAND_REPLY, 0, 
277                           buffer->data, buffer->len, FALSE);
278   silc_buffer_free(buffer);
279 }
280
281 /* Server side of command WHOIS. Processes user's query and sends found 
282    results as command replies back to the client. */
283
284 SILC_SERVER_CMD_FUNC(whois)
285 {
286   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
287   SilcServer server = cmd->server;
288   char *tmp, *nick = NULL, *server_name = NULL;
289   unsigned int i, argc, count = 0, len, clients_count;
290   int use_id = FALSE;
291   SilcClientID *client_id = NULL;
292   SilcBuffer packet, idp;
293   SilcClientEntry *clients = NULL, entry;
294   SilcCommandStatus status;
295
296   SILC_LOG_DEBUG(("Start"));
297
298   argc = silc_argument_get_arg_num(cmd->args);
299   if (argc < 1) {
300     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
301                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
302     goto out;
303   }
304   if (argc > 3) {
305     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
306                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
307     goto out;
308   }
309
310   /* If client ID is in the command it must be used instead of nickname */
311   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
312   if (!tmp) {
313
314     /* No ID, get the nickname@server string and parse it. */
315     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
316     if (tmp) {
317       if (strchr(tmp, '@')) {
318         len = strcspn(tmp, "@");
319         nick = silc_calloc(len + 1, sizeof(char));
320         memcpy(nick, tmp, len);
321         server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
322         memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
323       } else {
324         nick = strdup(tmp);
325       }
326     } else {
327       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
328                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
329       goto out;
330     }
331   } else {
332     /* Command includes ID, use that */
333     client_id = silc_id_payload_parse_id(tmp, len);
334     use_id = TRUE;
335   }
336
337   /* Get the max count of reply messages allowed */
338   if (argc == 3) {
339     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
340     if (!tmp) {
341       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
342                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
343       if (nick)
344         silc_free(nick);
345       if (server_name)
346         silc_free(server_name);
347       goto out;
348     }
349     count = atoi(tmp);
350   }
351
352   /* Protocol dictates that we must always send the received WHOIS request
353      to our router if we are normal server, so let's do it now unless we
354      are standalone. We will not send any replies to the client until we
355      have received reply from the router. */
356   if (!server->standalone) {
357     SilcBuffer tmpbuf;
358
359     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
360     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
361
362     /* Send WHOIS command to our router */
363     silc_server_packet_send(server, (SilcSocketConnection)
364                             server->id_entry->router->connection,
365                             SILC_PACKET_COMMAND, cmd->packet->flags,
366                             tmpbuf->data, tmpbuf->len, TRUE);
367     return;
368   } else {
369     /* We are standalone, let's just do local search and send reply to
370        requesting client. */
371
372     /* Get all clients matching that nickname */
373     if (!use_id) {
374       clients = silc_idlist_get_clients_by_nickname(server->local_list, 
375                                                     nick, server_name,
376                                                     &clients_count);
377     } else {
378       entry = silc_idlist_find_client_by_id(server->local_list, client_id);
379       if (entry) {
380         clients = silc_calloc(1, sizeof(*clients));
381         clients[0] = entry;
382         clients_count = 1;
383       }
384     }
385     
386     /* If we are router then we will check our global list as well. */
387     if (server->server_type == SILC_ROUTER) {
388       entry =
389         silc_idlist_find_client_by_nickname(server->global_list,
390                                             nick, server_name);
391       if (!entry) {
392         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
393                                              SILC_STATUS_ERR_NO_SUCH_NICK,
394                                              3, tmp, strlen(tmp));
395         goto out;
396       }
397       goto ok;
398     }
399       
400 #if 0
401     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
402                                          SILC_STATUS_ERR_NO_SUCH_NICK,
403                                          3, tmp, strlen(tmp));
404     goto out;
405 #endif
406   }
407
408   /* We are standalone and will send reply to client */
409  ok:
410  
411   status = SILC_STATUS_OK;
412   if (clients_count > 1)
413     status = SILC_STATUS_LIST_START;
414
415   for (i = 0; i < clients_count; i++) {
416     entry = clients[i];
417
418     if (count && i - 1 == count)
419       break;
420
421     if (clients_count > 2)
422       status = SILC_STATUS_LIST_ITEM;
423
424     if (clients_count > 1 && i == clients_count - 1)
425       status = SILC_STATUS_LIST_END;
426
427     /* Send WHOIS reply */
428     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
429     tmp = silc_argument_get_first_arg(cmd->args, NULL);
430     
431     /* XXX */
432     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
433       char nh[256], uh[256];
434       unsigned char idle[4];
435       SilcSocketConnection hsock;
436
437       memset(uh, 0, sizeof(uh));
438       memset(nh, 0, sizeof(nh));
439       
440       strncat(nh, entry->nickname, strlen(entry->nickname));
441       strncat(nh, "@", 1);
442       len = entry->router ? strlen(entry->router->server_name) :
443         strlen(server->server_name);
444       strncat(nh, entry->router ? entry->router->server_name :
445               server->server_name, len);
446       
447       strncat(uh, entry->username, strlen(entry->username));
448       strncat(uh, "@", 1);
449       hsock = (SilcSocketConnection)entry->connection;
450       len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
451       strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
452       
453       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
454       
455       /* XXX */
456       if (entry->userinfo)
457         packet = 
458           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
459                                                status, 0, 5, 
460                                                2, idp->data, idp->len,
461                                                3, nh, strlen(nh),
462                                                4, uh, strlen(uh),
463                                                5, entry->userinfo, 
464                                                strlen(entry->userinfo),
465                                                7, idle, 4);
466       else
467         packet = 
468           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
469                                                status, 0, 4, 
470                                                2, idp->data, idp->len,
471                                                3, nh, strlen(nh),
472                                                4, uh, strlen(uh),
473                                                7, idle, 4);
474       
475     } else {
476       /* XXX */
477       packet = 
478         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS, 
479                                              status, 0, 3, 
480                                              2, idp->data, idp->len,
481                                              3, entry->nickname, 
482                                              strlen(entry->nickname),
483                                              4, tmp, strlen(tmp)); /* XXX */
484     }
485     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
486                             0, packet->data, packet->len, FALSE);
487     
488     silc_buffer_free(packet);
489     silc_buffer_free(idp);
490   }
491
492   silc_free(clients);
493
494   if (client_id)
495     silc_free(client_id);
496
497  out:
498   silc_server_command_free(cmd);
499 }
500
501 SILC_SERVER_CMD_FUNC(whowas)
502 {
503 }
504
505 SILC_SERVER_CMD_FUNC(identify)
506 {
507   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
508   SilcServer server = cmd->server;
509   char *tmp, *nick = NULL, *server_name = NULL;
510   unsigned int argc, count = 0, len;
511   int use_id = FALSE;
512   SilcClientID *client_id = NULL;
513   SilcClientEntry entry;
514   SilcBuffer packet, idp;
515
516   SILC_LOG_DEBUG(("Start"));
517
518   argc = silc_argument_get_arg_num(cmd->args);
519   if (argc < 1) {
520     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
521                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
522     goto out;
523   }
524   if (argc > 3) {
525     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
526                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
527     goto out;
528   }
529
530   /* If client ID is in the command it must be used instead of nickname */
531   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
532   if (!tmp) {
533
534     /* Get the nickname@server string and parse it. */
535     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
536     if (tmp) {
537       if (strchr(tmp, '@')) {
538         len = strcspn(tmp, "@");
539         nick = silc_calloc(len + 1, sizeof(char));
540         memcpy(nick, tmp, len);
541         server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
542         memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
543       } else {
544         nick = strdup(tmp);
545       }
546     } else {
547       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
548                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
549       goto out;
550     }
551   } else {
552     /* Command includes ID, use that */
553     client_id = silc_id_payload_parse_id(tmp, len);
554     use_id = TRUE;
555   }
556
557   /* Get the max count of reply messages allowed */
558   if (argc == 3) {
559     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
560     if (!tmp) {
561       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
562                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
563       goto out;
564     }
565     count = atoi(tmp);
566   }
567
568   /* Find client */
569   if (!use_id) {
570     entry = silc_idlist_find_client_by_nickname(server->local_list,
571                                                 nick, NULL);
572     if (!entry)
573       entry = silc_idlist_find_client_by_hash(server->global_list,
574                                               nick, server->md5hash);
575   } else {
576     entry = silc_idlist_find_client_by_id(server->local_list, client_id);
577   }
578
579   /* If client was not found and if we are normal server and are connected
580      to a router we will make global query from the router. */
581   if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
582       !cmd->pending) {
583     SilcBuffer buffer = cmd->packet->buffer;
584     
585     SILC_LOG_DEBUG(("Requesting identify from router"));
586     
587     /* Send IDENTIFY command to our router */
588     silc_buffer_push(buffer, buffer->data - buffer->head);
589     silc_server_packet_forward(server, (SilcSocketConnection)
590                                server->id_entry->router->connection,
591                                buffer->data, buffer->len, TRUE);
592     return;
593   }
594
595   /* If we are router we have checked our local list by nickname and our
596      global list by hash so far. It is possible that the client is still not
597      found and we'll check it from local list by hash. */
598   if (!entry && server->server_type == SILC_ROUTER)
599     entry = silc_idlist_find_client_by_hash(server->local_list,
600                                             nick, server->md5hash);
601
602   if (!entry) {
603     /* The client definitely does not exist */
604     silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
605                                          SILC_STATUS_ERR_NO_SUCH_NICK,
606                                          3, tmp, strlen(tmp));
607     goto out;
608   }
609
610   /* Send IDENTIFY reply */
611   idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
612   tmp = silc_argument_get_first_arg(cmd->args, NULL);
613   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
614                                                 SILC_STATUS_OK, 0, 2,
615                                                 2, idp->data, idp->len, 
616                                                 3, nick, strlen(nick));
617   if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
618     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
619     silc_server_packet_send_dest(server, cmd->sock, 
620                                  SILC_PACKET_COMMAND_REPLY, 0,
621                                  id, cmd->packet->src_id_type,
622                                  packet->data, packet->len, FALSE);
623     silc_free(id);
624   } else {
625     silc_server_packet_send(server, cmd->sock, 
626                             SILC_PACKET_COMMAND_REPLY, 0, 
627                             packet->data, packet->len, FALSE);
628   }
629
630   silc_buffer_free(packet);
631   silc_buffer_free(idp);
632   if (client_id)
633     silc_free(client_id);
634
635  out:
636   if (nick)
637     silc_free(nick);
638   if (server_name)
639     silc_free(server_name);
640   silc_server_command_free(cmd);
641 }
642
643 /* Checks string for bad characters and returns TRUE if they are found. */
644
645 static int silc_server_command_bad_chars(char *nick)
646 {
647   if (strchr(nick, '\\')) return TRUE;
648   if (strchr(nick, '\"')) return TRUE;
649   if (strchr(nick, '´')) return TRUE;
650   if (strchr(nick, '`')) return TRUE;
651   if (strchr(nick, '\'')) return TRUE;
652   if (strchr(nick, '*')) return TRUE;
653   if (strchr(nick, '/')) return TRUE;
654   if (strchr(nick, '@')) return TRUE;
655
656   return FALSE;
657 }
658
659 /* Server side of command NICK. Sets nickname for user. Setting
660    nickname causes generation of a new client ID for the client. The
661    new client ID is sent to the client after changing the nickname. */
662
663 SILC_SERVER_CMD_FUNC(nick)
664 {
665   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
666   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
667   SilcServer server = cmd->server;
668   SilcBuffer packet, nidp, oidp;
669   SilcClientID *new_id;
670   char *nick;
671
672   SILC_LOG_DEBUG(("Start"));
673
674   /* Check number of arguments */
675   if (silc_argument_get_arg_num(cmd->args) < 1) {
676     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
677                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
678     goto out;
679   }
680
681   /* Check nickname */
682   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
683   if (silc_server_command_bad_chars(nick) == TRUE) {
684     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
685                                           SILC_STATUS_ERR_BAD_NICKNAME);
686     goto out;
687   }
688
689   /* Create new Client ID */
690   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
691                            cmd->server->md5hash, nick,
692                            &new_id);
693
694   /* Send notify about nickname change to our router. We send the new
695      ID and ask to replace it with the old one. */
696   if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
697     silc_server_send_replace_id(server, server->id_entry->router->connection, 
698                                 FALSE, client->id,
699                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
700                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
701
702   /* If we are router we have to distribute the new Client ID to all 
703      routers in SILC. */
704   if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
705     silc_server_send_replace_id(server, server->id_entry->router->connection,  
706                                 TRUE, client->id,
707                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
708                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
709
710   /* Remove old cache entry */
711   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
712                          client->id); 
713
714   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
715
716   /* Free old ID */
717   if (client->id) {
718     memset(client->id, 0, SILC_ID_CLIENT_LEN);
719     silc_free(client->id);
720   }
721
722   /* Save the nickname as this client is our local client */
723   if (client->nickname)
724     silc_free(client->nickname);
725
726   client->nickname = strdup(nick);
727   client->id = new_id;
728
729   /* Update client cache */
730   silc_idcache_add(server->local_list->clients, client->nickname, 
731                    SILC_ID_CLIENT, client->id, (void *)client, TRUE);
732
733   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
734
735   /* Send NICK_CHANGE notify */
736   silc_server_send_notify_on_channels(server, client, 
737                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
738                                       oidp->data, oidp->len, 
739                                       nidp->data, nidp->len);
740
741   /* Send the new Client ID as reply command back to client */
742   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
743                                                 SILC_STATUS_OK, 0, 1, 
744                                                 2, nidp->data, nidp->len);
745   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
746                           0, packet->data, packet->len, FALSE);
747
748   silc_buffer_free(packet);
749   silc_buffer_free(nidp);
750   silc_buffer_free(oidp);
751   
752  out:
753   silc_server_command_free(cmd);
754 }
755
756 SILC_SERVER_CMD_FUNC(list)
757 {
758 }
759
760 /* Server side of TOPIC command. Sets topic for channel and/or returns
761    current topic to client. */
762
763 SILC_SERVER_CMD_FUNC(topic)
764 {
765   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766   SilcServer server = cmd->server;
767   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
768   SilcChannelID *channel_id;
769   SilcChannelEntry channel;
770   SilcChannelClientEntry chl;
771   SilcBuffer packet, idp;
772   unsigned char *tmp;
773   unsigned int argc, tmp_len;
774
775   /* Check number of arguments */
776   argc = silc_argument_get_arg_num(cmd->args);
777   if (argc < 1) {
778     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
779                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
780     goto out;
781   }
782   if (argc > 2) {
783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
784                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
785     goto out;
786   }
787
788   /* Get Channel ID */
789   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
790   if (!tmp) {
791     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
792                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
793     goto out;
794   }
795   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
796
797   /* Check whether the channel exists */
798   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
799   if (!channel) {
800     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
801                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
802     goto out;
803   }
804
805   if (argc > 1) {
806     /* Get the topic */
807     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
808     if (!tmp) {
809       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
810                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
811       goto out;
812     }
813
814     if (strlen(tmp) > 256) {
815       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
816                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
817       goto out;
818     }
819
820     /* See whether has rights to change topic */
821     silc_list_start(channel->user_list);
822     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
823       if (chl->client == client) {
824         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
825           silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
826                                                 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
827           goto out;
828         } else {
829           break;
830         }
831       }
832     }
833
834     /* Set the topic for channel */
835     if (channel->topic)
836       silc_free(channel->topic);
837     channel->topic = strdup(tmp);
838
839     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
840
841     /* Send notify about topic change to all clients on the channel */
842     silc_server_send_notify_to_channel(server, channel,
843                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
844                                        idp->data, idp->len,
845                                        channel->topic, strlen(channel->topic));
846     silc_buffer_free(idp);
847   }
848
849   /* Send the topic to client as reply packet */
850   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
851   if (channel->topic)
852     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
853                                                   SILC_STATUS_OK, 0, 2, 
854                                                   2, idp->data, idp->len,
855                                                   3, channel->topic, 
856                                                   strlen(channel->topic));
857   else
858     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
859                                                   SILC_STATUS_OK, 0, 1, 
860                                                   2, idp->data, idp->len);
861   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
862                           0, packet->data, packet->len, FALSE);
863
864   silc_buffer_free(packet);
865   silc_buffer_free(idp);
866   silc_free(channel_id);
867
868  out:
869   silc_server_command_free(cmd);
870 }
871
872 /* Server side of INVITE command. Invites some client to join some channel. */
873
874 SILC_SERVER_CMD_FUNC(invite)
875 {
876   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
877   SilcServer server = cmd->server;
878   SilcSocketConnection sock = cmd->sock, dest_sock;
879   SilcClientEntry sender, dest;
880   SilcClientID *dest_id;
881   SilcChannelEntry channel;
882   SilcChannelID *channel_id;
883   SilcBuffer sidp;
884   unsigned char *tmp;
885   unsigned int argc, len;
886
887   /* Check number of arguments */
888   argc = silc_argument_get_arg_num(cmd->args);
889   if (argc < 1) {
890     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
891                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
892     goto out;
893   }
894   if (argc > 2) {
895     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
896                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
897     goto out;
898   }
899
900   /* Get destination ID */
901   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
902   if (!tmp) {
903     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
904                                           SILC_STATUS_ERR_NO_CLIENT_ID);
905     goto out;
906   }
907   dest_id = silc_id_payload_parse_id(tmp, len);
908
909   /* Get Channel ID */
910   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
911   if (!tmp) {
912     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
913                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
914     goto out;
915   }
916   channel_id = silc_id_payload_parse_id(tmp, len);
917
918   /* Check whether the channel exists */
919   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
920   if (!channel) {
921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
922                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
923     goto out;
924   }
925
926   /* Check whether the sender of this command is on the channel. */
927   sender = (SilcClientEntry)sock->user_data;
928   if (!silc_server_client_on_channel(sender, channel)) {
929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
930                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
931     goto out;
932   }
933
934   /* Check whether the channel is invite-only channel. If yes then the
935      sender of this command must be at least channel operator. */
936   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
937     SilcChannelClientEntry chl;
938
939     silc_list_start(channel->user_list);
940     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
941       if (chl->client == sender) {
942         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
943           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
944                                                 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
945           goto out;
946         }
947         break;
948       }
949   }
950
951   /* Find the connection data for the destination. If it is local we will
952      send it directly otherwise we will send it to router for routing. */
953   dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
954   if (dest)
955     dest_sock = (SilcSocketConnection)dest->connection;
956   else
957     dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
958
959   /* Check whether the requested client is already on the channel. */
960   /* XXX if we are normal server we don't know about global clients on
961      the channel thus we must request it (NAMES command), check from
962      local cache as well. */
963   if (silc_server_client_on_channel(dest, channel)) {
964     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
965                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
966     goto out;
967   }
968
969   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
970
971   /* Send notify to the client that is invited to the channel */
972   silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
973                                SILC_NOTIFY_TYPE_INVITE, 2, 
974                                sidp->data, sidp->len, tmp, len);
975
976   /* Send command reply */
977   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
978                                         SILC_STATUS_OK);
979
980   silc_buffer_free(sidp);
981
982  out:
983   silc_server_command_free(cmd);
984 }
985
986 /* Quits connection to client. This gets called if client won't
987    close the connection even when it has issued QUIT command. */
988
989 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
990 {
991   SilcServer server = (SilcServer)context;
992   SilcSocketConnection sock = server->sockets[fd];
993
994   /* Free all client specific data, such as client entry and entires
995      on channels this client may be on. */
996   silc_server_free_sock_user_data(server, sock);
997
998   /* Close the connection on our side */
999   silc_server_close_connection(server, sock);
1000 }
1001
1002 /* Quits SILC session. This is the normal way to disconnect client. */
1003  
1004 SILC_SERVER_CMD_FUNC(quit)
1005 {
1006   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007   SilcServer server = cmd->server;
1008   SilcSocketConnection sock = cmd->sock;
1009
1010   SILC_LOG_DEBUG(("Start"));
1011
1012   /* We quit the connection with little timeout */
1013   silc_task_register(server->timeout_queue, sock->sock,
1014                      silc_server_command_quit_cb, server,
1015                      0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1016
1017   silc_server_command_free(cmd);
1018 }
1019
1020 SILC_SERVER_CMD_FUNC(kill)
1021 {
1022 }
1023
1024 /* Server side of command INFO. This sends information about us to 
1025    the client. If client requested specific server we will send the 
1026    command to that server. */
1027
1028 SILC_SERVER_CMD_FUNC(info)
1029 {
1030   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1031   SilcServer server = cmd->server;
1032   SilcBuffer packet, idp;
1033   unsigned int argc;
1034   char info_string[256], *dest_server;
1035
1036   argc = silc_argument_get_arg_num(cmd->args);
1037   if (argc < 1) {
1038     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1039                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1040     goto out;
1041   }
1042   if (argc > 1) {
1043     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1044                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1045     goto out;
1046   }
1047
1048   /* Get server name */
1049   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1050   if (!dest_server) {
1051     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1052                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1053     goto out;
1054   }
1055
1056   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1057     /* Send our reply */
1058     memset(info_string, 0, sizeof(info_string));
1059     snprintf(info_string, sizeof(info_string), 
1060              "location: %s server: %s admin: %s <%s>",
1061              server->config->admin_info->location,
1062              server->config->admin_info->server_type,
1063              server->config->admin_info->admin_name,
1064              server->config->admin_info->admin_email);
1065
1066     idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1067
1068     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1069                                                   SILC_STATUS_OK, 0, 2,
1070                                                   2, idp->data, idp->len,
1071                                                   3, info_string, 
1072                                                   strlen(info_string));
1073     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1074                             packet->data, packet->len, FALSE);
1075     
1076     silc_buffer_free(packet);
1077     silc_buffer_free(idp);
1078   } else {
1079     /* Send this command to the requested server */
1080
1081     if (server->server_type == SILC_SERVER && !server->standalone) {
1082
1083     }
1084
1085     if (server->server_type == SILC_ROUTER) {
1086
1087     }
1088   }
1089   
1090  out:
1091   silc_server_command_free(cmd);
1092 }
1093
1094 SILC_SERVER_CMD_FUNC(connect)
1095 {
1096 }
1097
1098 /* Server side of command PING. This just replies to the ping. */
1099
1100 SILC_SERVER_CMD_FUNC(ping)
1101 {
1102   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1103   SilcServer server = cmd->server;
1104   SilcServerID *id;
1105   unsigned int argc, len;
1106   unsigned char *tmp;
1107
1108   argc = silc_argument_get_arg_num(cmd->args);
1109   if (argc < 1) {
1110     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1111                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1112     goto out;
1113   }
1114   if (argc > 2) {
1115     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1116                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1117     goto out;
1118   }
1119
1120   /* Get Server ID */
1121   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1122   if (!tmp) {
1123     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1124                                           SILC_STATUS_ERR_NO_SERVER_ID);
1125     goto out;
1126   }
1127   id = silc_id_payload_parse_id(tmp, len);
1128
1129   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1130     /* Send our reply */
1131     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1132                                           SILC_STATUS_OK);
1133   } else {
1134     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1135                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1136     goto out;
1137   }
1138
1139   silc_free(id);
1140
1141  out:
1142   silc_server_command_free(cmd);
1143 }
1144
1145 SILC_SERVER_CMD_FUNC(oper)
1146 {
1147 }
1148
1149 typedef struct {
1150   char *channel_name;
1151   char *nickname;
1152   char *username;
1153   char *hostname;
1154   SilcChannelEntry channel;
1155   SilcServer server;
1156   SilcClientEntry client;
1157 } JoinInternalContext;
1158
1159 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1160 {
1161   JoinInternalContext *ctx = (JoinInternalContext *)context;
1162
1163   if (ctx->channel->key && ctx->channel->key_len) {
1164     SilcBuffer clidp;
1165
1166     clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1167
1168     silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1169                                        SILC_NOTIFY_TYPE_JOIN, 1,
1170                                        clidp->data, clidp->len);
1171
1172     silc_buffer_free(clidp);
1173     silc_free(ctx);
1174   } else {
1175     silc_task_register(ctx->server->timeout_queue, fd,
1176                        silc_server_command_join_notify, context,
1177                        0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1178   }
1179 }
1180
1181 /* Assembles NAMES command and executes it. This is called when client
1182    joins to a channel and we wan't to send NAMES command reply to the 
1183    client. */
1184
1185 void silc_server_command_send_names(SilcServer server,
1186                                     SilcSocketConnection sock,
1187                                     SilcChannelEntry channel)
1188 {
1189   SilcServerCommandContext cmd;
1190   SilcBuffer buffer, idp;
1191
1192   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1193   buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1194                                           1, idp->data, idp->len);
1195
1196   cmd = silc_calloc(1, sizeof(*cmd));
1197   cmd->payload = silc_command_payload_parse(buffer);
1198   cmd->args = silc_command_get_args(cmd->payload);
1199   cmd->server = server;
1200   cmd->sock = sock;
1201   cmd->pending = FALSE;
1202
1203   silc_server_command_names((void *)cmd);
1204   silc_free(buffer);
1205   silc_free(idp);
1206 }
1207
1208 /* Server side of command JOIN. Joins client into requested channel. If 
1209    the channel does not exist it will be created. */
1210
1211 SILC_SERVER_CMD_FUNC(join)
1212 {
1213   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1214   SilcServer server = cmd->server;
1215   SilcSocketConnection sock = cmd->sock;
1216   SilcBuffer buffer = cmd->packet->buffer;
1217   int argc, i, k, tmp_len;
1218   char *tmp, *channel_name = NULL, *cipher = NULL;
1219   unsigned char *passphrase = NULL, mode[4];
1220   unsigned int umode = 0;
1221   SilcChannelEntry channel;
1222   SilcChannelClientEntry chl;
1223   SilcServerID *router_id;
1224   SilcBuffer packet, idp;
1225   SilcClientEntry client;
1226
1227   SILC_LOG_DEBUG(("Start"));
1228
1229   /* Check number of parameters */
1230   argc = silc_argument_get_arg_num(cmd->args);
1231   if (argc < 1) {
1232     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1233                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1234     goto out;
1235   }
1236   if (argc > 3) {
1237     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1238                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1239     goto out;
1240   }
1241
1242   /* Get channel name */
1243   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1244   if (!tmp) {
1245     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1246                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1247     goto out;
1248   }
1249   channel_name = tmp;
1250
1251   if (silc_server_command_bad_chars(channel_name) == TRUE) {
1252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1253                                           SILC_STATUS_ERR_BAD_CHANNEL);
1254     silc_free(channel_name);
1255     goto out;
1256   }
1257
1258   /* Get passphrase */
1259   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1260   if (tmp) {
1261     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1262     memcpy(passphrase, tmp, tmp_len);
1263   }
1264   
1265   /* Get cipher name */
1266   cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1267
1268   /* See if the channel exists */
1269   channel = 
1270     silc_idlist_find_channel_by_name(server->local_list, channel_name);
1271   if (!channel) {
1272     /* Channel not found */
1273
1274     /* If we are standalone server we don't have a router, we just create 
1275        the channel by  ourselves. */
1276     if (server->standalone) {
1277       router_id = server->id;
1278       channel = silc_server_new_channel(server, router_id, cipher, 
1279                                         channel_name);
1280       umode |= SILC_CHANNEL_UMODE_CHANOP;
1281       umode |= SILC_CHANNEL_UMODE_CHANFO;
1282       if (!channel)
1283         goto out;
1284
1285       goto join_channel;
1286     }
1287
1288     /* No channel ID found, the channel does not exist on our server.
1289        We send JOIN command to our router which will handle the joining
1290        procedure (either creates the channel if it doesn't exist or
1291        joins the client to it) - if we are normal server. */
1292     if (server->server_type == SILC_SERVER) {
1293
1294       /* Forward the original JOIN command to the router */
1295       silc_buffer_push(buffer, buffer->data - buffer->head);
1296       silc_server_packet_forward(server, (SilcSocketConnection)
1297                                  server->id_entry->router->connection,
1298                                  buffer->data, buffer->len, TRUE);
1299       
1300       /* Add the command to be pending. It will be re-executed after
1301          router has replied back to us. */
1302       cmd->pending = TRUE;
1303       silc_server_command_pending(SILC_COMMAND_JOIN, 0,
1304                                   silc_server_command_join, context);
1305       return;
1306     }
1307   }
1308
1309   /* If we are router and the channel does not exist we will check our
1310      global list for the channel. */
1311   if (!channel && server->server_type == SILC_ROUTER) {
1312
1313     /* Notify all routers about the new channel in SILC network. */
1314     if (!server->standalone) {
1315 #if 0
1316       silc_server_send_new_id(server, server->id_entry->router->connection, 
1317                               TRUE,
1318                               xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1319 #endif
1320     }
1321
1322   }
1323
1324  join_channel:
1325
1326   /*
1327    * Check channel modes
1328    */
1329
1330   /* Check invite list if channel is invite-only channel */
1331   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1332     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1333       /* Invite list is specified. Check whether client is invited in the
1334          list. If not, then check whether it has been invited otherwise. */
1335
1336     } else {
1337       /* XXX client must be invited to be able to join the channel */
1338     }
1339   }
1340
1341   /* Check ban list if set */
1342   if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1343
1344   }
1345
1346   /* Check the channel passphrase if set. */
1347   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1348     if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1349                               strlen(channel->mode_data.passphrase))) {
1350       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1351                                             SILC_STATUS_ERR_BAD_PASSWORD);
1352       goto out;
1353     }
1354   }
1355
1356   /* Check user count limit if set. */
1357   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1358     if (silc_list_count(channel->user_list) + 1 > 
1359         channel->mode_data.user_limit) {
1360       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1361                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
1362       goto out;
1363     }
1364   }
1365
1366   /*
1367    * Client is allowed to join to the channel. Make it happen.
1368    */
1369
1370   /* If the JOIN request was forwarded to us we will make a bit slower
1371      query to get the client pointer. Otherwise, we get the client pointer
1372      real easy. */
1373   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1374     client = (SilcClientEntry)sock->user_data;
1375   } else {
1376     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1377     client = silc_idlist_find_client_by_id(server->local_list, id);
1378     if (!client) {
1379       /* XXX */
1380       goto out;
1381     }
1382     silc_free(id);
1383   }
1384
1385   /* Check whether the client already is on the channel */
1386   if (silc_server_client_on_channel(client, channel)) {
1387     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1388                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1389     goto out;
1390   }
1391
1392   /* Join the client to the channel by adding it to channel's user list.
1393      Add also the channel to client entry's channels list for fast cross-
1394      referencing. */
1395   chl = silc_calloc(1, sizeof(*chl));
1396   chl->mode = umode;
1397   chl->client = client;
1398   chl->channel = channel;
1399   silc_list_add(channel->user_list, chl);
1400   silc_list_add(client->channels, chl);
1401
1402   /* Notify router about new user on channel. If we are normal server
1403      we send it to our router, if we are router we send it to our
1404      primary route. */
1405   if (!server->standalone) {
1406
1407   }
1408
1409   /* Send command reply to the client. Client receives the Channe ID,
1410      channel mode and possibly other information in this reply packet. */
1411   if (!cmd->pending) {
1412     idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1413     SILC_PUT32_MSB(channel->mode, mode);
1414
1415     if (!channel->topic)
1416       packet = 
1417         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1418                                              SILC_STATUS_OK, 0, 3,
1419                                              2, channel_name, 
1420                                              strlen(channel_name),
1421                                              3, idp->data, idp->len,
1422                                              4, mode, 4);
1423     else
1424       packet = 
1425         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1426                                              SILC_STATUS_OK, 0, 4, 
1427                                              2, channel_name, 
1428                                              strlen(channel_name),
1429                                              3, idp->data, idp->len,
1430                                              4, mode, 4,
1431                                              5, channel->topic, 
1432                                              strlen(channel->topic));
1433
1434     if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1435       void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1436       silc_server_packet_send_dest(cmd->server, cmd->sock, 
1437                                    SILC_PACKET_COMMAND_REPLY, 0,
1438                                    id, cmd->packet->src_id_type,
1439                                    packet->data, packet->len, FALSE);
1440       silc_free(id);
1441     } else
1442       silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1443                               packet->data, packet->len, FALSE);
1444     silc_buffer_free(packet);
1445
1446     /* Send channel key to the client. Client cannot start transmitting
1447        to the channel until we have sent the key. */
1448     tmp_len = strlen(channel->channel_key->cipher->name);
1449     packet = 
1450       silc_channel_key_payload_encode(idp->len, idp->data, 
1451                                       strlen(channel->channel_key->
1452                                              cipher->name),
1453                                       channel->channel_key->cipher->name,
1454                                       channel->key_len / 8, channel->key);
1455     
1456     silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
1457                             packet->data, packet->len, FALSE);
1458
1459     silc_buffer_free(packet);
1460     silc_buffer_free(idp);
1461   }
1462
1463   /* Finally, send notify message to all clients on the channel about
1464      new user on the channel. */
1465   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1466     if (!cmd->pending) {
1467       SilcBuffer clidp;
1468
1469       clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1470       
1471       silc_server_send_notify_to_channel(server, channel,
1472                                          SILC_NOTIFY_TYPE_JOIN, 1,
1473                                          clidp->data, clidp->len);
1474       
1475       silc_buffer_free(clidp);
1476     } else {
1477       /* This is pending command request. Send the notify after we have
1478          received the key for the channel from the router. */
1479       JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1480       ctx->channel_name = channel_name;
1481       ctx->nickname = client->nickname;
1482       ctx->username = client->username;
1483       ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1484       ctx->channel = channel;
1485       ctx->server = server;
1486       ctx->client = client;
1487       silc_task_register(server->timeout_queue, sock->sock,
1488                          silc_server_command_join_notify, ctx,
1489                          0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1490     }
1491   }
1492
1493   /* Send NAMES command reply to the joined channel so the user sees who
1494      is currently on the channel. */
1495   silc_server_command_send_names(server, sock, channel);
1496
1497  out:
1498   silc_server_command_free(cmd);
1499 }
1500
1501 /* Server side of command MOTD. Sends server's current "message of the
1502    day" to the client. */
1503
1504 SILC_SERVER_CMD_FUNC(motd)
1505 {
1506   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1507   SilcServer server = cmd->server;
1508   unsigned int argc;
1509   char *motd;
1510   int motd_len;
1511   
1512   SILC_LOG_DEBUG(("Start"));
1513
1514   argc = silc_argument_get_arg_num(cmd->args);
1515   if (argc < 1) {
1516     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1517                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1518     goto out;
1519   }
1520   if (argc > 2) {
1521     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1522                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1523     goto out;
1524   }
1525
1526   /* XXX show currently only our motd */
1527
1528   if (server->config && server->config->motd && 
1529       server->config->motd->motd_file) {
1530
1531     /* Send motd */
1532     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1533     if (!motd)
1534       goto out;
1535
1536     motd[motd_len] = 0;
1537     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1538                                          SILC_STATUS_OK,
1539                                          2, motd, motd_len);
1540     goto out;
1541   } else {
1542     /* No motd */
1543     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1544                                           SILC_STATUS_OK);
1545   }
1546
1547  out:
1548   silc_server_command_free(cmd);
1549 }
1550
1551 SILC_SERVER_CMD_FUNC(umode)
1552 {
1553 }
1554
1555 /* Checks that client has rights to add or remove channel modes. If any
1556    of the checks fails FALSE is returned. */
1557
1558 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1559                                    SilcChannelClientEntry client,
1560                                    unsigned int mode)
1561 {
1562   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1563   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1564
1565   /* Check whether has rights to change anything */
1566   if (!is_op && !is_fo)
1567     return FALSE;
1568
1569   /* Check whether has rights to change everything */
1570   if (is_op && is_fo)
1571     return TRUE;
1572
1573   /* We know that client is channel operator, check that they are not
1574      changing anything that requires channel founder rights. Rest of the
1575      modes are available automatically for channel operator. */
1576
1577   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1578     if (is_op && !is_fo)
1579       return FALSE;
1580   } else {
1581     if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1582       if (is_op && !is_fo)
1583         return FALSE;
1584     }
1585   }
1586   
1587   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1588     if (is_op && !is_fo)
1589       return FALSE;
1590   } else {
1591     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1592       if (is_op && !is_fo)
1593         return FALSE;
1594     }
1595   }
1596
1597   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1598     if (is_op && !is_fo)
1599       return FALSE;
1600   } else {
1601     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1602       if (is_op && !is_fo)
1603         return FALSE;
1604     }
1605   }
1606   
1607   return TRUE;
1608 }
1609
1610 /* Server side command of CMODE. Changes channel mode */
1611
1612 SILC_SERVER_CMD_FUNC(cmode)
1613 {
1614   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1615   SilcServer server = cmd->server;
1616   SilcSocketConnection sock = cmd->sock;
1617   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1618   SilcChannelID *channel_id;
1619   SilcClientID *client_id;
1620   SilcChannelEntry channel;
1621   SilcChannelClientEntry chl;
1622   SilcBuffer packet, cidp;
1623   unsigned char *tmp, *tmp_id, *tmp_mask;
1624   unsigned int argc, mode_mask, tmp_len, tmp_len2;
1625   int i;
1626
1627   SILC_LOG_DEBUG(("Start"));
1628
1629   argc = silc_argument_get_arg_num(cmd->args);
1630   if (argc < 2) {
1631     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1632                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1633     goto out;
1634   }
1635   if (argc > 8) {
1636     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1637                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1638     goto out;
1639   }
1640
1641   /* Get Channel ID */
1642   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1643   if (!tmp_id) {
1644     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1645                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1646     goto out;
1647   }
1648   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1649
1650   /* Get the channel mode mask */
1651   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1652   if (!tmp_mask) {
1653     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1654                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1655     goto out;
1656   }
1657   SILC_GET32_MSB(mode_mask, tmp_mask);
1658
1659   /* Get channel entry */
1660   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1661   if (!channel) {
1662     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1663                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1664     goto out;
1665   }
1666
1667   /* Check whether this client is on the channel */
1668   if (!silc_server_client_on_channel(client, channel)) {
1669     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1670                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1671     goto out;
1672   }
1673
1674   /* Get entry to the channel user list */
1675   silc_list_start(channel->user_list);
1676   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1677     if (chl->client == client)
1678       break;
1679
1680   /* Check that client has rights to change any requested channel modes */
1681   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1683                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1684     goto out;
1685   }
1686
1687   /*
1688    * Check the modes. Modes that requires nothing special operation are
1689    * not checked here.
1690    */
1691
1692   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1693     /* Channel uses private keys to protect traffic. Client(s) has set the
1694        key locally they want to use, server does not know that key. */
1695     /* Nothing interesting to do here now */
1696   } else {
1697     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1698       /* The mode is removed and we need to generate and distribute
1699          new channel key. Clients are not using private channel keys
1700          anymore after this. */
1701       unsigned int key_len;
1702       unsigned char channel_key[32];
1703
1704       /* XXX Duplicated code, make own function for this!! LEAVE uses this
1705          as well */
1706
1707       /* Re-generate channel key */
1708       key_len = channel->key_len / 8;
1709       for (i = 0; i < key_len; i++)
1710         channel_key[i] = silc_rng_get_byte(server->rng);
1711       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1712                                             channel_key, key_len);
1713       memset(channel->key, 0, key_len);
1714       silc_free(channel->key);
1715       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1716       memcpy(channel->key, channel_key, key_len);
1717       memset(channel_key, 0, sizeof(channel_key));
1718       
1719       /* Encode channel key payload to be distributed on the channel */
1720       packet = 
1721         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1722                                         strlen(channel->channel_key->
1723                                                cipher->name),
1724                                         channel->channel_key->cipher->name,
1725                                         key_len, channel->key);
1726       
1727       /* If we are normal server then we will send it to our router.  If we
1728          are router we will send it to all local servers that has clients on
1729          the channel */
1730       if (server->server_type == SILC_SERVER) {
1731         if (!server->standalone)
1732           silc_server_packet_send(server, 
1733                                   cmd->server->id_entry->router->connection,
1734                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1735                                   packet->len, TRUE);
1736       } else {
1737         
1738       }
1739       
1740       /* Send to locally connected clients on the channel */
1741       silc_server_packet_send_local_channel(server, channel, 
1742                                             SILC_PACKET_CHANNEL_KEY, 0,
1743                                             packet->data, packet->len, FALSE);
1744       silc_buffer_free(packet);
1745     }
1746   }
1747   
1748   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1749     /* User limit is set on channel */
1750     unsigned int user_limit;
1751       
1752     /* Get user limit */
1753     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1754     if (!tmp) {
1755       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1756         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1757                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1758         goto out;
1759       }
1760     } else {
1761       SILC_GET32_MSB(user_limit, tmp);
1762       channel->mode_data.user_limit = user_limit;
1763     }
1764   } else {
1765     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1766       /* User limit mode is unset. Remove user limit */
1767       channel->mode_data.user_limit = 0;
1768   }
1769
1770   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1771     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1772       /* Passphrase has been set to channel */
1773       
1774       /* Get the passphrase */
1775       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1776       if (!tmp) {
1777         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1778                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1779         goto out;
1780       }
1781
1782       /* Save the passphrase */
1783       channel->mode_data.passphrase = strdup(tmp);
1784     }
1785   } else {
1786     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1787       /* Passphrase mode is unset. remove the passphrase */
1788       if (channel->mode_data.passphrase) {
1789         silc_free(channel->mode_data.passphrase);
1790         channel->mode_data.passphrase = NULL;
1791       }
1792     }
1793   }
1794
1795   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1796     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1797       /* Ban list is specified for channel */
1798
1799       /* Get ban list */
1800       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1801       if (!tmp) {
1802         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1803                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1804         goto out;
1805       }
1806
1807       /* XXX check that channel founder is not banned */
1808
1809       /* Save the ban list */
1810       channel->mode_data.ban_list = strdup(tmp);
1811     }
1812   } else {
1813     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1814       /* Ban mode is unset. Remove the entire ban list */
1815       if (channel->mode_data.ban_list) {
1816         silc_free(channel->mode_data.ban_list);
1817         channel->mode_data.ban_list = NULL;
1818       }
1819     }
1820   }
1821
1822   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1823     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1824       /* Invite list is specified for channel */
1825
1826       /* Get invite list */
1827       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1828       if (!tmp) {
1829         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1830                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1831         goto out;
1832       }
1833
1834       /* Save the invite linst */
1835       channel->mode_data.invite_list = strdup(tmp);
1836     }
1837   } else {
1838     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1839       /* Invite list mode is unset. Remove the entire invite list */
1840       if (channel->mode_data.invite_list) {
1841         silc_free(channel->mode_data.invite_list);
1842         channel->mode_data.invite_list = NULL;
1843       }
1844     }
1845   }
1846
1847   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1848     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1849       /* Cipher to use protect the traffic */
1850       unsigned int key_len = 128;
1851       unsigned char channel_key[32];
1852       char *cp;
1853
1854       /* Get cipher */
1855       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1856       if (!tmp) {
1857         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1858                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1859         goto out;
1860       }
1861
1862       cp = strchr(tmp, ':');
1863       if (cp) {
1864         key_len = atoi(cp);
1865         *cp = '\0';
1866       }
1867
1868       /* XXX Duplicated code, make own function for this!! */
1869     
1870       /* Delete old cipher and allocate the new one */
1871       silc_cipher_free(channel->channel_key);
1872       silc_cipher_alloc(tmp, &channel->channel_key);
1873
1874       /* Re-generate channel key */
1875       key_len /= 8;
1876       if (key_len > sizeof(channel_key))
1877         key_len = sizeof(channel_key);
1878
1879       for (i = 0; i < key_len; i++)
1880         channel_key[i] = silc_rng_get_byte(server->rng);
1881       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1882                                             channel_key, key_len);
1883       memset(channel->key, 0, key_len);
1884       silc_free(channel->key);
1885       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1886       memcpy(channel->key, channel_key, key_len);
1887       memset(channel_key, 0, sizeof(channel_key));
1888     
1889       /* Encode channel key payload to be distributed on the channel */
1890       packet = 
1891         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1892                                         strlen(channel->channel_key->
1893                                                cipher->name),
1894                                         channel->channel_key->cipher->name,
1895                                         key_len, channel->key);
1896     
1897       /* If we are normal server then we will send it to our router.  If we
1898          are router we will send it to all local servers that has clients on
1899          the channel */
1900       if (server->server_type == SILC_SERVER) {
1901         if (!server->standalone)
1902           silc_server_packet_send(server, 
1903                                   cmd->server->id_entry->router->connection,
1904                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1905                                   packet->len, TRUE);
1906       } else {
1907         
1908       }
1909     
1910       /* Send to locally connected clients on the channel */
1911       silc_server_packet_send_local_channel(server, channel, 
1912                                             SILC_PACKET_CHANNEL_KEY, 0,
1913                                           packet->data, packet->len, FALSE);
1914       silc_buffer_free(packet);
1915     }
1916   } else {
1917     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1918       /* Cipher mode is unset. Remove the cipher and revert back to 
1919          default cipher */
1920       unsigned int key_len;
1921       unsigned char channel_key[32];
1922
1923       if (channel->mode_data.cipher) {
1924         silc_free(channel->mode_data.cipher);
1925         channel->mode_data.cipher = NULL;
1926         channel->mode_data.key_len = 0;
1927       }
1928
1929       /* Generate new cipher and key for the channel */
1930
1931       /* XXX Duplicated code, make own function for this!! */
1932
1933       /* Delete old cipher and allocate default one */
1934       silc_cipher_free(channel->channel_key);
1935       if (!channel->cipher)
1936         silc_cipher_alloc("twofish", &channel->channel_key);
1937       else
1938         silc_cipher_alloc(channel->cipher, &channel->channel_key);
1939
1940       /* Re-generate channel key */
1941       key_len = channel->key_len / 8;
1942       for (i = 0; i < key_len; i++)
1943         channel_key[i] = silc_rng_get_byte(server->rng);
1944       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1945                                             channel_key, key_len);
1946       memset(channel->key, 0, key_len);
1947       silc_free(channel->key);
1948       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1949       memcpy(channel->key, channel_key, key_len);
1950       memset(channel_key, 0, sizeof(channel_key));
1951       
1952       /* Encode channel key payload to be distributed on the channel */
1953       packet = 
1954         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1955                                         strlen(channel->channel_key->
1956                                                cipher->name),
1957                                         channel->channel_key->cipher->name,
1958                                         key_len, channel->key);
1959       
1960       /* If we are normal server then we will send it to our router.  If we
1961          are router we will send it to all local servers that has clients on
1962          the channel */
1963       if (server->server_type == SILC_SERVER) {
1964         if (!server->standalone)
1965           silc_server_packet_send(server, 
1966                                   cmd->server->id_entry->router->connection,
1967                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1968                                   packet->len, TRUE);
1969       } else {
1970         
1971       }
1972       
1973       /* Send to locally connected clients on the channel */
1974       silc_server_packet_send_local_channel(server, channel, 
1975                                             SILC_PACKET_CHANNEL_KEY, 0,
1976                                             packet->data, packet->len, FALSE);
1977       silc_buffer_free(packet);
1978     }
1979   }
1980
1981   /* Finally, set the mode */
1982   channel->mode = mode_mask;
1983
1984   /* Send CMODE_CHANGE notify */
1985   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1986   silc_server_send_notify_to_channel(server, channel, 
1987                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
1988                                      cidp->data, cidp->len, 
1989                                      tmp_mask, tmp_len);
1990   silc_free(cidp);
1991
1992   /* Send command reply to sender */
1993   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
1994                                                 SILC_STATUS_OK, 0, 1,
1995                                                 2, tmp_mask, 4);
1996   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1997                           packet->data, packet->len, FALSE);
1998     
1999   silc_buffer_free(packet);
2000   silc_free(channel_id);
2001
2002  out:
2003   silc_server_command_free(cmd);
2004 }
2005
2006 /* Server side of CUMODE command. Changes client's mode on a channel. */
2007
2008 SILC_SERVER_CMD_FUNC(cumode)
2009 {
2010   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2011   SilcServer server = cmd->server;
2012   SilcSocketConnection sock = cmd->sock;
2013   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2014   SilcChannelID *channel_id;
2015   SilcClientID *client_id;
2016   SilcChannelEntry channel;
2017   SilcClientEntry target_client;
2018   SilcChannelClientEntry chl;
2019   SilcBuffer packet, idp;
2020   unsigned char *tmp, *tmp_id, *tmp_mask;
2021   unsigned int argc, target_mask, sender_mask, tmp_len;
2022   int i, notify = FALSE;
2023
2024   SILC_LOG_DEBUG(("Start"));
2025
2026   argc = silc_argument_get_arg_num(cmd->args);
2027   if (argc < 3) {
2028     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2029                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2030     goto out;
2031   }
2032   if (argc > 3) {
2033     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2034                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2035     goto out;
2036   }
2037
2038   /* Get Channel ID */
2039   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2040   if (!tmp_id) {
2041     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2042                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2043     goto out;
2044   }
2045   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2046
2047   /* Get channel entry */
2048   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2049   if (!channel) {
2050     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2051                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2052     goto out;
2053   }
2054
2055   /* Check whether sender is on the channel */
2056   if (!silc_server_client_on_channel(client, channel)) {
2057     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2058                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2059     goto out;
2060   }
2061
2062   /* Check that client has rights to change other's rights */
2063   silc_list_start(channel->user_list);
2064   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2065     if (chl->client == client) {
2066       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2067           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2068         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2069                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2070         goto out;
2071       }
2072
2073       sender_mask = chl->mode;
2074       break;
2075     }
2076   }
2077   
2078   /* Get the target client's channel mode mask */
2079   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2080   if (!tmp_mask) {
2081     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2082                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2083     goto out;
2084   }
2085   SILC_GET32_MSB(target_mask, tmp_mask);
2086
2087   /* Get target Client ID */
2088   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2089   if (!tmp_id) {
2090     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2091                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2092     goto out;
2093   }
2094   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2095
2096   /* Get target client's entry */
2097   target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2098   if (!client) {
2099     /* XXX If target client is not one of mine send to primary route */
2100   }
2101
2102   /* Check whether target client is on the channel */
2103   if (!silc_server_client_on_channel(target_client, channel)) {
2104     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2105                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2106     goto out;
2107   }
2108
2109   /* Get entry to the channel user list */
2110   silc_list_start(channel->user_list);
2111   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2112     if (chl->client == target_client)
2113       break;
2114
2115   /* 
2116    * Change the mode 
2117    */
2118
2119   /* If the target client is founder, no one else can change their mode
2120      but themselves. */
2121   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2122     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2123                                           SILC_STATUS_ERR_NOT_YOU);
2124     goto out;
2125   }
2126
2127   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2128     /* Cannot promote anyone to channel founder */
2129     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2130                                           SILC_STATUS_ERR_NOT_YOU);
2131     goto out;
2132   } else {
2133     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2134       if (target_client == client) {
2135         /* Remove channel founder rights from itself */
2136         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2137         notify = TRUE;
2138       } else {
2139         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2140                                               SILC_STATUS_ERR_NOT_YOU);
2141         goto out;
2142       }
2143     }
2144   }
2145
2146   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2147     /* Promote to operator */
2148     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2149       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2150       notify = TRUE;
2151     }
2152   } else {
2153     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2154       /* Demote to normal user */
2155       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2156       notify = TRUE;
2157     }
2158   }
2159
2160   /* Send notify to channel, notify only if mode was actually changed. */
2161   if (notify) {
2162     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2163     silc_server_send_notify_to_channel(server, channel,
2164                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2165                                        idp->data, idp->len,
2166                                        tmp_mask, 4, tmp_id, tmp_len);
2167     silc_buffer_free(idp);
2168   }
2169
2170   /* Send command reply to sender */
2171   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2172                                                 SILC_STATUS_OK, 0, 2,
2173                                                 2, tmp_mask, 4,
2174                                                 3, tmp_id, tmp_len);
2175   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2176                           packet->data, packet->len, FALSE);
2177     
2178   silc_buffer_free(packet);
2179   silc_free(channel_id);
2180   silc_free(client_id);
2181
2182  out:
2183   silc_server_command_free(cmd);
2184 }
2185
2186 /* Server side of KICK command. Kicks client out of channel. */
2187
2188 SILC_SERVER_CMD_FUNC(kick)
2189 {
2190   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2191   SilcServer server = cmd->server;
2192   SilcSocketConnection sock = cmd->sock;
2193   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2194
2195 }
2196
2197 SILC_SERVER_CMD_FUNC(restart)
2198 {
2199 }
2200  
2201 SILC_SERVER_CMD_FUNC(close)
2202 {
2203 }
2204  
2205 SILC_SERVER_CMD_FUNC(die)
2206 {
2207 }
2208  
2209 SILC_SERVER_CMD_FUNC(silcoper)
2210 {
2211 }
2212
2213 /* Server side command of LEAVE. Removes client from a channel. */
2214
2215 SILC_SERVER_CMD_FUNC(leave)
2216 {
2217   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2218   SilcServer server = cmd->server;
2219   SilcSocketConnection sock = cmd->sock;
2220   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2221   SilcChannelID *id;
2222   SilcChannelEntry channel;
2223   SilcBuffer packet;
2224   unsigned int i, argc, key_len, len;
2225   unsigned char *tmp, channel_key[32];
2226
2227   SILC_LOG_DEBUG(("Start"));
2228
2229   argc = silc_argument_get_arg_num(cmd->args);
2230   if (argc < 1) {
2231     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2232                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2233     goto out;
2234   }
2235   if (argc > 2) {
2236     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2237                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2238     goto out;
2239   }
2240
2241   /* Get Channel ID */
2242   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2243   if (!tmp) {
2244     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2245                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2246     goto out;
2247   }
2248   id = silc_id_payload_parse_id(tmp, len);
2249
2250   /* Get channel entry */
2251   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2252   if (!channel) {
2253     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2254                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2255     goto out;
2256   }
2257
2258   /* Check whether this client is on the channel */
2259   if (!silc_server_client_on_channel(id_entry, channel)) {
2260     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2261                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2262     goto out;
2263   }
2264
2265   /* Notify routers that they should remove this client from their list
2266      of clients on the channel. */
2267   if (!server->standalone)
2268     silc_server_send_remove_channel_user(server, 
2269                                          server->id_entry->router->connection,
2270                                          server->server_type == SILC_ROUTER ?
2271                                          TRUE : FALSE, id_entry->id, id);
2272
2273   /* Remove client from channel */
2274   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2275                                           TRUE);
2276   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2277                                         SILC_STATUS_OK);
2278
2279   /* If the channel does not exist anymore we won't send anything */
2280   if (!i)
2281     goto out;
2282
2283   /* Re-generate channel key */
2284   key_len = channel->key_len / 8;
2285   for (i = 0; i < key_len; i++)
2286     channel_key[i] = silc_rng_get_byte(server->rng);
2287   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2288                                         channel_key, key_len);
2289   memset(channel->key, 0, key_len);
2290   silc_free(channel->key);
2291   channel->key = silc_calloc(key_len, sizeof(*channel->key));
2292   memcpy(channel->key, channel_key, key_len);
2293   memset(channel_key, 0, sizeof(channel_key));
2294
2295   /* Encode channel key payload to be distributed on the channel */
2296   packet = 
2297     silc_channel_key_payload_encode(len, tmp,
2298                                     strlen(channel->channel_key->cipher->name),
2299                                     channel->channel_key->cipher->name,
2300                                     key_len, channel->key);
2301
2302   /* If we are normal server then we will send it to our router.  If we
2303      are router we will send it to all local servers that has clients on
2304      the channel */
2305   if (server->server_type == SILC_SERVER) {
2306     if (!server->standalone)
2307       silc_server_packet_send(server, 
2308                               cmd->server->id_entry->router->connection,
2309                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2310                               packet->len, TRUE);
2311   } else {
2312
2313   }
2314
2315   /* Send to locally connected clients on the channel */
2316   silc_server_packet_send_local_channel(server, channel, 
2317                                         SILC_PACKET_CHANNEL_KEY, 0,
2318                                         packet->data, packet->len, FALSE);
2319
2320   silc_buffer_free(packet);
2321   silc_free(id);
2322
2323  out:
2324   silc_server_command_free(cmd);
2325 }
2326
2327 /* Server side of command NAMES. Resolves clients and their names currently
2328    joined on the requested channel. The name list is sent back to the
2329    client. */
2330
2331 SILC_SERVER_CMD_FUNC(names)
2332 {
2333   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2334   SilcServer server = cmd->server;
2335   SilcChannelEntry channel;
2336   SilcChannelClientEntry chl;
2337   SilcChannelID *id;
2338   SilcBuffer packet;
2339   unsigned int i, len, len2, tmp_len, argc;
2340   unsigned char *tmp;
2341   char *name_list = NULL, *n;
2342   SilcBuffer client_id_list;
2343   SilcBuffer client_mode_list;
2344
2345   SILC_LOG_DEBUG(("Start"));
2346
2347   argc = silc_argument_get_arg_num(cmd->args);
2348   if (argc < 1) {
2349     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2350                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2351     goto out;
2352   }
2353   if (argc > 2) {
2354     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2355                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2356     goto out;
2357   }
2358
2359   /* Get Channel ID */
2360   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2361   if (!tmp) {
2362     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2363                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2364     goto out;
2365   }
2366   id = silc_id_payload_parse_id(tmp, tmp_len);
2367
2368   /* Check whether the channel exists. If we are normal server and the
2369      channel does not exist we will send this same command to our router
2370      which will know if the channel exists. */
2371   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2372   if (!channel) {
2373     if (server->server_type == SILC_SERVER && !server->standalone) {
2374       /* XXX Send names command */
2375
2376       cmd->pending = TRUE;
2377       silc_server_command_pending(SILC_COMMAND_NAMES, 0,
2378                                   silc_server_command_names, context);
2379       return;
2380     }
2381
2382     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2384     goto out;
2385   }
2386
2387   /* Assemble the name list now */
2388   name_list = NULL;
2389   len = 0;
2390   silc_list_start(channel->user_list);
2391   i = 0;
2392   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2393     n = chl->client->nickname;
2394     if (n) {
2395       len2 = strlen(n);
2396       len += len2;
2397       name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2398       memcpy(name_list + (len - len2), n, len2);
2399       name_list[len] = 0;
2400
2401       if (i == silc_list_count(channel->user_list) - 1)
2402         break;
2403       memcpy(name_list + len, ",", 1);
2404       len++;
2405       i++;
2406     }
2407   }
2408   if (!name_list)
2409     name_list = "";
2410
2411   /* Assemble the Client ID list now */
2412   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
2413                                      silc_list_count(channel->user_list));
2414   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2415   silc_list_start(channel->user_list);
2416   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2417     SilcBuffer idp;
2418
2419     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2420     silc_buffer_format(client_id_list,
2421                        SILC_STR_UI_XNSTRING(idp->data, idp->len),
2422                        SILC_STR_END);
2423     silc_buffer_pull(client_id_list, idp->len);
2424     silc_buffer_free(idp);
2425   }
2426   silc_buffer_push(client_id_list, 
2427                    client_id_list->data - client_id_list->head);
2428
2429   /* Assemble mode list */
2430   client_mode_list = silc_buffer_alloc(4 * 
2431                                        silc_list_count(channel->user_list));
2432   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2433   silc_list_start(channel->user_list);
2434   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2435     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2436     silc_buffer_pull(client_mode_list, 4);
2437   }
2438   silc_buffer_push(client_mode_list, 
2439                    client_mode_list->data - client_mode_list->head);
2440
2441   /* Send reply */
2442   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2443                                                 SILC_STATUS_OK, 0, 4,
2444                                                 2, tmp, tmp_len,
2445                                                 3, name_list, 
2446                                                 strlen(name_list),
2447                                                 4, client_id_list->data,
2448                                                 client_id_list->len,
2449                                                 5, client_mode_list->data,
2450                                                 client_mode_list->len);
2451   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2452                           packet->data, packet->len, FALSE);
2453     
2454   silc_buffer_free(packet);
2455   silc_free(name_list);
2456   silc_buffer_free(client_id_list);
2457   silc_buffer_free(client_mode_list);
2458   silc_free(id);
2459
2460  out:
2461   silc_server_command_free(cmd);
2462 }