Added SILC Server library.
[silc.git] / lib / silccore / silcattrs.c
index 9359bf8b222e35ad9276b67c412c84301ae62dad..27f25f7373ebea728ba10e1c984ce7d5e9bca532 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcattrs.c 
+  silcattrs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2005 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
@@ -19,7 +19,7 @@
 /* Implementation of Attribute Payload routines */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcattrs.h"
 
 /******************************************************************************
@@ -35,112 +35,285 @@ struct SilcAttributePayloadStruct {
   unsigned char *data;
 };
 
-/* Parse one attribute payload */
+/* Internal routine for encoding a attribute */
 
-SilcAttributePayload
-silc_attribute_payload_parse(const unsigned char *payload,
-                            SilcUInt32 payload_len)
+static unsigned char *
+silc_attribute_payload_encode_int(SilcAttribute attribute,
+                                 SilcAttributeFlags flags,
+                                 void *object,
+                                 SilcUInt32 object_size,
+                                 SilcUInt32 *ret_len)
 {
-  SilcBufferStruct buffer;
-  SilcAttributePayload newp;
-  int ret;
+  SilcBuffer tmpbuf = NULL;
+  unsigned char tmp[4], *str = NULL, *ret;
+  SilcUInt32 len;
+
+  /* Encode according to attribute type */
+  if (flags & SILC_ATTRIBUTE_FLAG_VALID) {
+    if (!object && !object_size)
+      return NULL;
+
+    switch (attribute) {
+
+    case SILC_ATTRIBUTE_USER_INFO:
+      {
+       SilcVCard vcard = object;
+       if (object_size != sizeof(*vcard))
+         return NULL;
+       str = silc_vcard_encode(vcard, &object_size);
+       if (!str)
+         return NULL;
+       object = str;
+      }
+      break;
 
-  SILC_LOG_DEBUG(("Parsing attribute payload"));
+    case SILC_ATTRIBUTE_SERVICE:
+      {
+       SilcAttributeObjService *service = object;
+       SilcUInt32 len2;
+       if (object_size != sizeof(*service))
+         return NULL;
+       len = strlen(service->address);
+       len2 = strlen(service->signon);
+       tmpbuf = silc_buffer_alloc_size(13 + len + len2);
+       silc_buffer_format(tmpbuf,
+                          SILC_STR_UI_INT(service->port),
+                          SILC_STR_UI_SHORT(len),
+                          SILC_STR_UI_XNSTRING(service->address, len),
+                          SILC_STR_UI_CHAR(service->status),
+                          SILC_STR_UI_SHORT(len2),
+                          SILC_STR_UI_XNSTRING(service->signon, len2),
+                          SILC_STR_UI_INT(service->idle),
+                          SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = silc_buffer_len(tmpbuf);
+      }
+      break;
 
-  silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
-  newp = silc_calloc(1, sizeof(*newp));
-  if (!newp)
-    return NULL;
+    case SILC_ATTRIBUTE_STATUS_MOOD:
+    case SILC_ATTRIBUTE_PREFERRED_CONTACT:
+      {
+       SilcUInt32 mask = SILC_PTR_TO_32(object);
+       if (object_size != sizeof(SilcUInt32))
+         return NULL;
+       SILC_PUT32_MSB(mask, tmp);
+       object = tmp;
+       object_size = sizeof(SilcUInt32);
+      }
+      break;
 
-  /* Parse the Attribute Payload. */
-  ret = silc_buffer_unformat(&buffer,
-                            SILC_STR_UI_CHAR(&newp->attribute),
-                            SILC_STR_UI_CHAR(&newp->flags),
-                            SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
-                                                        &newp->data_len),
-                            SILC_STR_END);
-  if (ret == -1)
-    goto err;
+    case SILC_ATTRIBUTE_STATUS_FREETEXT:
+    case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
+    case SILC_ATTRIBUTE_TIMEZONE:
+      {
+       unsigned char *string = object;
+       str = silc_malloc(2 + object_size);
+       if (!str)
+         return NULL;
+       SILC_PUT16_MSB(object_size, str);
+       memcpy(str + 2, string, object_size);
+       object = str;
+       object_size += 2;
+      }
+      break;
 
-  if (newp->data_len > buffer.len - 4) {
-    SILC_LOG_ERROR(("Incorrect attribute payload"));
-    goto err;
-  }
+    case SILC_ATTRIBUTE_STATUS_MESSAGE:
+    case SILC_ATTRIBUTE_EXTENSION:
+    case SILC_ATTRIBUTE_USER_ICON:
+      {
+       SilcMime mime = object;
+       if (object_size != sizeof(*mime))
+         return NULL;
+       str = silc_mime_encode(mime, &object_size);
+       if (!str)
+         return NULL;
+      }
+      break;
 
-  return newp;
+    case SILC_ATTRIBUTE_GEOLOCATION:
+      {
+       SilcAttributeObjGeo *geo = object;
+       SilcUInt32 len1, len2, len3, len4;
+       if (object_size != sizeof(*geo))
+         return NULL;
+       len1 = (geo->longitude ? strlen(geo->longitude) : 0);
+       len2 = (geo->latitude  ? strlen(geo->latitude)  : 0);
+       len3 = (geo->altitude  ? strlen(geo->altitude)  : 0);
+       len4 = (geo->accuracy  ? strlen(geo->accuracy)  : 0);
+       if (len1 + len2 + len3 + len4 == 0)
+         return NULL;
+       len = len1 + len2 + len3 + len4;
+       tmpbuf = silc_buffer_alloc_size(8 + len);
+       if (!tmpbuf)
+         return NULL;
+       silc_buffer_format(tmpbuf,
+                          SILC_STR_UI_SHORT(len1),
+                          SILC_STR_UI16_STRING(len1 ? geo->longitude : ""),
+                          SILC_STR_UI_SHORT(len2),
+                          SILC_STR_UI16_STRING(len2 ? geo->latitude : ""),
+                          SILC_STR_UI_SHORT(len3),
+                          SILC_STR_UI16_STRING(len3 ? geo->altitude : ""),
+                          SILC_STR_UI_SHORT(len4),
+                          SILC_STR_UI16_STRING(len4 ? geo->accuracy : ""),
+                          SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = silc_buffer_len(tmpbuf);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_DEVICE_INFO:
+      {
+       SilcAttributeObjDevice *dev = object;
+       SilcUInt32 len1, len2, len3, len4;
+       if (object_size != sizeof(*dev))
+         return NULL;
+       len1 = (dev->manufacturer ? strlen(dev->manufacturer) : 0);
+       len2 = (dev->version      ? strlen(dev->version)      : 0);
+       len3 = (dev->model        ? strlen(dev->model)        : 0);
+       len4 = (dev->language     ? strlen(dev->language)     : 0);
+       if (len1 + len2 + len3 + len4 == 0)
+         return NULL;
+       len = len1 + len2 + len3 + len4;
+       tmpbuf = silc_buffer_alloc_size(4 + 8 + len);
+       if (!tmpbuf)
+         return NULL;
+       silc_buffer_format(tmpbuf,
+                          SILC_STR_UI_INT(dev->type),
+                          SILC_STR_UI_SHORT(len1),
+                          SILC_STR_UI16_STRING(len1 ? dev->manufacturer : ""),
+                          SILC_STR_UI_SHORT(len2),
+                          SILC_STR_UI16_STRING(len2 ? dev->version : ""),
+                          SILC_STR_UI_SHORT(len3),
+                          SILC_STR_UI16_STRING(len3 ? dev->model : ""),
+                          SILC_STR_UI_SHORT(len4),
+                          SILC_STR_UI16_STRING(len4 ? dev->language : ""),
+                          SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = silc_buffer_len(tmpbuf);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
+    case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
+      {
+       SilcAttributeObjPk *pk = object;
+       if (object_size != sizeof(*pk))
+         return NULL;
+       len = (pk->type ? strlen(pk->type) : 0);
+       tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len);
+       if (!tmpbuf)
+         return NULL;
+       silc_buffer_format(tmpbuf,
+                          SILC_STR_UI_SHORT(len),
+                          SILC_STR_UI16_STRING(pk->type),
+                          SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
+                          SILC_STR_END);
+       object = tmpbuf->data;
+       object_size = silc_buffer_len(tmpbuf);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
+    case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
+      {
+       SilcAttributeObjPk *pk = object;
+       if (object_size != sizeof(*pk))
+         return NULL;
+       object = pk->data;
+       object_size = pk->data_len;
+      }
+      break;
+
+    default:
+      return NULL;
+      break;
+    }
+
+    ret = silc_memdup(object, object_size);
+
+    if (tmpbuf)
+      silc_buffer_free(tmpbuf);
+    silc_free(str);
+
+    if (ret_len)
+      *ret_len = object_size;
+
+    return ret;
+  }
 
- err:
-  silc_attribute_payload_free(newp);
   return NULL;
 }
 
-/* Encode one attribute payload */
+/* Allocates attribute payload and encodes the attribute there */
 
-SilcBuffer silc_attribute_payload_encode(SilcAttribute attribute,
-                                        SilcAttributeFlags flags,
-                                        const unsigned char *data,
-                                        SilcUInt32 data_len)
+SilcAttributePayload silc_attribute_payload_alloc(SilcAttribute attribute,
+                                                 SilcAttributeFlags flags,
+                                                 void *object,
+                                                 SilcUInt32 object_size)
 {
-  SilcBuffer buffer;
-
-  SILC_LOG_DEBUG(("Encoding Attribute Payload"));
+  SilcAttributePayload attr;
+  SilcUInt32 tmp_len;
 
-  buffer = silc_buffer_alloc_size(4 + data_len);
-  if (!buffer)
+  attr = silc_calloc(1, sizeof(*attr));
+  if (!attr)
     return NULL;
 
-  /* Encode the Attribute Payload */
-  silc_buffer_format(buffer, 
-                    SILC_STR_UI_CHAR(attribute),
-                    SILC_STR_UI_CHAR(flags),
-                    SILC_STR_UI_SHORT((SilcUInt16)data_len),
-                    SILC_STR_UI_XNSTRING(data, data_len),
-                    SILC_STR_END);
+  attr->attribute = attribute;
+  attr->flags = flags;
+  attr->data =
+    silc_attribute_payload_encode_int(attribute, flags, object,
+                                     object_size, &tmp_len);
+  attr->data_len = (SilcUInt16)tmp_len;
+  if (!attr->data) {
+    silc_free(attr);
+    return NULL;
+  }
 
-  return buffer;
+  return attr;
 }
 
 /* Parse list of payloads */
 
-SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
-                                           SilcUInt32 payload_len)
+SilcDList silc_attribute_payload_parse(const unsigned char *payload,
+                                      SilcUInt32 payload_len)
 {
   SilcBufferStruct buffer;
   SilcDList list;
   SilcAttributePayload newp;
-  int len, ret;
+  SilcUInt32 len;
+  int ret;
 
   SILC_LOG_DEBUG(("Parsing Attribute Payload list"));
 
   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
   list = silc_dlist_init();
 
-  while (buffer.len) {
+  while (silc_buffer_len(&buffer)) {
     newp = silc_calloc(1, sizeof(*newp));
     if (!newp)
       goto err;
     ret = silc_buffer_unformat(&buffer,
                               SILC_STR_UI_CHAR(&newp->attribute),
                               SILC_STR_UI_CHAR(&newp->flags),
-                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
+                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
                                                           &newp->data_len),
                               SILC_STR_END);
     if (ret == -1)
       goto err;
 
-    if (newp->data_len > buffer.len) {
+    if (newp->data_len > silc_buffer_len(&buffer) - 4) {
       SILC_LOG_ERROR(("Incorrect attribute payload in list"));
       goto err;
     }
 
     len = 4 + newp->data_len;
-    if (buffer.len < len)
+    if (silc_buffer_len(&buffer) < len)
       break;
     silc_buffer_pull(&buffer, len);
 
     silc_dlist_add(list, newp);
   }
-  
+
   return list;
 
  err:
@@ -148,47 +321,48 @@ SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
   return NULL;
 }
 
-/* Encode list of payloads */
+/* Encode one attribute payload to buffer */
 
-SilcBuffer silc_attribute_payload_encode_list(SilcUInt32 num_attrs, ...)
+SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
+                                        SilcAttribute attribute,
+                                        SilcAttributeFlags flags,
+                                        void *object,
+                                        SilcUInt32 object_size)
 {
-  SilcBuffer buffer = NULL;
-  va_list ap;
-  int i, len = 0;
-  SilcAttribute attribute;
-  SilcAttributeFlags flags;
-  unsigned char *data;
-  SilcUInt32 data_len;
+  object = silc_attribute_payload_encode_int(attribute, flags, object,
+                                            object_size, &object_size);
+  attrs = silc_attribute_payload_encode_data(attrs, attribute, flags,
+                                            (const unsigned char *)object,
+                                            object_size);
+  silc_free(object);
+  return attrs;
+}
 
-  if (!num_attrs)
-    return NULL;
+/* Encoded the attribute data directly to buffer */
 
-  va_start(ap, num_attrs);
-  for (i = 0; i < num_attrs; i++) {
-    attribute = va_arg(ap, SilcUInt32);
-    flags = va_arg(ap, SilcUInt32);
-    data = va_arg(ap, unsigned char *);
-    data_len = va_arg(ap, SilcUInt32);
-
-    if (data || !data_len)
-      continue;
-
-    len = 4 + data_len;
-    buffer = silc_buffer_realloc(buffer,
-                                (buffer ? buffer->truelen + len : len));
-    silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_CHAR(attribute),
-                      SILC_STR_UI_CHAR(flags),
-                      SILC_STR_UI_SHORT((SilcUInt16)data_len),
-                      SILC_STR_UI_XNSTRING(data, data_len),
-                      SILC_STR_END);
-    silc_buffer_pull(buffer, len);
-  }
-  va_end(ap);
+SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
+                                             SilcAttribute attribute,
+                                             SilcAttributeFlags flags,
+                                             const unsigned char *data,
+                                             SilcUInt32 data_len)
+{
+  SilcBuffer buffer = attrs;
+  SilcUInt32 len;
 
-  if (buffer)
-    silc_buffer_push(buffer, buffer->data - buffer->head);
+  len = 4 + (SilcUInt16)data_len;
+  buffer = silc_buffer_realloc(buffer,
+                              (buffer ? silc_buffer_truelen(buffer) + len : len));
+  if (!buffer)
+    return NULL;
+  silc_buffer_pull(buffer, silc_buffer_len(buffer));
+  silc_buffer_pull_tail(buffer, len);
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_CHAR(attribute),
+                    SILC_STR_UI_CHAR(flags),
+                    SILC_STR_UI_SHORT((SilcUInt16)data_len),
+                    SILC_STR_UI_XNSTRING(data, (SilcUInt16)data_len),
+                    SILC_STR_END);
+  silc_buffer_push(buffer, buffer->data - buffer->head);
 
   return buffer;
 }
@@ -236,42 +410,111 @@ const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
                                             SilcUInt32 *data_len)
 {
   if (data_len)
-    *data_len = payload->data_len;
+    *data_len = (SilcUInt32)payload->data_len;
   return (const unsigned char *)payload->data;
 }
 
+/* Construct digital signature verification data */
+
+unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
+                                             SilcBool server_verification,
+                                             SilcUInt32 *data_len)
+{
+  SilcAttributePayload attr;
+  SilcBufferStruct buffer;
+  unsigned char *data = NULL;
+  SilcUInt32 len = 0;
+
+  silc_dlist_start(attrs);
+  while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
+    switch (attr->attribute) {
+    case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
+      /* Server signature is never part of the verification data */
+      break;
+
+    case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
+      /* For user signature verification this is not part of the data */
+      if (!server_verification)
+       break;
+
+      /* Fallback, for server signature verification, user digital signature
+        is part of verification data. */
+
+    default:
+      /* All other data is part of the verification data */
+      data = silc_realloc(data, sizeof(*data) * (4 + attr->data_len + len));
+      if (!data)
+       return NULL;
+      silc_buffer_set(&buffer, data + len, 4 + attr->data_len);
+      silc_buffer_format(&buffer,
+                        SILC_STR_UI_CHAR(attr->attribute),
+                        SILC_STR_UI_CHAR(attr->flags),
+                        SILC_STR_UI_SHORT(attr->data_len),
+                        SILC_STR_UI_XNSTRING(attr->data, attr->data_len),
+                        SILC_STR_END);
+      len += 4 + attr->data_len;
+      break;
+    }
+  }
+
+  if (data_len)
+    *data_len = len;
+
+  return data;
+}
+
 /* Return parsed attribute object */
 
-bool silc_attribute_get_object(SilcAttributePayload payload,
-                              SilcAttribute attribute,
-                              void **object, SilcUInt32 object_size)
+SilcBool silc_attribute_get_object(SilcAttributePayload payload,
+                              void *object, SilcUInt32 object_size)
 {
   SilcUInt16 len;
-  bool ret = FALSE;
+  SilcBool ret = FALSE;
 
-  if (!attribute || !object || !(*object))
+  if (!object || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
     return FALSE;
 
-  switch (attribute) {
+  switch (payload->attribute) {
   case SILC_ATTRIBUTE_USER_INFO:
-    SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
+    {
+      SilcVCard vcard = object;
+      if (object_size != sizeof(*vcard))
+       break;
+      if (!silc_vcard_decode(payload->data, payload->data_len, vcard))
+       break;
+      ret = TRUE;
+    }
     break;
 
   case SILC_ATTRIBUTE_SERVICE:
     {
-      SilcAttributeObjService *service = *object;
+      SilcAttributeObjService *service = object;
+      SilcBufferStruct buf;
+      SilcUInt16 addr_len, signon_len;
+      char *addr, *signon;
+      int res;
       if (object_size != sizeof(*service))
        break;
-      if (payload->data_len < 7)
+      if (payload->data_len < 13)
        break;
-      SILC_GET32_MSB(service->port, payload->data);
-      SILC_GET16_MSB(len, payload->data + 4);
-      if (payload->data_len < 7 + len)
+      silc_buffer_set(&buf, payload->data, payload->data_len);
+      res = silc_buffer_unformat(&buf,
+                                SILC_STR_UI_INT(&service->port),
+                                SILC_STR_UI16_NSTRING(&addr, &addr_len),
+                                SILC_STR_UI_CHAR(&service->status),
+                                SILC_STR_UI16_NSTRING(&signon, &signon_len),
+                                SILC_STR_UI_INT(&service->idle),
+                                SILC_STR_END);
+      if (res == -1)
        break;
-      memcpy(service->address, payload->data + 6,
-            (len < sizeof(service->address) - 1 ? len :
+      memset(service->address, 0, sizeof(service->address));
+      memset(service->signon, 0, sizeof(service->signon));
+      memcpy(service->address, addr,
+            (addr_len < sizeof(service->address) - 1 ? addr_len :
              sizeof(service->address) - 1));
-      service->status = payload->data[6 + len] ? TRUE : FALSE;
+      memcpy(service->signon, signon,
+            (signon_len < sizeof(service->signon) - 1 ? signon_len :
+             sizeof(service->signon) - 1));
       ret = TRUE;
     }
     break;
@@ -279,7 +522,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
   case SILC_ATTRIBUTE_STATUS_MOOD:
   case SILC_ATTRIBUTE_PREFERRED_CONTACT:
     {
-      SilcUInt32 *mask = *object;
+      SilcUInt32 *mask = (SilcUInt32 *)object;
       if (object_size != sizeof(SilcUInt32))
        break;
       if (payload->data_len < 4)
@@ -293,7 +536,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
   case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
   case SILC_ATTRIBUTE_TIMEZONE:
     {
-      char *string = *object;
+      char *string = object;
       if (payload->data_len < 2)
        break;
       SILC_GET16_MSB(len, payload->data);
@@ -308,19 +551,20 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
 
   case SILC_ATTRIBUTE_STATUS_MESSAGE:
   case SILC_ATTRIBUTE_EXTENSION:
+  case SILC_ATTRIBUTE_USER_ICON:
     {
-      SilcAttributeObjMime *mime = *object;
+      SilcMime mime = object;
       if (object_size != sizeof(*mime))
        break;
-      mime->mime = (const unsigned char *)payload->data;
-      mime->mime_len = payload->data_len;
+      if (!silc_mime_decode(mime, payload->data, payload->data_len))
+       break;
       ret = TRUE;
     }
     break;
 
   case SILC_ATTRIBUTE_GEOLOCATION:
     {
-      SilcAttributeObjGeo *geo = *object;
+      SilcAttributeObjGeo *geo = object;
       SilcBufferStruct buffer;
       int res;
       if (object_size != sizeof(*geo))
@@ -333,7 +577,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
                                 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
                                 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
                                 SILC_STR_END);
-      if (res == 1)
+      if (res == -1)
        break;
       ret = TRUE;
     }
@@ -341,7 +585,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
 
   case SILC_ATTRIBUTE_DEVICE_INFO:
     {
-      SilcAttributeObjDevice *dev = *object;
+      SilcAttributeObjDevice *dev = object;
       SilcBufferStruct buffer;
       SilcUInt32 type;
       int res;
@@ -357,7 +601,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
                             SILC_STR_UI16_STRING_ALLOC(&dev->model),
                             SILC_STR_UI16_STRING_ALLOC(&dev->language),
                             SILC_STR_END);
-      if (res == 1)
+      if (res == -1)
        break;
       dev->type = type;
       ret = TRUE;
@@ -367,7 +611,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
   case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
   case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
     {
-      SilcAttributeObjPk *pk = *object;
+      SilcAttributeObjPk *pk = object;
       SilcBufferStruct buffer;
       int res;
       if (object_size != sizeof(*pk))
@@ -378,7 +622,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
        silc_buffer_unformat(&buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
                             SILC_STR_END);
-      if (res == 1)
+      if (res == -1 || len > silc_buffer_len(&buffer) - 2)
        break;
       pk->data = silc_memdup(payload->data + 2 + len,
                             payload->data_len - 2 - len);
@@ -390,7 +634,7 @@ bool silc_attribute_get_object(SilcAttributePayload payload,
   case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
   case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
     {
-      SilcAttributeObjPk *pk = *object;
+      SilcAttributeObjPk *pk = object;
       if (object_size != sizeof(*pk))
        break;
       pk->type = NULL;