gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] 62/171: -change api


From: gnunet
Subject: [GNUnet-SVN] [gnunet] 62/171: -change api
Date: Thu, 04 Jan 2018 16:09:30 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

commit a84624407eedd5418d36de590571da47d2f47015
Author: Schanzenbach, Martin <address@hidden>
AuthorDate: Wed Dec 28 18:40:17 2016 +0100

    -change api
---
 src/credential/Makefile.am                 |   1 +
 src/credential/credential.h                |  47 +++-
 src/credential/credential_api.c            | 142 ++++++++---
 src/credential/credential_misc.c           |   1 +
 src/credential/credential_serialization.c  | 175 ++++++++++----
 src/credential/credential_serialization.h  |  17 ++
 src/credential/gnunet-credential.c         | 171 ++++++++++++--
 src/credential/gnunet-service-credential.c | 367 ++++++++++++++++++++++-------
 src/credential/plugin_rest_credential.c    |   3 +-
 src/credential/test_credential_collect.sh  |  47 ++++
 src/credential/test_credential_lookup.conf |   2 +-
 src/credential/test_credential_verify.sh   |   5 +-
 src/include/gnunet_credential_service.h    |  15 +-
 src/include/gnunet_protocols.h             |   4 +
 14 files changed, 797 insertions(+), 200 deletions(-)

diff --git a/src/credential/Makefile.am b/src/credential/Makefile.am
index db3bc8027..ca11c5e4f 100644
--- a/src/credential/Makefile.am
+++ b/src/credential/Makefile.am
@@ -69,6 +69,7 @@ gnunet_service_credential_LDADD = \
        libgnunetcredential.la \
   $(top_builddir)/src/util/libgnunetutil.la \
        $(top_builddir)/src/gns/libgnunetgns.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(GN_LIBINTL)
 
diff --git a/src/credential/credential.h b/src/credential/credential.h
index c5c0183cc..f16249c1b 100644
--- a/src/credential/credential.h
+++ b/src/credential/credential.h
@@ -30,6 +30,41 @@
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
+ * Message from client to Credential service to collect credentials.
+ */
+struct CollectMessage
+{
+  /**
+   * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Subject public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
+
+  /**
+   * Trust anchor
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+
+  /**
+   * Length of the issuer attribute
+   */
+  uint16_t issuer_attribute_len;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /* Followed by the zero-terminated attribute */
+
+};
+
+
+/**
  * Message from client to Credential service to verify attributes.
  */
 struct VerifyMessage
@@ -50,21 +85,21 @@ struct VerifyMessage
   struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
 
   /**
-   * Length of the issuer attribute
+   * Number of credentials
    */
-  uint16_t issuer_attribute_len;
+  uint32_t c_count;
 
   /**
-   * Length of the subject attribute
+   * Length of the issuer attribute
    */
-  uint16_t subject_attribute_len;
+  uint16_t issuer_attribute_len;
 
   /**
    * Unique identifier for this request (for key collisions).
    */
   uint32_t id GNUNET_PACKED;
 
-  /* Followed by the zero-terminated attributes to look up */
+  /* Followed by the zero-terminated attribute and credentials to look up */
 
 };
 
@@ -72,7 +107,7 @@ struct VerifyMessage
 /**
  * Message from CREDENTIAL service to client: new results.
  */
-struct VerifyResultMessage
+struct DelegationChainResultMessage
 {
   /**
     * Header of type #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT
diff --git a/src/credential/credential_api.c b/src/credential/credential_api.c
index e991b4153..b201d4d9c 100644
--- a/src/credential/credential_api.c
+++ b/src/credential/credential_api.c
@@ -61,7 +61,7 @@ struct GNUNET_CREDENTIAL_Request
   /**
    * processor to call on verify result
    */
-  GNUNET_CREDENTIAL_VerifyResultProcessor verify_proc;
+  GNUNET_CREDENTIAL_CredentialResultProcessor verify_proc;
 
   /**
    * @e verify_proc closure
@@ -100,12 +100,12 @@ struct GNUNET_CREDENTIAL_Handle
   /**
    * Head of linked list of active verify requests.
    */
-  struct GNUNET_CREDENTIAL_Request *verify_head;
+  struct GNUNET_CREDENTIAL_Request *request_head;
 
   /**
    * Tail of linked list of active verify requests.
    */
-  struct GNUNET_CREDENTIAL_Request *verify_tail;
+  struct GNUNET_CREDENTIAL_Request *request_tail;
 
   /**
    * Reconnect task
@@ -185,7 +185,6 @@ mq_error_handler (void *cls,
   force_reconnect (handle);
 }
 
-
 /**
  * Check validity of message received from the CREDENTIAL service
  *
@@ -194,7 +193,7 @@ mq_error_handler (void *cls,
  */
 static int
 check_result (void *cls,
-              const struct VerifyResultMessage *vr_msg)
+              const struct DelegationChainResultMessage *vr_msg)
 {
   //TODO
   return GNUNET_OK;
@@ -209,7 +208,7 @@ check_result (void *cls,
  */
 static void
 handle_result (void *cls,
-               const struct VerifyResultMessage *vr_msg)
+               const struct DelegationChainResultMessage *vr_msg)
 {
   struct GNUNET_CREDENTIAL_Handle *handle = cls;
   uint32_t r_id = ntohl (vr_msg->id);
@@ -219,30 +218,30 @@ handle_result (void *cls,
   uint32_t c_count = ntohl (vr_msg->c_count);
   struct GNUNET_CREDENTIAL_Delegation d_chain[d_count];
   struct GNUNET_CREDENTIAL_Credential creds[c_count];
-  GNUNET_CREDENTIAL_VerifyResultProcessor proc;
+  GNUNET_CREDENTIAL_CredentialResultProcessor proc;
   void *proc_cls;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received verify reply from CREDENTIAL service\n");
-  for (vr = handle->verify_head; NULL != vr; vr = vr->next)
+  for (vr = handle->request_head; NULL != vr; vr = vr->next)
     if (vr->r_id == r_id)
       break;
   if (NULL == vr)
     return;
   proc = vr->verify_proc;
   proc_cls = vr->proc_cls;
-  GNUNET_CONTAINER_DLL_remove (handle->verify_head,
-                               handle->verify_tail,
+  GNUNET_CONTAINER_DLL_remove (handle->request_head,
+                               handle->request_tail,
                                vr);
   GNUNET_MQ_discard (vr->env);
   GNUNET_free (vr);
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CREDENTIAL_delegation_chain_deserialize (mlen,
-                                                       (const char*) 
&vr_msg[1],
-                                                       d_count,
-                                                       d_chain,
-                                                       c_count,
-                                                       creds));
+                                                                 (const char*) 
&vr_msg[1],
+                                                                 d_count,
+                                                                 d_chain,
+                                                                 c_count,
+                                                                 creds));
   if (GNUNET_NO == ntohl (vr_msg->cred_found))
   {
     proc (proc_cls,
@@ -271,7 +270,11 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
   struct GNUNET_MQ_MessageHandler handlers[] = {
     GNUNET_MQ_hd_var_size (result,
                            GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT,
-                           struct VerifyResultMessage,
+                           struct DelegationChainResultMessage,
+                           handle),
+    GNUNET_MQ_hd_var_size (result,
+                           GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT,
+                           struct DelegationChainResultMessage,
                            handle),
     GNUNET_MQ_handler_end ()
   };
@@ -287,7 +290,7 @@ reconnect (struct GNUNET_CREDENTIAL_Handle *handle)
                                       handle);
   if (NULL == handle->mq)
     return;
-  for (vr = handle->verify_head; NULL != vr; vr = vr->next)
+  for (vr = handle->request_head; NULL != vr; vr = vr->next)
     GNUNET_MQ_send_copy (handle->mq,
                          vr->env);
 }
@@ -334,7 +337,7 @@ GNUNET_CREDENTIAL_disconnect (struct 
GNUNET_CREDENTIAL_Handle *handle)
     GNUNET_SCHEDULER_cancel (handle->reconnect_task);
     handle->reconnect_task = NULL;
   }
-  GNUNET_assert (NULL == handle->verify_head);
+  GNUNET_assert (NULL == handle->request_head);
   GNUNET_free (handle);
 }
 
@@ -349,13 +352,81 @@ GNUNET_CREDENTIAL_verify_cancel (struct 
GNUNET_CREDENTIAL_Request *vr)
 {
   struct GNUNET_CREDENTIAL_Handle *handle = vr->credential_handle;
 
-  GNUNET_CONTAINER_DLL_remove (handle->verify_head,
-                               handle->verify_tail,
+  GNUNET_CONTAINER_DLL_remove (handle->request_head,
+                               handle->request_tail,
                                vr);
   GNUNET_MQ_discard (vr->env);
   GNUNET_free (vr);
 }
 
+
+/**
+ * Performs attribute collection.
+ * Collects all credentials of subject to fulfill the 
+ * attribute, if possible
+ *
+ * @param handle handle to the Credential service
+ * @param issuer_key the issuer public key
+ * @param issuer_attribute the issuer attribute
+ * @param subject_key the subject public key
+ * @param credential_count number of credentials provided
+ * @param credentials subject credentials
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the queued request
+ */
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                           const char *issuer_attribute,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*subject_key,
+                           GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+                           void *proc_cls)
+{
+  /* IPC to shorten credential names, return shorten_handle */
+  struct CollectMessage *c_msg;
+  struct GNUNET_CREDENTIAL_Request *vr;
+  size_t nlen;
+
+  if (NULL == issuer_attribute)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  //DEBUG LOG
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to collect `%s' in CREDENTIAL\n",
+       issuer_attribute);
+  nlen = strlen (issuer_attribute) + 1;
+  if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  vr = GNUNET_new (struct GNUNET_CREDENTIAL_Request);
+  vr->credential_handle = handle;
+  vr->verify_proc = proc;
+  vr->proc_cls = proc_cls;
+  vr->r_id = handle->r_id_gen++;
+  vr->env = GNUNET_MQ_msg_extra (c_msg,
+                                 nlen,
+                                 GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT);
+  c_msg->id = htonl (vr->r_id);
+  c_msg->subject_key = *subject_key;
+  c_msg->issuer_key =  *issuer_key;
+  c_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
+  GNUNET_memcpy (&c_msg[1],
+                 issuer_attribute,
+                 strlen (issuer_attribute));
+  GNUNET_CONTAINER_DLL_insert (handle->request_head,
+                               handle->request_tail,
+                               vr);
+  if (NULL != handle->mq)
+    GNUNET_MQ_send_copy (handle->mq,
+                         vr->env);
+  return vr;
+}
 /**
  * Performs attribute verification.
  * Checks if there is a delegation chain from
@@ -368,7 +439,8 @@ GNUNET_CREDENTIAL_verify_cancel (struct 
GNUNET_CREDENTIAL_Request *vr)
  * @param issuer_key the issuer public key
  * @param issuer_attribute the issuer attribute
  * @param subject_key the subject public key
- * @param subject_attribute the attribute claimed by the subject
+ * @param credential_count number of credentials provided
+ * @param credentials subject credentials
  * @param proc function to call on result
  * @param proc_cls closure for processor
  * @return handle to the queued request
@@ -378,25 +450,31 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle 
*handle,
                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
                           const char *issuer_attribute,
                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject_key,
-                          const char *subject_attribute,
-                          GNUNET_CREDENTIAL_VerifyResultProcessor proc,
+                          uint32_t credential_count,
+                          const struct GNUNET_CREDENTIAL_Credential 
*credentials,
+                          GNUNET_CREDENTIAL_CredentialResultProcessor proc,
                           void *proc_cls)
 {
   /* IPC to shorten credential names, return shorten_handle */
   struct VerifyMessage *v_msg;
   struct GNUNET_CREDENTIAL_Request *vr;
   size_t nlen;
+  size_t clen;
 
-  if (NULL == issuer_attribute || NULL == subject_attribute)
+  if (NULL == issuer_attribute || NULL == credentials)
   {
     GNUNET_break (0);
     return NULL;
   }
+
+  clen = GNUNET_CREDENTIAL_credentials_get_size (credential_count,
+                                                 credentials);
+
   //DEBUG LOG
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Trying to verify `%s' in CREDENTIAL\n",
        issuer_attribute);
-  nlen = strlen (issuer_attribute) + strlen (subject_attribute) + 1;
+  nlen = strlen (issuer_attribute) + 1 + clen;
   if (nlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*vr))
   {
     GNUNET_break (0);
@@ -412,17 +490,19 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle 
*handle,
                                  GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY);
   v_msg->id = htonl (vr->r_id);
   v_msg->subject_key = *subject_key;
+  v_msg->c_count = htonl(credential_count);
   v_msg->issuer_key =  *issuer_key;
   v_msg->issuer_attribute_len = htons(strlen(issuer_attribute));
-  v_msg->subject_attribute_len = htons(strlen(subject_attribute));
   GNUNET_memcpy (&v_msg[1],
                  issuer_attribute,
                  strlen (issuer_attribute));
-  GNUNET_memcpy (((char*)&v_msg[1]) + strlen (issuer_attribute),
-                 subject_attribute,
-                 strlen (subject_attribute));
-  GNUNET_CONTAINER_DLL_insert (handle->verify_head,
-                               handle->verify_tail,
+  GNUNET_CREDENTIAL_credentials_serialize (credential_count,
+                                           credentials,
+                                           clen,
+                                           ((char*)&v_msg[1])
+                                           + strlen (issuer_attribute) + 1);
+  GNUNET_CONTAINER_DLL_insert (handle->request_head,
+                               handle->request_tail,
                                vr);
   if (NULL != handle->mq)
     GNUNET_MQ_send_copy (handle->mq,
diff --git a/src/credential/credential_misc.c b/src/credential/credential_misc.c
index f1be433e0..7849e81e6 100644
--- a/src/credential/credential_misc.c
+++ b/src/credential/credential_misc.c
@@ -105,6 +105,7 @@ GNUNET_CREDENTIAL_credential_from_string (const char* s)
   GNUNET_memcpy (&cred[1],
                  name,
                  strlen (name)+1);
+  cred->issuer_attribute_len = strlen ((char*)&cred[1]);
   cred->issuer_attribute = (char*)&cred[1];
   return cred;
 }
diff --git a/src/credential/credential_serialization.c 
b/src/credential/credential_serialization.c
index 0586e6baa..76bf491c9 100644
--- a/src/credential/credential_serialization.c
+++ b/src/credential/credential_serialization.c
@@ -138,6 +138,121 @@ GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
   }
   return GNUNET_OK;
 }
+
+
+/**
+ * Calculate how many bytes we will need to serialize
+ * the credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @return the required size to serialize
+ */
+size_t
+GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+                                        const struct 
GNUNET_CREDENTIAL_Credential *cd)
+{
+  unsigned int i;
+  size_t ret;
+
+  ret = sizeof (struct CredentialEntry) * (c_count);
+
+  for (i=0; i<c_count;i++)
+  {
+    GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
+    ret += cd[i].issuer_attribute_len;
+  }
+  return ret;
+}
+/**
+ * Serizalize the given credentials
+ *
+ * @param c_count number of credential entries
+ * @param cd a #GNUNET_CREDENTIAL_Credential
+ * @param dest_size size of the destination
+ * @param dest where to store the result
+ * @return the size of the data, -1 on failure
+ */
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+                                         const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                         size_t dest_size,
+                                         char *dest)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
+    c_rec.issuer_key = cd[i].issuer_key;
+    c_rec.subject_key = cd[i].subject_key;
+    c_rec.signature = cd[i].signature;
+    c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
+    c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + 
cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+    c_rec.expiration = htonl ((uint32_t) cd[i].expiration.abs_value_us);
+    if (off + sizeof (c_rec) > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   &c_rec,
+                   sizeof (c_rec));
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > dest_size)
+      return -1;
+    GNUNET_memcpy (&dest[off],
+                   cd[i].issuer_attribute,
+                   cd[i].issuer_attribute_len);
+    off += cd[i].issuer_attribute_len;
+  }
+
+  return off;
+}
+
+
+
+/**
+ * Deserialize the given destination
+ *
+ * @param len size of the serialized creds
+ * @param src the serialized data
+ * @param c_count the number of credential entries
+ * @param cd where to put the credential data
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+                                           const char *src,
+                                           unsigned int c_count,
+                                           struct GNUNET_CREDENTIAL_Credential 
*cd)
+{
+  struct CredentialEntry c_rec;
+  unsigned int i;
+  size_t off;
+
+  off = 0;
+  for (i=0;i<c_count;i++)
+  {
+    if (off + sizeof (c_rec) > len)
+      return GNUNET_SYSERR;
+    GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
+    cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
+    cd[i].issuer_key = c_rec.issuer_key;
+    cd[i].subject_key = c_rec.subject_key;
+    cd[i].signature = c_rec.signature;
+    cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration);
+    off += sizeof (c_rec);
+    if (off + cd[i].issuer_attribute_len > len)
+      return GNUNET_SYSERR;
+    cd[i].issuer_attribute = &src[off];
+    off += cd[i].issuer_attribute_len;
+  }
+  return GNUNET_OK;
+}
+
+
+
 /**
  * Calculate how many bytes we will need to serialize
  * the given delegation chain and credential
@@ -158,7 +273,6 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int 
d_count,
   size_t ret;
 
   ret = sizeof (struct ChainEntry) * (d_count);
-  ret += sizeof (struct CredentialEntry) * (c_count);
 
   for (i=0; i<d_count;i++)
   {
@@ -167,11 +281,7 @@ GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int 
d_count,
                     dd[i].subject_attribute_len) >= ret);
     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
   }
-  for (i=0; i<c_count;i++)
-  {
-    GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
-    ret += cd[i].issuer_attribute_len;
-  }
+  return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
   return ret;
 }
 
@@ -195,7 +305,6 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int 
d_count,
                                               char *dest)
 {
   struct ChainEntry rec;
-  struct CredentialEntry c_rec;
   unsigned int i;
   size_t off;
 
@@ -227,30 +336,10 @@ GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned 
int d_count,
                    dd[i].subject_attribute_len);
     off += dd[i].subject_attribute_len;
   }
-  for (i=0;i<c_count;i++)
-  {
-    c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
-    c_rec.issuer_key = cd[i].issuer_key;
-    c_rec.subject_key = cd[i].subject_key;
-    c_rec.signature = cd[i].signature;
-    c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
-    c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + 
cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
-    c_rec.expiration = htonl ((uint32_t) cd[i].expiration.abs_value_us);
-    if (off + sizeof (c_rec) > dest_size)
-      return -1;
-    GNUNET_memcpy (&dest[off],
-                   &c_rec,
-                   sizeof (c_rec));
-    off += sizeof (c_rec);
-    if (off + cd[i].issuer_attribute_len > dest_size)
-      return -1;
-    GNUNET_memcpy (&dest[off],
-                   cd[i].issuer_attribute,
-                   cd[i].issuer_attribute_len);
-    off += cd[i].issuer_attribute_len;
-  }
-
-  return off;
+  return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
+                                                      cd,
+                                                      dest_size-off,
+                                                      &dest[off]);
 }
 
 
@@ -274,7 +363,6 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
                                                 struct 
GNUNET_CREDENTIAL_Credential *cd)
 {
   struct ChainEntry rec;
-  struct CredentialEntry c_rec;
   unsigned int i;
   size_t off;
 
@@ -298,26 +386,11 @@ GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t 
len,
     dd[i].subject_attribute = &src[off];
     off += dd[i].subject_attribute_len;
   }
-  for (i=0;i<c_count;i++)
-  {
-    if (off + sizeof (c_rec) > len)
-      return GNUNET_SYSERR;
-    GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
-    cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
-    cd[i].issuer_key = c_rec.issuer_key;
-    cd[i].subject_key = c_rec.subject_key;
-    cd[i].signature = c_rec.signature;
-    cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration);
-    off += sizeof (c_rec);
-    if (off + cd[i].issuer_attribute_len > len)
-      return GNUNET_SYSERR;
-    cd[i].issuer_attribute = &src[off];
-    off += cd[i].issuer_attribute_len;
-  }
-  return GNUNET_OK;
+  return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
+                                                    &src[off],
+                                                    c_count,
+                                                    cd);
 }
-
-
 int
 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential 
*cred,
                                         char **data)
diff --git a/src/credential/credential_serialization.h 
b/src/credential/credential_serialization.h
index eb1327f34..b870d47dc 100644
--- a/src/credential/credential_serialization.h
+++ b/src/credential/credential_serialization.h
@@ -130,6 +130,23 @@ GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
                                                     struct 
GNUNET_CREDENTIAL_Delegation *dd,
                                                     unsigned int c_count,
                                                     struct 
GNUNET_CREDENTIAL_Credential *cd);
+  size_t
+  GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
+                                          const struct 
GNUNET_CREDENTIAL_Credential *cd);
+
+ssize_t
+GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
+                                         const struct 
GNUNET_CREDENTIAL_Credential *cd,
+                                         size_t dest_size,
+                                         char *dest);
+
+
+int
+GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
+                                           const char *src,
+                                           unsigned int c_count,
+                                           struct GNUNET_CREDENTIAL_Credential 
*cd);
+
 
 int
 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential 
*cred,
diff --git a/src/credential/gnunet-credential.c 
b/src/credential/gnunet-credential.c
index b31c2f66e..fb7bdb7f8 100644
--- a/src/credential/gnunet-credential.c
+++ b/src/credential/gnunet-credential.c
@@ -55,6 +55,11 @@ static struct GNUNET_TIME_Relative timeout;
 static struct GNUNET_CREDENTIAL_Request *verify_request;
 
 /**
+ * Handle to collect request
+ */
+static struct GNUNET_CREDENTIAL_Request *collect_request;
+
+/**
  * Task scheduled to handle timeout.
  */
 static struct GNUNET_SCHEDULER_Task *tt;
@@ -91,9 +96,9 @@ struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
 static char *issuer_key;
 
 /**
- * Issuer ego
+ * ego
  */
-static char *issuer_ego_name;
+static char *ego_name;
 
 /**
  * Issuer attribute
@@ -110,6 +115,10 @@ static uint32_t verify;
  */
 static uint32_t create_cred;
 
+/**
+ * Collect mode
+ */
+static uint32_t collect;
 
 /**
  * Task run on shutdown.  Cleans up everything.
@@ -149,6 +158,39 @@ do_timeout (void *cls)
   GNUNET_SCHEDULER_shutdown ();
 }
 
+/**
+ * Function called with the result of a Credential lookup.
+ *
+ * @param cls the 'const char *' name that was resolved
+ * @param cd_count number of records returned
+ * @param cd array of @a cd_count records with the results
+ */
+static void
+handle_collect_result (void *cls,
+                      unsigned int d_count,
+                      struct GNUNET_CREDENTIAL_Delegation *dc,
+                      unsigned int c_count,
+                      struct GNUNET_CREDENTIAL_Credential *cred)
+{
+  int i;
+  char* line;
+
+  verify_request = NULL;
+  if (NULL != cred)
+  {
+    for (i=0;i<c_count;i++)
+    {
+      line = GNUNET_CREDENTIAL_credential_to_string (&cred[i]);
+      printf ("%s\n",
+              line);
+      GNUNET_free (line);
+    }
+  }
+
+
+  GNUNET_SCHEDULER_shutdown ();
+}
+
 
 /**
  * Function called with the result of a Credential lookup.
@@ -230,15 +272,42 @@ identity_cb (void *cls,
   el = NULL;
   if (NULL == ego)
   {
-    if (NULL != issuer_ego_name)
+    if (NULL != ego_name)
     {
       fprintf (stderr,
                _("Ego `%s' not known to identity service\n"),
-               issuer_ego_name);
+               ego_name);
     }
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+
+  if (GNUNET_YES == collect)
+  {
+    
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
+                                                    strlen (issuer_key),
+                                                    &issuer_pkey))
+    {
+      fprintf (stderr,
+               _("Issuer public key `%s' is not well-formed\n"),
+               issuer_key);
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+
+    collect_request = GNUNET_CREDENTIAL_collect(credential,
+                                                &issuer_pkey,
+                                                issuer_attr, //TODO argument
+                                                privkey,
+                                                &handle_collect_result,
+                                                NULL);
+    return;
+  }
+
+  //Else issue
+
   if (NULL == expiration)
   {
     fprintf (stderr,
@@ -261,8 +330,8 @@ identity_cb (void *cls,
 
 
   privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-  GNUNET_free_non_null (issuer_ego_name);
-  issuer_ego_name = NULL;
+  GNUNET_free_non_null (ego_name);
+  ego_name = NULL;
   crd = GNUNET_CREDENTIAL_credential_issue (privkey,
                                             &subject_pkey,
                                             issuer_attr,
@@ -299,7 +368,46 @@ run (void *cls,
                                      &do_timeout, NULL);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
 
+  if (GNUNET_YES == collect) {
+    if (NULL == issuer_key)
+    {
+      fprintf (stderr,
+               _("Issuer public key not well-formed\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+
+    credential = GNUNET_CREDENTIAL_connect (cfg);
+
+    if (NULL == credential)
+    {
+      fprintf (stderr,
+               _("Failed to connect to CREDENTIAL\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    if (NULL == issuer_attr)
+    {
+      fprintf (stderr,
+               _("You must provide issuer the attribute\n"));
+      GNUNET_SCHEDULER_shutdown ();
+    }
+
+    if (NULL == ego_name)
+    {
+      fprintf (stderr,
+               _("ego required\n"));
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+
+    }
+    el = GNUNET_IDENTITY_ego_lookup (cfg,
+                                     ego_name,
+                                     &identity_cb,
+                                     (void *) cfg);
+    return;
 
+  } 
 
   if (NULL == subject_key)
   {
@@ -320,7 +428,6 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
   if (GNUNET_YES == verify) {
     if (NULL == issuer_key)
     {
@@ -348,7 +455,6 @@ run (void *cls,
                _("Failed to connect to CREDENTIAL\n"));
       GNUNET_SCHEDULER_shutdown ();
     }
-
     if (NULL == issuer_attr || NULL == subject_credential)
     {
       fprintf (stderr,
@@ -356,18 +462,50 @@ run (void *cls,
       GNUNET_SCHEDULER_shutdown ();
     }
 
-    printf ("Trying to find a chain from a credential under %s of %s to the 
attribute %s issued by %s\n",
-            subject_credential, subject_key, issuer_attr, issuer_key);
+    //Subject credentials are comma separated
+    char *tmp = GNUNET_strdup (subject_credential);
+    char *tok = strtok (tmp, ",");
+    if (NULL == tok)
+    {
+      fprintf (stderr,
+               "Invalid subject credentials\n");
+      GNUNET_free (tmp);
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    int count = 1;
+    int i;
+    while (NULL != (tok = strtok(NULL, ",")))
+      count++;
+    struct GNUNET_CREDENTIAL_Credential credentials[count];
+    struct GNUNET_CREDENTIAL_Credential *cred;
+    GNUNET_free (tmp);
+    tmp = GNUNET_strdup (subject_credential);
+    tok = strtok (tmp, ",");
+    for (i=0;i<count;i++)
+    {
+      cred = GNUNET_CREDENTIAL_credential_from_string (tok);
+      GNUNET_memcpy (&credentials[i],
+                     cred,
+                     sizeof (struct GNUNET_CREDENTIAL_Credential));
+      credentials[i].issuer_attribute = GNUNET_strdup (cred->issuer_attribute);
+      tok = strtok(NULL, ",");
+      GNUNET_free (cred);
+    }
 
     verify_request = GNUNET_CREDENTIAL_verify(credential,
                                               &issuer_pkey,
                                               issuer_attr, //TODO argument
                                               &subject_pkey,
-                                              subject_credential,
+                                              count,
+                                              credentials,
                                               &handle_verify_result,
                                               NULL);
+    for (i=0;i<count;i++)
+    {
+      GNUNET_free ((char*)credentials[i].issuer_attribute);
+    }
   } else if (GNUNET_YES == create_cred) {
-    if (NULL == issuer_ego_name)
+    if (NULL == ego_name)
     {
       fprintf (stderr,
                _("Issuer ego required\n"));
@@ -376,7 +514,7 @@ run (void *cls,
 
     }
     el = GNUNET_IDENTITY_ego_lookup (cfg,
-                                     issuer_ego_name,
+                                     ego_name,
                                      &identity_cb,
                                      (void *) cfg);
     return;
@@ -416,14 +554,17 @@ main (int argc, char *const *argv)
       gettext_noop ("The public key of the authority to verify the credential 
against"), 1,
       &GNUNET_GETOPT_set_string, &issuer_key},
     {'e', "ego", "EGO",
-      gettext_noop ("The ego to use to issue"), 1,
-      &GNUNET_GETOPT_set_string, &issuer_ego_name},
+      gettext_noop ("The ego to use"), 1,
+      &GNUNET_GETOPT_set_string, &ego_name},
     {'a', "attribute", "ATTR",
       gettext_noop ("The issuer attribute to verify against or to issue"), 1, 
       &GNUNET_GETOPT_set_string, &issuer_attr},
     {'T', "ttl", "EXP",
       gettext_noop ("The time to live for the credential"), 1,
       &GNUNET_GETOPT_set_string, &expiration},
+    {'g', "collect", NULL,
+      gettext_noop ("collect credentials"), 0,
+      &GNUNET_GETOPT_set_one, &collect},
     GNUNET_GETOPT_OPTION_END
   };
   int ret;
diff --git a/src/credential/gnunet-service-credential.c 
b/src/credential/gnunet-service-credential.c
index 942b38652..4841370b3 100644
--- a/src/credential/gnunet-service-credential.c
+++ b/src/credential/gnunet-service-credential.c
@@ -31,15 +31,11 @@
 #include "gnunet_protocols.h"
 #include "gnunet_signatures.h"
 
-// For Looking up GNS request
 #include <gnunet_dnsparser_lib.h>
 #include <gnunet_identity_service.h>
 #include <gnunet_gnsrecord_lib.h>
 #include <gnunet_namestore_service.h>
 #include <gnunet_gns_service.h>
-#include "gnunet_gns_service.h"
-
-
 
 
 #define GNUNET_CREDENTIAL_MAX_LENGTH 255
@@ -311,6 +307,16 @@ struct VerifyRequestHandle
    */
   uint64_t pending_lookups;
 
+  /**
+   * Credential iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *cred_collection_iter;
+
+  /**
+   * Collect task
+   */
+  struct GNUNET_SCHEDULER_Task *collect_next_task;
+
 };
 
 
@@ -335,6 +341,11 @@ static struct GNUNET_STATISTICS_Handle *statistics;
 static struct GNUNET_GNS_Handle *gns;
 
 
+/**
+ * Handle to namestore service
+ */
+static struct GNUNET_NAMESTORE_Handle *namestore;
+
 static void
 cleanup_delegation_set (struct DelegationSetQueueEntry *ds_entry)
 {
@@ -444,6 +455,11 @@ shutdown_task (void *cls)
     GNUNET_GNS_disconnect (gns);
     gns = NULL;
   }
+  if (NULL != namestore)
+  {
+    GNUNET_NAMESTORE_disconnect (namestore);
+    namestore = NULL;
+  }
   if (NULL != statistics)
   {
     GNUNET_STATISTICS_destroy (statistics,
@@ -453,42 +469,7 @@ shutdown_task (void *cls)
 
 }
 
-/**
- * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
- *
- * @param cls client sending the message
- * @param v_msg message of type `struct VerifyMessage`
- * @return #GNUNET_OK if @a v_msg is well-formed
- */
-static int
-check_verify (void *cls,
-              const struct VerifyMessage *v_msg)
-{
-  size_t msg_size;
-  const char* attrs;
 
-  msg_size = ntohs (v_msg->header.size);
-  if (msg_size < sizeof (struct VerifyMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if ((ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH) ||
-      (ntohs (v_msg->subject_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  attrs = (const char *) &v_msg[1];
-
-  if ( ('\0' != attrs[ntohs(v_msg->header.size) - sizeof (struct 
VerifyMessage) - 1]) ||
-       (strlen (attrs) > GNUNET_CREDENTIAL_MAX_LENGTH * 2) )
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
 
 /**
  * Send.
@@ -499,7 +480,7 @@ static void
 send_lookup_response (struct VerifyRequestHandle *vrh)
 {
   struct GNUNET_MQ_Envelope *env;
-  struct VerifyResultMessage *rmsg;
+  struct DelegationChainResultMessage *rmsg;
   struct DelegationChainEntry *dce;
   struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
   struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
@@ -792,21 +773,14 @@ backward_resolution (void* cls,
  * @param rd the record data
  */
 static void
-handle_credential_query (void* cls,
-                         uint32_t rd_count,
-                         const struct GNUNET_GNSRECORD_Data *rd)
+delegation_chain_resolution_start (void* cls)
 {
   struct VerifyRequestHandle *vrh = cls;
   struct DelegationSetQueueEntry *ds_entry;
-  struct GNUNET_CREDENTIAL_Credential *crd;
   struct CredentialRecordEntry *cr_entry;
-  int cred_record_count;
-  int i;
-
   vrh->lookup_request = NULL;
-  cred_record_count = 0;
 
-  if (0 == rd_count)
+  if (0 == vrh->cred_chain_size)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "No credentials found\n");
@@ -814,31 +788,13 @@ handle_credential_query (void* cls,
     return;
   }
 
-  for (i=0; i < rd_count; i++)
+  for (cr_entry = vrh->cred_chain_head; cr_entry != NULL; cr_entry = 
cr_entry->next)
   {
-    if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
-      continue;
-    cred_record_count++;
-    crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
-                                                    rd[i].data_size);
-    if (NULL == crd)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Invalid credential found\n");
-      continue;
-    }
-    cr_entry = GNUNET_new (struct CredentialRecordEntry);
-    cr_entry->credential = crd;
-    GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
-                                      vrh->cred_chain_tail,
-                                      cr_entry);
-    vrh->cred_chain_size++;
-
-    if (0 != memcmp (&crd->issuer_key,
+    if (0 != memcmp (&cr_entry->credential->issuer_key,
                      &vrh->issuer_key,
                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
       continue;
-    if (0 != strcmp (crd->issuer_attribute, vrh->issuer_attribute))
+    if (0 != strcmp (cr_entry->credential->issuer_attribute, 
vrh->issuer_attribute))
       continue;
     //Found match prematurely
     send_lookup_response (vrh);
@@ -878,6 +834,40 @@ handle_credential_query (void* cls,
                                                 ds_entry);
 }
 
+/**
+ * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY message
+ *
+ * @param cls client sending the message
+ * @param v_msg message of type `struct VerifyMessage`
+ * @return #GNUNET_OK if @a v_msg is well-formed
+ */
+static int
+check_verify (void *cls,
+              const struct VerifyMessage *v_msg)
+{
+  size_t msg_size;
+  const char* attr;
+
+  msg_size = ntohs (v_msg->header.size);
+  if (msg_size < sizeof (struct VerifyMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (ntohs (v_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  attr = (const char *) &v_msg[1];
+
+  if ( strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
 
 /**
  * Handle Credential verification requests from client
@@ -890,12 +880,11 @@ static void
 handle_verify (void *cls,
                const struct VerifyMessage *v_msg) 
 {
-  char attrs[GNUNET_CREDENTIAL_MAX_LENGTH*2 + 1];
+  char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
   char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
-  char subject_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1 + 4];
   struct VerifyRequestHandle *vrh;
   struct GNUNET_SERVICE_Client *client = cls;
-  char *attrptr = attrs;
+  char *attrptr = attr;
   const char *utf_in;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -904,12 +893,8 @@ handle_verify (void *cls,
   utf_in = (const char *) &v_msg[1];
   GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
 
-  GNUNET_memcpy (issuer_attribute, attrs, ntohs (v_msg->issuer_attribute_len));
+  GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
   issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
-  GNUNET_memcpy (subject_attribute, attrs+strlen(issuer_attribute), ntohs 
(v_msg->subject_attribute_len));
-  strcpy (subject_attribute+ntohs (v_msg->subject_attribute_len),
-          ".gnu");
-  subject_attribute[ntohs (v_msg->subject_attribute_len)+4] = '\0';
   vrh = GNUNET_new (struct VerifyRequestHandle);
   GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
   vrh->client = client;
@@ -917,14 +902,169 @@ handle_verify (void *cls,
   vrh->issuer_key = v_msg->issuer_key;
   vrh->subject_key = v_msg->subject_key;
   vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
-
-  if (NULL == subject_attribute)
+  if (NULL == issuer_attribute)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "No subject attribute provided!\n");
+                "No issuer attribute provided!\n");
+    send_lookup_response (vrh);
+    return;
+  }
+  /**
+   * First, collect credentials
+   * TODO: cleanup!
+   */
+  uint32_t credentials_count = ntohl(v_msg->c_count);
+  int i;
+  uint32_t credential_data_size = ntohs (v_msg->header.size) 
+    - sizeof (struct VerifyMessage)
+    - ntohs (v_msg->issuer_attribute_len)
+    - 1;
+  struct GNUNET_CREDENTIAL_Credential credentials[credentials_count];
+  char *credential_data = (char*)&v_msg[1] + ntohs 
(v_msg->issuer_attribute_len) + 1;
+  struct CredentialRecordEntry *cr_entry;
+  if (GNUNET_OK != GNUNET_CREDENTIAL_credentials_deserialize 
(credential_data_size,
+                                                              credential_data,
+                                                              
credentials_count,
+                                                              credentials))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "Cannot deserialize credentials!\n");
     send_lookup_response (vrh);
     return;
   }
+
+  for (i=0;i<credentials_count;i++) {
+    cr_entry = GNUNET_new (struct CredentialRecordEntry);
+    cr_entry->credential = GNUNET_malloc (sizeof (struct 
GNUNET_CREDENTIAL_Credential) +
+                                          strlen 
(credentials[i].issuer_attribute) + 1);
+    GNUNET_memcpy (cr_entry->credential,
+                   &credentials[i],
+                   sizeof (struct GNUNET_CREDENTIAL_Credential));
+    GNUNET_memcpy (&cr_entry->credential[1],
+                   credentials[i].issuer_attribute,
+                   strlen (credentials[i].issuer_attribute));
+    cr_entry->credential->issuer_attribute = (char*)&cr_entry->credential[1];
+    GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+                                      vrh->cred_chain_tail,
+                                      cr_entry);
+    vrh->cred_chain_size++;
+  }
+
+  delegation_chain_resolution_start (vrh);
+
+}
+
+/**
+ * We encountered an error while collecting
+ */
+static void
+handle_cred_collection_error_cb (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got disconnected from namestore database.\n");
+  vrh->cred_collection_iter = NULL;
+  send_lookup_response (vrh);
+}
+
+static void
+collect_next (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  vrh->collect_next_task = NULL;
+  GNUNET_assert (NULL != vrh->cred_collection_iter);
+  GNUNET_NAMESTORE_zone_iterator_next (vrh->cred_collection_iter);
+}
+
+/**
+ * Store credential
+ */
+static void
+handle_cred_collection_cb (void *cls,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+                           const char *label,
+                           unsigned int rd_count,
+                           const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  struct GNUNET_CREDENTIAL_Credential *crd;
+  struct CredentialRecordEntry *cr_entry;
+  int cred_record_count;
+  int i;
+
+  cred_record_count = 0;
+  for (i=0; i < rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_CREDENTIAL != rd[i].record_type)
+      continue;
+    cred_record_count++;
+    crd = GNUNET_CREDENTIAL_credential_deserialize (rd[i].data,
+                                                    rd[i].data_size);
+    if (NULL == crd)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Invalid credential found\n");
+      continue;
+    }
+    cr_entry = GNUNET_new (struct CredentialRecordEntry);
+    cr_entry->credential = crd;
+    GNUNET_CONTAINER_DLL_insert_tail (vrh->cred_chain_head,
+                                      vrh->cred_chain_tail,
+                                      cr_entry);
+    vrh->cred_chain_size++;
+  }
+  vrh->collect_next_task = GNUNET_SCHEDULER_add_now (&collect_next,
+                                                     vrh);
+}
+
+/**
+ * We encountered an error while collecting
+ */
+static void
+handle_cred_collection_finished_cb (void *cls)
+{
+  struct VerifyRequestHandle *vrh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Done collecting credentials.\n");
+  vrh->cred_collection_iter = NULL;
+  delegation_chain_resolution_start (vrh);
+}
+
+/**
+ * Handle Credential collection requests from client
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void
+handle_collect (void *cls,
+                const struct CollectMessage *c_msg) 
+{
+  char attr[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  char issuer_attribute[GNUNET_CREDENTIAL_MAX_LENGTH + 1];
+  struct VerifyRequestHandle *vrh;
+  struct GNUNET_SERVICE_Client *client = cls;
+  char *attrptr = attr;
+  const char *utf_in;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received COLLECT message\n");
+
+  utf_in = (const char *) &c_msg[1];
+  GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
+
+  GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
+  issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
+  vrh = GNUNET_new (struct VerifyRequestHandle);
+  GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
+  vrh->client = client;
+  vrh->request_id = c_msg->id;
+  vrh->issuer_key = c_msg->issuer_key;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key,
+                                      &vrh->subject_key);
+  vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
+
   if (NULL == issuer_attribute)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
@@ -933,23 +1073,58 @@ handle_verify (void *cls,
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Looking up %s\n",
-              subject_attribute);
+              "Getting credentials for subject\n");
   /**
    * First, get attribute from subject
    */
-  vrh->lookup_request = GNUNET_GNS_lookup (gns,
-                                           subject_attribute,
-                                           &v_msg->subject_key, //subject_pkey,
-                                           GNUNET_GNSRECORD_TYPE_CREDENTIAL,
-                                           GNUNET_GNS_LO_DEFAULT,
-                                           NULL, //shorten_key, always NULL
-                                           &handle_credential_query,
-                                           vrh);
+  vrh->cred_collection_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore,
+                                                                     
&c_msg->subject_key,
+                                                                     
&handle_cred_collection_error_cb,
+                                                                     vrh,
+                                                                     
&handle_cred_collection_cb,
+                                                                     vrh,
+                                                                     
&handle_cred_collection_finished_cb,
+                                                                     vrh);
 }
 
 
 /**
+ * Checks a #GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT message
+ *
+ * @param cls client sending the message
+ * @param v_msg message of type `struct CollectMessage`
+ * @return #GNUNET_OK if @a v_msg is well-formed
+ */
+static int
+check_collect (void *cls,
+               const struct CollectMessage *c_msg)
+{
+  size_t msg_size;
+  const char* attr;
+
+  msg_size = ntohs (c_msg->header.size);
+  if (msg_size < sizeof (struct CollectMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (ntohs (c_msg->issuer_attribute_len) > GNUNET_CREDENTIAL_MAX_LENGTH)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  attr = (const char *) &c_msg[1];
+
+  if ( ('\0' != attr[ntohs(c_msg->header.size) - sizeof (struct 
CollectMessage) - 1]) ||
+       (strlen (attr) > GNUNET_CREDENTIAL_MAX_LENGTH) )
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+/**
  * One of our clients disconnected, clean up after it.
  *
  * @param cls NULL
@@ -1003,6 +1178,12 @@ run (void *cls,
     fprintf (stderr,
              _("Failed to connect to GNS\n"));
   }
+  namestore = GNUNET_NAMESTORE_connect (c);
+  if (NULL == namestore)
+  {
+    fprintf (stderr,
+             _("Failed to connect to namestore\n"));
+  }
 
   statistics = GNUNET_STATISTICS_create ("credential", c);
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
@@ -1023,6 +1204,10 @@ GNUNET_SERVICE_MAIN
                         GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY,
                         struct VerifyMessage,
                         NULL),
+ GNUNET_MQ_hd_var_size (collect,
+                        GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT,
+                        struct CollectMessage,
+                        NULL),
  GNUNET_MQ_handler_end());
 
 /* end of gnunet-service-credential.c */
diff --git a/src/credential/plugin_rest_credential.c 
b/src/credential/plugin_rest_credential.c
index 651de0075..f13e26cd4 100644
--- a/src/credential/plugin_rest_credential.c
+++ b/src/credential/plugin_rest_credential.c
@@ -492,7 +492,8 @@ verify_cred_cont (struct GNUNET_REST_RequestHandle 
*conndata_handle,
                                                      &handle->issuer_key,
                                                      handle->issuer_attr,
                                                      &handle->subject_key,
-                                                     handle->subject_attr,
+                                                     0,
+                                                     
NULL,//TODOhandle->subject_attr,
                                                      &handle_verify_response,
                                                      handle);
 
diff --git a/src/credential/test_credential_collect.sh 
b/src/credential/test_credential_collect.sh
new file mode 100755
index 000000000..6c713063f
--- /dev/null
+++ b/src/credential/test_credential_collect.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_credential_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+       echo "GNUnet command line tools cannot be found, check environmental 
variables PATH and GNUNET_PREFIX"
+       exit 77
+fi
+
+rm -rf `gnunet-config -c test_credential_lookup.conf -s PATHS -o GNUNET_HOME 
-f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+TEST_ATTR2="test2"
+gnunet-arm -s -c test_credential_lookup.conf
+gnunet-identity -C testissuer -c test_credential_lookup.conf
+gnunet-identity -C testsubject -c test_credential_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_credential_lookup.conf | grep 
testissuer | awk '{print $3}')
+#TODO1 Get credential and store it with subject (3)
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR --ttl=5m -c 
test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c1 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=testissuer 
--subject=$SUBJECT_KEY --attribute=$TEST_ATTR2 --ttl=5m -c 
test_credential_lookup.conf`
+$DO_TIMEOUT gnunet-namestore -a -z testsubject -n c2 -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$ISSUER_KEY 
--attribute=$TEST_ATTR --ego=testsubject -c test_credential_lookup.conf | paste 
-d, -s`
+echo $CREDS
+RES=$?
+gnunet-arm -e -c test_credential_lookup.conf
+
+if test $? != 0
+then
+  echo "Error collecting..."
+  exit 1
+fi
+
diff --git a/src/credential/test_credential_lookup.conf 
b/src/credential/test_credential_lookup.conf
index 7aa193abd..93b4864d9 100644
--- a/src/credential/test_credential_lookup.conf
+++ b/src/credential/test_credential_lookup.conf
@@ -11,7 +11,7 @@ PLUGINS =
 
 [credential]
 AUTOSTART = YES
-#PREFIX = valgrind --leak-check=full --track-origins=yes 
--log-file=/tmp/credlog
+PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/credlog
 
 [rest]
 #PREFIX = valgrind --leak-check=full --track-origins=yes 
--log-file=/tmp/restlog
diff --git a/src/credential/test_credential_verify.sh 
b/src/credential/test_credential_verify.sh
index 6d69e337b..d042bcfe6 100755
--- a/src/credential/test_credential_verify.sh
+++ b/src/credential/test_credential_verify.sh
@@ -57,8 +57,11 @@ CRED=`$DO_TIMEOUT gnunet-credential --issue --ego=gnunet 
--subject=$ALICE_KEY --
 # Alice stores the credential under "mygnunetcreds"
 gnunet-namestore -p -z alice -a -n $TEST_CREDENTIAL -t CRED -V "$CRED" -e 5m 
-c test_credential_lookup.conf
 
+CREDS=`$DO_TIMEOUT gnunet-credential --collect --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --ego=alice -c test_credential_lookup.conf | paste -d, 
-s`
+
+echo gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR 
--subject=$ALICE_KEY --credential=\'$CREDS\' -c test_credential_lookup.conf
 #TODO2 Add -z swich like in gnunet-gns
-RES_CRED=`gnunet-credential --verify --issuer=$SERVICE_KEY 
--attribute=$USER_ATTR --subject=$ALICE_KEY --credential=$TEST_CREDENTIAL -c 
test_credential_lookup.conf`
+gnunet-credential --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR 
--subject=$ALICE_KEY --credential="$CREDS" -c test_credential_lookup.conf
 
 
 #TODO cleanup properly
diff --git a/src/include/gnunet_credential_service.h 
b/src/include/gnunet_credential_service.h
index 906163c14..d04c0a253 100644
--- a/src/include/gnunet_credential_service.h
+++ b/src/include/gnunet_credential_service.h
@@ -235,7 +235,7 @@ GNUNET_CREDENTIAL_disconnect (struct 
GNUNET_CREDENTIAL_Handle *handle);
  * @param c_count the number of credentials found
  * @param credential the credentials
  */
-typedef void (*GNUNET_CREDENTIAL_VerifyResultProcessor) (void *cls,
+typedef void (*GNUNET_CREDENTIAL_CredentialResultProcessor) (void *cls,
                                                          unsigned int d_count,
                                                          struct 
GNUNET_CREDENTIAL_Delegation *delegation_chain,
                                                          unsigned int c_count,
@@ -286,10 +286,19 @@ GNUNET_CREDENTIAL_verify (struct GNUNET_CREDENTIAL_Handle 
*handle,
                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
                           const char *issuer_attribute,
                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*subject_key,
-                          const char *subject_attribute,
-                          GNUNET_CREDENTIAL_VerifyResultProcessor proc,
+                          uint32_t credential_count,
+                          const struct GNUNET_CREDENTIAL_Credential 
*credentials,
+                          GNUNET_CREDENTIAL_CredentialResultProcessor proc,
                           void *proc_cls);
 
+struct GNUNET_CREDENTIAL_Request*
+GNUNET_CREDENTIAL_collect (struct GNUNET_CREDENTIAL_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey 
*issuer_key,
+                           const char *issuer_attribute,
+                           const struct GNUNET_CRYPTO_EcdsaPrivateKey 
*subject_key,
+                           GNUNET_CREDENTIAL_CredentialResultProcessor proc,
+                           void *proc_cls);
+
 /**
  * Delegate an attribute
  *
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 596196311..cf26f1727 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2616,6 +2616,10 @@ extern "C"
 
 #define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 972
 
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 973
+
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 974
+
 
/******************************************************************************/
 
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]