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