global reindent, now with uncrustify hook enabled
[oweals/gnunet.git] / src / credential / plugin_gnsrecord_credential.c
index f6aec9bccfd6a3ba6aa1c7b6d4237aa3ed970a4a..269e558c218a97b7e5cdf612da350d60ce7eee67 100644 (file)
@@ -2,35 +2,37 @@
      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.
+     Affero 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.
-*/
+     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/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
 
 /**
  * @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"
+
 #include "gnunet_util_lib.h"
-#include "gnunet_gnsrecord_lib.h"
+
+#include "credential_misc.h"
+#include "credential_serialization.h"
 #include "gnunet_credential_service.h"
+#include "gnunet_gnsrecord_lib.h"
 #include "gnunet_gnsrecord_plugin.h"
-
-
+#include "gnunet_signatures.h"
 /**
  * Convert the 'value' of a record to a string.
  *
  * @return NULL on error, otherwise human-readable representation of the value
  */
 static char *
-credential_value_to_string (void *cls,
-                              uint32_t type,
-                              const void *data,
-                              size_t data_size)
+credential_value_to_string (void *cls, uint32_t type, const void *data,
+                            size_t data_size)
 {
-
   const char *cdata;
 
   switch (type)
   {
-   case GNUNET_GNSRECORD_TYPE_ATTRIBUTE:
-   {
-    struct GNUNET_CREDENTIAL_AttributeRecordData attr;
-    char *attr_str;
-    char *subject_pkey;
-    
-    if (data_size < sizeof (struct GNUNET_CREDENTIAL_AttributeRecordData))
-      return NULL; /* malformed */
-    memcpy (&attr,
-            data,
-            sizeof (attr));
-    cdata = data;
-    subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&attr.subject_key);
-    GNUNET_asprintf (&attr_str,
-                     "%s.%s",
-                     subject_pkey,
-                     &cdata[sizeof (attr)]);
-    GNUNET_free (subject_pkey);
-    return attr_str;
-   }
-   case GNUNET_GNSRECORD_TYPE_CREDENTIAL:
-   {
-     struct GNUNET_CREDENTIAL_CredentialRecordData cred;
-     char *cred_str;
-     char *subject_pkey;
-     char *issuer_pkey;
-     char *signature;
-     
-     if (data_size < sizeof (struct GNUNET_CREDENTIAL_CredentialRecordData))
-       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);
-     GNUNET_STRINGS_base64_encode ((char*)&cred.sig,
-                                   sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
-                                   &signature);
-     GNUNET_asprintf (&cred_str,
-                      "%s.%s -> %s sig:%s",
-                      issuer_pkey,
-                      &cdata[sizeof (cred)],
-                      subject_pkey,
-                      signature);
-     GNUNET_free (subject_pkey);
-     GNUNET_free (issuer_pkey);
-     GNUNET_free (signature);
-     return cred_str;
-   }
-   default:
-   return NULL;
+  case GNUNET_GNSRECORD_TYPE_ATTRIBUTE: {
+      struct GNUNET_CREDENTIAL_DelegationRecord sets;
+      char *attr_str;
+      char *subject_pkey;
+      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);
+      }
+      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;
   }
 }
 
@@ -119,66 +137,114 @@ credential_value_to_string (void *cls,
  * @return #GNUNET_OK on success
  */
 static int
-credential_string_to_value (void *cls,
-                            uint32_t type,
-                            const char *s,
-                            void **data,
-                            size_t *data_size)
+credential_string_to_value (void *cls, 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_CredentialRecordData *cred;
-
-        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];
-        char signature[128]; //TODO max payload size
-        struct GNUNET_CRYPTO_EcdsaSignature *sig;
-
-        if (4 != SSCANF (s,
-                         "%52s.%253s -> %52s sig:%s",
-                         issuer_pkey,
-                         name,
-                         subject_pkey,
-                         signature))
+  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 CRED record string `%s'\n"),
-                      s);
+                      _ ("Unable to parse ATTR record string `%s'\n"), s);
+          GNUNET_free (tmp_str);
           return GNUNET_SYSERR;
         }
-        *data_size = sizeof (struct GNUNET_CREDENTIAL_CredentialRecordData) + 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);
-        GNUNET_STRINGS_base64_decode (signature,
-                                      strlen (signature),
-                                      (char**)&sig);
-        cred->sig = *sig;
-        GNUNET_free (sig);
-        GNUNET_memcpy (&cred[1],
-                       name,
-                       strlen (name));
-
-
-        *data = GNUNET_strdup (s);
-        *data_size = strlen (s);
-        return GNUNET_OK;
+        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, ",");
       }
-    default:
-      return GNUNET_SYSERR;
+      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, "Malformed string %s\n", s);
+        return GNUNET_SYSERR;
+      }
+      struct GNUNET_CREDENTIAL_DelegationSet set[entries];
+      memset (set, 0, sizeof(struct GNUNET_CREDENTIAL_DelegationSet) * 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);
+
+      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;
   }
 }
 
@@ -187,13 +253,14 @@ credential_string_to_value (void *cls,
  * Mapping of record type numbers to human-readable
  * record type names.
  */
-static struct {
+static struct
+{
   const char *name;
   uint32_t number;
-} name_map[] = {
-  { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
-  { NULL, UINT32_MAX }
-};
+} name_map[] = { { "CRED", GNUNET_GNSRECORD_TYPE_CREDENTIAL },
+                 { "ATTR", GNUNET_GNSRECORD_TYPE_ATTRIBUTE },
+                 { "POLICY", GNUNET_GNSRECORD_TYPE_POLICY },
+                 { NULL, UINT32_MAX } };
 
 
 /**
@@ -204,14 +271,13 @@ static struct {
  * @return corresponding number, UINT32_MAX on error
  */
 static uint32_t
-credential_typename_to_number (void *cls,
-                               const char *gns_typename)
+credential_typename_to_number (void *cls, const char *gns_typename)
 {
   unsigned int i;
 
-  i=0;
-  while ( (name_map[i].name != NULL) &&
-          (0 != strcasecmp (gns_typename, name_map[i].name)) )
+  i = 0;
+  while ((name_map[i].name != NULL) &&
+         (0 != strcasecmp (gns_typename, name_map[i].name)))
     i++;
   return name_map[i].number;
 }
@@ -225,14 +291,12 @@ credential_typename_to_number (void *cls,
  * @return corresponding typestring, NULL on error
  */
 static const char *
-credential_number_to_typename (void *cls,
-                               uint32_t type)
+credential_number_to_typename (void *cls, uint32_t type)
 {
   unsigned int i;
 
-  i=0;
-  while ( (name_map[i].name != NULL) &&
-          (type != name_map[i].number) )
+  i = 0;
+  while ((name_map[i].name != NULL) && (type != name_map[i].number))
     i++;
   return name_map[i].name;
 }