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 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; 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                                      uint32 arg_type,
38                                      unsigned char *arg,
39                                      uint32 arg_len);
40 static bool
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42                                         SilcServerCommandReplyContext cmdr,
43                                         SilcCommand command);
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
45
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
48 {
49   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59   SILC_SERVER_CMD(connect, CONNECT, 
60                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(close, CLOSE,
71                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
73                   SILC_CF_OPER),
74   SILC_SERVER_CMD(silcoper, SILCOPER,
75                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79
80   { NULL, 0 },
81 };
82
83 /* Performs several checks to the command. It first checks whether this
84    command was called as pending command callback. If it was then it checks
85    whether error occurred in the command reply where the pending command
86    callback was called. 
87
88    It also checks that the requested command includes correct amount
89    of arguments. */
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                 \
91 do {                                                                          \
92   uint32 _argc;                                                               \
93                                                                               \
94   SILC_LOG_DEBUG(("Start"));                                                  \
95                                                                               \
96   if (silc_server_command_pending_error_check(cmd, context2, command)) {      \
97     silc_server_command_free(cmd);                                            \
98     return;                                                                   \
99   }                                                                           \
100                                                                               \
101   _argc = silc_argument_get_arg_num(cmd->args);                               \
102   if (_argc < min) {                                                          \
103     silc_server_command_send_status_reply(cmd, command,                       \
104                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105     silc_server_command_free(cmd);                                            \
106     return;                                                                   \
107   }                                                                           \
108   if (_argc > max) {                                                          \
109     silc_server_command_send_status_reply(cmd, command,                       \
110                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
111     silc_server_command_free(cmd);                                            \
112     return;                                                                   \
113   }                                                                           \
114 } while(0)
115
116 /* Returns TRUE if the connection is registered. Unregistered connections
117    usually cannot send commands hence the check. */
118
119 static int silc_server_is_registered(SilcServer server,
120                                      SilcSocketConnection sock,
121                                      SilcServerCommandContext cmd,
122                                      SilcCommand command)
123 {
124   SilcIDListData idata = (SilcIDListData)sock->user_data;
125
126   if (!idata)
127     return FALSE;
128
129   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
130     return TRUE;
131
132   silc_server_command_send_status_reply(cmd, command,
133                                         SILC_STATUS_ERR_NOT_REGISTERED);
134   silc_server_command_free(cmd);
135   return FALSE;
136 }
137
138 /* Internal context to hold data when executed command with timeout. */
139 typedef struct {
140   SilcServerCommandContext ctx;
141   SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
143
144 /* Timeout callback to process commands with timeout for client. Client's
145    commands are always executed with timeout. */
146
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
148 {
149   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
151
152   /* Update access time */
153   client->last_command = time(NULL);
154
155   if (!(timeout->cmd->flags & SILC_CF_REG))
156     timeout->cmd->cb(timeout->ctx, NULL);
157   else if (silc_server_is_registered(timeout->ctx->server, 
158                                      timeout->ctx->sock, 
159                                      timeout->ctx, 
160                                      timeout->cmd->cmd))
161     timeout->cmd->cb(timeout->ctx, NULL);
162
163   silc_free(timeout);
164 }
165
166 /* Processes received command packet. */
167
168 void silc_server_command_process(SilcServer server,
169                                  SilcSocketConnection sock,
170                                  SilcPacketContext *packet)
171 {
172   SilcServerCommandContext ctx;
173   SilcServerCommand *cmd;
174   SilcCommand command;
175
176   /* Allocate command context. This must be free'd by the
177      command routine receiving it. */
178   ctx = silc_server_command_alloc();
179   ctx->server = server;
180   ctx->sock = silc_socket_dup(sock);
181   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
182   
183   /* Parse the command payload in the packet */
184   ctx->payload = silc_command_payload_parse(packet->buffer);
185   if (!ctx->payload) {
186     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
187     silc_buffer_free(packet->buffer);
188     silc_packet_context_free(packet);
189     silc_socket_free(ctx->sock);
190     silc_free(ctx);
191     return;
192   }
193   ctx->args = silc_command_get_args(ctx->payload);
194
195   /* Get the command */
196   command = silc_command_get(ctx->payload);
197   for (cmd = silc_command_list; cmd->cb; cmd++)
198     if (cmd->cmd == command)
199       break;
200
201   if (cmd == NULL) {
202     silc_server_command_send_status_reply(ctx, command,
203                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
204     silc_server_command_free(ctx);
205     return;
206   }
207
208   /* Execute client's commands always with timeout.  Normally they are
209      executed with zero (0) timeout but if client is sending command more
210      frequently than once in 2 seconds, then the timeout may be 0 to 2
211      seconds. */
212   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
213     SilcClientEntry client = (SilcClientEntry)sock->user_data;
214     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
215     int fast;
216
217     timeout->ctx = ctx;
218     timeout->cmd = cmd;
219
220     if (client->last_command && (time(NULL) - client->last_command) < 2) {
221       client->fast_command++;
222       fast = FALSE;
223     } else {
224       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
225                               client->fast_command--);
226       fast = TRUE;
227     }
228
229     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
230                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
231       silc_schedule_task_add(server->schedule, sock->sock, 
232                          silc_server_command_process_timeout,
233                          (void *)timeout, 
234                          2 - (time(NULL) - client->last_command), 0,
235                          SILC_TASK_TIMEOUT,
236                          SILC_TASK_PRI_NORMAL);
237     else
238       silc_schedule_task_add(server->schedule, sock->sock, 
239                          silc_server_command_process_timeout,
240                          (void *)timeout, 
241                          0, 1,
242                          SILC_TASK_TIMEOUT,
243                          SILC_TASK_PRI_NORMAL);
244     return;
245   }
246
247   /* Execute for server */
248
249   if (!(cmd->flags & SILC_CF_REG))
250     cmd->cb(ctx, NULL);
251   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
252     cmd->cb(ctx, NULL);
253 }
254
255 /* Allocate Command Context */
256
257 SilcServerCommandContext silc_server_command_alloc()
258 {
259   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
260   ctx->users++;
261   return ctx;
262 }
263
264 /* Free's the command context allocated before executing the command */
265
266 void silc_server_command_free(SilcServerCommandContext ctx)
267 {
268   ctx->users--;
269   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
270                   ctx->users));
271   if (ctx->users < 1) {
272     if (ctx->payload)
273       silc_command_payload_free(ctx->payload);
274     if (ctx->packet)
275       silc_packet_context_free(ctx->packet);
276     if (ctx->sock)
277       silc_socket_free(ctx->sock); /* Decrease reference counter */
278     silc_free(ctx);
279   }
280 }
281
282 /* Duplicate Command Context by adding reference counter. The context won't
283    be free'd untill it hits zero. */
284
285 SilcServerCommandContext 
286 silc_server_command_dup(SilcServerCommandContext ctx)
287 {
288   ctx->users++;
289   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
290                   ctx->users));
291   return ctx;
292 }
293
294 /* Add new pending command to be executed when reply to a command has been
295    received. The `reply_cmd' is the command that will call the `callback'
296    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
297    to match any command with the `ident'.  If `ident' is non-zero
298    the `callback' will be executed when received reply with command
299    identifier `ident'. */
300
301 void silc_server_command_pending(SilcServer server,
302                                  SilcCommand reply_cmd,
303                                  uint16 ident,
304                                  SilcServerPendingDestructor destructor,
305                                  SilcCommandCb callback,
306                                  void *context)
307 {
308   SilcServerCommandPending *reply;
309
310   reply = silc_calloc(1, sizeof(*reply));
311   reply->reply_cmd = reply_cmd;
312   reply->ident = ident;
313   reply->context = context;
314   reply->callback = callback;
315   reply->destructor = destructor;
316   silc_dlist_add(server->pending_commands, reply);
317 }
318
319 /* Deletes pending command by reply command type. */
320
321 void silc_server_command_pending_del(SilcServer server,
322                                      SilcCommand reply_cmd,
323                                      uint16 ident)
324 {
325   SilcServerCommandPending *r;
326
327   silc_dlist_start(server->pending_commands);
328   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
329     if (r->reply_cmd == reply_cmd && r->ident == ident) {
330       silc_dlist_del(server->pending_commands, r);
331       break;
332     }
333   }
334 }
335
336 /* Checks for pending commands and marks callbacks to be called from
337    the command reply function. Returns TRUE if there were pending command. */
338
339 SilcServerCommandPendingCallbacks
340 silc_server_command_pending_check(SilcServer server,
341                                   SilcServerCommandReplyContext ctx,
342                                   SilcCommand command, 
343                                   uint16 ident,
344                                   uint32 *callbacks_count)
345 {
346   SilcServerCommandPending *r;
347   SilcServerCommandPendingCallbacks callbacks = NULL;
348   int i = 0;
349
350   silc_dlist_start(server->pending_commands);
351   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
352     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
353         && r->ident == ident) {
354       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
355       callbacks[i].context = r->context;
356       callbacks[i].callback = r->callback;
357       callbacks[i].destructor = r->destructor;
358       ctx->ident = ident;
359       i++;
360     }
361   }
362
363   *callbacks_count = i;
364   return callbacks;
365 }
366
367 /* Destructor function for pending callbacks. This is called when using
368    pending commands to free the context given for the pending command. */
369
370 static void silc_server_command_destructor(void *context)
371 {
372   silc_server_command_free((SilcServerCommandContext)context);
373 }
374
375 /* Sends simple status message as command reply packet */
376
377 static void 
378 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
379                                       SilcCommand command,
380                                       SilcCommandStatus status)
381 {
382   SilcBuffer buffer;
383
384   SILC_LOG_DEBUG(("Sending command status %d", status));
385
386   buffer = 
387     silc_command_reply_payload_encode_va(command, status, 
388                                          silc_command_get_ident(cmd->payload),
389                                          0);
390   silc_server_packet_send(cmd->server, cmd->sock,
391                           SILC_PACKET_COMMAND_REPLY, 0, 
392                           buffer->data, buffer->len, FALSE);
393   silc_buffer_free(buffer);
394 }
395
396 /* Sends command status reply with one extra argument. The argument
397    type must be sent as argument. */
398
399 static void 
400 silc_server_command_send_status_data(SilcServerCommandContext cmd,
401                                      SilcCommand command,
402                                      SilcCommandStatus status,
403                                      uint32 arg_type,
404                                      unsigned char *arg,
405                                      uint32 arg_len)
406 {
407   SilcBuffer buffer;
408
409   SILC_LOG_DEBUG(("Sending command status %d", status));
410
411   buffer = 
412     silc_command_reply_payload_encode_va(command, status, 
413                                          silc_command_get_ident(cmd->payload),
414                                          1, arg_type, arg, arg_len);
415   silc_server_packet_send(cmd->server, cmd->sock,
416                           SILC_PACKET_COMMAND_REPLY, 0, 
417                           buffer->data, buffer->len, FALSE);
418   silc_buffer_free(buffer);
419 }
420
421 /* This function can be called to check whether in the command reply
422    an error occurred. This function has no effect if this is called
423    when the command function was not called as pending command callback. 
424    This returns TRUE if error had occurred. */
425
426 static bool
427 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
428                                         SilcServerCommandReplyContext cmdr,
429                                         SilcCommand command)
430 {
431   SilcCommandStatus status;
432
433   if (!cmd->pending || !cmdr)
434     return FALSE;
435
436   SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
437   if (status != SILC_STATUS_OK &&
438       status != SILC_STATUS_LIST_START &&
439       status != SILC_STATUS_LIST_ITEM &&
440       status != SILC_STATUS_LIST_END) {
441     /* Send the error message */
442     silc_server_command_send_status_reply(cmd, command, status);
443     return TRUE;
444   }
445
446   return FALSE;
447 }
448
449 /******************************************************************************
450
451                               WHOIS Functions
452
453 ******************************************************************************/
454
455 static int
456 silc_server_command_whois_parse(SilcServerCommandContext cmd,
457                                 SilcClientID ***client_id,
458                                 uint32 *client_id_count,
459                                 char **nickname,
460                                 char **server_name,
461                                 int *count,
462                                 SilcCommand command)
463 {
464   unsigned char *tmp;
465   uint32 len;
466   uint32 argc = silc_argument_get_arg_num(cmd->args);
467   int i, k;
468
469   /* If client ID is in the command it must be used instead of nickname */
470   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
471   if (!tmp) {
472     /* No ID, get the nickname@server string and parse it. */
473     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
474     if (tmp) {
475       silc_parse_userfqdn(tmp, nickname, server_name);
476     } else {
477       silc_server_command_send_status_reply(cmd, command,
478                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
479       return FALSE;
480     }
481   } else {
482     /* Command includes ID, we must use that.  Also check whether the command
483        has more than one ID set - take them all. */
484
485     *client_id = silc_calloc(1, sizeof(**client_id));
486     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
487     if ((*client_id)[0] == NULL) {
488       silc_free(*client_id);
489       return FALSE;
490     }
491     *client_id_count = 1;
492
493     /* Take all ID's from the command packet */
494     if (argc > 1) {
495       for (k = 1, i = 1; i < argc; i++) {
496         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
497         if (tmp) {
498           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
499                                     (*client_id_count + 1));
500           (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
501           if ((*client_id)[k] == NULL) {
502             /* Cleanup all and fail */
503             for (i = 0; i < *client_id_count; i++)
504               silc_free((*client_id)[i]);
505             silc_free(*client_id);
506             return FALSE;
507           }
508           (*client_id_count)++;
509           k++;
510         }
511       }
512     }
513   }
514
515   /* Get the max count of reply messages allowed */
516   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
517   if (tmp)
518     *count = atoi(tmp);
519   else
520     *count = 0;
521
522   return TRUE;
523 }
524
525 /* Resolve context used by both WHOIS and IDENTIFY commands */
526 typedef struct {
527   SilcServerEntry router;
528   uint16 ident;
529   unsigned char **res_argv;
530   uint32 *res_argv_lens;
531   uint32 *res_argv_types;
532   uint32 res_argc;
533 } *SilcServerResolveContext;
534
535 static bool
536 silc_server_command_whois_check(SilcServerCommandContext cmd,
537                                 SilcClientEntry *clients,
538                                 uint32 clients_count)
539 {
540   SilcServer server = cmd->server;
541   SilcClientEntry entry;
542   SilcServerResolveContext resolve = NULL, r = NULL;
543   uint32 resolve_count = 0;
544   int i, k;
545   bool no_res = TRUE;
546
547   for (i = 0; i < clients_count; i++) {
548     entry = clients[i];
549
550     if (!entry || (entry->nickname && entry->username && entry->userinfo) ||
551         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
552         !entry->router)
553       continue;
554
555     /* We need to resolve this entry since it is not complete */
556
557     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
558       /* The entry is being resolved (and we are not the resolver) so attach
559          to the command reply and we're done with this one. */
560       silc_server_command_pending(server, SILC_COMMAND_NONE, 
561                                   entry->resolve_cmd_ident,
562                                   silc_server_command_destructor,
563                                   silc_server_command_whois,
564                                   silc_server_command_dup(cmd));
565       no_res = FALSE;
566     } else {
567       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
568         /* We've resolved this and it still is not ready.  We'll return
569            and are that this will be handled again after it is resolved. */
570         for (i = 0; i < resolve_count; i++) {
571           for (k = 0; k < r->res_argc; k++)
572             silc_free(r->res_argv[k]);
573           silc_free(r->res_argv);
574           silc_free(r->res_argv_lens);
575           silc_free(r->res_argv_types);
576         }
577         silc_free(resolve);
578         return FALSE;
579       } else {
580         /* We'll resolve this client */
581         SilcBuffer idp;
582
583         r = NULL;
584         for (k = 0; k < resolve_count; k++) {
585           if (resolve[k].router == entry->router) {
586             r = &resolve[k];
587             break;
588           }
589         }
590
591         if (!r) {
592           resolve = silc_realloc(resolve, sizeof(*resolve) * 
593                                  (resolve_count + 1));
594           r = &resolve[resolve_count];
595           memset(r, 0, sizeof(*r));
596           r->router = entry->router;
597           r->ident = ++server->cmd_ident;
598           resolve_count++;
599         }
600
601         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
602                                    (r->res_argc + 1));
603         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
604                                         sizeof(*r->res_argv_lens) *
605                                         (r->res_argc + 1));
606         r->res_argv_types = silc_realloc(r->res_argv_types, 
607                                          sizeof(*r->res_argv_types) *
608                                          (r->res_argc + 1));
609         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
610         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
611                                                sizeof(**r->res_argv));
612         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
613         r->res_argv_lens[r->res_argc] = idp->len;
614         r->res_argv_types[r->res_argc] = r->res_argc + 3;
615         r->res_argc++;
616         silc_buffer_free(idp);
617
618         entry->resolve_cmd_ident = r->ident;
619         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
620         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
621       }
622     }
623   }
624
625   /* Do the resolving */
626   for (i = 0; i < resolve_count; i++) {
627     SilcBuffer res_cmd;
628
629     r = &resolve[i];
630
631     /* Send WHOIS request. We send WHOIS since we're doing the requesting
632        now anyway so make it a good one. */
633     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
634                                           r->res_argc, r->res_argv, 
635                                           r->res_argv_lens,
636                                           r->res_argv_types, 
637                                           r->ident);
638     silc_server_packet_send(server, r->router->connection,
639                             SILC_PACKET_COMMAND, cmd->packet->flags,
640                             res_cmd->data, res_cmd->len, FALSE);
641
642     /* Reprocess this packet after received reply */
643     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
644                                 r->ident,
645                                 silc_server_command_destructor,
646                                 silc_server_command_whois,
647                                 silc_server_command_dup(cmd));
648     cmd->pending = TRUE;
649
650     silc_buffer_free(res_cmd);
651     for (k = 0; k < r->res_argc; k++)
652       silc_free(r->res_argv[k]);
653     silc_free(r->res_argv);
654     silc_free(r->res_argv_lens);
655     silc_free(r->res_argv_types);
656     no_res = FALSE;
657   }
658   silc_free(resolve);
659
660   return no_res;
661 }
662
663 static void
664 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
665                                      SilcClientEntry *clients,
666                                      uint32 clients_count,
667                                      int count)
668 {
669   SilcServer server = cmd->server;
670   char *tmp;
671   int i, k, len;
672   SilcBuffer packet, idp, channels;
673   SilcClientEntry entry;
674   SilcCommandStatus status;
675   uint16 ident = silc_command_get_ident(cmd->payload);
676   char nh[256], uh[256];
677   unsigned char idle[4], mode[4];
678   SilcSocketConnection hsock;
679
680   len = 0;
681   for (i = 0; i < clients_count; i++)
682     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
683       len++;
684
685   if (len == 0 && clients_count) {
686     entry = clients[0];
687     if (entry->nickname) {
688       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
689                                            SILC_STATUS_ERR_NO_SUCH_NICK,
690                                            3, entry->nickname, 
691                                            strlen(entry->nickname));
692     } else {
693       SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
694       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
695                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
696                                            2, idp->data, idp->len);
697       silc_buffer_free(idp);
698     }
699
700     return;
701   }
702
703   status = SILC_STATUS_OK;
704   if (len > 1)
705     status = SILC_STATUS_LIST_START;
706
707   for (i = 0, k = 0; i < clients_count; i++) {
708     entry = clients[i];
709
710     if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
711       if (clients_count == 1) {
712         if (entry->nickname) {
713           silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
714                                                SILC_STATUS_ERR_NO_SUCH_NICK,
715                                                3, entry->nickname, 
716                                                strlen(entry->nickname));
717         } else {
718           SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
719           silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
720                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
721                                                2, idp->data, idp->len);
722           silc_buffer_free(idp);
723         }
724       }
725       continue;
726     }
727
728     if (k >= 1)
729       status = SILC_STATUS_LIST_ITEM;
730
731     if (clients_count > 1 && k == clients_count - 1)
732       status = SILC_STATUS_LIST_END;
733
734     if (count && k - 1 == count)
735       status = SILC_STATUS_LIST_END;
736
737     if (count && k - 1 > count)
738       break;
739
740     /* Sanity check, however these should never fail. However, as
741        this sanity check has been added here they have failed. */
742     if (!entry->nickname || !entry->username || !entry->userinfo)
743       continue;
744       
745     /* Send WHOIS reply */
746     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
747     tmp = silc_argument_get_first_arg(cmd->args, NULL);
748     
749     memset(uh, 0, sizeof(uh));
750     memset(nh, 0, sizeof(nh));
751     memset(idle, 0, sizeof(idle));
752     
753     strncat(nh, entry->nickname, strlen(entry->nickname));
754     if (!strchr(entry->nickname, '@')) {
755       strncat(nh, "@", 1);
756       if (entry->servername) {
757         strncat(nh, entry->servername, strlen(entry->servername));
758       } else {
759         len = entry->router ? strlen(entry->router->server_name) :
760           strlen(server->server_name);
761         strncat(nh, entry->router ? entry->router->server_name :
762                 server->server_name, len);
763       }
764     }
765       
766     strncat(uh, entry->username, strlen(entry->username));
767     if (!strchr(entry->username, '@')) {
768       strncat(uh, "@", 1);
769       hsock = (SilcSocketConnection)entry->connection;
770       len = strlen(hsock->hostname);
771       strncat(uh, hsock->hostname, len);
772     }
773
774     channels = silc_server_get_client_channel_list(server, entry);
775       
776     SILC_PUT32_MSB(entry->mode, mode);
777
778     if (entry->connection) {
779       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
780     }
781
782     if (channels)
783       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
784                                                     status, ident, 7, 
785                                                     2, idp->data, idp->len,
786                                                     3, nh, strlen(nh),
787                                                     4, uh, strlen(uh),
788                                                     5, entry->userinfo, 
789                                                     strlen(entry->userinfo),
790                                                     6, channels->data,
791                                                     channels->len,
792                                                     7, mode, 4,
793                                                     8, idle, 4);
794     else
795       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
796                                                     status, ident, 6, 
797                                                     2, idp->data, idp->len,
798                                                     3, nh, strlen(nh),
799                                                     4, uh, strlen(uh),
800                                                     5, entry->userinfo, 
801                                                     strlen(entry->userinfo),
802                                                     7, mode, 4,
803                                                     8, idle, 4);
804     
805     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
806                             0, packet->data, packet->len, FALSE);
807     
808     silc_buffer_free(packet);
809     silc_buffer_free(idp);
810     if (channels)
811       silc_buffer_free(channels);
812
813     k++;
814   }
815 }
816
817 static int
818 silc_server_command_whois_process(SilcServerCommandContext cmd)
819 {
820   SilcServer server = cmd->server;
821   char *nick = NULL, *server_name = NULL;
822   int count = 0;
823   SilcClientEntry *clients = NULL, entry;
824   SilcClientID **client_id = NULL;
825   uint32 client_id_count = 0, clients_count = 0;
826   int i, ret = 0;
827   bool check_global = FALSE;
828
829   /* Protocol dictates that we must always send the received WHOIS request
830      to our router if we are normal server, so let's do it now unless we
831      are standalone. We will not send any replies to the client until we
832      have received reply from the router. */
833   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
834       server->server_type == SILC_SERVER && !cmd->pending && 
835       !server->standalone) {
836     SilcBuffer tmpbuf;
837     uint16 old_ident;
838
839     old_ident = silc_command_get_ident(cmd->payload);
840     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
841     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
842
843     /* Send WHOIS command to our router */
844     silc_server_packet_send(server, (SilcSocketConnection)
845                             server->router->connection,
846                             SILC_PACKET_COMMAND, cmd->packet->flags,
847                             tmpbuf->data, tmpbuf->len, TRUE);
848
849     /* Reprocess this packet after received reply from router */
850     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
851                                 silc_command_get_ident(cmd->payload),
852                                 silc_server_command_destructor,
853                                 silc_server_command_whois,
854                                 silc_server_command_dup(cmd));
855     cmd->pending = TRUE;
856
857     silc_command_set_ident(cmd->payload, old_ident);
858
859     silc_buffer_free(tmpbuf);
860     ret = -1;
861     goto out;
862   }
863
864   /* We are ready to process the command request. Let's search for the
865      requested client and send reply to the requesting client. */
866
867   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
868     check_global = TRUE;
869   else if (server->server_type != SILC_SERVER)
870     check_global = TRUE;
871
872   /* Parse the whois request */
873   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
874                                        &nick, &server_name, &count,
875                                        SILC_COMMAND_WHOIS))
876     return 0;
877
878   /* Get all clients matching that ID or nickname from local list */
879   if (client_id_count) {
880     /* Check all Client ID's received in the command packet */
881     for (i = 0; i < client_id_count; i++) {
882       entry = silc_idlist_find_client_by_id(server->local_list, 
883                                             client_id[i], TRUE, NULL);
884       if (!entry && check_global)
885         entry = silc_idlist_find_client_by_id(server->global_list, 
886                                               client_id[i], TRUE, NULL);
887       if (entry) {
888         clients = silc_realloc(clients, sizeof(*clients) * 
889                                (clients_count + 1));
890         clients[clients_count++] = entry;
891       }
892     }
893   } else {
894     if (!silc_idlist_get_clients_by_hash(server->local_list, 
895                                          nick, server->md5hash,
896                                          &clients, &clients_count))
897       silc_idlist_get_clients_by_nickname(server->local_list, 
898                                           nick, server_name,
899                                           &clients, &clients_count);
900     if (check_global) {
901       if (!silc_idlist_get_clients_by_hash(server->global_list, 
902                                            nick, server->md5hash,
903                                            &clients, &clients_count))
904         silc_idlist_get_clients_by_nickname(server->global_list, 
905                                             nick, server_name,
906                                             &clients, &clients_count);
907     }
908   }
909   
910   if (!clients) {
911     /* Such client(s) really does not exist in the SILC network. */
912     if (!client_id_count) {
913       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
914                                            SILC_STATUS_ERR_NO_SUCH_NICK,
915                                            3, nick, strlen(nick));
916     } else {
917       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
918       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
919                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
920                                            2, idp->data, idp->len);
921       silc_buffer_free(idp);
922     }
923     goto out;
924   }
925
926   /* Router always finds the client entry if it exists in the SILC network.
927      However, it might be incomplete entry and does not include all the
928      mandatory fields that WHOIS command reply requires. Check for these and
929      make query from the server who owns the client if some fields are 
930      missing. */
931   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
932     ret = -1;
933     goto out;
934   }
935
936   /* Send the command reply */
937   silc_server_command_whois_send_reply(cmd, clients, clients_count,
938                                        count);
939
940  out:
941   if (client_id_count) {
942     for (i = 0; i < client_id_count; i++)
943       silc_free(client_id[i]);
944     silc_free(client_id);
945   }
946   silc_free(clients);
947   silc_free(nick);
948   silc_free(server_name);
949
950   return ret;
951 }
952
953 /* Server side of command WHOIS. Processes user's query and sends found 
954    results as command replies back to the client. */
955
956 SILC_SERVER_CMD_FUNC(whois)
957 {
958   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
959   int ret = 0;
960
961   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
962
963   ret = silc_server_command_whois_process(cmd);
964
965   if (!ret)
966     silc_server_command_free(cmd);
967 }
968
969 /******************************************************************************
970
971                               WHOWAS Functions
972
973 ******************************************************************************/
974
975 static int
976 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
977                                  char **nickname,
978                                  char **server_name,
979                                  int *count)
980 {
981   unsigned char *tmp;
982   uint32 len;
983
984   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
985   if (!tmp) {
986     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
987                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
988     return FALSE;
989   }
990
991   /* Get the nickname@server string and parse it. */
992   silc_parse_userfqdn(tmp, nickname, server_name);
993
994   /* Get the max count of reply messages allowed */
995   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
996   if (tmp)
997     *count = atoi(tmp);
998   else
999     *count = 0;
1000
1001   return TRUE;
1002 }
1003
1004 static char
1005 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1006                                  SilcClientEntry *clients,
1007                                  uint32 clients_count)
1008 {
1009   SilcServer server = cmd->server;
1010   int i;
1011   SilcClientEntry entry;
1012
1013   for (i = 0; i < clients_count; i++) {
1014     entry = clients[i];
1015
1016     if (!entry->nickname || !entry->username) {
1017       SilcBuffer tmpbuf;
1018       uint16 old_ident;
1019
1020       if (!entry->router)
1021         continue;
1022       
1023       old_ident = silc_command_get_ident(cmd->payload);
1024       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1025       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1026
1027       /* Send WHOWAS command */
1028       silc_server_packet_send(server, entry->router->connection,
1029                               SILC_PACKET_COMMAND, cmd->packet->flags,
1030                               tmpbuf->data, tmpbuf->len, TRUE);
1031       
1032       /* Reprocess this packet after received reply */
1033       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1034                                   silc_command_get_ident(cmd->payload),
1035                                   silc_server_command_destructor,
1036                                   silc_server_command_whowas, 
1037                                   silc_server_command_dup(cmd));
1038       cmd->pending = TRUE;
1039       
1040       silc_command_set_ident(cmd->payload, old_ident);
1041
1042       silc_buffer_free(tmpbuf);
1043       return FALSE;
1044     }
1045   }
1046
1047   return TRUE;
1048 }
1049
1050 static void
1051 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1052                                       SilcClientEntry *clients,
1053                                       uint32 clients_count)
1054 {
1055   SilcServer server = cmd->server;
1056   char *tmp;
1057   int i, count = 0, len;
1058   SilcBuffer packet, idp;
1059   SilcClientEntry entry = NULL;
1060   SilcCommandStatus status;
1061   uint16 ident = silc_command_get_ident(cmd->payload);
1062   char found = FALSE;
1063   char nh[256], uh[256];
1064
1065   status = SILC_STATUS_OK;
1066   if (clients_count > 1)
1067     status = SILC_STATUS_LIST_START;
1068
1069   for (i = 0; i < clients_count; i++) {
1070     entry = clients[i];
1071
1072     /* We will take only clients that are not valid anymore. They are the
1073        ones that are not registered anymore but still have a ID. They
1074        have disconnected us, and thus valid for WHOWAS. */
1075     if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1076       continue;
1077     if (entry->id == NULL)
1078       continue;
1079
1080     if (count && i - 1 == count)
1081       break;
1082
1083     found = TRUE;
1084
1085     if (clients_count > 2)
1086       status = SILC_STATUS_LIST_ITEM;
1087
1088     if (clients_count > 1 && i == clients_count - 1)
1089       status = SILC_STATUS_LIST_END;
1090
1091     /* Sanity check, however these should never fail. However, as
1092        this sanity check has been added here they have failed. */
1093     if (!entry->nickname || !entry->username)
1094       continue;
1095       
1096     /* Send WHOWAS reply */
1097     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1098     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1099     
1100     memset(uh, 0, sizeof(uh));
1101     memset(nh, 0, sizeof(nh));
1102
1103     strncat(nh, entry->nickname, strlen(entry->nickname));
1104     if (!strchr(entry->nickname, '@')) {
1105       strncat(nh, "@", 1);
1106       if (entry->servername) {
1107         strncat(nh, entry->servername, strlen(entry->servername));
1108       } else {
1109         len = entry->router ? strlen(entry->router->server_name) :
1110           strlen(server->server_name);
1111         strncat(nh, entry->router ? entry->router->server_name :
1112                 server->server_name, len);
1113       }
1114     }
1115       
1116     strncat(uh, entry->username, strlen(entry->username));
1117     if (!strchr(entry->username, '@')) {
1118       strncat(uh, "@", 1);
1119       strcat(uh, "*private*");
1120     }
1121       
1122     if (entry->userinfo)
1123       packet = 
1124         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1125                                              status, ident, 4, 
1126                                              2, idp->data, idp->len,
1127                                              3, nh, strlen(nh),
1128                                              4, uh, strlen(uh),
1129                                              5, entry->userinfo, 
1130                                              strlen(entry->userinfo));
1131     else
1132       packet = 
1133         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1134                                              status, ident, 3, 
1135                                              2, idp->data, idp->len,
1136                                              3, nh, strlen(nh),
1137                                              4, uh, strlen(uh));
1138
1139     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1140                             0, packet->data, packet->len, FALSE);
1141     
1142     silc_buffer_free(packet);
1143     silc_buffer_free(idp);
1144   }
1145
1146   if (found == FALSE && entry)
1147     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1148                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1149                                          3, entry->nickname, 
1150                                          strlen(entry->nickname));
1151 }
1152
1153 static int
1154 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1155 {
1156   SilcServer server = cmd->server;
1157   char *nick = NULL, *server_name = NULL;
1158   int count = 0;
1159   SilcClientEntry *clients = NULL;
1160   uint32 clients_count = 0;
1161   int ret = 0;
1162   bool check_global = FALSE;
1163
1164   /* Protocol dictates that we must always send the received WHOWAS request
1165      to our router if we are normal server, so let's do it now unless we
1166      are standalone. We will not send any replies to the client until we
1167      have received reply from the router. */
1168   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1169       server->server_type == SILC_SERVER && !cmd->pending && 
1170       !server->standalone) {
1171     SilcBuffer tmpbuf;
1172     uint16 old_ident;
1173
1174     old_ident = silc_command_get_ident(cmd->payload);
1175     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1176     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1177
1178     /* Send WHOWAS command to our router */
1179     silc_server_packet_send(server, (SilcSocketConnection)
1180                             server->router->connection,
1181                             SILC_PACKET_COMMAND, cmd->packet->flags,
1182                             tmpbuf->data, tmpbuf->len, TRUE);
1183
1184     /* Reprocess this packet after received reply from router */
1185     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1186                                 silc_command_get_ident(cmd->payload),
1187                                 silc_server_command_destructor,
1188                                 silc_server_command_whowas,
1189                                 silc_server_command_dup(cmd));
1190     cmd->pending = TRUE;
1191
1192     silc_command_set_ident(cmd->payload, old_ident);
1193
1194     silc_buffer_free(tmpbuf);
1195     ret = -1;
1196     goto out;
1197   }
1198
1199   /* We are ready to process the command request. Let's search for the
1200      requested client and send reply to the requesting client. */
1201
1202   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1203     check_global = TRUE;
1204   else if (server->server_type != SILC_SERVER)
1205     check_global = TRUE;
1206
1207   /* Parse the whowas request */
1208   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1209     return 0;
1210
1211   /* Get all clients matching that nickname from local list */
1212   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1213                                            nick, server_name,
1214                                            &clients, &clients_count))
1215     silc_idlist_get_clients_by_hash(server->local_list, 
1216                                     nick, server->md5hash,
1217                                     &clients, &clients_count);
1218   
1219   /* Check global list as well */
1220   if (check_global) {
1221     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1222                                              nick, server_name,
1223                                              &clients, &clients_count))
1224       silc_idlist_get_clients_by_hash(server->global_list, 
1225                                       nick, server->md5hash,
1226                                       &clients, &clients_count);
1227   }
1228   
1229   if (!clients) {
1230     /* Such a client really does not exist in the SILC network. */
1231     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1232                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1233                                          3, nick, strlen(nick));
1234     goto out;
1235   }
1236
1237   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1238     ret = -1;
1239     goto out;
1240   }
1241
1242   /* Send the command reply to the client */
1243   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1244
1245  out:
1246   silc_free(clients);
1247   silc_free(nick);
1248   silc_free(server_name);
1249
1250   return ret;
1251 }
1252
1253 /* Server side of command WHOWAS. */
1254
1255 SILC_SERVER_CMD_FUNC(whowas)
1256 {
1257   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1258   int ret = 0;
1259
1260   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1261
1262   ret = silc_server_command_whowas_process(cmd);
1263
1264   if (!ret)
1265     silc_server_command_free(cmd);
1266 }
1267
1268 /******************************************************************************
1269
1270                               IDENTIFY Functions
1271
1272 ******************************************************************************/
1273
1274 static bool
1275 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1276                                    SilcClientEntry **clients,
1277                                    uint32 *clients_count,
1278                                    SilcServerEntry **servers,
1279                                    uint32 *servers_count,
1280                                    SilcChannelEntry **channels,
1281                                    uint32 *channels_count,
1282                                    uint32 *count)
1283 {
1284   SilcServer server = cmd->server;
1285   unsigned char *tmp;
1286   uint32 len;
1287   uint32 argc = silc_argument_get_arg_num(cmd->args);
1288   SilcIDPayload idp;
1289   bool check_global = FALSE;
1290   void *entry;
1291   int i;
1292   bool error = FALSE;
1293
1294   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1295     check_global = TRUE;
1296   else if (server->server_type != SILC_SERVER)
1297     check_global = TRUE;
1298
1299   /* If ID Payload is in the command it must be used instead of names */
1300   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1301   if (!tmp) {
1302     /* No ID, get the names. */
1303
1304     /* Try to get nickname@server. */
1305     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1306     if (tmp) {
1307       char *nick = NULL;
1308       char *nick_server = NULL;
1309
1310       silc_parse_userfqdn(tmp, &nick, &nick_server);
1311
1312       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1313                                            nick, server->md5hash,
1314                                            clients, clients_count))
1315         silc_idlist_get_clients_by_nickname(server->local_list, 
1316                                             nick, nick_server,
1317                                             clients, clients_count);
1318       if (check_global) {
1319         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1320                                              nick, server->md5hash,
1321                                              clients, clients_count))
1322           silc_idlist_get_clients_by_nickname(server->global_list, 
1323                                               nick, nick_server,
1324                                               clients, clients_count);
1325       }
1326
1327       silc_free(nick);
1328       silc_free(nick_server);
1329
1330       if (!(*clients)) {
1331         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1332                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1333                                              3, tmp, strlen(tmp));
1334         return FALSE;
1335       }
1336     }
1337
1338     /* Try to get server name */
1339     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1340     if (tmp) {
1341       entry = silc_idlist_find_server_by_name(server->local_list,
1342                                               tmp, TRUE, NULL);
1343       if (!entry && check_global)
1344         entry = silc_idlist_find_server_by_name(server->global_list,
1345                                                 tmp, TRUE, NULL);
1346       if (entry) {
1347         *servers = silc_realloc(*servers, sizeof(**servers) * 
1348                                 (*servers_count + 1));
1349         (*servers)[(*servers_count)++] = entry;
1350       }
1351
1352       if (!(*servers)) {
1353         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1354                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1355                                              3, tmp, strlen(tmp));
1356         return FALSE;
1357       }
1358     }
1359
1360     /* Try to get channel name */
1361     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1362     if (tmp) {
1363       entry = silc_idlist_find_channel_by_name(server->local_list,
1364                                                tmp, NULL);
1365       if (!entry && check_global)
1366         entry = silc_idlist_find_channel_by_name(server->global_list,
1367                                                  tmp, NULL);
1368       if (entry) {
1369         *channels = silc_realloc(*channels, sizeof(**channels) * 
1370                                  (*channels_count + 1));
1371         (*channels)[(*channels_count)++] = entry;
1372       }
1373
1374       if (!(*channels)) {
1375         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1376                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1377                                              3, tmp, strlen(tmp));
1378         return FALSE;
1379       }
1380     }
1381
1382     if (!(*clients) && !(*servers) && !(*channels)) {
1383       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1384                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1385       return FALSE;
1386     }
1387   } else {
1388     /* Command includes ID, we must use that.  Also check whether the command
1389        has more than one ID set - take them all. */
1390
1391     /* Take all ID's from the command packet */
1392     for (i = 0; i < argc; i++) {
1393       void *id;
1394
1395       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1396       if (!tmp)
1397         continue;
1398       
1399       idp = silc_id_payload_parse_data(tmp, len);
1400       if (!idp) {
1401         silc_free(*clients);
1402         silc_free(*servers);
1403         silc_free(*channels);
1404         silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1405                                       SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1406         return FALSE;
1407       }
1408
1409       id = silc_id_payload_get_id(idp);
1410       
1411       switch (silc_id_payload_get_type(idp)) {
1412         
1413       case SILC_ID_CLIENT:
1414         entry = (void *)silc_idlist_find_client_by_id(server->local_list, 
1415                                                       id, TRUE, NULL);
1416         if (!entry && check_global)
1417           entry = (void *)silc_idlist_find_client_by_id(server->global_list, 
1418                                                         id, TRUE, NULL);
1419         if (entry) {
1420           *clients = silc_realloc(*clients, sizeof(**clients) * 
1421                                   (*clients_count + 1));
1422           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1423         } else {
1424           silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1425                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1426                                                2, tmp, len);
1427           error = TRUE;
1428         }
1429
1430         break;
1431         
1432       case SILC_ID_SERVER:
1433         entry = (void *)silc_idlist_find_server_by_id(server->local_list, 
1434                                                       id, TRUE, NULL);
1435         if (!entry && check_global)
1436           entry = (void *)silc_idlist_find_server_by_id(server->global_list, 
1437                                                         id, TRUE, NULL);
1438         if (entry) {
1439           *servers = silc_realloc(*servers, sizeof(**servers) * 
1440                                   (*servers_count + 1));
1441           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1442         } else {
1443           silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1444                                         SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1445                                                2, tmp, len);
1446           error = TRUE;
1447         }
1448         break;
1449         
1450       case SILC_ID_CHANNEL:
1451         entry = (void *)silc_idlist_find_channel_by_id(server->local_list, 
1452                                                        id, NULL);
1453         if (!entry && check_global)
1454           entry = (void *)silc_idlist_find_channel_by_id(server->global_list, 
1455                                                          id, NULL);
1456         if (entry) {
1457           *channels = silc_realloc(*channels, sizeof(**channels) * 
1458                                    (*channels_count + 1));
1459           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1460         } else {
1461           silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1462                                         SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1463                                                2, tmp, len);
1464           error = TRUE;
1465         }
1466         break;
1467       }
1468
1469       silc_free(id);
1470     }
1471   }
1472
1473   if (error) {
1474     silc_free(*clients);
1475     silc_free(*servers);
1476     silc_free(*channels);
1477     return FALSE;
1478   }
1479   
1480   /* Get the max count of reply messages allowed */
1481   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1482   if (tmp)
1483     *count = atoi(tmp);
1484   else
1485     *count = 0;
1486
1487   return TRUE;
1488 }
1489
1490 /* Checks that all mandatory fields in client entry are present. If not
1491    then send WHOIS request to the server who owns the client. We use
1492    WHOIS because we want to get as much information as possible at once. */
1493
1494 static bool
1495 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1496                                           SilcClientEntry *clients,
1497                                           uint32 clients_count)
1498 {
1499   SilcServer server = cmd->server;
1500   SilcClientEntry entry;
1501   SilcServerResolveContext resolve = NULL, r = NULL;
1502   uint32 resolve_count = 0;
1503   int i, k;
1504   bool no_res = TRUE;
1505
1506   for (i = 0; i < clients_count; i++) {
1507     entry = clients[i];
1508
1509     if (!entry || entry->nickname || 
1510         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
1511         !entry->router)
1512       continue;
1513
1514     /* We need to resolve this entry since it is not complete */
1515
1516     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1517       /* The entry is being resolved (and we are not the resolver) so attach
1518          to the command reply and we're done with this one. */
1519       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1520                                   entry->resolve_cmd_ident,
1521                                   silc_server_command_destructor,
1522                                   silc_server_command_identify,
1523                                   silc_server_command_dup(cmd));
1524       no_res = FALSE;
1525     } else {
1526       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1527         /* We've resolved this and it still is not ready.  We'll return
1528            and are that this will be handled again after it is resolved. */
1529         for (i = 0; i < resolve_count; i++) {
1530           for (k = 0; k < r->res_argc; k++)
1531             silc_free(r->res_argv[k]);
1532           silc_free(r->res_argv);
1533           silc_free(r->res_argv_lens);
1534           silc_free(r->res_argv_types);
1535         }
1536         silc_free(resolve);
1537         return FALSE;
1538       } else {
1539         /* We'll resolve this client */
1540         SilcBuffer idp;
1541
1542         r = NULL;
1543         for (k = 0; k < resolve_count; k++) {
1544           if (resolve[k].router == entry->router) {
1545             r = &resolve[k];
1546             break;
1547           }
1548         }
1549
1550         if (!r) {
1551           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1552                                  (resolve_count + 1));
1553           r = &resolve[resolve_count];
1554           memset(r, 0, sizeof(*r));
1555           r->router = entry->router;
1556           r->ident = ++server->cmd_ident;
1557           resolve_count++;
1558         }
1559
1560         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1561                                    (r->res_argc + 1));
1562         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1563                                         sizeof(*r->res_argv_lens) *
1564                                         (r->res_argc + 1));
1565         r->res_argv_types = silc_realloc(r->res_argv_types, 
1566                                          sizeof(*r->res_argv_types) *
1567                                          (r->res_argc + 1));
1568         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1569         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1570                                                sizeof(**r->res_argv));
1571         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1572         r->res_argv_lens[r->res_argc] = idp->len;
1573         r->res_argv_types[r->res_argc] = r->res_argc + 3;
1574         r->res_argc++;
1575         silc_buffer_free(idp);
1576
1577         entry->resolve_cmd_ident = r->ident;
1578         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1579         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1580       }
1581     }
1582   }
1583
1584   /* Do the resolving */
1585   for (i = 0; i < resolve_count; i++) {
1586     SilcBuffer res_cmd;
1587
1588     r = &resolve[i];
1589
1590     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1591        now anyway so make it a good one. */
1592     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1593                                           r->res_argc, r->res_argv, 
1594                                           r->res_argv_lens,
1595                                           r->res_argv_types, 
1596                                           r->ident);
1597     silc_server_packet_send(server, r->router->connection,
1598                             SILC_PACKET_COMMAND, cmd->packet->flags,
1599                             res_cmd->data, res_cmd->len, FALSE);
1600
1601     /* Reprocess this packet after received reply */
1602     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1603                                 r->ident,
1604                                 silc_server_command_destructor,
1605                                 silc_server_command_identify,
1606                                 silc_server_command_dup(cmd));
1607     cmd->pending = TRUE;
1608
1609     silc_buffer_free(res_cmd);
1610     for (k = 0; k < r->res_argc; k++)
1611       silc_free(r->res_argv[k]);
1612     silc_free(r->res_argv);
1613     silc_free(r->res_argv_lens);
1614     silc_free(r->res_argv_types);
1615     no_res = FALSE;
1616   }
1617   silc_free(resolve);
1618
1619   return no_res;
1620 }
1621
1622 static void
1623 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1624                                         SilcClientEntry *clients,
1625                                         uint32 clients_count,
1626                                         SilcServerEntry *servers,
1627                                         uint32 servers_count,
1628                                         SilcChannelEntry *channels,
1629                                         uint32 channels_count,
1630                                         int count)
1631 {
1632   SilcServer server = cmd->server;
1633   int i, k, len;
1634   SilcBuffer packet, idp;
1635   SilcCommandStatus status;
1636   uint16 ident = silc_command_get_ident(cmd->payload);
1637   char nh[256], uh[256];
1638   SilcSocketConnection hsock;
1639
1640   status = SILC_STATUS_OK;
1641
1642   if (clients) {
1643     SilcClientEntry entry;
1644
1645     len = 0;
1646     for (i = 0; i < clients_count; i++)
1647       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1648         len++;
1649
1650     if (len == 0 && clients_count) {
1651       entry = clients[0];
1652       if (entry->nickname) {
1653         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1654                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1655                                              3, entry->nickname, 
1656                                              strlen(entry->nickname));
1657       } else {
1658         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1659         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1660                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1661                                              2, idp->data, idp->len);
1662         silc_buffer_free(idp);
1663       }
1664       
1665       return;
1666     }
1667
1668     if (len > 1)
1669       status = SILC_STATUS_LIST_START;
1670
1671     for (i = 0, k = 0; i < clients_count; i++) {
1672       entry = clients[i];
1673       
1674       if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1675         if (clients_count == 1) {
1676           SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1677           silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1678                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1679                                                2, idp->data, idp->len);
1680           silc_buffer_free(idp);
1681         }
1682         continue;
1683       }
1684       
1685       if (k >= 1)
1686         status = SILC_STATUS_LIST_ITEM;
1687       if (clients_count > 1 && k == clients_count - 1 
1688           && !servers_count && !channels_count)
1689         status = SILC_STATUS_LIST_END;
1690       if (count && k - 1 == count)
1691         status = SILC_STATUS_LIST_END;
1692       if (count && k - 1 > count)
1693         break;
1694       
1695       /* Send IDENTIFY reply */
1696       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1697       
1698       memset(uh, 0, sizeof(uh));
1699       memset(nh, 0, sizeof(nh));
1700       
1701       strncat(nh, entry->nickname, strlen(entry->nickname));
1702       if (!strchr(entry->nickname, '@')) {
1703         strncat(nh, "@", 1);
1704         if (entry->servername) {
1705           strncat(nh, entry->servername, strlen(entry->servername));
1706         } else {
1707           len = entry->router ? strlen(entry->router->server_name) :
1708             strlen(server->server_name);
1709           strncat(nh, entry->router ? entry->router->server_name :
1710                   server->server_name, len);
1711         }
1712       }
1713       
1714       if (!entry->username) {
1715         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1716                                                       status, ident, 2,
1717                                                       2, idp->data, idp->len, 
1718                                                       3, nh, strlen(nh));
1719       } else {
1720         strncat(uh, entry->username, strlen(entry->username));
1721         if (!strchr(entry->username, '@')) {
1722           strncat(uh, "@", 1);
1723           hsock = (SilcSocketConnection)entry->connection;
1724           len = strlen(hsock->hostname);
1725           strncat(uh, hsock->hostname, len);
1726         }
1727         
1728         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1729                                                       status, ident, 3,
1730                                                       2, idp->data, idp->len, 
1731                                                       3, nh, strlen(nh),
1732                                                       4, uh, strlen(uh));
1733       }
1734       
1735       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1736                               0, packet->data, packet->len, FALSE);
1737       
1738       silc_buffer_free(packet);
1739       silc_buffer_free(idp);
1740       
1741       k++;
1742     }
1743   }
1744
1745   status = (status == SILC_STATUS_LIST_ITEM ? 
1746             SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1747
1748   if (servers) {
1749     SilcServerEntry entry;
1750
1751     if (status == SILC_STATUS_OK && servers_count > 1)
1752       status = SILC_STATUS_LIST_START;
1753
1754     for (i = 0, k = 0; i < servers_count; i++) {
1755       entry = servers[i];
1756       
1757       if (k >= 1)
1758         status = SILC_STATUS_LIST_ITEM;
1759       if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1760         status = SILC_STATUS_LIST_END;
1761       if (count && k - 1 == count)
1762         status = SILC_STATUS_LIST_END;
1763       if (count && k - 1 > count)
1764         break;
1765       
1766       /* Send IDENTIFY reply */
1767       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1768       if (entry->server_name) {
1769         packet = 
1770           silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1771                                                status, ident, 2,
1772                                                2, idp->data, idp->len, 
1773                                                3, entry->server_name, 
1774                                                strlen(entry->server_name));
1775       } else {
1776         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1777                                                       status, ident, 1,
1778                                                       2, idp->data, idp->len);
1779       }
1780       
1781       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1782                               0, packet->data, packet->len, FALSE);
1783       
1784       silc_buffer_free(packet);
1785       silc_buffer_free(idp);
1786       
1787       k++;
1788     }
1789   }
1790
1791   status = (status == SILC_STATUS_LIST_ITEM ? 
1792             SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1793
1794   if (channels) {
1795     SilcChannelEntry entry;
1796
1797     if (status == SILC_STATUS_OK && channels_count > 1)
1798       status = SILC_STATUS_LIST_START;
1799
1800     for (i = 0, k = 0; i < channels_count; i++) {
1801       entry = channels[i];
1802       
1803       if (k >= 1)
1804         status = SILC_STATUS_LIST_ITEM;
1805       if (channels_count > 1 && k == channels_count - 1)
1806         status = SILC_STATUS_LIST_END;
1807       if (count && k - 1 == count)
1808         status = SILC_STATUS_LIST_END;
1809       if (count && k - 1 > count)
1810         break;
1811       
1812       /* Send IDENTIFY reply */
1813       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1814       if (entry->channel_name) {
1815         packet = 
1816           silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1817                                                status, ident, 2,
1818                                                2, idp->data, idp->len, 
1819                                                3, entry->channel_name, 
1820                                                strlen(entry->channel_name));
1821       } else {
1822         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1823                                                       status, ident, 1,
1824                                                       2, idp->data, idp->len);
1825       }
1826       
1827       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1828                               0, packet->data, packet->len, FALSE);
1829       
1830       silc_buffer_free(packet);
1831       silc_buffer_free(idp);
1832       
1833       k++;
1834     }
1835   }
1836 }
1837
1838 static int
1839 silc_server_command_identify_process(SilcServerCommandContext cmd)
1840 {
1841   SilcServer server = cmd->server;
1842   uint32 count = 0;
1843   int ret = 0;
1844   SilcClientEntry *clients = NULL;
1845   SilcServerEntry *servers = NULL;
1846   SilcChannelEntry *channels = NULL;
1847   uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1848
1849   /* Protocol dictates that we must always send the received IDENTIFY request
1850      to our router if we are normal server, so let's do it now unless we
1851      are standalone. We will not send any replies to the client until we
1852      have received reply from the router. */
1853   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1854       server->server_type == SILC_SERVER && !cmd->pending && 
1855       !server->standalone) {
1856     SilcBuffer tmpbuf;
1857     uint16 old_ident;
1858
1859     old_ident = silc_command_get_ident(cmd->payload);
1860     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1861     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1862
1863     /* Send IDENTIFY command to our router */
1864     silc_server_packet_send(server, (SilcSocketConnection)
1865                             server->router->connection,
1866                             SILC_PACKET_COMMAND, cmd->packet->flags,
1867                             tmpbuf->data, tmpbuf->len, TRUE);
1868
1869     /* Reprocess this packet after received reply from router */
1870     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1871                                 silc_command_get_ident(cmd->payload),
1872                                 silc_server_command_destructor,
1873                                 silc_server_command_identify,
1874                                 silc_server_command_dup(cmd));
1875     cmd->pending = TRUE;
1876
1877     silc_command_set_ident(cmd->payload, old_ident);
1878
1879     silc_buffer_free(tmpbuf);
1880     ret = -1;
1881     goto out;
1882   }
1883
1884   /* We are ready to process the command request. Let's search for the
1885      requested client and send reply to the requesting client. */
1886
1887   /* Parse the IDENTIFY request */
1888   if (!silc_server_command_identify_parse(cmd,
1889                                           &clients, &clients_count,
1890                                           &servers, &servers_count,
1891                                           &channels, &channels_count,
1892                                           &count))
1893     return 0;
1894
1895   /* Check that all mandatory fields are present and request those data
1896      from the server who owns the client if necessary. */
1897   if (clients && !silc_server_command_identify_check_client(cmd, clients, 
1898                                                             clients_count)) {
1899     ret = -1;
1900     goto out;
1901   }
1902
1903   /* Send the command reply to the client */
1904   silc_server_command_identify_send_reply(cmd, 
1905                                           clients, clients_count,
1906                                           servers, servers_count,
1907                                           channels, channels_count, 
1908                                           count);
1909
1910  out:
1911   silc_free(clients);
1912   silc_free(servers);
1913   silc_free(channels);
1914
1915   return ret;
1916 }
1917
1918 SILC_SERVER_CMD_FUNC(identify)
1919 {
1920   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1921   int ret = 0;
1922
1923   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1924
1925   ret = silc_server_command_identify_process(cmd);
1926
1927   if (!ret)
1928     silc_server_command_free(cmd);
1929 }
1930
1931 /* Checks string for bad characters and returns TRUE if they are found. */
1932
1933 static int silc_server_command_bad_chars(char *nick)
1934 {
1935   int i;
1936
1937   for (i = 0; i < strlen(nick); i++) {
1938     if (!isascii(nick[i]))
1939       return TRUE;
1940     if (nick[i] <= 32) return TRUE;
1941     if (nick[i] == ' ') return TRUE;
1942     if (nick[i] == '\\') return TRUE;
1943     if (nick[i] == '\"') return TRUE;
1944     if (nick[i] == '*') return TRUE;
1945     if (nick[i] == '?') return TRUE;
1946     if (nick[i] == ',') return TRUE;
1947     if (nick[i] == '@') return TRUE;
1948   }
1949
1950   return FALSE;
1951 }
1952
1953 /* Server side of command NICK. Sets nickname for user. Setting
1954    nickname causes generation of a new client ID for the client. The
1955    new client ID is sent to the client after changing the nickname. */
1956
1957 SILC_SERVER_CMD_FUNC(nick)
1958 {
1959   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1960   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1961   SilcServer server = cmd->server;
1962   SilcBuffer packet, nidp, oidp;
1963   SilcClientID *new_id;
1964   char *nick;
1965   uint16 ident = silc_command_get_ident(cmd->payload);
1966   int nickfail = 0;
1967
1968   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1969     goto out;
1970
1971   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1972
1973   /* Check nickname */
1974   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1975   if (silc_server_command_bad_chars(nick) == TRUE) {
1976     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1977                                           SILC_STATUS_ERR_BAD_NICKNAME);
1978     goto out;
1979   }
1980
1981   if (strlen(nick) > 128)
1982     nick[128] = '\0';
1983
1984   /* Create new Client ID */
1985   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
1986                                    cmd->server->rng, 
1987                                    cmd->server->md5hash, nick,
1988                                    &new_id)) {
1989     nickfail++;
1990     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1991   }
1992
1993   /* Send notify about nickname change to our router. We send the new
1994      ID and ask to replace it with the old one. If we are router the
1995      packet is broadcasted. Send NICK_CHANGE notify. */
1996   if (!server->standalone)
1997     silc_server_send_notify_nick_change(server, server->router->connection, 
1998                                         server->server_type == SILC_SERVER ? 
1999                                         FALSE : TRUE, client->id,
2000                                         new_id);
2001
2002   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2003
2004   /* Remove old cache entry */
2005   silc_idcache_del_by_context(server->local_list->clients, client);
2006
2007   /* Free old ID */
2008   silc_free(client->id);
2009
2010   /* Save the nickname as this client is our local client */
2011   silc_free(client->nickname);
2012
2013   client->nickname = strdup(nick);
2014   client->id = new_id;
2015
2016   /* Update client cache */
2017   silc_idcache_add(server->local_list->clients, client->nickname, 
2018                    client->id, (void *)client, FALSE);
2019
2020   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2021
2022   /* Send NICK_CHANGE notify to the client's channels */
2023   silc_server_send_notify_on_channels(server, NULL, client, 
2024                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2025                                       oidp->data, oidp->len, 
2026                                       nidp->data, nidp->len);
2027
2028   /* Send the new Client ID as reply command back to client */
2029   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2030                                                 SILC_STATUS_OK, ident, 1, 
2031                                                 2, nidp->data, nidp->len);
2032   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2033                           0, packet->data, packet->len, FALSE);
2034
2035   silc_buffer_free(packet);
2036   silc_buffer_free(nidp);
2037   silc_buffer_free(oidp);
2038   
2039  out:
2040   silc_server_command_free(cmd);
2041 }
2042
2043 /* Sends the LIST command reply */
2044
2045 static void
2046 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2047                                     SilcChannelEntry *lch, 
2048                                     uint32 lch_count,
2049                                     SilcChannelEntry *gch,
2050                                     uint32 gch_count)
2051 {
2052   int i;
2053   SilcBuffer packet, idp;
2054   SilcChannelEntry entry;
2055   SilcCommandStatus status;
2056   uint16 ident = silc_command_get_ident(cmd->payload);
2057   char *topic;
2058   unsigned char usercount[4];
2059   uint32 users;
2060
2061   for (i = 0; i < lch_count; i++)
2062     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2063       lch[i] = NULL;
2064   for (i = 0; i < gch_count; i++)
2065     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2066       gch[i] = NULL;
2067
2068   status = SILC_STATUS_OK;
2069   if ((lch_count + gch_count) > 1)
2070     status = SILC_STATUS_LIST_START;
2071
2072   /* Local list */
2073   for (i = 0; i < lch_count; i++) {
2074     entry = lch[i];
2075
2076     if (!entry)
2077       continue;
2078
2079     if (i >= 1)
2080       status = SILC_STATUS_LIST_ITEM;
2081
2082     if (i == lch_count - 1 && gch_count)
2083       break;
2084     if (lch_count > 1 && i == lch_count - 1)
2085       status = SILC_STATUS_LIST_END;
2086
2087     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2088
2089     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2090       topic = "*private*";
2091       memset(usercount, 0, sizeof(usercount));
2092     } else {
2093       topic = entry->topic;
2094       users = silc_hash_table_count(entry->user_list);
2095       SILC_PUT32_MSB(users, usercount);
2096     }
2097
2098     /* Send the reply */
2099     if (topic)
2100       packet = 
2101         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2102                                              status, ident, 4, 
2103                                              2, idp->data, idp->len,
2104                                              3, entry->channel_name, 
2105                                              strlen(entry->channel_name),
2106                                              4, topic, strlen(topic),
2107                                              5, usercount, 4);
2108     else
2109       packet = 
2110         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2111                                              status, ident, 3, 
2112                                              2, idp->data, idp->len,
2113                                              3, entry->channel_name, 
2114                                              strlen(entry->channel_name),
2115                                              5, usercount, 4);
2116     silc_server_packet_send(cmd->server, cmd->sock, 
2117                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2118                             packet->len, FALSE);
2119     silc_buffer_free(packet);
2120     silc_buffer_free(idp);
2121   }
2122
2123   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2124
2125   /* Global list */
2126   for (i = 0; i < gch_count; i++) {
2127     entry = gch[i];
2128
2129     if (!entry)
2130       continue;
2131
2132     if (i >= 1)
2133       status = SILC_STATUS_LIST_ITEM;
2134
2135     if (gch_count > 1 && i == lch_count - 1)
2136       status = SILC_STATUS_LIST_END;
2137
2138     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2139
2140     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2141       topic = "*private*";
2142       memset(usercount, 0, sizeof(usercount));
2143     } else {
2144       topic = entry->topic;
2145       users = silc_hash_table_count(entry->user_list);
2146       SILC_PUT32_MSB(users, usercount);
2147     }
2148
2149     /* Send the reply */
2150     if (topic)
2151       packet = 
2152         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2153                                              status, ident, 4, 
2154                                              2, idp->data, idp->len,
2155                                              3, entry->channel_name, 
2156                                              strlen(entry->channel_name),
2157                                              4, topic, strlen(topic),
2158                                              5, usercount, 4);
2159     else
2160       packet = 
2161         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2162                                              status, ident, 3, 
2163                                              2, idp->data, idp->len,
2164                                              3, entry->channel_name, 
2165                                              strlen(entry->channel_name),
2166                                              5, usercount, 4);
2167     silc_server_packet_send(cmd->server, cmd->sock, 
2168                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2169                             packet->len, FALSE);
2170     silc_buffer_free(packet);
2171     silc_buffer_free(idp);
2172   }
2173 }
2174
2175 /* Server side of LIST command. This lists the channel of the requested
2176    server. Secret channels are not listed. */
2177
2178 SILC_SERVER_CMD_FUNC(list)
2179 {
2180   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2181   SilcServer server = cmd->server;
2182   SilcChannelID *channel_id = NULL;
2183   unsigned char *tmp;
2184   uint32 tmp_len;
2185   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2186   uint32 lch_count = 0, gch_count = 0;
2187
2188   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
2189
2190   /* Get Channel ID */
2191   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2192   if (tmp) {
2193     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2194     if (!channel_id) {
2195       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2196                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2197       goto out;
2198     }
2199   }
2200
2201   /* Get the channels from local list */
2202   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2203                                        &lch_count);
2204   
2205   /* Get the channels from global list if we are router */
2206   if (server->server_type != SILC_SERVER) 
2207     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2208                                          &gch_count);
2209
2210   /* Send the reply */
2211   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2212                                       gchannels, gch_count);
2213
2214  out:
2215   silc_server_command_free(cmd);
2216 }
2217
2218 /* Server side of TOPIC command. Sets topic for channel and/or returns
2219    current topic to client. */
2220
2221 SILC_SERVER_CMD_FUNC(topic)
2222 {
2223   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2224   SilcServer server = cmd->server;
2225   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2226   SilcChannelID *channel_id;
2227   SilcChannelEntry channel;
2228   SilcChannelClientEntry chl;
2229   SilcBuffer packet, idp;
2230   unsigned char *tmp;
2231   uint32 argc, tmp_len;
2232   uint16 ident = silc_command_get_ident(cmd->payload);
2233
2234   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2235
2236   argc = silc_argument_get_arg_num(cmd->args);
2237
2238   /* Get Channel ID */
2239   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2240   if (!tmp) {
2241     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2242                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2243     goto out;
2244   }
2245   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2246   if (!channel_id) {
2247     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2248                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2249     goto out;
2250   }
2251
2252   /* Check whether the channel exists */
2253   channel = silc_idlist_find_channel_by_id(server->local_list, 
2254                                            channel_id, NULL);
2255   if (!channel) {
2256     channel = silc_idlist_find_channel_by_id(server->global_list, 
2257                                              channel_id, NULL);
2258     if (!channel) {
2259       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2260                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2261       goto out;
2262     }
2263   }
2264
2265   if (argc > 1) {
2266     /* Get the topic */
2267     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2268     if (!tmp) {
2269       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2270                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2271       goto out;
2272     }
2273
2274     if (strlen(tmp) > 256) {
2275       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2276                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2277       goto out;
2278     }
2279
2280     /* See whether the client is on channel and has rights to change topic */
2281     if (!silc_hash_table_find(channel->user_list, client, NULL, 
2282                               (void *)&chl)) {
2283       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2285       goto out;
2286     }
2287
2288     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2289       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2290         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2291                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2292         goto out;
2293       }
2294     }
2295
2296     /* Set the topic for channel */
2297     silc_free(channel->topic);
2298     channel->topic = strdup(tmp);
2299
2300     /* Send TOPIC_SET notify type to the network */
2301     if (!server->standalone)
2302       silc_server_send_notify_topic_set(server, server->router->connection,
2303                                         server->server_type == SILC_ROUTER ?
2304                                         TRUE : FALSE, channel, client->id,
2305                                         channel->topic);
2306
2307     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2308
2309     /* Send notify about topic change to all clients on the channel */
2310     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2311                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2312                                        idp->data, idp->len,
2313                                        channel->topic, strlen(channel->topic));
2314     silc_buffer_free(idp);
2315   }
2316
2317   /* Send the topic to client as reply packet */
2318   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2319   if (channel->topic)
2320     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2321                                                   SILC_STATUS_OK, ident, 2, 
2322                                                   2, idp->data, idp->len,
2323                                                   3, channel->topic, 
2324                                                   strlen(channel->topic));
2325   else
2326     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2327                                                   SILC_STATUS_OK, ident, 1, 
2328                                                   2, idp->data, idp->len);
2329   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2330                           0, packet->data, packet->len, FALSE);
2331
2332   silc_buffer_free(packet);
2333   silc_buffer_free(idp);
2334   silc_free(channel_id);
2335
2336  out:
2337   silc_server_command_free(cmd);
2338 }
2339
2340 /* Server side of INVITE command. Invites some client to join some channel. 
2341    This command is also used to manage the invite list of the channel. */
2342
2343 SILC_SERVER_CMD_FUNC(invite)
2344 {
2345   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2346   SilcServer server = cmd->server;
2347   SilcSocketConnection sock = cmd->sock, dest_sock;
2348   SilcChannelClientEntry chl;
2349   SilcClientEntry sender, dest;
2350   SilcClientID *dest_id = NULL;
2351   SilcChannelEntry channel;
2352   SilcChannelID *channel_id = NULL;
2353   SilcIDListData idata;
2354   SilcBuffer idp, idp2, packet;
2355   unsigned char *tmp, *add, *del;
2356   uint32 len;
2357   uint16 ident = silc_command_get_ident(cmd->payload);
2358
2359   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2360
2361   /* Get Channel ID */
2362   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2363   if (!tmp) {
2364     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2365                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2366     goto out;
2367   }
2368   channel_id = silc_id_payload_parse_id(tmp, len);
2369   if (!channel_id) {
2370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2371                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2372     goto out;
2373   }
2374
2375   /* Get the channel entry */
2376   channel = silc_idlist_find_channel_by_id(server->local_list, 
2377                                            channel_id, NULL);
2378   if (!channel) {
2379     channel = silc_idlist_find_channel_by_id(server->global_list, 
2380                                              channel_id, NULL);
2381     if (!channel) {
2382       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2384       goto out;
2385     }
2386   }
2387
2388   /* Check whether the sender of this command is on the channel. */
2389   sender = (SilcClientEntry)sock->user_data;
2390   if (!silc_server_client_on_channel(sender, channel)) {
2391     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2392                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2393     goto out;
2394   }
2395
2396   /* Check whether the channel is invite-only channel. If yes then the
2397      sender of this command must be at least channel operator. */
2398   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2399     silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2400     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2401       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2403       goto out;
2404     }
2405   }
2406
2407   /* Get destination client ID */
2408   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2409   if (tmp) {
2410     char invite[512];
2411
2412     dest_id = silc_id_payload_parse_id(tmp, len);
2413     if (!dest_id) {
2414       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2415                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2416       goto out;
2417     }
2418
2419     /* Get the client entry */
2420     dest = silc_server_get_client_resolve(server, dest_id);
2421     if (!dest) {
2422       if (server->server_type != SILC_SERVER) {
2423         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2425         goto out;
2426       }
2427       
2428       /* The client info is being resolved. Reprocess this packet after
2429          receiving the reply to the query. */
2430       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2431                                   server->cmd_ident,
2432                                   silc_server_command_destructor,
2433                                   silc_server_command_invite, 
2434                                   silc_server_command_dup(cmd));
2435       cmd->pending = TRUE;
2436       silc_free(channel_id);
2437       silc_free(dest_id);
2438       return;
2439     }
2440
2441     /* Check whether the requested client is already on the channel. */
2442     if (silc_server_client_on_channel(dest, channel)) {
2443       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2444                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2445       goto out;
2446     }
2447     
2448     /* Get route to the client */
2449     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2450     if (!dest_sock) {
2451       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2452                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2453       goto out;
2454     }
2455
2456     memset(invite, 0, sizeof(invite));
2457     strncat(invite, dest->nickname, strlen(dest->nickname));
2458     strncat(invite, "!", 1);
2459     strncat(invite, dest->username, strlen(dest->username));
2460     if (!strchr(dest->username, '@')) {
2461       strncat(invite, "@", 1);
2462       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2463     }
2464
2465     len = strlen(invite);
2466     if (!channel->invite_list)
2467       channel->invite_list = silc_calloc(len + 2, 
2468                                          sizeof(*channel->invite_list));
2469     else
2470       channel->invite_list = silc_realloc(channel->invite_list, 
2471                                           sizeof(*channel->invite_list) * 
2472                                           (len + 
2473                                            strlen(channel->invite_list) + 2));
2474     strncat(channel->invite_list, invite, len);
2475     strncat(channel->invite_list, ",", 1);
2476
2477     /* Send notify to the client that is invited to the channel */
2478     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2479     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2480     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2481                                  SILC_ID_CLIENT,
2482                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2483                                  idp->data, idp->len, 
2484                                  channel->channel_name, 
2485                                  strlen(channel->channel_name),
2486                                  idp2->data, idp2->len);
2487     silc_buffer_free(idp);
2488     silc_buffer_free(idp2);
2489   }
2490
2491   /* Add the client to the invite list of the channel */
2492   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2493   if (add) {
2494     if (!channel->invite_list)
2495       channel->invite_list = silc_calloc(len + 2, 
2496                                          sizeof(*channel->invite_list));
2497     else
2498       channel->invite_list = silc_realloc(channel->invite_list, 
2499                                           sizeof(*channel->invite_list) * 
2500                                           (len + 
2501                                            strlen(channel->invite_list) + 2));
2502     if (add[len - 1] == ',')
2503       add[len - 1] = '\0';
2504     
2505     strncat(channel->invite_list, add, len);
2506     strncat(channel->invite_list, ",", 1);
2507   }
2508
2509   /* Get the invite to be removed and remove it from the list */
2510   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2511   if (del && channel->invite_list) {
2512     char *start, *end, *n;
2513
2514     if (!strncmp(channel->invite_list, del, 
2515                  strlen(channel->invite_list) - 1)) {
2516       silc_free(channel->invite_list);
2517       channel->invite_list = NULL;
2518     } else {
2519       start = strstr(channel->invite_list, del);
2520       if (start && strlen(start) >= len) {
2521         end = start + len;
2522         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2523         strncat(n, channel->invite_list, start - channel->invite_list);
2524         strncat(n, end + 1, ((channel->invite_list + 
2525                               strlen(channel->invite_list)) - end) - 1);
2526         silc_free(channel->invite_list);
2527         channel->invite_list = n;
2528       }
2529     }
2530   }
2531
2532   /* Send notify to the primary router */
2533   if (!server->standalone)
2534     silc_server_send_notify_invite(server, server->router->connection,
2535                                    server->server_type == SILC_ROUTER ?
2536                                    TRUE : FALSE, channel,
2537                                    sender->id, add, del);
2538
2539   /* Send command reply */
2540   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2541
2542   if (add || del)
2543     packet = 
2544       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2545                                            SILC_STATUS_OK, ident, 2,
2546                                            2, tmp, len,
2547                                            3, channel->invite_list,
2548                                            channel->invite_list ?
2549                                            strlen(channel->invite_list) : 0);
2550   else
2551     packet = 
2552       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2553                                            SILC_STATUS_OK, ident, 1,
2554                                            2, tmp, len);
2555   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2556                           packet->data, packet->len, FALSE);
2557   silc_buffer_free(packet);
2558
2559  out:
2560   silc_free(dest_id);
2561   silc_free(channel_id);
2562   silc_server_command_free(cmd);
2563 }
2564
2565 typedef struct {
2566   SilcServer server;
2567   SilcSocketConnection sock;
2568   char *signoff;
2569 } *QuitInternal;
2570
2571 /* Quits connection to client. This gets called if client won't
2572    close the connection even when it has issued QUIT command. */
2573
2574 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2575 {
2576   QuitInternal q = (QuitInternal)context;
2577
2578   /* Free all client specific data, such as client entry and entires
2579      on channels this client may be on. */
2580   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2581                                TRUE, q->signoff);
2582   q->sock->user_data = NULL;
2583
2584   /* Close the connection on our side */
2585   silc_server_close_connection(q->server, q->sock);
2586
2587   silc_free(q->signoff);
2588   silc_free(q);
2589 }
2590
2591 /* Quits SILC session. This is the normal way to disconnect client. */
2592  
2593 SILC_SERVER_CMD_FUNC(quit)
2594 {
2595   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2596   SilcServer server = cmd->server;
2597   SilcSocketConnection sock = cmd->sock;
2598   QuitInternal q;
2599   unsigned char *tmp = NULL;
2600   uint32 len = 0;
2601
2602   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2603
2604   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2605     goto out;
2606
2607   /* Get destination ID */
2608   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2609   if (len > 128)
2610     tmp = NULL;
2611
2612   q = silc_calloc(1, sizeof(*q));
2613   q->server = server;
2614   q->sock = sock;
2615   q->signoff = tmp ? strdup(tmp) : NULL;
2616
2617   /* We quit the connection with little timeout */
2618   silc_schedule_task_add(server->schedule, sock->sock,
2619                      silc_server_command_quit_cb, (void *)q,
2620                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2621
2622  out:
2623   silc_server_command_free(cmd);
2624 }
2625
2626 /* Server side of command KILL. This command is used by router operator
2627    to remove an client from the SILC Network temporarily. */
2628
2629 SILC_SERVER_CMD_FUNC(kill)
2630 {
2631   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2632   SilcServer server = cmd->server;
2633   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2634   SilcClientEntry remote_client;
2635   SilcClientID *client_id;
2636   unsigned char *tmp, *comment;
2637   uint32 tmp_len, tmp_len2;
2638
2639   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2640
2641   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2642     goto out;
2643
2644   /* KILL command works only on router */
2645   if (server->server_type != SILC_ROUTER) {
2646     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2647                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2648     goto out;
2649   }
2650
2651   /* Check whether client has the permissions. */
2652   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2653     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2654                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2655     goto out;
2656   }
2657
2658   /* Get the client ID */
2659   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2660   if (!tmp) {
2661     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2662                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2663     goto out;
2664   }
2665   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2666   if (!client_id) {
2667     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2668                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2669     goto out;
2670   }
2671
2672   /* Get the client entry */
2673   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2674                                                 client_id, TRUE, NULL);
2675   if (!remote_client) {
2676     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2677                                                   client_id, TRUE, NULL);
2678     if (!remote_client) {
2679       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2680                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2681       goto out;
2682     }
2683   }
2684
2685   /* Get comment */
2686   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2687   if (tmp_len2 > 128)
2688     comment = NULL;
2689
2690   /* Send reply to the sender */
2691   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2692                                         SILC_STATUS_OK);
2693
2694   /* Send the KILL notify packets. First send it to the channel, then
2695      to our primary router and then directly to the client who is being
2696      killed right now. */
2697
2698   /* Send KILLED notify to the channels. It is not sent to the client
2699      as it will be sent differently destined directly to the client and not
2700      to the channel. */
2701   silc_server_send_notify_on_channels(server, remote_client, 
2702                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2703                                       comment ? 2 : 1,
2704                                       tmp, tmp_len,
2705                                       comment, comment ? tmp_len2 : 0);
2706
2707   /* Send KILLED notify to primary route */
2708   if (!server->standalone)
2709     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2710                                    remote_client->id, comment);
2711
2712   /* Send KILLED notify to the client directly */
2713   silc_server_send_notify_killed(server, remote_client->connection ? 
2714                                  remote_client->connection : 
2715                                  remote_client->router->connection, FALSE,
2716                                  remote_client->id, comment);
2717
2718   /* Remove the client from all channels. This generates new keys to the
2719      channels as well. */
2720   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2721                                    NULL, TRUE);
2722
2723   /* Remove the client entry, If it is locally connected then we will also
2724      disconnect the client here */
2725   if (remote_client->connection) {
2726     /* Remove locally conneted client */
2727     SilcSocketConnection sock = remote_client->connection;
2728     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2729     silc_server_close_connection(server, sock);
2730   } else {
2731     /* Remove remote client */
2732     if (!silc_idlist_del_client(server->global_list, remote_client))
2733       silc_idlist_del_client(server->local_list, remote_client);
2734   }
2735
2736  out:
2737   silc_server_command_free(cmd);
2738 }
2739
2740 /* Server side of command INFO. This sends information about us to 
2741    the client. If client requested specific server we will send the 
2742    command to that server. */
2743
2744 SILC_SERVER_CMD_FUNC(info)
2745 {
2746   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2747   SilcServer server = cmd->server;
2748   SilcBuffer packet, idp;
2749   unsigned char *tmp;
2750   uint32 tmp_len;
2751   char *dest_server, *server_info = NULL, *server_name;
2752   uint16 ident = silc_command_get_ident(cmd->payload);
2753   SilcServerEntry entry = NULL;
2754   SilcServerID *server_id = NULL;
2755
2756   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2757
2758   /* Get server name */
2759   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2760
2761   /* Get Server ID */
2762   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2763   if (tmp) {
2764     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2765     if (!server_id) {
2766       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2767                                             SILC_STATUS_ERR_NO_SERVER_ID);
2768       goto out;
2769     }
2770   }
2771
2772   if (server_id) {
2773     /* Check whether we have this server cached */
2774     entry = silc_idlist_find_server_by_id(server->local_list,
2775                                           server_id, TRUE, NULL);
2776     if (!entry) {
2777       entry = silc_idlist_find_server_by_id(server->global_list,
2778                                             server_id, TRUE, NULL);
2779       if (!entry && server->server_type != SILC_SERVER) {
2780         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2781                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2782         goto out;
2783       }
2784     }
2785   }
2786
2787   /* Some buggy servers has sent request to router about themselves. */
2788   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2789     goto out;
2790
2791   if ((!dest_server && !server_id && !entry) || (entry && 
2792                                                  entry == server->id_entry) ||
2793       (dest_server && !cmd->pending && 
2794        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2795     /* Send our reply */
2796     char info_string[256];
2797
2798     memset(info_string, 0, sizeof(info_string));
2799     snprintf(info_string, sizeof(info_string), 
2800              "location: %s server: %s admin: %s <%s>",
2801              server->config->admin_info->location,
2802              server->config->admin_info->server_type,
2803              server->config->admin_info->admin_name,
2804              server->config->admin_info->admin_email);
2805
2806     server_info = info_string;
2807     entry = server->id_entry;
2808   } else {
2809     /* Check whether we have this server cached */
2810     if (!entry && dest_server) {
2811       entry = silc_idlist_find_server_by_name(server->global_list,
2812                                               dest_server, TRUE, NULL);
2813       if (!entry) {
2814         entry = silc_idlist_find_server_by_name(server->local_list,
2815                                                 dest_server, TRUE, NULL);
2816       }
2817     }
2818
2819     if (!cmd->pending &&
2820         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2821       /* Send to the server */
2822       SilcBuffer tmpbuf;
2823       uint16 old_ident;
2824
2825       old_ident = silc_command_get_ident(cmd->payload);
2826       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2827       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2828
2829       silc_server_packet_send(server, entry->connection,
2830                               SILC_PACKET_COMMAND, cmd->packet->flags,
2831                               tmpbuf->data, tmpbuf->len, TRUE);
2832
2833       /* Reprocess this packet after received reply from router */
2834       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2835                                   silc_command_get_ident(cmd->payload),
2836                                   silc_server_command_destructor,
2837                                   silc_server_command_info,
2838                                   silc_server_command_dup(cmd));
2839       cmd->pending = TRUE;
2840       silc_command_set_ident(cmd->payload, old_ident);
2841       silc_buffer_free(tmpbuf);
2842       return;
2843     }
2844
2845     if (!entry && !cmd->pending && !server->standalone) {
2846       /* Send to the primary router */
2847       SilcBuffer tmpbuf;
2848       uint16 old_ident;
2849
2850       old_ident = silc_command_get_ident(cmd->payload);
2851       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2852       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2853
2854       silc_server_packet_send(server, server->router->connection,
2855                               SILC_PACKET_COMMAND, cmd->packet->flags,
2856                               tmpbuf->data, tmpbuf->len, TRUE);
2857
2858       /* Reprocess this packet after received reply from router */
2859       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2860                                   silc_command_get_ident(cmd->payload),
2861                                   silc_server_command_destructor,
2862                                   silc_server_command_info,
2863                                   silc_server_command_dup(cmd));
2864       cmd->pending = TRUE;
2865       silc_command_set_ident(cmd->payload, old_ident);
2866       silc_buffer_free(tmpbuf);
2867       return;
2868     }
2869   }
2870
2871   silc_free(server_id);
2872
2873   if (!entry) {
2874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2875                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2876     goto out;
2877   }
2878
2879   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2880   if (!server_info)
2881     server_info = entry->server_info;
2882   server_name = entry->server_name;
2883
2884   /* Send the reply */
2885   if (server_info)
2886     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2887                                                   SILC_STATUS_OK, ident, 3,
2888                                                   2, idp->data, idp->len,
2889                                                   3, server_name, 
2890                                                   strlen(server_name),
2891                                                   4, server_info, 
2892                                                   strlen(server_info));
2893   else
2894     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2895                                                   SILC_STATUS_OK, ident, 2,
2896                                                   2, idp->data, idp->len,
2897                                                   3, server_name, 
2898                                                   strlen(server_name));
2899   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2900                           packet->data, packet->len, FALSE);
2901     
2902   silc_buffer_free(packet);
2903   silc_buffer_free(idp);
2904
2905  out:
2906   silc_server_command_free(cmd);
2907 }
2908
2909 /* Server side of command PING. This just replies to the ping. */
2910
2911 SILC_SERVER_CMD_FUNC(ping)
2912 {
2913   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2914   SilcServer server = cmd->server;
2915   SilcServerID *id;
2916   uint32 len;
2917   unsigned char *tmp;
2918
2919   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2920
2921   /* Get Server ID */
2922   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2923   if (!tmp) {
2924     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2925                                           SILC_STATUS_ERR_NO_SERVER_ID);
2926     goto out;
2927   }
2928   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2929   if (!id)
2930     goto out;
2931
2932   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2933     /* Send our reply */
2934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935                                           SILC_STATUS_OK);
2936   } else {
2937     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2938                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2939     goto out;
2940   }
2941
2942   silc_free(id);
2943
2944  out:
2945   silc_server_command_free(cmd);
2946 }
2947
2948 /* Internal routine to join channel. The channel sent to this function
2949    has been either created or resolved from ID lists. This joins the sent
2950    client to the channel. */
2951
2952 static void silc_server_command_join_channel(SilcServer server, 
2953                                              SilcServerCommandContext cmd,
2954                                              SilcChannelEntry channel,
2955                                              SilcClientID *client_id,
2956                                              bool created,
2957                                              bool create_key,
2958                                              uint32 umode)
2959 {
2960   SilcSocketConnection sock = cmd->sock;
2961   unsigned char *tmp;
2962   uint32 tmp_len, user_count;
2963   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2964   SilcClientEntry client;
2965   SilcChannelClientEntry chl;
2966   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2967   uint16 ident = silc_command_get_ident(cmd->payload);
2968   char check[512], check2[512];
2969
2970   SILC_LOG_DEBUG(("Start"));
2971
2972   if (!channel)
2973     return;
2974
2975   /* Get the client entry */
2976   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2977     client = (SilcClientEntry)sock->user_data;
2978   } else {
2979     client = silc_server_get_client_resolve(server, client_id);
2980     if (!client) {
2981       if (cmd->pending)
2982         goto out;
2983
2984       /* The client info is being resolved. Reprocess this packet after
2985          receiving the reply to the query. */
2986       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2987                                   server->cmd_ident, NULL,
2988                                   silc_server_command_join, 
2989                                   silc_server_command_dup(cmd));
2990       cmd->pending = TRUE;
2991       return;
2992     }
2993
2994     cmd->pending = FALSE;
2995   }
2996
2997   /*
2998    * Check channel modes
2999    */
3000
3001   memset(check, 0, sizeof(check));
3002   memset(check2, 0, sizeof(check2));
3003   strncat(check, client->nickname, strlen(client->nickname));
3004   strncat(check, "!", 1);
3005   strncat(check, client->username, strlen(client->username));
3006   if (!strchr(client->username, '@')) {
3007     strncat(check, "@", 1);
3008     strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3009   }
3010
3011   strncat(check2, client->nickname, strlen(client->nickname));
3012   if (!strchr(client->nickname, '@')) {
3013     strncat(check2, "@", 1);
3014     strncat(check2, server->server_name, strlen(server->server_name));
3015   }
3016   strncat(check2, "!", 1);
3017   strncat(check2, client->username, strlen(client->username));
3018   if (!strchr(client->username, '@')) {
3019     strncat(check2, "@", 1);
3020     strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3021   }
3022
3023   /* Check invite list if channel is invite-only channel */
3024   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3025     if (!channel->invite_list ||
3026         (!silc_string_match(channel->invite_list, check) &&
3027          !silc_string_match(channel->invite_list, check2))) {
3028       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3029                                             SILC_STATUS_ERR_NOT_INVITED);
3030       goto out;
3031     }
3032   }
3033
3034   /* Check ban list if it exists. If the client's nickname, server,
3035      username and/or hostname is in the ban list the access to the
3036      channel is denied. */
3037   if (channel->ban_list) {
3038     if (silc_string_match(channel->ban_list, check) ||
3039         silc_string_match(channel->ban_list, check2)) {
3040       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3041                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3042       goto out;
3043     }
3044   }
3045
3046   /* Get passphrase */
3047   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3048   if (tmp) {
3049     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3050     memcpy(passphrase, tmp, tmp_len);
3051   }
3052   
3053   /* Check the channel passphrase if set. */
3054   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3055     if (!passphrase || memcmp(channel->passphrase, passphrase,
3056                               strlen(channel->passphrase))) {
3057       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3058                                             SILC_STATUS_ERR_BAD_PASSWORD);
3059       goto out;
3060     }
3061   }
3062
3063   /* Check user count limit if set. */
3064   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3065     if (silc_hash_table_count(channel->user_list) + 1 > 
3066         channel->user_limit) {
3067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
3069       goto out;
3070     }
3071   }
3072
3073   /*
3074    * Client is allowed to join to the channel. Make it happen.
3075    */
3076
3077   /* Check whether the client already is on the channel */
3078   if (silc_server_client_on_channel(client, channel)) {
3079     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3080                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3081     goto out;
3082   }
3083
3084   /* Generate new channel key as protocol dictates */
3085   if (create_key) {
3086     if (!silc_server_create_channel_key(server, channel, 0))
3087       goto out;
3088
3089     /* Send the channel key. This is broadcasted to the channel but is not
3090        sent to the client who is joining to the channel. */
3091     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3092       silc_server_send_channel_key(server, NULL, channel, 
3093                                    server->server_type == SILC_ROUTER ? 
3094                                    FALSE : !server->standalone);
3095   }
3096
3097   /* Join the client to the channel by adding it to channel's user list.
3098      Add also the channel to client entry's channels list for fast cross-
3099      referencing. */
3100   chl = silc_calloc(1, sizeof(*chl));
3101   chl->mode = umode;
3102   chl->client = client;
3103   chl->channel = channel;
3104   silc_hash_table_add(channel->user_list, client, chl);
3105   silc_hash_table_add(client->channels, channel, chl);
3106
3107   /* Get users on the channel */
3108   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3109                                    &user_count);
3110
3111   /* Encode Client ID Payload of the original client who wants to join */
3112   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3113
3114   /* Encode command reply packet */
3115   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3116   SILC_PUT32_MSB(channel->mode, mode);
3117   SILC_PUT32_MSB(created, tmp2);
3118   SILC_PUT32_MSB(user_count, tmp3);
3119
3120   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3121     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3122     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3123                                            strlen(channel->channel_key->
3124                                                   cipher->name),
3125                                            channel->channel_key->cipher->name,
3126                                            channel->key_len / 8, channel->key);
3127     silc_free(tmp);
3128   }
3129
3130   reply = 
3131     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3132                                          SILC_STATUS_OK, ident, 13,
3133                                          2, channel->channel_name,
3134                                          strlen(channel->channel_name),
3135                                          3, chidp->data, chidp->len,
3136                                          4, clidp->data, clidp->len,
3137                                          5, mode, 4,
3138                                          6, tmp2, 4,
3139                                          7, keyp ? keyp->data : NULL, 
3140                                          keyp ? keyp->len : 0,
3141                                          8, channel->ban_list, 
3142                                          channel->ban_list ?
3143                                          strlen(channel->ban_list) : 0,
3144                                          9, channel->invite_list,
3145                                          channel->invite_list ?
3146                                          strlen(channel->invite_list) : 0,
3147                                          10, channel->topic,
3148                                          channel->topic ?
3149                                          strlen(channel->topic) : 0,
3150                                          11, silc_hmac_get_name(channel->hmac),
3151                                          strlen(silc_hmac_get_name(channel->
3152                                                                    hmac)),
3153                                          12, tmp3, 4,
3154                                          13, user_list->data, user_list->len,
3155                                          14, mode_list->data, 
3156                                          mode_list->len);
3157
3158   /* Send command reply */
3159   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3160                           reply->data, reply->len, FALSE);
3161
3162   /* Send JOIN notify to locally connected clients on the channel. If
3163      we are normal server then router will send or have sent JOIN notify
3164      already. However since we've added the client already to our channel
3165      we'll ignore it (in packet_receive.c) so we must send it here. If
3166      we are router then this will send it to local clients and local
3167      servers. */
3168   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3169                                      SILC_NOTIFY_TYPE_JOIN, 2,
3170                                      clidp->data, clidp->len,
3171                                      chidp->data, chidp->len);
3172
3173   if (!cmd->pending) {
3174     /* Send JOIN notify packet to our primary router */
3175     if (!server->standalone)
3176       silc_server_send_notify_join(server, server->router->connection,
3177                                    server->server_type == SILC_ROUTER ?
3178                                    TRUE : FALSE, channel, client->id);
3179
3180     if (keyp)
3181       /* Distribute the channel key to all backup routers. */
3182       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3183                               keyp->data, keyp->len, FALSE, TRUE);
3184   }
3185
3186   silc_buffer_free(reply);
3187   silc_buffer_free(clidp);
3188   silc_buffer_free(chidp);
3189   silc_buffer_free(keyp);
3190   silc_buffer_free(user_list);
3191   silc_buffer_free(mode_list);
3192
3193  out:
3194   silc_free(passphrase);
3195 }
3196
3197 /* Server side of command JOIN. Joins client into requested channel. If 
3198    the channel does not exist it will be created. */
3199
3200 SILC_SERVER_CMD_FUNC(join)
3201 {
3202   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3203   SilcServer server = cmd->server;
3204   uint32 tmp_len;
3205   char *tmp, *channel_name = NULL, *cipher, *hmac;
3206   SilcChannelEntry channel;
3207   uint32 umode = 0;
3208   bool created = FALSE, create_key = TRUE;
3209   SilcClientID *client_id;
3210
3211   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3212
3213   /* Get channel name */
3214   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3215   if (!tmp) {
3216     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3217                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3218     goto out;
3219   }
3220   channel_name = tmp;
3221
3222   if (strlen(channel_name) > 256)
3223     channel_name[255] = '\0';
3224
3225   if (silc_server_command_bad_chars(channel_name) == TRUE) {
3226     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3227                                           SILC_STATUS_ERR_BAD_CHANNEL);
3228     goto out;
3229   }
3230
3231   /* Get Client ID of the client who is joining to the channel */
3232   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3233   if (!tmp) {
3234     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3235                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3236     goto out;
3237   }
3238   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3239   if (!client_id) {
3240     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3241                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3242     goto out;
3243   }
3244
3245   /* Get cipher and hmac name */
3246   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3247   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3248
3249   /* See if the channel exists */
3250   channel = silc_idlist_find_channel_by_name(server->local_list, 
3251                                              channel_name, NULL);
3252
3253   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3254     /* If this is coming from client the Client ID in the command packet must
3255        be same as the client's ID. */
3256     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3257       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3258       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3259         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3260                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3261         goto out;
3262       }
3263     }
3264
3265     if (!channel || channel->disabled) {
3266       /* Channel not found */
3267
3268       /* If we are standalone server we don't have a router, we just create 
3269          the channel by ourselves. */
3270       if (server->standalone) {
3271         channel = silc_server_create_new_channel(server, server->id, cipher, 
3272                                                  hmac, channel_name, TRUE);
3273         if (!channel) {
3274           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3275                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3276           goto out;
3277         }
3278         
3279         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3280         created = TRUE;
3281         create_key = FALSE;
3282         
3283       } else {
3284
3285         /* The channel does not exist on our server. If we are normal server 
3286            we will send JOIN command to our router which will handle the
3287            joining procedure (either creates the channel if it doesn't exist 
3288            or joins the client to it). */
3289         if (server->server_type != SILC_ROUTER) {
3290           SilcBuffer tmpbuf;
3291           uint16 old_ident;
3292
3293           /* If this is pending command callback then we've resolved
3294              it and it didn't work, return since we've notified the
3295              client already in the command reply callback. */
3296           if (cmd->pending)
3297             goto out;
3298           
3299           old_ident = silc_command_get_ident(cmd->payload);
3300           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3301           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3302           
3303           /* Send JOIN command to our router */
3304           silc_server_packet_send(server, (SilcSocketConnection)
3305                                   server->router->connection,
3306                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3307                                   tmpbuf->data, tmpbuf->len, TRUE);
3308           
3309           /* Reprocess this packet after received reply from router */
3310           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3311                                       silc_command_get_ident(cmd->payload),
3312                                       silc_server_command_destructor,
3313                                       silc_server_command_join,
3314                                       silc_server_command_dup(cmd));
3315           cmd->pending = TRUE;
3316           return;
3317         }
3318         
3319         /* We are router and the channel does not seem exist so we will check
3320            our global list as well for the channel. */
3321         channel = silc_idlist_find_channel_by_name(server->global_list, 
3322                                                    channel_name, NULL);
3323         if (!channel) {
3324           /* Channel really does not exist, create it */
3325           channel = silc_server_create_new_channel(server, server->id, cipher, 
3326                                                    hmac, channel_name, TRUE);
3327           if (!channel) {
3328             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3329                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3330             goto out;
3331           }
3332
3333           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3334           created = TRUE;
3335           create_key = FALSE;
3336         }
3337       }
3338     }
3339   } else {
3340     if (!channel) {
3341       /* Channel not found */
3342
3343       /* If the command came from router and we are normal server then
3344          something went wrong with the joining as the channel was not found.
3345          We can't do anything else but ignore this. */
3346       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3347           server->server_type != SILC_ROUTER)
3348         goto out;
3349       
3350       /* We are router and the channel does not seem exist so we will check
3351          our global list as well for the channel. */
3352       channel = silc_idlist_find_channel_by_name(server->global_list, 
3353                                                  channel_name, NULL);
3354       if (!channel) {
3355         /* Channel really does not exist, create it */
3356         channel = silc_server_create_new_channel(server, server->id, cipher, 
3357                                                  hmac, channel_name, TRUE);
3358         if (!channel) {
3359           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3360                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3361           goto out;
3362         }
3363
3364         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3365         created = TRUE;
3366         create_key = FALSE;
3367       }
3368     }
3369   }
3370
3371   /* Check whether the channel was created by our router */
3372   if (cmd->pending && context2) {
3373     SilcServerCommandReplyContext reply = 
3374       (SilcServerCommandReplyContext)context2;
3375     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3376       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3377       SILC_GET32_MSB(created, tmp);
3378       create_key = FALSE;       /* Router returned the key already */
3379     }
3380   }
3381
3382   /* If the channel does not have global users and is also empty the client
3383      will be the channel founder and operator. */
3384   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3385     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3386
3387   /* Join to the channel */
3388   silc_server_command_join_channel(server, cmd, channel, client_id,
3389                                    created, create_key, umode);
3390
3391   silc_free(client_id);
3392
3393  out:
3394   silc_server_command_free(cmd);
3395 }
3396
3397 /* Server side of command MOTD. Sends server's current "message of the
3398    day" to the client. */
3399
3400 SILC_SERVER_CMD_FUNC(motd)
3401 {
3402   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3403   SilcServer server = cmd->server;
3404   SilcBuffer packet, idp;
3405   char *motd, *dest_server;
3406   uint32 motd_len;
3407   uint16 ident = silc_command_get_ident(cmd->payload);
3408   
3409   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3410
3411   /* Get server name */
3412   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3413   if (!dest_server) {
3414     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3415                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3416     goto out;
3417   }
3418
3419   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3420     /* Send our MOTD */
3421
3422     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3423
3424     if (server->config && server->config->motd && 
3425         server->config->motd->motd_file) {
3426       /* Send motd */
3427       motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3428       if (!motd)
3429         goto out;
3430       
3431       motd[motd_len] = 0;
3432       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3433                                                     SILC_STATUS_OK, ident, 2,
3434                                                     2, idp, idp->len,
3435                                                     3, motd, motd_len);
3436       goto out;
3437     } else {
3438       /* No motd */
3439       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3440                                                     SILC_STATUS_OK, ident, 1,
3441                                                     2, idp, idp->len);
3442     }
3443
3444     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3445                             packet->data, packet->len, FALSE);
3446     silc_buffer_free(packet);
3447     silc_buffer_free(idp);
3448   } else {
3449     SilcServerEntry entry;
3450
3451     /* Check whether we have this server cached */
3452     entry = silc_idlist_find_server_by_name(server->global_list,
3453                                             dest_server, TRUE, NULL);
3454     if (!entry) {
3455       entry = silc_idlist_find_server_by_name(server->local_list,
3456                                               dest_server, TRUE, NULL);
3457     }
3458
3459     if (server->server_type != SILC_SERVER && !cmd->pending && 
3460         entry && !entry->motd) {
3461       /* Send to the server */
3462       SilcBuffer tmpbuf;
3463       uint16 old_ident;
3464
3465       old_ident = silc_command_get_ident(cmd->payload);
3466       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3467       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3468
3469       silc_server_packet_send(server, entry->connection,
3470                               SILC_PACKET_COMMAND, cmd->packet->flags,
3471                               tmpbuf->data, tmpbuf->len, TRUE);
3472
3473       /* Reprocess this packet after received reply from router */
3474       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3475                                   silc_command_get_ident(cmd->payload),
3476                                   silc_server_command_destructor,
3477                                   silc_server_command_motd,
3478                                   silc_server_command_dup(cmd));
3479       cmd->pending = TRUE;
3480       silc_command_set_ident(cmd->payload, old_ident);
3481       silc_buffer_free(tmpbuf);
3482       return;
3483     }
3484
3485     if (!entry && !cmd->pending && !server->standalone) {
3486       /* Send to the primary router */
3487       SilcBuffer tmpbuf;
3488       uint16 old_ident;
3489
3490       old_ident = silc_command_get_ident(cmd->payload);
3491       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3492       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3493
3494       silc_server_packet_send(server, server->router->connection,
3495                               SILC_PACKET_COMMAND, cmd->packet->flags,
3496                               tmpbuf->data, tmpbuf->len, TRUE);
3497
3498       /* Reprocess this packet after received reply from router */
3499       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3500                                   silc_command_get_ident(cmd->payload),
3501                                   silc_server_command_destructor,
3502                                   silc_server_command_motd,
3503                                   silc_server_command_dup(cmd));
3504       cmd->pending = TRUE;
3505       silc_command_set_ident(cmd->payload, old_ident);
3506       silc_buffer_free(tmpbuf);
3507       return;
3508     }
3509
3510     if (!entry) {
3511       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3512                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3513       goto out;
3514     }
3515
3516     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3517
3518     if (entry->motd)
3519       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3520                                                     SILC_STATUS_OK, ident, 2,
3521                                                     2, idp, idp->len,
3522                                                     3, entry->motd,
3523                                                     strlen(entry->motd));
3524     else
3525       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3526                                                     SILC_STATUS_OK, ident, 1,
3527                                                     2, idp, idp->len);
3528
3529     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3530                             packet->data, packet->len, FALSE);
3531     silc_buffer_free(packet);
3532     silc_buffer_free(idp);
3533   }
3534
3535  out:
3536   silc_server_command_free(cmd);
3537 }
3538
3539 /* Server side of command UMODE. Client can use this command to set/unset
3540    user mode. Client actually cannot set itself to be as server/router
3541    operator so this can be used only to unset the modes. */
3542
3543 SILC_SERVER_CMD_FUNC(umode)
3544 {
3545   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3546   SilcServer server = cmd->server;
3547   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3548   SilcBuffer packet;
3549   unsigned char *tmp_mask;
3550   uint32 mask;
3551   uint16 ident = silc_command_get_ident(cmd->payload);
3552
3553   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3554     goto out;
3555
3556   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3557
3558   /* Get the client's mode mask */
3559   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3560   if (!tmp_mask) {
3561     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3562                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3563     goto out;
3564   }
3565   SILC_GET32_MSB(mask, tmp_mask);
3566
3567   /* 
3568    * Change the mode 
3569    */
3570
3571   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3572     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3573       /* Cannot operator mode */
3574       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3575                                             SILC_STATUS_ERR_PERM_DENIED);
3576       goto out;
3577     }
3578   } else {
3579     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3580       /* Remove the server operator rights */
3581       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3582   }
3583
3584   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3585     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3586       /* Cannot operator mode */
3587       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3588                                             SILC_STATUS_ERR_PERM_DENIED);
3589       goto out;
3590     }
3591   } else {
3592     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3593       /* Remove the router operator rights */
3594       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3595   }
3596
3597   if (mask & SILC_UMODE_GONE) {
3598     client->mode |= SILC_UMODE_GONE;
3599   } else {
3600     if (client->mode & SILC_UMODE_GONE)
3601       /* Remove the gone status */
3602       client->mode &= ~SILC_UMODE_GONE;
3603   }
3604
3605   /* Send UMODE change to primary router */
3606   if (!server->standalone)
3607     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3608                                   client->id, client->mode);
3609
3610   /* Send command reply to sender */
3611   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3612                                                 SILC_STATUS_OK, ident, 1,
3613                                                 2, tmp_mask, 4);
3614   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3615                           packet->data, packet->len, FALSE);
3616   silc_buffer_free(packet);
3617
3618  out:
3619   silc_server_command_free(cmd);
3620 }
3621
3622 /* Checks that client has rights to add or remove channel modes. If any
3623    of the checks fails FALSE is returned. */
3624
3625 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3626                                    SilcChannelClientEntry client,
3627                                    uint32 mode)
3628 {
3629   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3630   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3631
3632   /* Check whether has rights to change anything */
3633   if (!is_op && !is_fo)
3634     return FALSE;
3635
3636   /* Check whether has rights to change everything */
3637   if (is_op && is_fo)
3638     return TRUE;
3639
3640   /* We know that client is channel operator, check that they are not
3641      changing anything that requires channel founder rights. Rest of the
3642      modes are available automatically for channel operator. */
3643
3644   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3645     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3646       if (is_op && !is_fo)
3647         return FALSE;
3648   } else {
3649     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3650       if (is_op && !is_fo)
3651         return FALSE;
3652     }
3653   }
3654   
3655   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3656     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3657       if (is_op && !is_fo)
3658         return FALSE;
3659   } else {
3660     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3661       if (is_op && !is_fo)
3662         return FALSE;
3663     }
3664   }
3665
3666   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3667     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3668       if (is_op && !is_fo)
3669         return FALSE;
3670   } else {
3671     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3672       if (is_op && !is_fo)
3673         return FALSE;
3674     }
3675   }
3676   
3677   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3678     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3679       if (is_op && !is_fo)
3680         return FALSE;
3681   } else {
3682     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3683       if (is_op && !is_fo)
3684         return FALSE;
3685     }
3686   }
3687   
3688   return TRUE;
3689 }
3690
3691 /* Server side command of CMODE. Changes channel mode */
3692
3693 SILC_SERVER_CMD_FUNC(cmode)
3694 {
3695   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3696   SilcServer server = cmd->server;
3697   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3698   SilcIDListData idata = (SilcIDListData)client;
3699   SilcChannelID *channel_id;
3700   SilcChannelEntry channel;
3701   SilcChannelClientEntry chl;
3702   SilcBuffer packet, cidp;
3703   unsigned char *tmp, *tmp_id, *tmp_mask;
3704   char *cipher = NULL, *hmac = NULL;
3705   uint32 mode_mask, tmp_len, tmp_len2;
3706   uint16 ident = silc_command_get_ident(cmd->payload);
3707
3708   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3709
3710   /* Get Channel ID */
3711   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3712   if (!tmp_id) {
3713     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3714                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3715     goto out;
3716   }
3717   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3718   if (!channel_id) {
3719     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3720                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3721     goto out;
3722   }
3723
3724   /* Get the channel mode mask */
3725   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3726   if (!tmp_mask) {
3727     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3728                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3729     goto out;
3730   }
3731   SILC_GET32_MSB(mode_mask, tmp_mask);
3732
3733   /* Get channel entry */
3734   channel = silc_idlist_find_channel_by_id(server->local_list, 
3735                                            channel_id, NULL);
3736   if (!channel) {
3737     channel = silc_idlist_find_channel_by_id(server->global_list, 
3738                                              channel_id, NULL);
3739     if (!channel) {
3740       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3741                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3742       goto out;
3743     }
3744   }
3745
3746   /* Check whether this client is on the channel */
3747   if (!silc_server_client_on_channel(client, channel)) {
3748     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3749                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3750     goto out;
3751   }
3752
3753   /* Get entry to the channel user list */
3754   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3755
3756   /* Check that client has rights to change any requested channel modes */
3757   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3758     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3759                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3760     goto out;
3761   }
3762
3763   /*
3764    * Check the modes. Modes that requires nothing special operation are
3765    * not checked here.
3766    */
3767
3768   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3769     /* Channel uses private keys to protect traffic. Client(s) has set the
3770        key locally they want to use, server does not know that key. */
3771     /* Nothing interesting to do here */
3772   } else {
3773     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3774       /* The mode is removed and we need to generate and distribute
3775          new channel key. Clients are not using private channel keys
3776          anymore after this. */
3777
3778       /* Re-generate channel key */
3779       if (!silc_server_create_channel_key(server, channel, 0))
3780         goto out;
3781       
3782       /* Send the channel key. This sends it to our local clients and if
3783          we are normal server to our router as well. */
3784       silc_server_send_channel_key(server, NULL, channel, 
3785                                    server->server_type == SILC_ROUTER ? 
3786                                    FALSE : !server->standalone);
3787
3788       cipher = channel->channel_key->cipher->name;
3789       hmac = (char *)silc_hmac_get_name(channel->hmac);
3790     }
3791   }
3792   
3793   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3794     /* User limit is set on channel */
3795     uint32 user_limit;
3796       
3797     /* Get user limit */
3798     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3799     if (!tmp) {
3800       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3801         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3802                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3803         goto out;
3804       }
3805     } else {
3806       SILC_GET32_MSB(user_limit, tmp);
3807       channel->user_limit = user_limit;
3808     }
3809   } else {
3810     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3811       /* User limit mode is unset. Remove user limit */
3812       channel->user_limit = 0;
3813   }
3814
3815   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3816     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3817       /* Passphrase has been set to channel */
3818       
3819       /* Get the passphrase */
3820       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3821       if (!tmp) {
3822         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3824         goto out;
3825       }
3826
3827       /* Save the passphrase */
3828       channel->passphrase = strdup(tmp);
3829     }
3830   } else {
3831     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832       /* Passphrase mode is unset. remove the passphrase */
3833       if (channel->passphrase) {
3834         silc_free(channel->passphrase);
3835         channel->passphrase = NULL;
3836       }
3837     }
3838   }
3839
3840   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3841     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3842       /* Cipher to use protect the traffic */
3843
3844       /* Get cipher */
3845       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3846       if (!cipher) {
3847         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3848                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3849         goto out;
3850       }
3851
3852       /* Delete old cipher and allocate the new one */
3853       silc_cipher_free(channel->channel_key);
3854       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3855         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3856                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3857         goto out;
3858       }
3859
3860       /* Re-generate channel key */
3861       if (!silc_server_create_channel_key(server, channel, 0))
3862         goto out;
3863     
3864       /* Send the channel key. This sends it to our local clients and if
3865          we are normal server to our router as well. */
3866       silc_server_send_channel_key(server, NULL, channel, 
3867                                    server->server_type == SILC_ROUTER ? 
3868                                    FALSE : !server->standalone);
3869     }
3870   } else {
3871     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3872       /* Cipher mode is unset. Remove the cipher and revert back to 
3873          default cipher */
3874       cipher = channel->cipher;
3875
3876       /* Delete old cipher and allocate default one */
3877       silc_cipher_free(channel->channel_key);
3878       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, 
3879                              &channel->channel_key)) {
3880         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3881                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3882         goto out;
3883       }
3884
3885       /* Re-generate channel key */
3886       if (!silc_server_create_channel_key(server, channel, 0))
3887         goto out;
3888       
3889       /* Send the channel key. This sends it to our local clients and if
3890          we are normal server to our router as well. */
3891       silc_server_send_channel_key(server, NULL, channel, 
3892                                    server->server_type == SILC_ROUTER ? 
3893                                    FALSE : !server->standalone);
3894     }
3895   }
3896
3897   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3898     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3899       /* HMAC to use protect the traffic */
3900       unsigned char hash[32];
3901
3902       /* Get hmac */
3903       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3904       if (!hmac) {
3905         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3906                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3907         goto out;
3908       }
3909
3910       /* Delete old hmac and allocate the new one */
3911       silc_hmac_free(channel->hmac);
3912       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3913         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3914                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3915         goto out;
3916       }
3917
3918       /* Set the HMAC key out of current channel key. The client must do
3919          this locally. */
3920       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3921                      channel->key_len / 8, 
3922                      hash);
3923       silc_hmac_set_key(channel->hmac, hash, 
3924                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3925       memset(hash, 0, sizeof(hash));
3926     }
3927   } else {
3928     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3929       /* Hmac mode is unset. Remove the hmac and revert back to 
3930          default hmac */
3931       unsigned char hash[32];
3932       hmac = channel->hmac_name;
3933
3934       /* Delete old hmac and allocate default one */
3935       silc_hmac_free(channel->hmac);
3936       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, 
3937                            &channel->hmac)) {
3938         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3939                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3940         goto out;
3941       }
3942
3943       /* Set the HMAC key out of current channel key. The client must do
3944          this locally. */
3945       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
3946                      channel->key_len / 8, 
3947                      hash);
3948       silc_hmac_set_key(channel->hmac, hash, 
3949                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3950       memset(hash, 0, sizeof(hash));
3951     }
3952   }
3953
3954   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3955     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3956       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3957         /* Set the founder authentication */
3958         SilcAuthPayload auth;
3959         
3960         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3961         if (!tmp) {
3962           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3964           goto out;
3965         }
3966
3967         auth = silc_auth_payload_parse(tmp, tmp_len);
3968         if (!auth) {
3969           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3970                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3971           goto out;
3972         }
3973
3974         /* Save the public key */
3975         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3976         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3977         silc_free(tmp);
3978         
3979         channel->founder_method = silc_auth_get_method(auth);
3980
3981         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3982           tmp = silc_auth_get_data(auth, &tmp_len);
3983           channel->founder_passwd = 
3984             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3985           memcpy(channel->founder_passwd, tmp, tmp_len);
3986           channel->founder_passwd_len = tmp_len;
3987         } else {
3988           /* Verify the payload before setting the mode */
3989           if (!silc_auth_verify(auth, channel->founder_method, 
3990                                 channel->founder_key, 0, idata->hash,
3991                                 client->id, SILC_ID_CLIENT)) {
3992             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3993                                                   SILC_STATUS_ERR_AUTH_FAILED);
3994             goto out;
3995           }
3996         }
3997
3998         silc_auth_payload_free(auth);
3999       }
4000     }
4001   } else {
4002     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4003       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4004         if (channel->founder_key)
4005           silc_pkcs_public_key_free(channel->founder_key);
4006         if (channel->founder_passwd) {
4007           silc_free(channel->founder_passwd);
4008           channel->founder_passwd = NULL;
4009         }
4010       }
4011     }
4012   }
4013
4014   /* Finally, set the mode */
4015   channel->mode = mode_mask;
4016
4017   /* Send CMODE_CHANGE notify */
4018   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4019   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4020                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4021                                      cidp->data, cidp->len, 
4022                                      tmp_mask, 4,
4023                                      cipher, cipher ? strlen(cipher) : 0,
4024                                      hmac, hmac ? strlen(hmac) : 0);
4025
4026   /* Set CMODE notify type to network */
4027   if (!server->standalone)
4028     silc_server_send_notify_cmode(server, server->router->connection,
4029                                   server->server_type == SILC_ROUTER ? 
4030                                   TRUE : FALSE, channel,
4031                                   mode_mask, client->id, SILC_ID_CLIENT,
4032                                   cipher, hmac);
4033
4034   /* Send command reply to sender */
4035   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4036                                                 SILC_STATUS_OK, ident, 2,
4037                                                 2, tmp_id, tmp_len2,
4038                                                 3, tmp_mask, 4);
4039   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4040                           packet->data, packet->len, FALSE);
4041     
4042   silc_buffer_free(packet);
4043   silc_free(channel_id);
4044   silc_free(cidp);
4045
4046  out:
4047   silc_server_command_free(cmd);
4048 }
4049
4050 /* Server side of CUMODE command. Changes client's mode on a channel. */
4051
4052 SILC_SERVER_CMD_FUNC(cumode)
4053 {
4054   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4055   SilcServer server = cmd->server;
4056   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4057   SilcIDListData idata = (SilcIDListData)client;
4058   SilcChannelID *channel_id;
4059   SilcClientID *client_id;
4060   SilcChannelEntry channel;
4061   SilcClientEntry target_client;
4062   SilcChannelClientEntry chl;
4063   SilcBuffer packet, idp;
4064   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4065   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4066   int notify = FALSE;
4067   uint16 ident = silc_command_get_ident(cmd->payload);
4068
4069   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4070
4071   /* Get Channel ID */
4072   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4073   if (!tmp_ch_id) {
4074     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4075                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4076     goto out;
4077   }
4078   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4079   if (!channel_id) {
4080     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4081                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4082     goto out;
4083   }
4084
4085   /* Get channel entry */
4086   channel = silc_idlist_find_channel_by_id(server->local_list, 
4087                                            channel_id, NULL);
4088   if (!channel) {
4089     channel = silc_idlist_find_channel_by_id(server->global_list, 
4090                                              channel_id, NULL);
4091     if (!channel) {
4092       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4093                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4094       goto out;
4095     }
4096   }
4097
4098   /* Check whether sender is on the channel */
4099   if (!silc_server_client_on_channel(client, channel)) {
4100     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4101                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4102     goto out;
4103   }
4104
4105   /* Check that client has rights to change other's rights */
4106   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4107   sender_mask = chl->mode;
4108   
4109   /* Get the target client's channel mode mask */
4110   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4111   if (!tmp_mask) {
4112     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4113                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4114     goto out;
4115   }
4116   SILC_GET32_MSB(target_mask, tmp_mask);
4117
4118   /* Get target Client ID */
4119   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4120   if (!tmp_id) {
4121     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4122                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4123     goto out;
4124   }
4125   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4126   if (!client_id) {
4127     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4128                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4129     goto out;
4130   }
4131
4132   /* Get target client's entry */
4133   target_client = silc_idlist_find_client_by_id(server->local_list, 
4134                                                 client_id, TRUE, NULL);
4135   if (!target_client) {
4136     target_client = silc_idlist_find_client_by_id(server->global_list, 
4137                                                   client_id, TRUE, NULL);
4138   }
4139
4140   if (target_client != client &&
4141       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4142       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4143     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4144                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4145     goto out;
4146   }
4147
4148   /* Check whether target client is on the channel */
4149   if (target_client != client) {
4150     if (!silc_server_client_on_channel(target_client, channel)) {
4151       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4152                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4153       goto out;
4154     }
4155
4156     /* Get entry to the channel user list */
4157     silc_hash_table_find(channel->user_list, target_client, NULL, 
4158                          (void *)&chl);
4159   }
4160
4161   /* 
4162    * Change the mode 
4163    */
4164
4165   /* If the target client is founder, no one else can change their mode
4166      but themselves. */
4167   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4168     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4169                                           SILC_STATUS_ERR_NOT_YOU);
4170     goto out;
4171   }
4172
4173   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4174     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4175       /* The client tries to claim the founder rights. */
4176       unsigned char *tmp_auth;
4177       uint32 tmp_auth_len, auth_len;
4178       void *auth;
4179       
4180       if (target_client != client) {
4181         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4182                                               SILC_STATUS_ERR_NOT_YOU);
4183         goto out;
4184       }
4185
4186       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4187           !channel->founder_key) {
4188         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4189                                               SILC_STATUS_ERR_NOT_YOU);
4190         goto out;
4191       }
4192
4193       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4194       if (!tmp_auth) {
4195         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4196                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4197         goto out;
4198       }
4199       
4200       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4201               (void *)channel->founder_passwd : (void *)channel->founder_key);
4202       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4203                   channel->founder_passwd_len : 0);
4204       
4205       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4206                                  channel->founder_method, auth, auth_len,
4207                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4208         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4209                                               SILC_STATUS_ERR_AUTH_FAILED);
4210         goto out;
4211       }
4212       
4213       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4214       notify = TRUE;
4215     }
4216   } else {
4217     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4218       if (target_client == client) {
4219         /* Remove channel founder rights from itself */
4220         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4221         notify = TRUE;
4222       } else {
4223         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224                                               SILC_STATUS_ERR_NOT_YOU);
4225         goto out;
4226       }
4227     }
4228   }
4229
4230   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4231     /* Promote to operator */
4232     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4233       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4234           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4235         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4237         goto out;
4238       }
4239
4240       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4241       notify = TRUE;
4242     }
4243   } else {
4244     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4245       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4246           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4247         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4248                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4249         goto out;
4250       }
4251
4252       /* Demote to normal user */
4253       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4254       notify = TRUE;
4255     }
4256   }
4257
4258   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4259   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4260
4261   /* Send notify to channel, notify only if mode was actually changed. */
4262   if (notify) {
4263     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4264                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4265                                        idp->data, idp->len,
4266                                        tmp_mask, 4, 
4267                                        tmp_id, tmp_len);
4268
4269     /* Set CUMODE notify type to network */
4270     if (!server->standalone)
4271       silc_server_send_notify_cumode(server, server->router->connection,
4272                                      server->server_type == SILC_ROUTER ? 
4273                                      TRUE : FALSE, channel,
4274                                      target_mask, client->id, 
4275                                      SILC_ID_CLIENT,
4276                                      target_client->id);
4277   }
4278
4279   /* Send command reply to sender */
4280   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4281                                                 SILC_STATUS_OK, ident, 3,
4282                                                 2, tmp_mask, 4,
4283                                                 3, tmp_ch_id, tmp_ch_len,
4284                                                 4, tmp_id, tmp_len);
4285   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4286                           packet->data, packet->len, FALSE);
4287     
4288   silc_buffer_free(packet);
4289   silc_free(channel_id);
4290   silc_free(client_id);
4291   silc_buffer_free(idp);
4292
4293  out:
4294   silc_server_command_free(cmd);
4295 }
4296
4297 /* Server side of KICK command. Kicks client out of channel. */
4298
4299 SILC_SERVER_CMD_FUNC(kick)
4300 {
4301   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4302   SilcServer server = cmd->server;
4303   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4304   SilcClientEntry target_client;
4305   SilcChannelID *channel_id;
4306   SilcClientID *client_id;
4307   SilcChannelEntry channel;
4308   SilcChannelClientEntry chl;
4309   SilcBuffer idp;
4310   uint32 tmp_len;
4311   unsigned char *tmp, *comment;
4312
4313   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4314
4315   /* Get Channel ID */
4316   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4317   if (!tmp) {
4318     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4319                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4320     goto out;
4321   }
4322   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4323   if (!channel_id) {
4324     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4325                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4326     goto out;
4327   }
4328
4329   /* Get channel entry */
4330   channel = silc_idlist_find_channel_by_id(server->local_list, 
4331                                            channel_id, NULL);
4332   if (!channel) {
4333     channel = silc_idlist_find_channel_by_id(server->local_list, 
4334                                              channel_id, NULL);
4335     if (!channel) {
4336       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4337                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4338       goto out;
4339     }
4340   }
4341
4342   /* Check whether sender is on the channel */
4343   if (!silc_server_client_on_channel(client, channel)) {
4344     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4345                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4346     goto out;
4347   }
4348
4349   /* Check that the kicker is channel operator or channel founder */
4350   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4351   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4352     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4353                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4354     goto out;
4355   }
4356   
4357   /* Get target Client ID */
4358   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4359   if (!tmp) {
4360     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4361                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4362     goto out;
4363   }
4364   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4365   if (!client_id) {
4366     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4367                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4368     goto out;
4369   }
4370
4371   /* Get target client's entry */
4372   target_client = silc_idlist_find_client_by_id(server->local_list, 
4373                                                 client_id, TRUE, NULL);
4374   if (!target_client) {
4375     target_client = silc_idlist_find_client_by_id(server->global_list, 
4376                                                   client_id, TRUE, NULL);
4377   }
4378
4379   /* Check that the target client is not channel founder. Channel founder
4380      cannot be kicked from the channel. */
4381   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4382   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4383     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4384                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4385     goto out;
4386   }
4387   
4388   /* Check whether target client is on the channel */
4389   if (!silc_server_client_on_channel(target_client, channel)) {
4390     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4391                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4392     goto out;
4393   }
4394
4395   /* Get comment */
4396   tmp_len = 0;
4397   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4398   if (tmp_len > 128)
4399     comment = NULL;
4400
4401   /* Send command reply to sender */
4402   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4403                                         SILC_STATUS_OK);
4404
4405   /* Send KICKED notify to local clients on the channel */
4406   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4407   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4408                                      SILC_NOTIFY_TYPE_KICKED, 
4409                                      comment ? 2 : 1,
4410                                      idp->data, idp->len,
4411                                      comment, comment ? strlen(comment) : 0);
4412   silc_buffer_free(idp);
4413
4414   /* Remove the client from the channel. If the channel does not exist
4415      after removing the client then the client kicked itself off the channel
4416      and we don't have to send anything after that. */
4417   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4418                                            target_client, FALSE))
4419     goto out;
4420
4421   /* Send KICKED notify to primary route */
4422   if (!server->standalone)
4423     silc_server_send_notify_kicked(server, server->router->connection,
4424                                    server->server_type == SILC_ROUTER ?
4425                                    TRUE : FALSE, channel,
4426                                    target_client->id, comment);
4427
4428   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4429     /* Re-generate channel key */
4430     if (!silc_server_create_channel_key(server, channel, 0))
4431       goto out;
4432     
4433     /* Send the channel key to the channel. The key of course is not sent
4434        to the client who was kicked off the channel. */
4435     silc_server_send_channel_key(server, target_client->connection, channel, 
4436                                  server->server_type == SILC_ROUTER ? 
4437                                  FALSE : !server->standalone);
4438   }
4439
4440  out:
4441   silc_server_command_free(cmd);
4442 }
4443
4444 /* Server side of OPER command. Client uses this comand to obtain server
4445    operator privileges to this server/router. */
4446
4447 SILC_SERVER_CMD_FUNC(oper)
4448 {
4449   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4450   SilcServer server = cmd->server;
4451   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4452   unsigned char *username, *auth;
4453   uint32 tmp_len;
4454   SilcServerConfigSectionAdminConnection *admin;
4455   SilcIDListData idata = (SilcIDListData)client;
4456
4457   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4458
4459   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4460     goto out;
4461
4462   /* Get the username */
4463   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4464   if (!username) {
4465     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4466                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4467     goto out;
4468   }
4469
4470   /* Get the admin configuration */
4471   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4472                                         username, client->nickname);
4473   if (!admin) {
4474     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4475                                           username, client->nickname);
4476     if (!admin) {
4477       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4478                                             SILC_STATUS_ERR_AUTH_FAILED);
4479       goto out;
4480     }
4481   }
4482
4483   /* Get the authentication payload */
4484   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4485   if (!auth) {
4486     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4487                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4488     goto out;
4489   }
4490
4491   /* Verify the authentication data */
4492   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4493                              admin->auth_data, admin->auth_data_len,
4494                              idata->hash, client->id, SILC_ID_CLIENT)) {
4495     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4496                                           SILC_STATUS_ERR_AUTH_FAILED);
4497     goto out;
4498   }
4499
4500   /* Client is now server operator */
4501   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4502
4503   /* Send UMODE change to primary router */
4504   if (!server->standalone)
4505     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4506                                   client->id, client->mode);
4507
4508   /* Send reply to the sender */
4509   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4510                                         SILC_STATUS_OK);
4511
4512  out:
4513   silc_server_command_free(cmd);
4514 }
4515
4516 /* Server side of SILCOPER command. Client uses this comand to obtain router
4517    operator privileges to this router. */
4518
4519 SILC_SERVER_CMD_FUNC(silcoper)
4520 {
4521   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4522   SilcServer server = cmd->server;
4523   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4524   unsigned char *username, *auth;
4525   uint32 tmp_len;
4526   SilcServerConfigSectionAdminConnection *admin;
4527   SilcIDListData idata = (SilcIDListData)client;
4528
4529   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4530
4531   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4532     goto out;
4533
4534   if (server->server_type != SILC_ROUTER) {
4535     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4536                                           SILC_STATUS_ERR_AUTH_FAILED);
4537     goto out;
4538   }
4539
4540   /* Get the username */
4541   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4542   if (!username) {
4543     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4544                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4545     goto out;
4546   }
4547
4548   /* Get the admin configuration */
4549   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4550                                         username, client->nickname);
4551   if (!admin) {
4552     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4553                                           username, client->nickname);
4554     if (!admin) {
4555       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4556                                             SILC_STATUS_ERR_AUTH_FAILED);
4557       goto out;
4558     }
4559   }
4560
4561   /* Get the authentication payload */
4562   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4563   if (!auth) {
4564     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4565                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4566     goto out;
4567   }
4568
4569   /* Verify the authentication data */
4570   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4571                              admin->auth_data, admin->auth_data_len,
4572                              idata->hash, client->id, SILC_ID_CLIENT)) {
4573     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4574                                           SILC_STATUS_ERR_AUTH_FAILED);
4575     goto out;
4576   }
4577
4578   /* Client is now router operator */
4579   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4580
4581   /* Send UMODE change to primary router */
4582   if (!server->standalone)
4583     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4584                                   client->id, client->mode);
4585
4586   /* Send reply to the sender */
4587   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4588                                         SILC_STATUS_OK);
4589
4590  out:
4591   silc_server_command_free(cmd);
4592 }
4593
4594 /* Server side command of CONNECT. Connects us to the specified remote
4595    server or router. */
4596
4597 SILC_SERVER_CMD_FUNC(connect)
4598 {
4599   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4600   SilcServer server = cmd->server;
4601   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4602   unsigned char *tmp, *host;
4603   uint32 tmp_len;
4604   uint32 port = SILC_PORT;
4605
4606   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4607
4608   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4609     goto out;
4610
4611   /* Check whether client has the permissions. */
4612   if (client->mode == SILC_UMODE_NONE) {
4613     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4614                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4615     goto out;
4616   }
4617
4618   if (server->server_type == SILC_ROUTER && 
4619       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4620     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4621                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4622     goto out;
4623   }
4624
4625   /* Get the remote server */
4626   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4627   if (!host) {
4628     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4629                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4630     goto out;
4631   }
4632
4633   /* Get port */
4634   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4635   if (tmp)
4636     SILC_GET32_MSB(port, tmp);
4637
4638   /* Create the connection. It is done with timeout and is async. */
4639   silc_server_create_connection(server, host, port);
4640
4641   /* Send reply to the sender */
4642   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4643                                         SILC_STATUS_OK);
4644
4645  out:
4646   silc_server_command_free(cmd);
4647 }
4648
4649 /* Server side of command BAN. This is used to manage the ban list of the
4650    channel. To add clients and remove clients from the ban list. */
4651
4652 SILC_SERVER_CMD_FUNC(ban)
4653 {
4654   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4655   SilcServer server = cmd->server;
4656   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4657   SilcBuffer packet;
4658   SilcChannelEntry channel;
4659   SilcChannelClientEntry chl;
4660   SilcChannelID *channel_id = NULL;
4661   unsigned char *id, *add, *del;
4662   uint32 id_len, tmp_len;
4663   uint16 ident = silc_command_get_ident(cmd->payload);
4664
4665   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4666     goto out;
4667
4668   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4669
4670   /* Get Channel ID */
4671   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4672   if (id) {
4673     channel_id = silc_id_payload_parse_id(id, id_len);
4674     if (!channel_id) {
4675       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4676                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4677       goto out;
4678     }
4679   }
4680
4681   /* Get channel entry. The server must know about the channel since the
4682      client is expected to be on the channel. */
4683   channel = silc_idlist_find_channel_by_id(server->local_list, 
4684                                            channel_id, NULL);
4685   if (!channel) {
4686     channel = silc_idlist_find_channel_by_id(server->global_list, 
4687                                              channel_id, NULL);
4688     if (!channel) {
4689       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4690                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4691       goto out;
4692     }
4693   }
4694
4695   /* Check whether this client is on the channel */
4696   if (!silc_server_client_on_channel(client, channel)) {
4697     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4698                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4699     goto out;
4700   }
4701
4702   /* Get entry to the channel user list */
4703   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4704
4705   /* The client must be at least channel operator. */
4706   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4707     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4708                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4709     goto out;
4710   }
4711
4712   /* Get the new ban and add it to the ban list */
4713   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4714   if (add) {
4715     if (!channel->ban_list)
4716       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4717     else
4718       channel->ban_list = silc_realloc(channel->ban_list, 
4719                                        sizeof(*channel->ban_list) * 
4720                                        (tmp_len + 
4721                                         strlen(channel->ban_list) + 2));
4722     if (add[tmp_len - 1] == ',')
4723       add[tmp_len - 1] = '\0';
4724
4725     strncat(channel->ban_list, add, tmp_len);
4726     strncat(channel->ban_list, ",", 1);
4727   }
4728
4729   /* Get the ban to be removed and remove it from the list */
4730   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4731   if (del && channel->ban_list) {
4732     char *start, *end, *n;
4733
4734     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4735       silc_free(channel->ban_list);
4736       channel->ban_list = NULL;
4737     } else {
4738       start = strstr(channel->ban_list, del);
4739       if (start && strlen(start) >= tmp_len) {
4740         end = start + tmp_len;
4741         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4742         strncat(n, channel->ban_list, start - channel->ban_list);
4743         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4744                              end) - 1);
4745         silc_free(channel->ban_list);
4746         channel->ban_list = n;
4747       }
4748     }
4749   }
4750
4751   /* Send the BAN notify type to our primary router. */
4752   if (!server->standalone && (add || del))
4753     silc_server_send_notify_ban(server, server->router->connection,
4754                                 server->server_type == SILC_ROUTER ?
4755                                 TRUE : FALSE, channel, add, del);
4756
4757   /* Send the reply back to the client */
4758   if (channel->ban_list)
4759     packet = 
4760       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4761                                            SILC_STATUS_OK, ident, 2,
4762                                            2, id, id_len,
4763                                            3, channel->ban_list, 
4764                                            strlen(channel->ban_list) - 1);
4765   else
4766     packet = 
4767       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4768                                            SILC_STATUS_OK, ident, 1,
4769                                            2, id, id_len);
4770
4771   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4772                           packet->data, packet->len, FALSE);
4773     
4774   silc_buffer_free(packet);
4775
4776  out:
4777   silc_free(channel_id);
4778   silc_server_command_free(cmd);
4779 }
4780
4781 /* Server side command of CLOSE. Closes connection to a specified server. */
4782  
4783 SILC_SERVER_CMD_FUNC(close)
4784 {
4785   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4786   SilcServer server = cmd->server;
4787   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4788   SilcServerEntry server_entry;
4789   SilcSocketConnection sock;
4790   unsigned char *tmp;
4791   uint32 tmp_len;
4792   unsigned char *name;
4793   uint32 port = SILC_PORT;
4794
4795   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4796
4797   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4798     goto out;
4799
4800   /* Check whether client has the permissions. */
4801   if (client->mode == SILC_UMODE_NONE) {
4802     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4803                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4804     goto out;
4805   }
4806
4807   /* Get the remote server */
4808   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4809   if (!name) {
4810     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4811                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4812     goto out;
4813   }
4814
4815   /* Get port */
4816   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4817   if (tmp)
4818     SILC_GET32_MSB(port, tmp);
4819
4820   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4821                                                  name, port, FALSE, NULL);
4822   if (!server_entry)
4823     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4824                                                    name, port, FALSE, NULL);
4825   if (!server_entry) {
4826     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4827                                           SILC_STATUS_ERR_NO_SERVER_ID);
4828     goto out;
4829   }
4830
4831   /* Send reply to the sender */
4832   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4833                                         SILC_STATUS_OK);
4834
4835   /* Close the connection to the server */
4836   sock = (SilcSocketConnection)server_entry->connection;
4837
4838   /* If we shutdown primary router connection manually then don't trigger
4839      any reconnect or backup router connections, by setting the router
4840      to NULL here. */
4841   if (server->router == server_entry) {
4842     server->id_entry->router = NULL;
4843     server->router = NULL;
4844     server->standalone = TRUE;
4845   }
4846   silc_server_free_sock_user_data(server, sock);
4847   silc_server_close_connection(server, sock);
4848   
4849  out:
4850   silc_server_command_free(cmd);
4851 }
4852
4853 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4854    active connections. */
4855  
4856 SILC_SERVER_CMD_FUNC(shutdown)
4857 {
4858   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4859   SilcServer server = cmd->server;
4860   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4861
4862   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4863
4864   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4865     goto out;
4866
4867   /* Check whether client has the permission. */
4868   if (client->mode == SILC_UMODE_NONE) {
4869     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4870                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4871     goto out;
4872   }
4873
4874   /* Send reply to the sender */
4875   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4876                                         SILC_STATUS_OK);
4877
4878   /* Then, gracefully, or not, bring the server down. */
4879   silc_server_stop(server);
4880   exit(0);
4881
4882  out:
4883   silc_server_command_free(cmd);
4884 }
4885  
4886 /* Server side command of LEAVE. Removes client from a channel. */
4887
4888 SILC_SERVER_CMD_FUNC(leave)
4889 {
4890   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4891   SilcServer server = cmd->server;
4892   SilcSocketConnection sock = cmd->sock;
4893   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4894   SilcChannelID *id = NULL;
4895   SilcChannelEntry channel;
4896   uint32 len;
4897   unsigned char *tmp;
4898
4899   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4900
4901   /* Get Channel ID */
4902   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4903   if (!tmp) {
4904     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4905                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4906     goto out;
4907   }
4908   id = silc_id_payload_parse_id(tmp, len);
4909   if (!id) {
4910     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4911                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4912     goto out;
4913   }
4914
4915   /* Get channel entry */
4916   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4917   if (!channel) {
4918     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4919     if (!channel) {
4920       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4921                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4922       goto out;
4923     }
4924   }
4925
4926   /* Check whether this client is on the channel */
4927   if (!silc_server_client_on_channel(id_entry, channel)) {
4928     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4929                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4930     goto out;
4931   }
4932
4933   /* Notify routers that they should remove this client from their list
4934      of clients on the channel. Send LEAVE notify type. */
4935   if (!server->standalone)
4936     silc_server_send_notify_leave(server, server->router->connection,
4937                                   server->server_type == SILC_ROUTER ?
4938                                   TRUE : FALSE, channel, id_entry->id);
4939
4940   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4941                                         SILC_STATUS_OK);
4942
4943   /* Remove client from channel */
4944   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4945                                            TRUE))
4946     /* If the channel does not exist anymore we won't send anything */
4947     goto out;
4948
4949   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4950     /* Re-generate channel key */
4951     if (!silc_server_create_channel_key(server, channel, 0))
4952       goto out;
4953
4954     /* Send the channel key */
4955     silc_server_send_channel_key(server, NULL, channel, 
4956                                  server->server_type == SILC_ROUTER ? 
4957                                  FALSE : !server->standalone);
4958   }
4959
4960  out:
4961   silc_free(id);
4962   silc_server_command_free(cmd);
4963 }
4964
4965 /* Server side of command USERS. Resolves clients and their USERS currently
4966    joined on the requested channel. The list of Client ID's and their modes
4967    on the channel is sent back. */
4968
4969 SILC_SERVER_CMD_FUNC(users)
4970 {
4971   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4972   SilcServer server = cmd->server;
4973   SilcChannelEntry channel;
4974   SilcChannelID *id = NULL;
4975   SilcBuffer packet, idp;
4976   unsigned char *channel_id;
4977   uint32 channel_id_len;
4978   SilcBuffer client_id_list;
4979   SilcBuffer client_mode_list;
4980   unsigned char lc[4];
4981   uint32 list_count = 0;
4982   uint16 ident = silc_command_get_ident(cmd->payload);
4983   char *channel_name;
4984
4985   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4986
4987   /* Get Channel ID */
4988   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4989
4990   /* Get channel name */
4991   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4992
4993   if (!channel_id && !channel_name) {
4994     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4995                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4996     goto out;
4997   }
4998
4999   if (channel_id) {
5000     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5001     if (!id) {
5002       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5003                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5004       goto out;
5005     }
5006   }
5007
5008   /* If we are server and we don't know about this channel we will send
5009      the command to our router. If we know about the channel then we also
5010      have the list of users already. */
5011   if (id)
5012     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5013   else
5014     channel = silc_idlist_find_channel_by_name(server->local_list, 
5015                                                channel_name, NULL);
5016
5017   if (!channel || channel->disabled) {
5018     if (server->server_type != SILC_ROUTER && !server->standalone &&
5019         !cmd->pending) {
5020       SilcBuffer tmpbuf;
5021       
5022       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5023       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5024       
5025       /* Send USERS command */
5026       silc_server_packet_send(server, server->router->connection,
5027                               SILC_PACKET_COMMAND, cmd->packet->flags,
5028                               tmpbuf->data, tmpbuf->len, TRUE);
5029       
5030       /* Reprocess this packet after received reply */
5031       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5032                                   silc_command_get_ident(cmd->payload),
5033                                   silc_server_command_destructor,
5034                                   silc_server_command_users,
5035                                   silc_server_command_dup(cmd));
5036       cmd->pending = TRUE;
5037       silc_command_set_ident(cmd->payload, ident);
5038       
5039       silc_buffer_free(tmpbuf);
5040       silc_free(id);
5041       return;
5042     }
5043
5044     /* Check the global list as well. */
5045     if (id)
5046       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5047     else
5048       channel = silc_idlist_find_channel_by_name(server->global_list, 
5049                                                  channel_name, NULL);
5050     if (!channel) {
5051       /* Channel really does not exist */
5052       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5053                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5054       goto out;
5055     }
5056   }
5057
5058   /* If the channel is private or secret do not send anything, unless the
5059      user requesting this command is on the channel. */
5060   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5061     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5062         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5063       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5064                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5065       goto out;
5066     }
5067   } else {
5068     if (channel->mode & 
5069         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5070       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5071                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5072       goto out;
5073     }
5074   }
5075
5076   /* Get the users list */
5077   silc_server_get_users_on_channel(server, channel, &client_id_list,
5078                                    &client_mode_list, &list_count);
5079
5080   /* List count */
5081   SILC_PUT32_MSB(list_count, lc);
5082
5083   /* Send reply */
5084   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5085   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5086                                                 SILC_STATUS_OK, ident, 4,
5087                                                 2, idp->data, idp->len,
5088                                                 3, lc, 4,
5089                                                 4, client_id_list->data,
5090                                                 client_id_list->len,
5091                                                 5, client_mode_list->data,
5092                                                 client_mode_list->len);
5093   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5094                           packet->data, packet->len, FALSE);
5095     
5096   silc_buffer_free(idp);
5097   silc_buffer_free(packet);
5098   silc_buffer_free(client_id_list);
5099   silc_buffer_free(client_mode_list);
5100   silc_free(id);
5101
5102  out:
5103   silc_server_command_free(cmd);
5104 }
5105
5106 /* Server side of command GETKEY. This fetches the client's public key
5107    from the server where to the client is connected. */
5108
5109 SILC_SERVER_CMD_FUNC(getkey)
5110 {
5111   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5112   SilcServer server = cmd->server;
5113   SilcBuffer packet;
5114   SilcClientEntry client;
5115   SilcServerEntry server_entry;
5116   SilcClientID *client_id = NULL;
5117   SilcServerID *server_id = NULL;
5118   SilcIDPayload idp = NULL;
5119   uint16 ident = silc_command_get_ident(cmd->payload);
5120   unsigned char *tmp, *pkdata;
5121   uint32 tmp_len, pklen;
5122   SilcBuffer pk = NULL;
5123   SilcIdType id_type;
5124
5125   SILC_LOG_DEBUG(("Start"));
5126
5127   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5128   if (!tmp) {
5129     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5130                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5131     goto out;
5132   }
5133   idp = silc_id_payload_parse_data(tmp, tmp_len);
5134   if (!idp) {
5135     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5136                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5137     goto out;
5138   }
5139
5140   id_type = silc_id_payload_get_type(idp);
5141   if (id_type == SILC_ID_CLIENT) {
5142     client_id = silc_id_payload_get_id(idp);
5143
5144     /* If the client is not found from local list there is no chance it
5145        would be locally connected client so send the command further. */
5146     client = silc_idlist_find_client_by_id(server->local_list, 
5147                                            client_id, TRUE, NULL);
5148     if (!client)
5149       client = silc_idlist_find_client_by_id(server->global_list, 
5150                                              client_id, TRUE, NULL);
5151     
5152     if ((!client && !cmd->pending && !server->standalone) ||
5153         (client && !client->connection && !cmd->pending) ||
5154         (client && !client->data.public_key && !cmd->pending)) {
5155       SilcBuffer tmpbuf;
5156       uint16 old_ident;
5157       SilcSocketConnection dest_sock;
5158       
5159       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5160                                                client_id, NULL);
5161       if (!dest_sock)
5162         goto out;
5163       
5164       old_ident = silc_command_get_ident(cmd->payload);
5165       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5166       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5167       
5168       silc_server_packet_send(server, dest_sock,
5169                               SILC_PACKET_COMMAND, cmd->packet->flags,
5170                               tmpbuf->data, tmpbuf->len, TRUE);
5171       
5172       /* Reprocess this packet after received reply from router */
5173       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5174                                   silc_command_get_ident(cmd->payload),
5175                                   silc_server_command_destructor,
5176                                   silc_server_command_getkey,
5177                                   silc_server_command_dup(cmd));
5178       cmd->pending = TRUE;
5179       
5180       silc_command_set_ident(cmd->payload, old_ident);
5181       silc_buffer_free(tmpbuf);
5182       return;
5183     }
5184
5185     if (!client) {
5186       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5187                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5188       goto out;
5189     }
5190
5191     /* The client is locally connected, just get the public key and
5192        send it back. If they key does not exist then do not send it, 
5193        send just OK reply */
5194     if (!client->data.public_key) {
5195       pkdata = NULL;
5196       pklen = 0;
5197     } else {
5198       tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5199       pk = silc_buffer_alloc(4 + tmp_len);
5200       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5201       silc_buffer_format(pk,
5202                          SILC_STR_UI_SHORT(tmp_len),
5203                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5204                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5205                          SILC_STR_END);
5206       silc_free(tmp);
5207       pkdata = pk->data;
5208       pklen = pk->len;
5209     }
5210   } else if (id_type == SILC_ID_SERVER) {
5211     server_id = silc_id_payload_get_id(idp);
5212
5213     /* If the server is not found from local list there is no chance it
5214        would be locally connected server so send the command further. */
5215     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5216                                                  server_id, TRUE, NULL);
5217     if (!server_entry)
5218       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5219                                                    server_id, TRUE, NULL);
5220     
5221     if (server_entry != server->id_entry &&
5222         ((!server_entry && !cmd->pending && !server->standalone) ||
5223          (server_entry && !server_entry->connection && !cmd->pending &&
5224           !server->standalone) ||
5225          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5226           !server->standalone))) {
5227       SilcBuffer tmpbuf;
5228       uint16 old_ident;
5229       
5230       old_ident = silc_command_get_ident(cmd->payload);
5231       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
5232       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5233       
5234       silc_server_packet_send(server, server->router->connection,
5235                               SILC_PACKET_COMMAND, cmd->packet->flags,
5236                               tmpbuf->data, tmpbuf->len, TRUE);
5237       
5238       /* Reprocess this packet after received reply from router */
5239       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5240                                   silc_command_get_ident(cmd->payload),
5241                                   silc_server_command_destructor,
5242                                   silc_server_command_getkey,
5243                                   silc_server_command_dup(cmd));
5244       cmd->pending = TRUE;
5245       
5246       silc_command_set_ident(cmd->payload, old_ident);
5247       silc_buffer_free(tmpbuf);
5248       return;
5249     }
5250
5251     if (!server_entry) {
5252       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5253                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5254       goto out;
5255     }
5256
5257     /* If they key does not exist then do not send it, send just OK reply */
5258     if (!server_entry->data.public_key) {
5259       pkdata = NULL;
5260       pklen = 0;
5261     } else {
5262       tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, 
5263                                         &tmp_len);
5264       pk = silc_buffer_alloc(4 + tmp_len);
5265       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5266       silc_buffer_format(pk,
5267                          SILC_STR_UI_SHORT(tmp_len),
5268                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5269                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5270                          SILC_STR_END);
5271       silc_free(tmp);
5272       pkdata = pk->data;
5273       pklen = pk->len;
5274     }
5275   } else {
5276     goto out;
5277   }
5278
5279   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5280   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5281                                                 SILC_STATUS_OK, ident, 
5282                                                 pkdata ? 2 : 1,
5283                                                 2, tmp, tmp_len,
5284                                                 3, pkdata, pklen);
5285   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5286                           packet->data, packet->len, FALSE);
5287   silc_buffer_free(packet);
5288
5289   if (pk)
5290     silc_buffer_free(pk);
5291
5292  out:
5293   if (idp)
5294     silc_id_payload_free(idp);
5295   silc_free(client_id);
5296   silc_free(server_id);
5297   silc_server_command_free(cmd);
5298 }