Changed SILC code to use new SRT and SCT APIs.
[silc.git] / lib / silcclient / client_attrs.c
index 4a28d9e8637741c83f548c6553dc6fefa4040740..1947c1fb3e5d7592f892ef40f6953a88f0d64400 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  client_attrs.c 
+  client_attrs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 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
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "client_internal.h"
 
+typedef struct {
+  SilcBuffer buffer;
+  SilcPKCSSignCb sign_cb;
+  void *context;
+} *SilcAttrSign;
+
 typedef struct {
   SilcBuffer buffer;
 } SilcAttrForeach;
@@ -31,10 +37,11 @@ typedef struct {
 static void silc_client_attributes_process_foreach(void *key, void *context,
                                                   void *user_context)
 {
-  SilcAttribute attribute = (SilcAttribute)(SilcUInt32)key;
+  SilcAttribute attribute = (SilcAttribute)SILC_PTR_TO_32(key);
   SilcAttributePayload attr = context;
   SilcAttrForeach *f = user_context;
   const unsigned char *data;
+  unsigned char tmp[32];
   SilcUInt32 data_len;
 
   if (!context) {
@@ -56,11 +63,13 @@ static void silc_client_attributes_process_foreach(void *key, void *context,
 
   /* We replace the TIMEZONE with valid value here */
   if (attribute == SILC_ATTRIBUTE_TIMEZONE) {
-    data = (const unsigned char *)silc_get_time(0);
-    data_len = strlen(data);
-    f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
-                                             SILC_ATTRIBUTE_FLAG_VALID,
-                                             (void *)data, data_len);
+    if (silc_timezone(tmp, sizeof(tmp))) {
+      data = tmp;
+      data_len = strlen(tmp);
+      f->buffer = silc_attribute_payload_encode(f->buffer, attribute,
+                                               SILC_ATTRIBUTE_FLAG_VALID,
+                                               (void *)data, data_len);
+    }
     return;
   }
 
@@ -69,31 +78,63 @@ static void silc_client_attributes_process_foreach(void *key, void *context,
                                                 data, data_len);
 }
 
+/* Attribute signature callback */
+
+static void
+silc_client_attributes_process_signed(SilcBool success,
+                                     const unsigned char *signature,
+                                     SilcUInt32 signature_len,
+                                     void *context)
+{
+  SilcAttrSign s = context;
+  SilcAttributeObjPk pk;
+
+  if (success) {
+    pk.type = NULL;
+    pk.data = (unsigned char *)signature;
+    pk.data_len = signature_len;
+    s->buffer =
+      silc_attribute_payload_encode(s->buffer,
+                                   SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
+                                   SILC_ATTRIBUTE_FLAG_VALID,
+                                   &pk, sizeof(pk));
+  }
+
+  s->sign_cb(TRUE, silc_buffer_data(s->buffer), silc_buffer_len(s->buffer),
+            s->context);
+
+  silc_buffer_free(s->buffer);
+  silc_free(s);
+}
+
 /* Process list of attributes.  Returns reply to the requested attributes. */
 
-SilcBuffer silc_client_attributes_process(SilcClient client,
-                                         SilcSocketConnection sock,
-                                         SilcDList attrs)
+void silc_client_attributes_process(SilcClient client,
+                                   SilcClientConnection conn,
+                                   SilcDList attrs,
+                                   SilcPKCSSignCb sign_cb,
+                                   void *context)
 {
-  SilcClientConnection conn = sock->user_data;
+  SilcAttrSign s;
   SilcBuffer buffer = NULL;
   SilcAttrForeach f;
   SilcAttribute attribute;
   SilcAttributePayload attr;
   SilcAttributeObjPk pk;
-  unsigned char sign[2048];
-  SilcUInt32 sign_len;
 
   SILC_LOG_DEBUG(("Process Requested Attributes"));
 
   /* If nothing is set by application assume that we don't want to use
      attributes, ignore the request. */
-  if (!conn->attrs)
-    return NULL;
+  if (!conn->internal->attrs) {
+    SILC_LOG_DEBUG(("User has not set any attributes"));
+    sign_cb(FALSE, NULL, 0, context);
+    return;
+  }
 
   /* Always put our public key. */
   pk.type = "silc-rsa";
-  pk.data = silc_pkcs_public_key_encode(client->public_key, &pk.data_len);
+  pk.data = silc_pkcs_public_key_encode(NULL, conn->public_key, &pk.data_len);
   buffer = silc_attribute_payload_encode(buffer,
                                         SILC_ATTRIBUTE_USER_PUBLIC_KEY,
                                         pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
@@ -112,27 +153,26 @@ SilcBuffer silc_client_attributes_process(SilcClient client,
     if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
       continue;
 
-    silc_hash_table_find_foreach(conn->attrs, (void *)(SilcUInt32)attribute,
+    silc_hash_table_find_foreach(conn->internal->attrs,
+                                SILC_32_TO_PTR(attribute),
                                 silc_client_attributes_process_foreach,
                                 &f);
   }
   buffer = f.buffer;
 
-  /* Finally compute the digital signature of all the data we provided. */
-  if (silc_pkcs_sign_with_hash(client->pkcs, client->sha1hash,
-                              buffer->data, buffer->len,
-                              sign, &sign_len)) {
-    pk.type = NULL;
-    pk.data = sign;
-    pk.data_len = sign_len;
-    buffer =
-      silc_attribute_payload_encode(buffer,
-                                   SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
-                                   SILC_ATTRIBUTE_FLAG_VALID,
-                                   &pk, sizeof(pk));
+  s = silc_calloc(1, sizeof(*s));
+  if (!s) {
+    sign_cb(FALSE, NULL, 0, context);
+    return;
   }
+  s->sign_cb = sign_cb;
+  s->context = context;
+  s->buffer = buffer;
 
-  return buffer;
+  /* Finally compute the digital signature of all the data we provided. */
+  silc_pkcs_sign_async(conn->private_key, silc_buffer_data(buffer),
+                      silc_buffer_len(buffer), TRUE, NULL,
+                      client->rng, silc_client_attributes_process_signed, s);
 }
 
 static void silc_client_attribute_destruct(void *key, void *context,
@@ -156,11 +196,13 @@ SilcAttributePayload silc_client_attribute_add(SilcClient client,
   if (!attr)
     return NULL;
 
-  if (!conn->attrs)
-    conn->attrs = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
-                                       NULL, silc_client_attribute_destruct,
-                                       NULL, TRUE);
-  silc_hash_table_add(conn->attrs, (void *)(SilcUInt32)attribute, attr);
+  if (!conn->internal->attrs)
+    conn->internal->attrs =
+      silc_hash_table_alloc(NULL, 0, silc_hash_ptr, NULL, NULL,
+                           NULL, silc_client_attribute_destruct,
+                           NULL, TRUE);
+  silc_hash_table_add(conn->internal->attrs,
+                     SILC_32_TO_PTR(attribute), attr);
   return attr;
 }
 
@@ -173,28 +215,29 @@ static void silc_client_attribute_del_foreach(void *key, void *context,
   if (!attr)
     return;
   attribute = silc_attribute_get_attribute(attr);
-  silc_hash_table_del_by_context(conn->attrs,
-                                (void *)(SilcUInt32)attribute, attr);
+  silc_hash_table_del_by_context(conn->internal->attrs,
+                                SILC_32_TO_PTR(attribute), attr);
 }
 
 /* Delete one attribute */
 
-bool silc_client_attribute_del(SilcClient client,
-                              SilcClientConnection conn,
-                              SilcAttribute attribute,
-                              SilcAttributePayload attr)
+SilcBool silc_client_attribute_del(SilcClient client,
+                                  SilcClientConnection conn,
+                                  SilcAttribute attribute,
+                                  SilcAttributePayload attr)
 {
-  bool ret;
+  SilcBool ret;
 
-  if (!conn->attrs)
+  if (!conn->internal->attrs)
     return FALSE;
 
   if (attr) {
     attribute = silc_attribute_get_attribute(attr);
-    ret = silc_hash_table_del_by_context(conn->attrs,
-                                        (void *)(SilcUInt32)attribute, attr);
+    ret = silc_hash_table_del_by_context(conn->internal->attrs,
+                                        SILC_32_TO_PTR(attribute), attr);
   } else if (attribute) {
-    silc_hash_table_find_foreach(conn->attrs, (void *)(SilcUInt32)attribute,
+    silc_hash_table_find_foreach(conn->internal->attrs,
+                                SILC_32_TO_PTR(attribute),
                                 silc_client_attribute_del_foreach, conn);
     ret = TRUE;
   } else{
@@ -202,9 +245,9 @@ bool silc_client_attribute_del(SilcClient client,
   }
 
   if (ret)
-    if (!silc_hash_table_count(conn->attrs)) {
-      silc_hash_table_free(conn->attrs);
-      conn->attrs = NULL;
+    if (!silc_hash_table_count(conn->internal->attrs)) {
+      silc_hash_table_free(conn->internal->attrs);
+      conn->internal->attrs = NULL;
     }
 
   return ret;
@@ -212,10 +255,10 @@ bool silc_client_attribute_del(SilcClient client,
 
 /* Return all attributes */
 
-const SilcHashTable silc_client_attributes_get(SilcClient client,
-                                              SilcClientConnection conn)
+SilcHashTable silc_client_attributes_get(SilcClient client,
+                                        SilcClientConnection conn)
 {
-  return (const SilcHashTable)conn->attrs;
+  return conn->internal->attrs;
 }
 
 /* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
@@ -231,6 +274,7 @@ SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...)
 
   if (!attribute)
     return silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
+                                         SILC_ATTRIBUTE_USER_ICON,
                                          SILC_ATTRIBUTE_SERVICE,
                                          SILC_ATTRIBUTE_STATUS_MOOD,
                                          SILC_ATTRIBUTE_STATUS_FREETEXT,