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);
+ c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
if (off + sizeof (c_rec) > dest_size)
return -1;
GNUNET_memcpy (&dest[off],
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);
+ cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
off += sizeof (c_rec);
if (off + cd[i].issuer_attribute_len > len)
return GNUNET_SYSERR;
* DLL
*/
struct CredentialRecordEntry *prev;
-
+
+ /**
+ * Number of references in delegation chains
+ */
+ uint32_t refcount;
/**
* Payload
struct GNUNET_CREDENTIAL_Delegation dd[vrh->delegation_chain_size];
struct GNUNET_CREDENTIAL_Credential cred[vrh->cred_chain_size];
struct CredentialRecordEntry *cd;
+ struct CredentialRecordEntry *tmp;
size_t size;
int i;
dce = dce->next;
}
+ /**
+ * Remove all credentials not needed
+ */
+ for (cd = vrh->cred_chain_head; NULL != cd;)
+ {
+ if (cd->refcount > 0)
+ {
+ cd = cd->next;
+ continue;
+ }
+ tmp = cd;
+ cd = cd->next;
+ GNUNET_CONTAINER_DLL_remove (vrh->cred_chain_head,
+ vrh->cred_chain_tail,
+ tmp);
+ GNUNET_free (tmp->credential);
+ GNUNET_free (tmp);
+ vrh->cred_chain_size--;
+ }
+
/**
* Get serialized record data
* Append at the end of rmsg
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found issuer\n");
-
+ cred_pointer->refcount++;
//Backtrack
for (tmp_set = ds_entry;
NULL != tmp_set->parent_queue_entry;
continue;
if (0 != strcmp (cr_entry->credential->issuer_attribute, vrh->issuer_attribute))
continue;
+ cr_entry->refcount++;
//Found match prematurely
send_lookup_response (vrh);
return;
$(top_builddir)/src/namestore/libgnunetnamestore.la \
$(top_builddir)/src/identity/libgnunetidentity.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/credential/libgnunetcredential.la \
$(top_builddir)/src/gns/libgnunetgns.la \
$(GN_LIBINTL) \
-ljansson
#include "gnunet_identity_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_namestore_service.h"
+#include "gnunet_credential_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_gns_service.h"
#include "gnunet_signatures.h"
*/
static struct GNUNET_GNS_Handle *gns_handle;
+/**
+ * Credential handle
+ */
+static struct GNUNET_CREDENTIAL_Handle *credential_handle;
+
/**
* Namestore qe
*/
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
+struct VerifiedAttributeEntry
+{
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *prev;
+
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *next;
+
+ /**
+ * Attribute Name
+ */
+ char* name;
+};
struct ExchangeHandle
{
*/
char *scopes;
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *v_attr_head;
+
+ /**
+ * DLL
+ */
+ struct VerifiedAttributeEntry *v_attr_tail;
+
/**
* nonce
*/
*/
struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+ /**
+ * Cred request
+ */
+ struct GNUNET_CREDENTIAL_Request *credential_request;
+
/**
* Attribute map
*/
GNUNET_IDENTITY_disconnect (identity_handle);
if (NULL != gns_handle)
GNUNET_GNS_disconnect (gns_handle);
+ if (NULL != credential_handle)
+ GNUNET_CREDENTIAL_disconnect (credential_handle);
if (NULL != ns_it)
GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
if (NULL != ns_qe)
GNUNET_free (token_metadata);
}
+/**
+ * Credential to JSON
+ * @param cred the credential
+ * @return the resulting json, NULL if failed
+ */
+static json_t*
+credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ char *issuer;
+ char *subject;
+ char *signature;
+ char attribute[cred->issuer_attribute_len + 1];
+ json_t *cred_obj;
+
+ issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+ if (NULL == issuer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Issuer in credential malformed\n");
+ return NULL;
+ }
+ subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+ if (NULL == subject)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Subject in credential malformed\n");
+ GNUNET_free (issuer);
+ return NULL;
+ }
+ GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
+ sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ &signature);
+ memcpy (attribute,
+ cred->issuer_attribute,
+ cred->issuer_attribute_len);
+ attribute[cred->issuer_attribute_len] = '\0';
+ cred_obj = json_object ();
+ json_object_set_new (cred_obj, "issuer", json_string (issuer));
+ json_object_set_new (cred_obj, "subject", json_string (subject));
+ json_object_set_new (cred_obj, "attribute", json_string (attribute));
+ json_object_set_new (cred_obj, "signature", json_string (signature));
+ json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
+ GNUNET_free (issuer);
+ GNUNET_free (subject);
+ GNUNET_free (signature);
+ return cred_obj;
+}
+
+
+static void
+handle_vattr_collection (void* cls,
+ unsigned int d_count,
+ struct GNUNET_CREDENTIAL_Delegation *dc,
+ unsigned int c_count,
+ struct GNUNET_CREDENTIAL_Credential *cred)
+{
+ struct IssueHandle *handle = cls;
+ struct VerifiedAttributeEntry *vattr;
+ json_t *cred_json;
+ json_t *cred_array;
+ int i;
+ handle->credential_request = NULL;
+
+ if (NULL == cred)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ cred_array = json_array();
+ for (i=0;i<c_count;i++)
+ {
+ cred_json = credential_to_json (cred);
+ if (NULL == cred_json)
+ continue;
+ json_array_append (cred_array, cred_json);
+ token_add_attr_json (handle->token,
+ handle->v_attr_head->name,
+ cred_array);
+ }
+ json_decref (cred_array);
+ vattr = handle->v_attr_head;
+
+ GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
+ handle->v_attr_tail,
+ vattr);
+ GNUNET_free (vattr->name);
+ GNUNET_free (vattr);
+
+ if (NULL == handle->v_attr_head)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
+ &handle->aud_key,
+ handle->v_attr_head->name,
+ &handle->iss_key,
+ &handle_vattr_collection,
+ handle);
+
+}
+
static void
attr_collect_error (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
handle->ns_it = NULL;
- GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
-}
-
+ if (NULL == handle->v_attr_head)
+ {
+ GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
+ return;
+ }
+ handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
+ &handle->aud_key,
+ handle->v_attr_head->name,
+ &handle->iss_key,
+ &handle_vattr_collection,
+ handle);
+}
/**
* Collect attributes for token
*/
const char *scopes;
char *scopes_tmp;
char *scope;
+ const char *v_attrs;
struct GNUNET_HashCode key;
struct IssueHandle *issue_handle;
+ struct VerifiedAttributeEntry *vattr_entry;
struct GNUNET_SERVICE_Client *client = cls;
scopes = (const char *) &im[1];
+ v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
GNUNET_NO);
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
}
GNUNET_free (scopes_tmp);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "VATTRS: %s\n", v_attrs);
+ scopes_tmp = GNUNET_strdup (v_attrs);
+
+ for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
+ {
+ vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
+ vattr_entry->name = GNUNET_strdup (scope);
+ GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
+ issue_handle->v_attr_tail,
+ vattr_entry);
+ }
+ GNUNET_free (scopes_tmp);
+
+
+
issue_handle->r_id = im->id;
issue_handle->aud_key = im->aud_key;
issue_handle->iss_key = im->iss_key;
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
}
-
+ credential_handle = GNUNET_CREDENTIAL_connect (cfg);
+ if (NULL == credential_handle)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
+ }
identity_handle = GNUNET_IDENTITY_connect (cfg,
&list_ego,
NULL);
*/
uint64_t nonce;
+ /**
+ * Length of scopes
+ */
+ uint64_t scope_len;
+
/**
* Expiration of token in NBO.
*/
const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const char* scopes,
+ const char* vattr,
struct GNUNET_TIME_Absolute expiration,
uint64_t nonce,
GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
size_t slen;
slen = strlen (scopes) + 1;
+ if (NULL != vattr)
+ slen += strlen (vattr) + 1;
if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage))
{
GNUNET_break (0);
im->id = op->r_id;
im->iss_key = *iss_key;
im->aud_key = *aud_key;
+ im->scope_len = htonl (strlen(scopes)+1);
im->nonce = htonl (nonce);
im->expiration = GNUNET_TIME_absolute_hton (expiration);
- GNUNET_memcpy (&im[1], scopes, slen);
+ GNUNET_memcpy (&im[1], scopes, strlen(scopes));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "VATTRAPI: %s\n", vattr);
+ if (NULL != vattr)
+ GNUNET_memcpy ((char*)&im[1]+strlen(scopes)+1, vattr, strlen(vattr));
GNUNET_CONTAINER_DLL_insert_tail (id->op_head,
id->op_tail,
op);
GNUNET_free (token);
}
+void
+token_add_attr_json (struct IdentityToken *token,
+ const char* key,
+ json_t* value)
+{
+ struct TokenAttr *attr;
+ struct TokenAttrValue *new_val;
+ GNUNET_assert (NULL != token);
+
+ new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
+ new_val->json_value = value;
+ json_incref(value);
+ for (attr = token->attr_head; NULL != attr; attr = attr->next)
+ {
+ if (0 == strcmp (key, attr->name))
+ break;
+ }
+
+ if (NULL == attr)
+ {
+ attr = GNUNET_malloc (sizeof (struct TokenAttr));
+ attr->name = GNUNET_strdup (key);
+ GNUNET_CONTAINER_DLL_insert (token->attr_head,
+ token->attr_tail,
+ attr);
+ }
+
+ GNUNET_CONTAINER_DLL_insert (attr->val_head,
+ attr->val_tail,
+ new_val);
+}
+
void
token_add_attr (struct IdentityToken *token,
const char* key,
if (json_is_integer (arr_value))
token_add_attr_int (token, key,
json_integer_value (arr_value));
- else
+ else if (json_is_string (arr_value))
token_add_attr (token,
key,
json_string_value (arr_value));
+ else
+ token_add_attr_json (token,
+ key,
+ (json_t*)arr_value);
}
} else {
if (json_is_integer (value))
token_add_attr_int (token, key,
json_integer_value (value));
- else
+ else if (json_is_string (value))
token_add_attr (token, key, json_string_value (value));
+ else
+ token_add_attr_json (token, key, (json_t*)value);
}
}
GNUNET_asprintf (&tmp_buf, "%s", raw_data);
ecdh_pubkey_str = strtok (tmp_buf, ",");
enc_token_str = strtok (NULL, ",");
-
+
GNUNET_assert (NULL != ecdh_pubkey_str);
GNUNET_assert (NULL != enc_token_str);
json_object_set_new (root,
attr->name,
json_string (val->value));
- } else {
+ } else if (NULL != val->json_value) {
+ json_object_set (root,
+ attr->name,
+ val->json_value);
+ }else {
json_object_set_new (root,
attr->name,
json_integer (val->int_value));
purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
write_ptr = (char*) &purpose[1];
GNUNET_memcpy (write_ptr,
- &ticket->ecdh_pubkey,
- sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+ &ticket->ecdh_pubkey,
+ sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
nonce_str = json_string_value (nonce_json);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
-
+
GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
*result = ticket_payload_create (nonce,
* used if NULL == value
*/
uint64_t int_value;
+
+ /**
+ * Json value
+ */
+ json_t *json_value;
};
struct TokenTicketPayload
* @param value the value
*
*/
- void
- token_add_json (const struct IdentityToken *token,
- const char* key,
- json_t* value);
+void
+token_add_attr_json (struct IdentityToken *token,
+ const char* key,
+ json_t* value);
/**
* Serialize a token. The token will be signed and base64 according to the
*
* @return GNUNET_OK on success
*/
- int
- token_serialize (const struct IdentityToken*token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
- char **result);
+int
+token_serialize (const struct IdentityToken*token,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey,
+ char **result);
/**
* Parses the serialized token and returns a token
*
* @return GNUNET_OK on success
*/
- int
- token_parse (const char* data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct IdentityToken **result);
+int
+token_parse (const char* data,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct IdentityToken **result);
/**
* Parses the serialized token and returns a token
*
* @return GNUNET_OK on success
*/
- int
- token_to_string (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
+int
+token_to_string (const struct IdentityToken *token,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ char **result);
/**
*
*
* @return GNUNET_OK on success
*/
- int
- ticket_serialize (struct TokenTicket *ticket,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result);
+int
+ticket_serialize (struct TokenTicket *ticket,
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ char **result);
/**
* Destroys a ticket
*/
#define GNUNET_IDENTITY_TOKEN_ATTR_LIST "requested_attrs"
+/**
+ * Attributes passed to issue request
+ */
+#define GNUNET_IDENTITY_TOKEN_V_ATTR_LIST "requested_verified_attrs"
+
+
/**
* Token expiration string
*/
char *exp_str;
char *nonce_str;
char *scopes;
+ char *vattrs;
uint64_t time;
uint64_t nonce;
scopes = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
&key);
+ //vattrs
+ GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST,
+ strlen (GNUNET_IDENTITY_TOKEN_V_ATTR_LIST),
+ &key);
+
+ vattrs = NULL;
+ if ( GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+ &key) )
+ {
+ vattrs = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+ &key);
+ }
+
+
//Token audience
GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST,
&key) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Audience missing!\n");
+ "Audience missing!\n");
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
&key);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Audience to issue token for: %s\n",
- audience);
+ "Audience to issue token for: %s\n",
+ audience);
priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
&key);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Request nonce: %s\n",
- nonce_str);
+ "Request nonce: %s\n",
+ nonce_str);
GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &nonce));
//Get expiration for token from URL parameter
priv_key,
&aud_key,
scopes,
+ vattrs,
exp_time,
nonce,
&token_creat_cont,
rd[i].data_size);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding token: %s\n", data);
json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- label);
+ label);
issuer = json_string (handle->ego_head->identifier);
GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
- issuer);
+ GNUNET_REST_JSONAPI_IDENTITY_ISS_REQUEST,
+ issuer);
json_decref (issuer);
token = json_string (data);
GNUNET_JSONAPI_resource_add_attr (json_resource,
- GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
- token);
+ GNUNET_REST_JSONAPI_IDENTITY_TOKEN,
+ token);
json_decref (token);
GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
return;
}
nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
+ &key);
GNUNET_assert (1 == sscanf (nonce_str, "%"SCNu64, &expected_nonce));
if (ticket_nonce != expected_nonce)
const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
const char* scope,
+ const char* vattr,
struct GNUNET_TIME_Absolute expiration,
uint64_t nonce,
GNUNET_IDENTITY_PROVIDER_IssueCallback cb,