X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fcommand_reply.c;h=a72e6c206a8ccdef7d0f727f6fe7ec6fbbd94fba;hp=3696ec3accb78127416f2b8fa92c4f5eafaa4645;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=f82024f04b73e3b80ddd6c590699206d3dc5c1eb diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 3696ec3a..a72e6c20 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -52,6 +52,7 @@ SilcServerCommandReply silc_command_reply_list[] = SILC_SERVER_CMD_REPLY(users, USERS), SILC_SERVER_CMD_REPLY(getkey, GETKEY), SILC_SERVER_CMD_REPLY(list, LIST), + SILC_SERVER_CMD_REPLY(watch, WATCH), { NULL, 0 }, }; @@ -66,7 +67,6 @@ void silc_server_command_reply_process(SilcServer server, SilcServerCommandReplyContext ctx; SilcCommandPayload payload; SilcCommand command; - SilcUInt16 ident; SILC_LOG_DEBUG(("Start")); @@ -85,16 +85,22 @@ void silc_server_command_reply_process(SilcServer server, ctx->sock = silc_socket_dup(sock); ctx->payload = payload; ctx->args = silc_command_get_args(ctx->payload); - ident = silc_command_get_ident(ctx->payload); + ctx->ident = silc_command_get_ident(ctx->payload); + command = silc_command_get(ctx->payload); + + /* Client is not allowed to send reply to all commands */ + if (sock->type == SILC_SOCKET_TYPE_CLIENT && + command != SILC_COMMAND_WHOIS) { + silc_server_command_reply_free(ctx); + return; + } /* Check for pending commands and mark to be exeucted */ ctx->callbacks = - silc_server_command_pending_check(server, ctx, - silc_command_get(ctx->payload), - ident, &ctx->callbacks_count); + silc_server_command_pending_check(server, command, + ctx->ident, &ctx->callbacks_count); /* Execute command reply */ - command = silc_command_get(ctx->payload); for (cmd = silc_command_reply_list; cmd->cb; cmd++) if (cmd->cmd == command) break; @@ -142,7 +148,8 @@ silc_server_command_process_error(SilcServerCommandReplyContext cmd, client_id, FALSE, NULL); if (client) { silc_server_remove_from_channels(server, NULL, client, TRUE, - NULL, TRUE); + NULL, TRUE, FALSE); + silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } silc_free(client_id); @@ -209,8 +216,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) client = silc_idlist_add_client(server->global_list, nick, strdup(username), strdup(realname), client_id, - cmd->sock->user_data, NULL, - time(NULL) + 300); + cmd->sock->user_data, NULL, 0); if (!client) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); return FALSE; @@ -249,7 +255,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) /* Create new cache entry */ silc_idcache_add(global ? server->global_list->clients : server->local_list->clients, nick, client->id, - client, 0, &cache); + client, 0, NULL); silc_free(client_id); } @@ -267,16 +273,51 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL); } - if (cache) - /* If client is global and is not on any channel then add that we'll - expire the entry after a while. */ - if (global && !silc_hash_table_count(client->channels)) + /* If client is global and is not on any channel then add that we'll + expire the entry after a while. */ + if (global) { + silc_idlist_find_client_by_id(server->global_list, client->id, + FALSE, &cache); + if (!silc_hash_table_count(client->channels)) cache->expire = time(NULL) + 300; + else + cache->expire = 0; + } } if (fingerprint && flen == sizeof(client->data.fingerprint)) memcpy(client->data.fingerprint, fingerprint, flen); + /* Take Requested Attributes if set. */ + tmp = silc_argument_get_arg_type(cmd->args, 11, &len); + if (tmp) { + silc_free(client->attrs); + client->attrs = silc_memdup(tmp, len); + client->attrs_len = len; + } + + return TRUE; +} + +/* Handle requested attributes reply in WHOIS from client */ + +static char +silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd) +{ + unsigned char *tmp; + SilcUInt32 len; + SilcClientEntry client = cmd->sock->user_data; + + /* Take Requested Attributes if set. */ + tmp = silc_argument_get_arg_type(cmd->args, 11, &len); + if (tmp && client) { + silc_free(client->attrs); + client->attrs = silc_memdup(tmp, len); + client->attrs_len = len; + } + + client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; + return TRUE; } @@ -293,8 +334,13 @@ SILC_SERVER_CMD_REPLY_FUNC(whois) COMMAND_CHECK_STATUS; - if (!silc_server_command_reply_whois_save(cmd)) - goto out; + if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) { + if (!silc_server_command_reply_whois_save(cmd)) + goto out; + } else { + if (!silc_server_command_reply_whois_save_client(cmd)) + goto out; + } /* Pending callbacks are not executed if this was an list entry */ if (status != SILC_STATUS_OK && @@ -373,6 +419,8 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) return FALSE; } + client->data.status |= SILC_IDLIST_STATUS_RESOLVED; + client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; client->servername = servername; } else { @@ -383,10 +431,13 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) silc_free(client->nickname); silc_free(client->username); + silc_free(client->servername); client->nickname = nick; client->username = strdup(username); client->servername = servername; + client->data.status |= SILC_IDLIST_STATUS_RESOLVED; + client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; /* Remove the old cache entry and create a new one */ silc_idcache_del_by_context(global ? server->global_list->clients : @@ -396,6 +447,17 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd) client, 0, NULL); } + /* If client is global and is not on any channel then add that we'll + expire the entry after a while. */ + if (global) { + silc_idlist_find_client_by_id(server->global_list, client->id, + FALSE, &cache); + if (!silc_hash_table_count(client->channels)) + cache->expire = SILC_ID_CACHE_EXPIRE_DEF; + else + cache->expire = 0; + } + silc_free(client_id); return TRUE; @@ -422,8 +484,13 @@ SILC_SERVER_CMD_REPLY_FUNC(whowas) } out: + silc_server_command_process_error(cmd, error); SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS); + silc_server_command_reply_free(cmd); + return; + err: + silc_server_command_process_error(cmd, error); silc_server_command_reply_free(cmd); } @@ -490,8 +557,8 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) global. */ client = silc_idlist_add_client(server->global_list, nick, info ? strdup(info) : NULL, NULL, - client_id, cmd->sock->user_data, NULL, - time(NULL) + 300); + client_id, cmd->sock->user_data, + NULL, time(NULL) + 300); if (!client) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); goto error; @@ -525,18 +592,24 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING; if (name) { - /* If client is global and is not on any channel then add that we'll - expire the entry after a while. */ - if (global && !silc_hash_table_count(client->channels) && - server->server_type == SILC_SERVER) - expire = time(NULL) + 300; - /* Add new cache entry */ silc_idcache_add(global ? server->global_list->clients : server->local_list->clients, nick, client->id, client, expire, NULL); } + /* If client is global and is not on any channel then add that we'll + expire the entry after a while. */ + if (global && server->server_type == SILC_SERVER) { + SilcIDCacheEntry cache = NULL; + silc_idlist_find_client_by_id(server->global_list, client->id, + FALSE, &cache); + if (!silc_hash_table_count(client->channels)) + cache->expire = time(NULL) + 300; + else + cache->expire = 0; + } + silc_free(client_id); } @@ -566,7 +639,8 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) /* We don't have that server anywhere, add it. */ server_entry = silc_idlist_add_server(server->global_list, strdup(name), 0, - server_id, NULL, NULL); + server_id, server->router, + SILC_PRIMARY_ROUTE(server)); if (!server_entry) { silc_free(server_id); goto error; @@ -601,7 +675,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd) if (server->server_type != SILC_SERVER) goto error; - /* We don't have that server anywhere, add it. */ + /* We don't have that channel anywhere, add it. */ channel = silc_idlist_add_channel(server->global_list, strdup(name), SILC_CHANNEL_MODE_NONE, channel_id, server->router, NULL, NULL, 0); @@ -693,7 +767,8 @@ SILC_SERVER_CMD_REPLY_FUNC(info) /* Add the server to global list */ server_id = silc_id_dup(server_id, SILC_ID_SERVER); entry = silc_idlist_add_server(server->global_list, name, 0, - server_id, NULL, NULL); + server_id, cmd->sock->user_data, + cmd->sock); if (!entry) { silc_free(server_id); goto out; @@ -781,6 +856,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join) char *channel_name, *tmp; SilcUInt32 mode, created; SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL; + SilcPublicKey founder_key = NULL; COMMAND_CHECK_STATUS; @@ -860,6 +936,11 @@ SILC_SERVER_CMD_REPLY_FUNC(join) silc_buffer_pull_tail(client_mode_list, len); silc_buffer_put(client_mode_list, tmp, len); + /* Get founder key */ + tmp = silc_argument_get_arg_type(cmd->args, 15, &len); + if (tmp) + silc_pkcs_public_key_payload_decode(tmp, len, &founder_key); + /* See whether we already have the channel. */ entry = silc_idlist_find_channel_by_name(server->local_list, channel_name, &cache); @@ -885,7 +966,9 @@ SILC_SERVER_CMD_REPLY_FUNC(join) silc_free(id); goto out; } + hmac = NULL; server->stat.my_channels++; + server->stat.channels++; } else { /* The entry exists. */ @@ -903,23 +986,60 @@ SILC_SERVER_CMD_REPLY_FUNC(join) } } - if (entry->hmac_name && hmac) { + if (founder_key) { + if (entry->founder_key) + silc_pkcs_public_key_free(entry->founder_key); + entry->founder_key = founder_key; + founder_key = NULL; + } + + if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) { silc_free(entry->hmac_name); - entry->hmac_name = strdup(silc_hmac_get_name(hmac)); + entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac)); } /* Get the ban list */ tmp = silc_argument_get_arg_type(cmd->args, 8, &len); - if (tmp) { - silc_free(entry->ban_list); - entry->ban_list = silc_memdup(tmp, len); + if (tmp && len > 2) { + SilcArgumentPayload iargs; + SilcUInt16 iargc; + SILC_GET16_MSB(iargc, tmp); + iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc); + if (iargs) { + /* Delete old ban list */ + if (entry->ban_list) + silc_hash_table_free(entry->ban_list); + entry->ban_list = + silc_hash_table_alloc(0, silc_hash_ptr, + NULL, NULL, NULL, + silc_server_inviteban_destruct, entry, TRUE); + + /* Add new ban list */ + silc_server_inviteban_process(server, entry->ban_list, 0, iargs); + silc_argument_payload_free(iargs); + } } /* Get the invite list */ tmp = silc_argument_get_arg_type(cmd->args, 9, &len); - if (tmp) { - silc_free(entry->invite_list); - entry->invite_list = silc_memdup(tmp, len); + if (tmp && len > 2) { + SilcArgumentPayload iargs; + SilcUInt16 iargc; + SILC_GET16_MSB(iargc, tmp); + iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc); + if (iargs) { + /* Delete old invite list */ + if (entry->invite_list) + silc_hash_table_free(entry->invite_list); + entry->invite_list = + silc_hash_table_alloc(0, silc_hash_ptr, + NULL, NULL, NULL, + silc_server_inviteban_destruct, entry, TRUE); + + /* Add new invite list */ + silc_server_inviteban_process(server, entry->invite_list, 0, iargs); + silc_argument_payload_free(iargs); + } } /* Get the topic */ @@ -959,9 +1079,12 @@ SILC_SERVER_CMD_REPLY_FUNC(join) out: SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN); err: + if (hmac) + silc_hmac_free(hmac); silc_free(client_id); silc_server_command_reply_free(cmd); + silc_pkcs_public_key_free(founder_key); if (client_id_list) silc_buffer_free(client_id_list); if (client_mode_list) @@ -983,7 +1106,7 @@ SILC_SERVER_CMD_REPLY_FUNC(stats) /* Get statistics structure */ tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len); - if (server->server_type == SILC_SERVER && tmp) { + if (server->server_type != SILC_ROUTER && tmp) { silc_buffer_set(&buf, tmp, tmp_len); silc_buffer_unformat(&buf, SILC_STR_UI_INT(NULL), @@ -1046,7 +1169,7 @@ SILC_SERVER_CMD_REPLY_FUNC(users) goto out; idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL); - silc_server_send_command(server, server->router->connection, + silc_server_send_command(server, SILC_PRIMARY_ROUTE(server), SILC_COMMAND_IDENTIFY, ++server->cmd_ident, 1, 5, idp->data, idp->len); silc_buffer_free(idp); @@ -1112,10 +1235,8 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey) SilcServerEntry server_entry = NULL; SilcClientID *client_id = NULL; SilcServerID *server_id = NULL; - SilcSKEPKType type; - unsigned char *tmp, *pk; + unsigned char *tmp; SilcUInt32 len; - SilcUInt16 pk_len; SilcIDPayload idp = NULL; SilcIdType id_type; SilcPublicKey public_key = NULL; @@ -1134,16 +1255,8 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey) if (!tmp) goto out; - /* Decode the public key */ - - SILC_GET16_MSB(pk_len, tmp); - SILC_GET16_MSB(type, tmp + 2); - pk = tmp + 4; - - if (type != SILC_SKE_PK_TYPE_SILC) - goto out; - - if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key)) + /* Decode the public key payload */ + if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key)) goto out; id_type = silc_id_payload_get_type(idp);