/*
- 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;
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) {
/* 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;
}
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 + 1];
- 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->internal->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 :
continue;
silc_hash_table_find_foreach(conn->internal->attrs,
- (void *)(SilcUInt32)attribute,
+ 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,
if (!conn->internal->attrs)
conn->internal->attrs =
- silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
+ 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,
- (void *)(SilcUInt32)attribute, attr);
+ SILC_32_TO_PTR(attribute), attr);
return attr;
}
return;
attribute = silc_attribute_get_attribute(attr);
silc_hash_table_del_by_context(conn->internal->attrs,
- (void *)(SilcUInt32)attribute, attr);
+ 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->internal->attrs)
return FALSE;
if (attr) {
attribute = silc_attribute_get_attribute(attr);
ret = silc_hash_table_del_by_context(conn->internal->attrs,
- (void *)(SilcUInt32)attribute, attr);
+ SILC_32_TO_PTR(attribute), attr);
} else if (attribute) {
silc_hash_table_find_foreach(conn->internal->attrs,
- (void *)(SilcUInt32)attribute,
+ SILC_32_TO_PTR(attribute),
silc_client_attribute_del_foreach, conn);
ret = TRUE;
} else{
/* 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->internal->attrs;
+ return conn->internal->attrs;
}
/* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
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,