X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fserver_query.c;h=59eda8024e40cb5d513ef8bc89656311bb9b7150;hb=805fddcf6431e784f9f77114782a90c9d12f9cbe;hp=f54145da589c2cd00c4601e13bc4d36101bde079;hpb=816a5b080c797c0db47b7b274a85646343c3466e;p=silc.git diff --git a/apps/silcd/server_query.c b/apps/silcd/server_query.c index f54145da..59eda802 100644 --- a/apps/silcd/server_query.c +++ b/apps/silcd/server_query.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2002 - 2005 Pekka Riikonen + Copyright (C) 2002 - 2005, 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ #include "server_internal.h" typedef struct { - SilcSocketConnection sock; /* Connection of this query */ + SilcPacketStream sock; /* Connection of this query */ unsigned char **arg; /* Query argument */ SilcUInt32 *arg_lens; /* Query argument lengths */ SilcUInt32 *arg_types; /* Query argument types */ @@ -51,8 +51,8 @@ typedef struct { /* Query session context */ typedef struct { /* Queried data */ - char *nickname; /* Queried nickname, normalized */ - char *nick_server; /* Queried nickname's server */ + char nickname[128 + 1]; /* Queried nickname, normalized */ + char nick_server[128 + 1]; /* Queried nickname's server */ char *server_name; /* Queried server name, normalized */ char *channel_name; /* Queried channel name, normalized */ SilcServerQueryID ids; /* Queried IDs */ @@ -61,6 +61,7 @@ typedef struct { SilcDList attrs; /* Requested Attributes in WHOIS */ /* Query session data */ + SilcPacketStream router; /* Router to send our query */ SilcServerCommandContext cmd; /* Command context for query */ SilcServerQueryList querylist; /* Temporary query list context */ SilcServerQueryID queries; /* Ongoing queries */ @@ -69,11 +70,16 @@ typedef struct { SilcUInt16 queries_count; /* Number of ongoing queries */ SilcUInt16 queries_left; /* Number of ongoing queries left */ SilcUInt16 errors_count; /* number of errors */ - unsigned int querycmd : 7; /* Query command (SilcCommand) */ - unsigned int resolved : 1; /* TRUE if normal server has resolved + unsigned int querycmd : 7; /* Query command (SilcCommand) */ + unsigned int resolved : 1; /* TRUE if normal server has resolved information from router */ + unsigned int dynamic_prim : 1; /* Dynamic connection attempt to primary */ + unsigned int dynamic_retry : 1; /* Primary returned error, send to + nick@serv server. */ + unsigned int parsed : 1; /* Set when query is parsed */ } *SilcServerQuery; + void silc_server_query_free(SilcServerQuery query); void silc_server_query_send_error(SilcServer server, SilcServerQuery query, @@ -89,11 +95,12 @@ void silc_server_query_add_error_id(SilcServer server, void *id, SilcIdType id_type); void silc_server_query_send_router(SilcServer server, SilcServerQuery query); void silc_server_query_send_router_reply(void *context, void *reply); -void silc_server_query_parse(SilcServer server, SilcServerQuery query); +SilcBool silc_server_query_parse(SilcServer server, SilcServerQuery query, + SilcBool parse_only); void silc_server_query_process(SilcServer server, SilcServerQuery query, - bool resolve); + SilcBool resolve); void silc_server_query_resolve(SilcServer server, SilcServerQuery query, - SilcSocketConnection sock, + SilcPacketStream sock, SilcClientEntry client_entry); void silc_server_query_resolve_reply(void *context, void *reply); void silc_server_query_send_reply(SilcServer server, @@ -120,8 +127,6 @@ void silc_server_query_free(SilcServerQuery query) silc_free(query->queries[i].id); silc_free(query->queries); - silc_free(query->nickname); - silc_free(query->nick_server); silc_free(query->server_name); silc_free(query->channel_name); @@ -222,16 +227,22 @@ void silc_server_query_add_error_id(SilcServer server, to the entity who sent this query to us automatically. Returns TRUE if the query is being processed or FALSE on error. */ -bool silc_server_query_command(SilcServer server, SilcCommand querycmd, - SilcServerCommandContext cmd) +SilcBool silc_server_query_command(SilcServer server, + SilcCommand querycmd, + SilcServerCommandContext cmd, + void *old_query) { SilcServerQuery query; SILC_LOG_DEBUG(("Query %s command", silc_get_command_name(querycmd))); - query = silc_calloc(1, sizeof(*query)); - query->querycmd = querycmd; - query->cmd = silc_server_command_dup(cmd); + if (!old_query) { + query = silc_calloc(1, sizeof(*query)); + query->querycmd = querycmd; + query->cmd = silc_server_command_dup(cmd); + query->router = SILC_PRIMARY_ROUTE(server); + } else + query = old_query; switch (querycmd) { @@ -245,6 +256,8 @@ bool silc_server_query_command(SilcServer server, SilcCommand querycmd, (!silc_argument_get_arg_type(cmd->args, 1, NULL) && !silc_argument_get_arg_type(cmd->args, 4, NULL) && silc_argument_get_arg_type(cmd->args, 3, NULL)))) { + if (!silc_server_query_parse(server, query, TRUE)) + return FALSE; silc_server_query_send_router(server, query); return TRUE; } @@ -266,6 +279,8 @@ bool silc_server_query_command(SilcServer server, SilcCommand querycmd, if (server->server_type == SILC_SERVER && !server->standalone && cmd->sock != SILC_PRIMARY_ROUTE(server) && !silc_argument_get_arg_type(cmd->args, 5, NULL)) { + if (!silc_server_query_parse(server, query, TRUE)) + return FALSE; silc_server_query_send_router(server, query); return TRUE; } @@ -278,11 +293,50 @@ bool silc_server_query_command(SilcServer server, SilcCommand querycmd, } /* Now parse the request */ - silc_server_query_parse(server, query); + silc_server_query_parse(server, query, FALSE); return TRUE; } +/* Remote server connected callback. */ + +void silc_server_query_connected(SilcServer server, + SilcServerEntry server_entry, + void *context) +{ + SilcServerQuery query = context; + + if (!server_entry) { + /* Connecting failed */ + SilcConnectionType type = (server->server_type == SILC_ROUTER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER); + + if (query->dynamic_prim /* && @serv != prim.host.name */ && + !silc_server_num_sockets_by_remote(server, query->nick_server, + query->nick_server, 706, type)) { + /* Connection attempt to primary router failed, now try to the one + specified in nick@server. */ + silc_server_create_connection(server, FALSE, TRUE, query->nick_server, + 706, silc_server_query_connected, + query); + query->dynamic_prim = FALSE; + return; + } + + /* Process the query after failed connect. This will send error back + because such nick was not found. */ + SILC_LOG_DEBUG(("Process query, connecting failed")); + silc_server_query_process(server, query, TRUE); + return; + } + + /* Reprocess the query */ + SILC_LOG_DEBUG(("Reprocess query after creating connection to %s", + server_entry->server_name)); + query->router = server_entry->data.sconn->sock; + silc_server_query_command(server, query->querycmd, query->cmd, query); +} + /* Send the received query to our primary router since we could not handle the query directly. We will reprocess the query after our router replies back. */ @@ -292,7 +346,8 @@ void silc_server_query_send_router(SilcServer server, SilcServerQuery query) SilcBuffer tmpbuf; SilcUInt16 old_ident; - SILC_LOG_DEBUG(("Forwarding the query to router for processing")); + SILC_LOG_DEBUG(("Forwarding the query to router %p for processing", + query->router)); /* Statistics */ server->stat.commands_sent++; @@ -301,10 +356,9 @@ void silc_server_query_send_router(SilcServer server, SilcServerQuery query) old_ident = silc_command_get_ident(query->cmd->payload); silc_command_set_ident(query->cmd->payload, ++server->cmd_ident); tmpbuf = silc_command_payload_encode_payload(query->cmd->payload); - silc_server_packet_send(server, - SILC_PRIMARY_ROUTE(server), + silc_server_packet_send(server, query->router, SILC_PACKET_COMMAND, 0, - tmpbuf->data, tmpbuf->len, TRUE); + tmpbuf->data, silc_buffer_len(tmpbuf)); silc_command_set_ident(query->cmd->payload, old_ident); silc_buffer_free(tmpbuf); @@ -327,7 +381,7 @@ void silc_server_query_send_router_reply(void *context, void *reply) SILC_LOG_DEBUG(("Received reply from router to query")); /* If the original command caller has gone away, just stop. */ - if (query->cmd->sock->users == 1) { + if (!silc_packet_stream_is_valid(query->cmd->sock)) { SILC_LOG_DEBUG(("Original command caller vanished")); silc_server_query_free(query); return; @@ -336,6 +390,23 @@ void silc_server_query_send_router_reply(void *context, void *reply) /* Check if router sent error reply */ if (cmdr && !silc_command_get_status(cmdr->payload, NULL, NULL)) { SilcBuffer buffer; + SilcConnectionType type = (server->server_type == SILC_ROUTER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER); + + /* If this was nick@server query, retry to @serv if the primary router + returned error. */ + if (query->nick_server[0] && !query->dynamic_retry && + !silc_server_num_sockets_by_remote(server, query->nick_server, + query->nick_server, 706, type)) { + SILC_LOG_DEBUG(("Retry query by connecting to %s:%d", + query->nick_server, 706)); + silc_server_create_connection(server, FALSE, TRUE, query->nick_server, + 706, silc_server_query_connected, + query); + query->dynamic_retry = TRUE; + query->resolved = FALSE; + return; + } SILC_LOG_DEBUG(("Sending error to original query")); @@ -349,30 +420,34 @@ void silc_server_query_send_router_reply(void *context, void *reply) buffer = silc_command_payload_encode_payload(cmdr->payload); silc_server_packet_send(server, query->cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, - buffer->data, buffer->len, FALSE); + buffer->data, silc_buffer_len(buffer)); silc_buffer_free(buffer); silc_server_query_free(query); return; } /* Continue with parsing */ - silc_server_query_parse(server, query); + silc_server_query_parse(server, query, FALSE); } /* Parse the command query and start processing the queries in detail. */ -void silc_server_query_parse(SilcServer server, SilcServerQuery query) +SilcBool silc_server_query_parse(SilcServer server, SilcServerQuery query, + SilcBool parse_only) { SilcServerCommandContext cmd = query->cmd; + SilcIDListData idata = silc_packet_get_context(cmd->sock); unsigned char *tmp; SilcUInt32 tmp_len, argc = silc_argument_get_arg_num(cmd->args); - void *id; - SilcIdType id_type; + SilcID id; int i; SILC_LOG_DEBUG(("Parsing %s query", silc_get_command_name(query->querycmd))); + if (query->parsed) + goto parsed; + switch (query->querycmd) { case SILC_COMMAND_WHOIS: @@ -384,9 +459,8 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) /* When Requested Attributes is present we will assure that this client cannot execute the WHOIS command too fast. This would be same as having SILC_CF_LAG_STRICT. */ - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && - cmd->sock->user_data) - ((SilcClientEntry)cmd->sock->user_data)->fast_command = 6; + if (idata && idata->conn_type == SILC_CONN_CLIENT) + ((SilcClientEntry)idata)->fast_command = 6; } /* Get Client IDs if present. Take IDs always instead of nickname. */ @@ -400,16 +474,19 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0); silc_server_query_free(query); - return; + return FALSE; } /* Get the nickname@server string and parse it */ if (tmp && ((tmp_len > 128) || - !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server))) { + !silc_parse_userfqdn(tmp, query->nickname, + sizeof(query->nickname), + query->nick_server, + sizeof(query->nick_server)))) { silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); - return; + return FALSE; } /* Check nickname */ @@ -420,10 +497,11 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); - return; + return FALSE; } - silc_free(query->nickname); - query->nickname = tmp; + memset(query->nickname, 0, sizeof(query->nickname)); + silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp); + silc_free(tmp); } } else { @@ -435,8 +513,8 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) if (!tmp) continue; - id = silc_id_payload_parse_id(tmp, tmp_len, &id_type); - if (!id || id_type != SILC_ID_CLIENT) { + if (!silc_id_payload_parse_id(tmp, tmp_len, &id) || + id.type != SILC_ID_CLIENT) { silc_server_query_add_error(server, query, 1, i + 4, SILC_STATUS_ERR_BAD_CLIENT_ID); continue; @@ -446,23 +524,23 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) send the query to router, unless done so already */ if (server->server_type == SILC_SERVER && !query->resolved) { if (!silc_idlist_find_client_by_id(server->local_list, - id, TRUE, NULL)) { - if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || + &id.u.client_id, TRUE, NULL)) { + if (idata->conn_type != SILC_CONN_CLIENT || !silc_idlist_find_client_by_id(server->global_list, - id, TRUE, NULL)) { + &id.u.client_id, TRUE, NULL)) { silc_server_query_send_router(server, query); for (i = 0; i < query->ids_count; i++) silc_free(query->ids[i].id); silc_free(query->ids); query->ids = NULL; query->ids_count = 0; - silc_free(id); - return; + return FALSE; } } } - query->ids[query->ids_count].id = id; + query->ids[query->ids_count].id = silc_id_dup(&id.u.client_id, + SILC_ID_CLIENT); query->ids[query->ids_count].id_type = SILC_ID_CLIENT; query->ids_count++; } @@ -481,16 +559,17 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0); silc_server_query_free(query); - return; + return FALSE; } /* Get the nickname@server string and parse it */ if (tmp_len > 128 || - !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server)) { + !silc_parse_userfqdn(tmp, query->nickname, sizeof(query->nickname), + query->nick_server, sizeof(query->nick_server))) { silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); - return; + return FALSE; } /* Check nickname */ @@ -500,10 +579,11 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); - return; + return FALSE; } - silc_free(query->nickname); - query->nickname = tmp; + memset(query->nickname, 0, sizeof(query->nickname)); + silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp); + silc_free(tmp); /* Get the max count of reply messages allowed */ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); @@ -521,7 +601,10 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) if (tmp) { /* Get the nickname@server string and parse it */ if (tmp_len > 128 || - !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server)) + !silc_parse_userfqdn(tmp, query->nickname, + sizeof(query->nickname), + query->nick_server, + sizeof(query->nick_server))) silc_server_query_add_error(server, query, 1, 1, SILC_STATUS_ERR_BAD_NICKNAME); @@ -532,10 +615,11 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_NICKNAME, 0); silc_server_query_free(query); - return; + return FALSE; } - silc_free(query->nickname); - query->nickname = tmp; + memset(query->nickname, 0, sizeof(query->nickname)); + silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp); + silc_free(tmp); } /* Try get server name */ @@ -548,7 +632,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_SERVER, 0); silc_server_query_free(query); - return; + return FALSE; } query->server_name = tmp; } @@ -563,16 +647,16 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_server_query_send_error(server, query, SILC_STATUS_ERR_BAD_CHANNEL, 0); silc_server_query_free(query); - return; + return FALSE; } query->channel_name = tmp; } - if (!query->nickname && !query->server_name && !query->channel_name) { + if (!query->nickname[0] && !query->server_name && !query->channel_name) { silc_server_query_send_error(server, query, SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0); silc_server_query_free(query); - return; + return FALSE; } } else { @@ -584,8 +668,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) if (!tmp) continue; - id = silc_id_payload_parse_id(tmp, tmp_len, &id_type); - if (!id) { + if (!silc_id_payload_parse_id(tmp, tmp_len, &id)) { silc_server_query_add_error(server, query, 1, i + 5, SILC_STATUS_ERR_BAD_CLIENT_ID); continue; @@ -594,20 +677,20 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) /* Normal server must check whether this ID exist, and if not then send the query to router, unless done so already */ if (server->server_type == SILC_SERVER && !query->resolved) { - if (id_type == SILC_ID_CLIENT) { + if (id.type == SILC_ID_CLIENT) { if (!silc_idlist_find_client_by_id(server->local_list, - id, TRUE, NULL)) { - if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || + &id.u.client_id, TRUE, NULL)) { + if (idata->conn_type != SILC_CONN_CLIENT || !silc_idlist_find_client_by_id(server->global_list, - id, TRUE, NULL)) { + &id.u.client_id, TRUE, + NULL)) { silc_server_query_send_router(server, query); for (i = 0; i < query->ids_count; i++) silc_free(query->ids[i].id); silc_free(query->ids); query->ids = NULL; query->ids_count = 0; - silc_free(id); - return; + return FALSE; } } } else { @@ -619,13 +702,20 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) silc_free(query->ids); query->ids = NULL; query->ids_count = 0; - silc_free(id); - return; + return FALSE; } } - query->ids[query->ids_count].id = id; - query->ids[query->ids_count].id_type = id_type; + if (id.type == SILC_ID_CLIENT) + query->ids[query->ids_count].id = silc_id_dup(&id.u.client_id, + SILC_ID_CLIENT); + if (id.type == SILC_ID_SERVER) + query->ids[query->ids_count].id = silc_id_dup(&id.u.server_id, + SILC_ID_SERVER); + if (id.type == SILC_ID_CHANNEL) + query->ids[query->ids_count].id = silc_id_dup(&id.u.channel_id, + SILC_ID_CHANNEL); + query->ids[query->ids_count].id_type = id.type; query->ids_count++; } } @@ -637,33 +727,89 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query) break; } + query->parsed = TRUE; + + parsed: + if (!parse_only && query->nickname) { + switch (query->querycmd) { + case SILC_COMMAND_WHOIS: + case SILC_COMMAND_IDENTIFY: + /* Check server name. If we are open server and don't yet have + connection to remote router, create it now. */ + if (query->nick_server[0] && server->config->dynamic_server && + !query->resolved) { + /* If primary router is specified, use that. Otherwise connect + to the server in nick@server string. */ + SilcServerConfigRouter *router; + SilcConnectionType type = (server->server_type == SILC_ROUTER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER); + + router = silc_server_config_get_primary_router(server); + if (router && server->standalone) { + /* Create connection to primary router */ + SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d", + router->host, router->port)); + query->dynamic_prim = TRUE; + silc_server_create_connection(server, FALSE, TRUE, + router->host, router->port, + silc_server_query_connected, query); + return FALSE; + } else if (!silc_server_num_sockets_by_remote(server, + query->nick_server, + query->nick_server, + 706, type)) { + /* Create connection and handle the query after connection */ + SILC_LOG_DEBUG(("Create dynamic connection to %s:%d", + query->nick_server, 706)); + silc_server_create_connection(server, FALSE, TRUE, + query->nick_server, 706, + silc_server_query_connected, query); + return FALSE; + } + } + } + } + /* Start processing the query information */ - silc_server_query_process(server, query, TRUE); + if (!parse_only) + silc_server_query_process(server, query, TRUE); + + return TRUE; } /* Context for holding clients searched by public key. */ typedef struct { SilcClientEntry **clients; SilcUInt32 *clients_count; - bool found; + SilcBool found; } *SilcServerPublicKeyUser, SilcServerPublicKeyUserStruct; -void silc_server_public_key_hash_foreach(void *key, void *context, - void *user_context) +/* SKR find callbcak */ + +static void silc_server_query_skr_callback(SilcSKR skr, + SilcSKRFind find, + SilcSKRStatus status, + SilcDList keys, + void *context) { - SilcServerPublicKeyUser uc = user_context; - SilcClientEntry entry = context; + SilcServerPublicKeyUser uc = context; + SilcSKRKey key; - /* Nothing was found, just return */ - if (!context) - return; + if (keys) { + (*uc->clients) = silc_realloc((*uc->clients), + sizeof((**uc->clients)) * + ((*uc->clients_count) + + silc_dlist_count(keys))); - uc->found = TRUE; + silc_dlist_start(keys); + while ((key = silc_dlist_get(keys))) + (*uc->clients)[(*uc->clients_count)++] = key->key_context; - (*uc->clients) = silc_realloc((*uc->clients), - sizeof((**uc->clients)) * - ((*uc->clients_count) + 1)); - (*uc->clients)[(*uc->clients_count)++] = entry; + uc->found = TRUE; + silc_dlist_uninit(keys); + } + + silc_skr_find_free(find); } /* If clients are set, limit the found clients using the attributes in @@ -678,15 +824,16 @@ void silc_server_query_check_attributes(SilcServer server, SilcAttributePayload attr; SilcAttribute attribute; SilcAttributeObjPk pk; - SilcPublicKey publickey; + SilcPublicKey publickey, cmp_pubkey; + SilcPKCSType type; + SilcBool found = FALSE, no_clients = FALSE, search_pubkey = FALSE; int i; - bool found = FALSE, no_clients = FALSE; /* If no clients were found, we only check the attributes if the user wasn't searching for nickname/ids */ if (!(*clients)) { no_clients = TRUE; - if (query->nickname || query->ids_count) + if (query->nickname[0] || query->ids_count) return; } @@ -701,26 +848,43 @@ void silc_server_query_check_attributes(SilcServer server, if (!silc_attribute_get_object(attr, &pk, sizeof(pk))) continue; - if (!silc_pkcs_public_key_decode(pk.data, pk.data_len, - &publickey)) { + if (!strcmp(pk.type, "silc-rsa")) + type = SILC_PKCS_SILC; + else if (!strcmp(pk.type, "ssh-rsa")) + type = SILC_PKCS_SSH2; + else if (!strcmp(pk.type, "x509v3-sign-rsa")) + type = SILC_PKCS_X509V3; + else if (!strcmp(pk.type, "pgp-sign-rsa")) + type = SILC_PKCS_OPENPGP; + else + continue; + + if (!silc_pkcs_public_key_alloc(type, pk.data, pk.data_len, + &publickey)) { silc_free(pk.type); silc_free(pk.data); continue; } + search_pubkey = TRUE; - /* If no clients were set on calling this function, we - just search for clients, otherwise we try to limit - the clients */ + /* If no clients were set on calling this function, we just search + for clients, otherwise we try to limit the clients. */ if (no_clients) { SilcServerPublicKeyUserStruct usercontext; + SilcSKRFind find; usercontext.clients = clients; usercontext.clients_count = clients_count; usercontext.found = FALSE; - silc_hash_table_find_foreach(server->pk_hash, publickey, - silc_server_public_key_hash_foreach, - &usercontext); + find = silc_skr_find_alloc(); + if (!find) + continue; + + silc_skr_find_set_public_key(find, publickey); + silc_skr_find_set_usage(find, SILC_SKR_USAGE_IDENTIFICATION); + silc_skr_find(server->repository, server->schedule, + find, silc_server_query_skr_callback, &usercontext); if (usercontext.found == TRUE) found = TRUE; @@ -731,11 +895,15 @@ void silc_server_query_check_attributes(SilcServer server, if (!entry->data.public_key) continue; - if (!silc_hash_table_find_by_context(server->pk_hash, publickey, - entry, NULL)) - (*clients)[i] = NULL; - else - found = TRUE; + if (silc_server_get_public_key_by_client(server, entry, + &cmp_pubkey)) { + if (silc_pkcs_public_key_compare(cmp_pubkey, publickey)) { + found = TRUE; + continue; + } + } + + (*clients)[i] = NULL; } } silc_free(pk.type); @@ -745,9 +913,11 @@ void silc_server_query_check_attributes(SilcServer server, } } - if (!found && !query->nickname && !query->ids) + if (!found && !query->nickname[0] && !query->ids) silc_server_query_add_error(server, query, 2, 0, - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + search_pubkey ? + SILC_STATUS_ERR_NO_SUCH_PUBLIC_KEY : + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); } /* Processes the parsed query. This does the actual finding of the @@ -755,10 +925,11 @@ void silc_server_query_check_attributes(SilcServer server, sender of the query command. */ void silc_server_query_process(SilcServer server, SilcServerQuery query, - bool resolve) + SilcBool resolve) { SilcServerCommandContext cmd = query->cmd; - bool check_global = FALSE; + SilcIDListData idata = silc_packet_get_context(cmd->sock); + SilcBool check_global = FALSE; void *entry; SilcClientEntry *clients = NULL, client_entry; SilcChannelEntry *channels = NULL; @@ -771,29 +942,37 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query, /* Check global lists if query is coming from client or we are not normal server (we know global information). */ - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) + if (idata->conn_type == SILC_CONN_CLIENT) check_global = TRUE; else if (server->server_type != SILC_SERVER) check_global = TRUE; - if (query->nickname) { + if (query->nickname[0]) { /* Get all clients matching nickname from local list */ if (!silc_idlist_get_clients_by_hash(server->local_list, - query->nickname, server->md5hash, + query->nickname, + query->nick_server[0] ? + query->nick_server : NULL, + server->md5hash, &clients, &clients_count)) silc_idlist_get_clients_by_nickname(server->local_list, query->nickname, - query->nick_server, + query->nick_server[0] ? + query->nick_server : NULL, &clients, &clients_count); /* Check global list as well */ if (check_global) { if (!silc_idlist_get_clients_by_hash(server->global_list, - query->nickname, server->md5hash, + query->nickname, + query->nick_server[0] ? + query->nick_server : NULL, + server->md5hash, &clients, &clients_count)) silc_idlist_get_clients_by_nickname(server->global_list, query->nickname, - query->nick_server, + query->nick_server[0] ? + query->nick_server : NULL, &clients, &clients_count); } @@ -1064,7 +1243,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query, client entry calls this function to do the resolving. */ void silc_server_query_resolve(SilcServer server, SilcServerQuery query, - SilcSocketConnection sock, + SilcPacketStream sock, SilcClientEntry client_entry) { SilcServerCommandContext cmd = query->cmd; @@ -1116,7 +1295,7 @@ void silc_server_query_resolve(SilcServer server, SilcServerQuery query, r->argc, r->arg, r->arg_lens, r->arg_types, r->ident); silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND, 0, - res_cmd->data, res_cmd->len, FALSE); + res_cmd->data, silc_buffer_len(res_cmd)); silc_buffer_free(res_cmd); /* Reprocess this packet after received reply */ @@ -1187,8 +1366,8 @@ void silc_server_query_resolve(SilcServer server, SilcServerQuery query, /* Add the client entry to be resolved */ idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT); - r->arg[r->argc] = silc_memdup(idp->data, idp->len); - r->arg_lens[r->argc] = idp->len; + r->arg[r->argc] = silc_memdup(idp->data, silc_buffer_len(idp)); + r->arg_lens[r->argc] = silc_buffer_len(idp); r->arg_types[r->argc] = r->argc + 4; r->argc++; silc_buffer_free(idp); @@ -1300,7 +1479,7 @@ void silc_server_query_resolve_reply(void *context, void *reply) SILC_LOG_DEBUG(("Reprocess the query")); /* If the original command caller has gone away, just stop. */ - if (query->cmd->sock->users == 1) { + if (!silc_packet_stream_is_valid(query->cmd->sock)) { SILC_LOG_DEBUG(("Original command caller vanished")); silc_server_query_free(query); return; @@ -1333,14 +1512,16 @@ void silc_server_query_send_reply(SilcServer server, SilcUInt32 channels_count) { SilcServerCommandContext cmd = query->cmd; + SilcIDListData idata = silc_packet_get_context(cmd->sock); SilcUInt16 ident = silc_command_get_ident(cmd->payload); SilcStatus status; unsigned char *tmp; + char *tmp2; SilcUInt32 len; SilcBuffer idp; int i, k, valid_count; char nh[384], uh[384]; - bool sent_reply = FALSE; + SilcBool sent_reply = FALSE; SILC_LOG_DEBUG(("Sending reply to query")); SILC_LOG_DEBUG(("Sending %d clients", clients_count)); @@ -1353,7 +1534,7 @@ void silc_server_query_send_reply(SilcServer server, /* Send clients */ if (clients_count) { SilcClientEntry entry; - SilcSocketConnection hsock; + SilcPacketStream hsock; /* Mark all invalid entries */ for (i = 0, valid_count = 0; i < clients_count; i++) { @@ -1461,11 +1642,12 @@ void silc_server_query_send_reply(SilcServer server, if (!strchr(entry->username, '@') && entry->connection) { hsock = entry->connection; silc_strncat(uh, sizeof(uh), "@", 1); - len = strlen(hsock->hostname); - silc_strncat(uh, sizeof(uh), hsock->hostname, len); + silc_socket_stream_get_info(silc_packet_stream_get_stream(hsock), + NULL, (const char **)&tmp2, NULL, NULL); + silc_strncat(uh, sizeof(uh), tmp2, strlen(tmp2)); } - if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) + if (idata->conn_type == SILC_CONN_CLIENT) channels = silc_server_get_client_channel_list(server, entry, FALSE, FALSE, &umode_list); @@ -1500,19 +1682,21 @@ void silc_server_query_send_reply(SilcServer server, /* Send command reply */ silc_server_send_command_reply(server, cmd->sock, query->querycmd, status, 0, ident, 10, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, nh, strlen(nh), 4, uh, strlen(uh), 5, entry->userinfo, strlen(entry->userinfo), 6, channels ? channels->data : NULL, - channels ? channels->len : 0, + channels ? silc_buffer_len(channels) + : 0, 7, mode, 4, 8, idle, 4, 9, fingerprint, fingerprint ? 20 : 0, 10, umode_list ? umode_list->data : - NULL, umode_list ? umode_list->len : + NULL, umode_list ? + silc_buffer_len(umode_list) : 0, 11, attrs, len); sent_reply = TRUE; @@ -1539,22 +1723,25 @@ void silc_server_query_send_reply(SilcServer server, if (!entry->username) { silc_server_send_command_reply(server, cmd->sock, query->querycmd, status, 0, ident, 2, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, nh, strlen(nh)); sent_reply = TRUE; } else { + memset(uh, 0, sizeof(uh)); silc_strncat(uh, sizeof(uh), entry->username, strlen(entry->username)); if (!strchr(entry->username, '@') && entry->connection) { hsock = entry->connection; silc_strncat(uh, sizeof(uh), "@", 1); - len = strlen(hsock->hostname); - silc_strncat(uh, sizeof(uh), hsock->hostname, len); + silc_socket_stream_get_info(silc_packet_stream_get_stream(hsock), + NULL, (const char **)&tmp2, + NULL, NULL); + silc_strncat(uh, sizeof(uh), tmp2, strlen(tmp2)); } silc_server_send_command_reply(server, cmd->sock, query->querycmd, status, 0, ident, 3, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, nh, strlen(nh), 4, uh, strlen(uh)); sent_reply = TRUE; @@ -1562,6 +1749,7 @@ void silc_server_query_send_reply(SilcServer server, break; case SILC_COMMAND_WHOWAS: + memset(uh, 0, sizeof(uh)); silc_strncat(uh, sizeof(uh), entry->username, strlen(entry->username)); if (!strchr(entry->username, '@')) silc_strncat(uh, sizeof(uh), "@-private-", 10); @@ -1569,7 +1757,7 @@ void silc_server_query_send_reply(SilcServer server, /* Send command reply */ silc_server_send_command_reply(server, cmd->sock, query->querycmd, status, 0, ident, 4, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, nh, strlen(nh), 4, uh, strlen(uh), 5, entry->userinfo, @@ -1590,7 +1778,7 @@ void silc_server_query_send_reply(SilcServer server, /* Not one valid entry was found, send error. If nickname was used in query send error based on that, otherwise the query->errors already includes proper errors. */ - if (query->nickname || (!query->ids && query->attrs)) + if (query->nickname[0] || (!query->ids && query->attrs)) silc_server_query_add_error(server, query, 1, 1, SILC_STATUS_ERR_NO_SUCH_NICK); @@ -1635,7 +1823,7 @@ void silc_server_query_send_reply(SilcServer server, idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER); silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_IDENTIFY, status, 0, ident, 2, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, entry->server_name, entry->server_name ? strlen(entry->server_name) : 0); @@ -1682,7 +1870,7 @@ void silc_server_query_send_reply(SilcServer server, idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL); silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_IDENTIFY, status, 0, ident, 2, - 2, idp->data, idp->len, + 2, idp->data, silc_buffer_len(idp), 3, entry->channel_name, entry->channel_name ? strlen(entry->channel_name) : 0); @@ -1724,14 +1912,14 @@ void silc_server_query_send_reply(SilcServer server, silc_id_payload_encode(query->ids[query->errors[i].index].id, query->ids[query->errors[k].index].id_type); tmp = idp->data; - len = idp->len; + len = silc_buffer_len(idp); type = 2; } else { /* Take added ID. */ idp = silc_id_payload_encode(query->errors[i].id, query->errors[k].id_type); tmp = idp->data; - len = idp->len; + len = silc_buffer_len(idp); type = 2; } @@ -1922,10 +2110,11 @@ SilcBuffer silc_server_query_reply_attrs(SilcServer server, /* Finally compute the digital signature of all the data we provided as an indication that we provided rightfull information, and this also authenticates our public key. */ - if (silc_pkcs_get_key_len(server->pkcs) / 8 <= sizeof(sign) -1 && - silc_pkcs_sign_with_hash(server->pkcs, server->sha1hash, - buffer->data, buffer->len, - sign, &sign_len)) { + if (silc_pkcs_private_key_get_len(server->private_key) / 8 <= + sizeof(sign) -1 && + silc_pkcs_sign(server->private_key, buffer->data, + silc_buffer_len(buffer), sign, sizeof(sign), &sign_len, + TRUE, server->sha1hash)) { pk.type = NULL; pk.data = sign; pk.data_len = sign_len; @@ -1951,8 +2140,8 @@ SilcBuffer silc_server_query_reply_attrs(SilcServer server, SilcClientEntry silc_server_query_client(SilcServer server, const SilcClientID *client_id, - bool always_resolve, - bool *resolved) + SilcBool always_resolve, + SilcBool *resolved) { SilcClientEntry client; @@ -1991,11 +2180,12 @@ SilcClientEntry silc_server_query_client(SilcServer server, idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT); buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS, server->cmd_ident, 1, - 4, idp->data, idp->len); + 4, idp->data, + silc_buffer_len(idp)); silc_server_packet_send(server, client ? client->router->connection : SILC_PRIMARY_ROUTE(server), SILC_PACKET_COMMAND, 0, - buffer->data, buffer->len, FALSE); + buffer->data, silc_buffer_len(buffer)); silc_buffer_free(idp); silc_buffer_free(buffer);