Save public key from attributes in WHOIS command reply on normal
authorPekka Riikonen <priikone@silcnet.org>
Thu, 6 Nov 2003 19:11:47 +0000 (19:11 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 6 Nov 2003 19:11:47 +0000 (19:11 +0000)
server.

apps/silcd/command_reply.c
apps/silcd/server_query.c

index 5a0ce2e813642c0253040424bf4b10cb8297c7aa..97fc56c70cf642a479ac729d8ca16d8970322675 100644 (file)
@@ -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;
index 6d9c111199c2263b4eb25df363cf7c80067f9766..c8d768af72301fade2c2842c5ca306ab7d9320d6 100644 (file)
@@ -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. */