Added Requested Attributes support to WHOIS command, and the server
authorPekka Riikonen <priikone@silcnet.org>
Mon, 7 Oct 2002 15:48:22 +0000 (15:48 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 7 Oct 2002 15:48:22 +0000 (15:48 +0000)
is now able to reply to the attributes on behalf of client.

CHANGES
apps/silcd/server_query.c

diff --git a/CHANGES b/CHANGES
index a110310cbd74e76ee787b29cf8c727b1b5c2f9ed..c0604310201f2e58b5cfc6e63d0de8afe99b0479 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,19 @@
+Mon Oct  7 18:25:35 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Changed the silc_attribute_payload_encode to support list
+         of attributes (function may be called several times to add
+         a new attribute).  Removed the silc_attribute_payload_encode_list
+         function.  The encoding function now also automatically encodes
+         the data, so the caller does not need to do that.  Affected
+         files lib/silccore/silcattrs.[ch].
+
+       * Added support for replying on behalf of the user to the
+         Requested Attributes in WHOIS command in the server.  Affected
+         file silcd/server_query.c.
+
+       * SILC_NOT_IMPLEMENTED macro use SILC_LOG_INFO now instead of
+         SILC_LOG_DEBUG.  Affected file lib/silcutil/silclog.h.
+
 Sun Oct  6 16:48:32 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Don't swtich to become primary router if we are backup if
index 0ebc05ed779be3929e396773eaf2438bbe36bad2..cad646be1f28b0ea2f008a811103ec3abd9f7cb6 100644 (file)
@@ -18,8 +18,6 @@
 */
 /* $Id$ */
 
-/* XXX TODO Requested Attributes to WHOIS */
-
 #include "serverincludes.h"
 #include "server_internal.h"
 
@@ -106,9 +104,9 @@ void silc_server_query_send_reply(SilcServer server,
                                  SilcUInt32 servers_count,
                                  SilcChannelEntry *channels,
                                  SilcUInt32 channels_count);
-unsigned char *silc_server_query_reply_attrs(SilcServer server,
-                                            SilcServerQuery query,
-                                            SilcUInt32 *attrs_len);
+SilcBuffer silc_server_query_reply_attrs(SilcServer server,
+                                        SilcServerQuery query,
+                                        SilcClientEntry client_entry);
 
 /* Free the query context structure and all allocated resources. */
 
@@ -1204,7 +1202,7 @@ void silc_server_query_send_reply(SilcServer server,
        {
          unsigned char idle[4], mode[4];
          unsigned char *fingerprint, fempty[20], *attrs = NULL;
-         SilcBuffer channels, umode_list = NULL;
+         SilcBuffer channels, umode_list = NULL, tmpattrs = NULL;
 
          memset(fempty, 0, sizeof(fempty));
          memset(idle, 0, sizeof(idle));
@@ -1240,7 +1238,9 @@ void silc_server_query_send_reply(SilcServer server,
          len = 0;
          if (query->attrs) {
            if (!entry->attrs) {
-             attrs = silc_server_query_reply_attrs(server, query, &len);
+             tmpattrs = silc_server_query_reply_attrs(server, query, entry);
+             attrs = tmpattrs->data;
+             len = tmpattrs->len;
            } else {
              attrs = entry->attrs;
              len = entry->attrs_len;
@@ -1273,6 +1273,8 @@ void silc_server_query_send_reply(SilcServer server,
 
          if (channels)
            silc_buffer_free(channels);
+         if (tmpattrs)
+           silc_buffer_free(tmpattrs);
          if (umode_list) {
            silc_buffer_free(umode_list);
            umode_list = NULL;
@@ -1508,19 +1510,103 @@ void silc_server_query_send_reply(SilcServer server,
    Either client does not support Requested Attributes or isn't replying
    to them like it should. */
 
-unsigned char *silc_server_query_reply_attrs(SilcServer server,
-                                            SilcServerQuery query,
-                                            SilcUInt32 *attrs_len)
+SilcBuffer silc_server_query_reply_attrs(SilcServer server,
+                                        SilcServerQuery query,
+                                        SilcClientEntry client_entry)
 {
-  unsigned char *attrs = NULL;
-  SilcUInt32 len = 0;
+  SilcBuffer buffer = NULL;
+  SilcAttributePayload attr;
+  SilcAttribute attribute;
+  unsigned char *tmp;
+  SilcAttributeObjPk pk;
 
   SILC_LOG_DEBUG(("Constructing Requested Attributes"));
 
-  if (attrs_len)
-    *attrs_len = len;
+  /* Go through all requested attributes */
+  silc_dlist_start(query->attrs);
+  while ((attr = silc_dlist_get(query->attrs)) != SILC_LIST_END) {
+    attribute = silc_attribute_get_attribute(attr);
+    switch (attribute) {
+
+    case SILC_ATTRIBUTE_USER_INFO:
+      /* Put USER_INFO */
+      SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
+      break;
+
+    case SILC_ATTRIBUTE_STATUS_MOOD:
+      /* Put STATUS_MOOD */
+      buffer = silc_attribute_payload_encode(buffer, attribute,
+                                            SILC_ATTRIBUTE_FLAG_VALID,
+                                            (void *)
+                                            SILC_ATTRIBUTE_MOOD_NORMAL,
+                                            sizeof(SilcUInt32));
+      break;
+
+    case SILC_ATTRIBUTE_STATUS_FREETEXT:
+      /* Put STATUS_FREETEXT.  We just tell in the message that we are
+        replying on behalf of the client. */
+      tmp = 
+       "This information was provided by the server on behalf of the user";
+      buffer = silc_attribute_payload_encode(buffer, attribute,
+                                            SILC_ATTRIBUTE_FLAG_VALID,
+                                            tmp, strlen(tmp));
+      break;
+
+    case SILC_ATTRIBUTE_PREFERRED_CONTACT:
+      /* Put PREFERRED_CONTACT */
+      buffer = silc_attribute_payload_encode(buffer, attribute,
+                                            SILC_ATTRIBUTE_FLAG_VALID,
+                                            (void *)
+                                            SILC_ATTRIBUTE_CONTACT_CHAT,
+                                            sizeof(SilcUInt32));
+      break;
+
+    case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
+      /* Put USER_PUBLIC_KEY */
+      if (client_entry->data.public_key) {
+       pk.type = "silc-rsa";
+       pk.data = silc_pkcs_public_key_encode(client_entry->data.public_key,
+                                             &pk.data_len);
+       buffer = silc_attribute_payload_encode(buffer, attribute, pk.data ?
+                                              SILC_ATTRIBUTE_FLAG_VALID :
+                                              SILC_ATTRIBUTE_FLAG_INVALID,
+                                              &pk, sizeof(pk));
+       silc_free(pk.data);
+       break;
+      }
+
+      /* No public key available */
+      buffer = silc_attribute_payload_encode(buffer, attribute,
+                                            SILC_ATTRIBUTE_FLAG_INVALID,
+                                            NULL, 0);
+      break;
+
+    default:
+      /* Ignore SERVER_PUBLIC_KEY since we are going to put it anyway later */
+      if (attribute == SILC_ATTRIBUTE_SERVER_PUBLIC_KEY)
+       break;
+      
+      /* For other attributes we cannot reply so mark it invalid */
+      buffer = silc_attribute_payload_encode(buffer, attribute,
+                                            SILC_ATTRIBUTE_FLAG_INVALID,
+                                            NULL, 0);
+      break;
+    }
+  }
 
-  return attrs;
+  /* Always put our public key.  This assures that we send at least
+     something valid back always. */
+  /* XXX We should also compute digital signature */
+  pk.type = "silc-rsa";
+  pk.data = silc_pkcs_public_key_encode(server->public_key, &pk.data_len);
+  buffer = silc_attribute_payload_encode(buffer,
+                                        SILC_ATTRIBUTE_SERVER_PUBLIC_KEY,
+                                        pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
+                                        SILC_ATTRIBUTE_FLAG_INVALID,
+                                        &pk, sizeof(pk));
+  silc_free(pk.data);
+
+  return buffer;
 }
 
 /* Find client by the Client ID indicated by the `client_id', and if not