paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / credential / plugin_gnsrecord_credential.c
index 6ae3b8980c956e1436fbf72efcf0f81073df2542..72f174fca8e95d4601001c592fd8ea502900f527 100644 (file)
@@ -2,26 +2,24 @@
      This file is part of GNUnet
      Copyright (C) 2013 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /**
  * @file credential/plugin_gnsrecord_credential.c
  * @brief gnsrecord plugin to provide the API for CREDENTIAL records
- * @author Adnan Husain
+ * @author Martin Schanzenbach
  */
 
 #include "platform.h"
@@ -29,7 +27,9 @@
 #include "gnunet_gnsrecord_lib.h"
 #include "gnunet_credential_service.h"
 #include "gnunet_gnsrecord_plugin.h"
-
+#include "gnunet_signatures.h"
+#include "credential_serialization.h"
+#include "credential_misc.h"
 
 /**
  * Convert the 'value' of a record to a string.
@@ -51,41 +51,84 @@ credential_value_to_string (void *cls,
 
   switch (type)
   {
-   case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+   case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
    {
-    struct GNUNET_CREDENTIAL_RecordData cred;
-    char *cred_str;
+    struct GNUNET_CREDENTIAL_DelegationRecord sets;
+    char *attr_str;
     char *subject_pkey;
-    char *issuer_pkey;
-    uint32_t cf; // Credential flags
-    uint32_t mdd; // Max delegation depth
-    if (data_size < sizeof (struct GNUNET_CREDENTIAL_RecordData))
-        return NULL; /* malformed */
-    memcpy (&cred,
-              data,
-              sizeof (cred));
-    cdata = data;  
-    subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred.subject_key);
-    issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred.issuer_key);
-    cf = ntohl (cred.credential_flags);
-    mdd = ntohl (cred.max_delegation_depth);
-
-     GNUNET_asprintf (&cred_str,
-                     "%s %s %u %u %s",
-                     subject_pkey,
-                     issuer_pkey,
-                     (unsigned int) cf,
-                     (unsigned int) mdd,
-                     &cdata[sizeof (cred)]);
+    char *tmp_str;
+    int i;
+    if (data_size < sizeof (struct GNUNET_CREDENTIAL_DelegationRecord))
+      return NULL; /* malformed */
+    GNUNET_memcpy (&sets,
+                   data,
+                   sizeof (sets));
+    cdata = data;
+    struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets.set_count)];
+    if (GNUNET_OK != GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll (sets.data_size),
+                                                                   &cdata[sizeof (sets)],
+                                                                   ntohl (sets.set_count),
+                                                                   set))
+      return NULL;
+
+    for (i=0;i<ntohl(sets.set_count);i++)
+    {
+      subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "%d len attr\n", set[i].subject_attribute_len);
+      if (0 == set[i].subject_attribute_len)
+      {
+        if (0 == i)
+        {
+          GNUNET_asprintf (&attr_str,
+                           "%s",
+                           subject_pkey);
+        } else {
+          GNUNET_asprintf (&tmp_str,
+                           "%s,%s",
+                           attr_str,
+                           subject_pkey);
+          GNUNET_free (attr_str);
+          attr_str = tmp_str;
+        }
+      } else {
+        if (0 == i)
+        {
+          GNUNET_asprintf (&attr_str,
+                           "%s %s",
+                           subject_pkey,
+                           set[i].subject_attribute);
+        } else {
+          GNUNET_asprintf (&tmp_str,
+                           "%s,%s %s",
+                           attr_str,
+                           subject_pkey,
+                           set[i].subject_attribute);
+          GNUNET_free (attr_str);
+          attr_str = tmp_str;
+        }
+      }
       GNUNET_free (subject_pkey);
-      GNUNET_free (issuer_pkey);
-
-
-
-    return cred_str;
     }
-  default:
-    return NULL;
+    return attr_str;
+   }
+   case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+   {
+     struct GNUNET_CREDENTIAL_Credential *cred;
+     char *cred_str;
+
+     cred = GNUNET_CREDENTIAL_credential_deserialize (data,
+                                                      data_size);
+     cred_str = GNUNET_CREDENTIAL_credential_to_string (cred);
+     GNUNET_free (cred);
+     return cred_str;
+   }
+   case GNUNET_GNSRECORD_TYPE_POLICY:
+   {
+     return GNUNET_strndup (data,data_size);
+   }
+   default:
+   return NULL;
   }
 }
 
@@ -103,63 +146,122 @@ credential_value_to_string (void *cls,
  */
 static int
 credential_string_to_value (void *cls,
-                     uint32_t type,
-                     const char *s,
-                     void **data,
-                     size_t *data_size)
+                            uint32_t type,
+                            const char *s,
+                            void **data,
+                            size_t *data_size)
 {
   if (NULL == s)
     return GNUNET_SYSERR;
   switch (type)
   {
-   case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
-    { 
-      struct GNUNET_CREDENTIAL_RecordData *cred;
-      unsigned int cf; // credential flags
-      unsigned int mdd; // max delegation depth
-
-      size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
-        if (enclen % 5 > 0)
-          enclen += 5 - enclen % 5;
-        enclen /= 5; /* 260/5 = 52 */
-      char subject_pkey[enclen + 1];
-      char issuer_pkey[enclen + 1];
-      char name[253 + 1];
-
-      if (5 != SSCANF (s,
-                         "%52s %52s %u %u %253s",
-                         subject_pkey,
-                         issuer_pkey,
-                         &cf,
-                         &mdd,
-                         name))
+    case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
+      {
+        struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+        char attr_str[253 + 1];
+        char subject_pkey[52 + 1];
+        char *token;
+        char *tmp_str;
+        int matches = 0;
+        int entries;
+        size_t tmp_data_size;
+        int i;
+
+        tmp_str = GNUNET_strdup (s);
+        token = strtok (tmp_str, ",");
+        entries = 0;
+        tmp_data_size = 0;
+        *data_size = sizeof (struct GNUNET_CREDENTIAL_DelegationRecord);
+        while (NULL != token)
+        {
+          matches = SSCANF (token,
+                            "%s %s",
+                            subject_pkey,
+                            attr_str);
+          if (0 == matches)
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        _("Unable to parse ATTR record string `%s'\n"),
+                        s);
+            GNUNET_free (tmp_str);
+            return GNUNET_SYSERR;
+          }
+          if (1 == matches) {
+            tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet);
+          } else if (2 == matches) {
+            tmp_data_size += sizeof (struct GNUNET_CREDENTIAL_DelegationRecordSet) + strlen (attr_str) + 1;
+          }
+          entries++;
+          token = strtok (NULL, ",");
+        }
+        GNUNET_free (tmp_str);
+        tmp_str = GNUNET_strdup (s);
+        token = strtok (tmp_str, ",");
+        if (NULL == token)
         {
+          GNUNET_free (tmp_str);
           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      _("Unable to parse CRED record string `%s'\n"),
-                      s);
+                      "Malformed string %s\n", s);
           return GNUNET_SYSERR;
         }
-        *data_size = sizeof (struct GNUNET_CREDENTIAL_RecordData) + strlen (name) + 1;
-        *data = cred = GNUNET_malloc (*data_size);
-        GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
-                                                    strlen (subject_pkey),
-                                                    &cred->subject_key);
-        GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
-                                                    strlen (issuer_pkey),
-                                                    &cred->issuer_key);
-        cred->credential_flags = htonl (cf);
-        cred->max_delegation_depth = htonl (mdd);
-        GNUNET_memcpy (&cred[1],
-                       name,
-                       strlen (name));
-
+        struct GNUNET_CREDENTIAL_DelegationSet set[entries];
+        for (i=0;i<entries;i++)
+        {
+          matches = SSCANF (token,
+                            "%s %s",
+                            subject_pkey,
+                            attr_str);
+          GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
+                                                      strlen (subject_pkey),
+                                                      &set[i].subject_key);
+          if (2 == matches) {
+            set[i].subject_attribute_len = strlen (attr_str) + 1;
+            set[i].subject_attribute = GNUNET_strdup (attr_str);
+          }
+          token = strtok (NULL , ",");
+        }
+        tmp_data_size = GNUNET_CREDENTIAL_delegation_set_get_size (entries,
+                                                                   set);
 
-      *data = GNUNET_strdup (s);
-      *data_size = strlen (s);
-      return GNUNET_OK;
-    }
-  default:
-    return GNUNET_SYSERR;
+        if (-1 == tmp_data_size)
+        {
+          GNUNET_free (tmp_str);
+          return GNUNET_SYSERR;
+        }
+        *data_size += tmp_data_size;
+        *data = sets = GNUNET_malloc (*data_size);
+        GNUNET_CREDENTIAL_delegation_set_serialize (entries,
+                                                    set,
+                                                    tmp_data_size,
+                                                    (char*)&sets[1]);
+        for (i=0;i<entries;i++)
+        {
+          if (0 != set[i].subject_attribute_len)
+            GNUNET_free ((char*)set[i].subject_attribute);
+        }
+        sets->set_count = htonl (entries);
+        sets->data_size = GNUNET_htonll (tmp_data_size);
+
+        GNUNET_free (tmp_str);
+        return GNUNET_OK;
+      }
+    case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
+      {
+        struct GNUNET_CREDENTIAL_Credential *cred;
+        cred = GNUNET_CREDENTIAL_credential_from_string (s);
+
+        *data_size = GNUNET_CREDENTIAL_credential_serialize (cred,
+                                                             (char**)data);
+        return GNUNET_OK;
+      }
+    case GNUNET_GNSRECORD_TYPE_POLICY:
+      {
+        *data_size = strlen (s);
+        *data = GNUNET_strdup (s);
+        return GNUNET_OK;
+      }
+    default:
+      return GNUNET_SYSERR;
   }
 }
 
@@ -173,6 +275,8 @@ static struct {
   uint32_t number;
 } name_map[] = {
   { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
+  { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
+  { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
   { NULL, UINT32_MAX }
 };
 
@@ -186,13 +290,13 @@ static struct {
  */
 static uint32_t
 credential_typename_to_number (void *cls,
-                        const char *gns_typename)
+                               const char *gns_typename)
 {
   unsigned int i;
 
   i=0;
   while ( (name_map[i].name != NULL) &&
-         (0 != strcasecmp (gns_typename, name_map[i].name)) )
+          (0 != strcasecmp (gns_typename, name_map[i].name)) )
     i++;
   return name_map[i].number;
 }
@@ -207,13 +311,13 @@ credential_typename_to_number (void *cls,
  */
 static const char *
 credential_number_to_typename (void *cls,
-                        uint32_t type)
+                               uint32_t type)
 {
   unsigned int i;
 
   i=0;
   while ( (name_map[i].name != NULL) &&
-         (type != name_map[i].number) )
+          (type != name_map[i].number) )
     i++;
   return name_map[i].name;
 }