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