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