From ea090c5ea8c45402dcec130bac46031ed7cde41b Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 6 Nov 2003 19:11:47 +0000 Subject: [PATCH] Save public key from attributes in WHOIS command reply on normal server. --- apps/silcd/command_reply.c | 71 +++++++++++++++++++++++++++++++++++--- apps/silcd/server_query.c | 18 ++++++++-- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 5a0ce2e8..97fc56c7 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -300,6 +300,70 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd) silc_free(client->attrs); client->attrs = silc_memdup(tmp, len); client->attrs_len = len; + + /* Try to take public key from attributes if present and we don't have + the key already. Do this only on normal server. Routers do GETKEY + for all clients anyway. */ + if (server->server_type != SILC_ROUTER && !client->data.public_key) { + SilcAttributePayload attr; + SilcAttributeObjPk pk; + unsigned char f[20]; + SilcDList attrs = silc_attribute_payload_parse(tmp, len); + + SILC_LOG_DEBUG(("Take client public key from attributes")); + + if (attrs) { + silc_dlist_start(attrs); + while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) { + switch (silc_attribute_get_attribute(attr)) { + case SILC_ATTRIBUTE_USER_PUBLIC_KEY: + if (!silc_attribute_get_object(attr, &pk, sizeof(pk))) + continue; + + /* Take only SILC public keys */ + if (strcmp(pk.type, "silc-rsa")) { + silc_free(pk.type); + silc_free(pk.data); + continue; + } + + /* Verify that the server provided fingerprint matches the key */ + silc_hash_make(server->sha1hash, pk.data, pk.data_len, f); + if (memcmp(f, client->data.fingerprint, sizeof(f))) { + silc_free(pk.type); + silc_free(pk.data); + continue; + } + + /* Save the public key. */ + if (!silc_pkcs_public_key_decode(pk.data, pk.data_len, + &client->data.public_key)) { + silc_free(pk.type); + silc_free(pk.data); + continue; + } + + SILC_LOG_DEBUG(("Saved client public key from attributes")); + + /* Add to public key hash table */ + if (!silc_hash_table_find_by_context(server->pk_hash, + client->data.public_key, + client, NULL)) + silc_hash_table_add(server->pk_hash, + client->data.public_key, client); + + silc_free(pk.type); + silc_free(pk.data); + break; + + default: + break; + } + } + + silc_attribute_payload_list_free(attrs); + } + } } return TRUE; @@ -1283,10 +1347,9 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey) goto out; } - if (server->server_type != SILC_SERVER) - if (!silc_hash_table_find_by_context(server->pk_hash, public_key, - client, NULL)) - silc_hash_table_add(server->pk_hash, public_key, client); + if (!silc_hash_table_find_by_context(server->pk_hash, public_key, + client, NULL)) + silc_hash_table_add(server->pk_hash, public_key, client); client->data.public_key = public_key; public_key = NULL; diff --git a/apps/silcd/server_query.c b/apps/silcd/server_query.c index 6d9c1111..c8d768af 100644 --- a/apps/silcd/server_query.c +++ b/apps/silcd/server_query.c @@ -237,7 +237,7 @@ bool silc_server_query_command(SilcServer server, SilcCommand querycmd, /* If we are normal server and query contains nickname OR query doesn't contain nickname or ids BUT attributes, send it to the router */ - if (server->server_type == SILC_SERVER && !server->standalone && + if (server->server_type != SILC_ROUTER && !server->standalone && cmd->sock != SILC_PRIMARY_ROUTE(server) && (silc_argument_get_arg_type(cmd->args, 1, NULL) || (!silc_argument_get_arg_type(cmd->args, 1, NULL) && @@ -586,7 +586,7 @@ void silc_server_public_key_hash_foreach(void *key, void *context, (*uc->clients) = silc_realloc((*uc->clients), sizeof((**uc->clients)) * - ((*uc->clients_count) + 1)); + ((*uc->clients_count) + 1)); (*uc->clients)[(*uc->clients_count)++] = entry; } @@ -622,12 +622,17 @@ void silc_server_query_check_attributes(SilcServer server, case SILC_ATTRIBUTE_USER_PUBLIC_KEY: found = TRUE; + SILC_LOG_DEBUG(("Finding clients by public key attribute")); + if (!silc_attribute_get_object(attr, &pk, sizeof(pk))) continue; if (!silc_pkcs_public_key_decode(pk.data, pk.data_len, - &publickey)) + &publickey)) { + silc_free(pk.type); + silc_free(pk.data); continue; + } /* If no clients were set on calling this function, we just search for clients, otherwise we try to limit @@ -653,6 +658,8 @@ void silc_server_query_check_attributes(SilcServer server, (*clients)[i] = NULL; } } + silc_free(pk.type); + silc_free(pk.data); silc_pkcs_public_key_free(publickey); break; } @@ -895,6 +902,11 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query, client_entry->data.status & SILC_IDLIST_STATUS_NOATTR)) continue; + /* If attributes are present in query, and in the entry and we have + done resolvings already we don't need to resolve anymore */ + if (query->resolved && query->attrs && client_entry->attrs) + continue; + /* Resolve the detailed client information. If client is local we know that attributes were present and we will resolve directly from the client. Otherwise resolve from client's owner. */ -- 2.43.0