+ /* 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;
+
+ /* 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[SILC_HASH_MAXLEN];
+ 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) {
+ if (silc_attribute_get_attribute(attr) ==
+ 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_alloc(SILC_PKCS_SILC,
+ 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 client's public key to repository */
+ if (!silc_server_get_public_key_by_client(server, client, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ client->data.public_key,
+ SILC_SKR_USAGE_IDENTIFICATION,
+ client, NULL);
+
+ silc_free(pk.type);
+ silc_free(pk.data);
+ break;
+ }
+ }
+
+ silc_attribute_payload_list_free(attrs);
+ }
+ }
+ }
+
+ 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 = silc_packet_get_context(cmd->sock);
+
+ /* 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;
+