aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim
diff options
context:
space:
mode:
authorMarkus Voggenreiter <Markus.Voggenreiter@tum.de>2019-10-13 16:31:17 +0200
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2020-01-13 13:31:02 +0100
commit2c65283b0bd97a8719f4c71aee8cc091a491129a (patch)
tree61f1644f36c111342edbd1d19dfd3212b659da04 /src/reclaim
parentd5178cdc05a0d91293d9ee2cef45ab9a1c515bac (diff)
downloadgnunet-2c65283b0bd97a8719f4c71aee8cc091a491129a.tar.gz
gnunet-2c65283b0bd97a8719f4c71aee8cc091a491129a.zip
Add Attestations via Reclaim Service
Diffstat (limited to 'src/reclaim')
-rw-r--r--src/reclaim/gnunet-service-reclaim.c144
-rw-r--r--src/reclaim/plugin_rest_reclaim.c342
-rw-r--r--src/reclaim/reclaim_api.c46
3 files changed, 201 insertions, 331 deletions
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
index a83ea05a6..d6c93812f 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -328,6 +328,11 @@ struct AttributeStoreHandle
328 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; 328 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
329 329
330 /** 330 /**
331 * The attestation to store
332 */
333 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
334
335 /**
331 * The attribute expiration interval 336 * The attribute expiration interval
332 */ 337 */
333 struct GNUNET_TIME_Relative exp; 338 struct GNUNET_TIME_Relative exp;
@@ -486,6 +491,8 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
486 GNUNET_NAMESTORE_cancel (ash->ns_qe); 491 GNUNET_NAMESTORE_cancel (ash->ns_qe);
487 if (NULL != ash->claim) 492 if (NULL != ash->claim)
488 GNUNET_free (ash->claim); 493 GNUNET_free (ash->claim);
494 if (NULL != ash->attest)
495 GNUNET_free (ash->attest);
489 GNUNET_free (ash); 496 GNUNET_free (ash);
490} 497}
491 498
@@ -1023,6 +1030,139 @@ handle_attribute_store_message (void *cls,
1023 1030
1024 1031
1025/** 1032/**
1033 * Attestation store result handler
1034 *
1035 * @param cls our attribute store handle
1036 * @param success GNUNET_OK if successful
1037 * @param emsg error message (NULL if success=GNUNET_OK)
1038 */
1039static void
1040attest_store_cont (void *cls, int32_t success, const char *emsg)
1041{
1042 struct AttributeStoreHandle *ash = cls;
1043 struct GNUNET_MQ_Envelope *env;
1044 struct SuccessResultMessage *acr_msg;
1045
1046 ash->ns_qe = NULL;
1047 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1048 ash->client->store_op_tail,
1049 ash);
1050
1051 if (GNUNET_SYSERR == success)
1052 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1054 "Failed to store attestation %s\n",
1055 emsg);
1056 cleanup_as_handle (ash);
1057 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1058 return;
1059 }
1060
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1062 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1063 acr_msg->id = htonl (ash->r_id);
1064 acr_msg->op_result = htonl (GNUNET_OK);
1065 GNUNET_MQ_send (ash->client->mq, env);
1066 cleanup_as_handle (ash);
1067}
1068
1069/**
1070 * Add a new attestation
1071 *
1072 * @param cls the AttributeStoreHandle
1073 */
1074static void
1075attest_store_task (void *cls)
1076{
1077 struct AttributeStoreHandle *ash = cls;
1078 struct GNUNET_GNSRECORD_Data rd[1];
1079 char *buf;
1080 char *label;
1081 size_t buf_size;
1082
1083 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attestation\n");
1084 buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest);
1085 buf = GNUNET_malloc (buf_size);
1086 // Give the ash a new id if unset
1087 if (0 == ash->attest->id)
1088 ash->attest->id
1089 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1090 GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf);
1091 label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
1092 sizeof(uint64_t));
1093 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1094
1095 rd[0].data_size = buf_size;
1096 rd[0].data = buf;
1097 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
1098 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1099 rd[0].expiration_time = ash->exp.rel_value_us;
1100 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1101 &ash->identity,
1102 label,
1103 1,
1104 rd,
1105 &attest_store_cont,
1106 ash);
1107 GNUNET_free (buf);
1108 GNUNET_free (label);
1109}
1110
1111/**
1112 * Check an attestation store message
1113 *
1114 * @param cls unused
1115 * @param sam the message to check
1116 */
1117static int
1118check_attestation_store_message (void *cls,
1119 const struct AttributeStoreMessage *sam)
1120{
1121 uint16_t size;
1122
1123 size = ntohs (sam->header.size);
1124 if (size <= sizeof(struct AttributeStoreMessage))
1125 {
1126 GNUNET_break (0);
1127 return GNUNET_SYSERR;
1128 }
1129 return GNUNET_OK;
1130}
1131
1132/**
1133* Handle an attestation store message
1134*
1135* @param cls our client
1136* @param sam the message to handle
1137*/
1138static void
1139handle_attestation_store_message (void *cls,
1140 const struct AttributeStoreMessage *sam)
1141{
1142 struct AttributeStoreHandle *ash;
1143 struct IdpClient *idp = cls;
1144 size_t data_len;
1145
1146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
1147
1148 data_len = ntohs (sam->attr_len);
1149
1150 ash = GNUNET_new (struct AttributeStoreHandle);
1151 ash->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &sam[1],
1152 data_len);
1153
1154 ash->r_id = ntohl (sam->id);
1155 ash->identity = sam->identity;
1156 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1157 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1158
1159 GNUNET_SERVICE_client_continue (idp->client);
1160 ash->client = idp;
1161 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1162 GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
1163}
1164
1165/**
1026 * Send a deletion success response 1166 * Send a deletion success response
1027 * 1167 *
1028 * @param adh our attribute deletion handle 1168 * @param adh our attribute deletion handle
@@ -1742,6 +1882,10 @@ GNUNET_SERVICE_MAIN (
1742 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE, 1882 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1743 struct AttributeStoreMessage, 1883 struct AttributeStoreMessage,
1744 NULL), 1884 NULL),
1885 GNUNET_MQ_hd_var_size (attestation_store_message,
1886 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
1887 struct AttributeStoreMessage,
1888 NULL),
1745 GNUNET_MQ_hd_var_size (attribute_delete_message, 1889 GNUNET_MQ_hd_var_size (attribute_delete_message,
1746 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE, 1890 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1747 struct AttributeDeleteMessage, 1891 struct AttributeDeleteMessage,
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index bb08e6385..9290925b8 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -242,210 +242,6 @@ struct RequestHandle
242}; 242};
243 243
244/** 244/**
245 * Handle for attribute store request
246 */
247struct AttributeStoreHandle
248{
249 /**
250 * DLL
251 */
252 struct AttributeStoreHandle *next;
253
254 /**
255 * DLL
256 */
257 struct AttributeStoreHandle *prev;
258
259 /**
260 * Client connection
261 */
262 struct IdpClient *client;
263
264 /**
265 * Identity
266 */
267 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
268
269 /**
270 * Identity pubkey
271 */
272 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
273
274 /**
275 * QueueEntry
276 */
277 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
278
279 /**
280 * The attribute to store
281 */
282 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
283
284 /**
285 * The attestation to store
286 */
287 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
288
289 /**
290 * The attribute expiration interval
291 */
292 struct GNUNET_TIME_Relative exp;
293
294 /**
295 * request id
296 */
297 uint32_t r_id;
298};
299
300/**
301 * Handle for attribute deletion request
302 */
303struct AttributeDeleteHandle
304{
305 /**
306 * DLL
307 */
308 struct AttributeDeleteHandle *next;
309
310 /**
311 * DLL
312 */
313 struct AttributeDeleteHandle *prev;
314
315 /**
316 * Client connection
317 */
318 struct IdpClient *client;
319
320 /**
321 * Identity
322 */
323 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
324
325
326 /**
327 * QueueEntry
328 */
329 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
330
331 /**
332 * Iterator
333 */
334 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
335
336 /**
337 * The attribute to delete
338 */
339 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
340
341 /**
342 * The attestation to store
343 */
344 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
345
346 /**
347 * Tickets to update
348 */
349 struct TicketRecordsEntry *tickets_to_update_head;
350
351 /**
352 * Tickets to update
353 */
354 struct TicketRecordsEntry *tickets_to_update_tail;
355
356 /**
357 * Attribute label
358 */
359 char *label;
360
361 /**
362 * request id
363 */
364 uint32_t r_id;
365};
366
367/**
368 * Handle to the service.
369 */
370struct GNUNET_RECLAIM_Handle
371{
372 /**
373 * Configuration to use.
374 */
375 const struct GNUNET_CONFIGURATION_Handle *cfg;
376
377 /**
378 * Socket (if available).
379 */
380 struct GNUNET_CLIENT_Connection *client;
381
382 /**
383 * Closure for 'cb'.
384 */
385 void *cb_cls;
386
387 /**
388 * Head of active operations.
389 */
390 struct GNUNET_RECLAIM_Operation *op_head;
391
392 /**
393 * Tail of active operations.
394 */
395 struct GNUNET_RECLAIM_Operation *op_tail;
396
397 /**
398 * Head of active iterations
399 */
400 struct GNUNET_RECLAIM_AttributeIterator *it_head;
401
402 /**
403 * Tail of active iterations
404 */
405 struct GNUNET_RECLAIM_AttributeIterator *it_tail;
406
407 /**
408 * Head of active iterations
409 */
410 struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
411
412 /**
413 * Tail of active iterations
414 */
415 struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
416
417 /**
418 * Currently pending transmission request, or NULL for none.
419 */
420 struct GNUNET_CLIENT_TransmitHandle *th;
421
422 /**
423 * Task doing exponential back-off trying to reconnect.
424 */
425 struct GNUNET_SCHEDULER_Task *reconnect_task;
426
427 /**
428 * Time for next connect retry.
429 */
430 struct GNUNET_TIME_Relative reconnect_backoff;
431
432 /**
433 * Connection to service (if available).
434 */
435 struct GNUNET_MQ_Handle *mq;
436
437 /**
438 * Request Id generator. Incremented by one for each request.
439 */
440 uint32_t r_id_gen;
441
442 /**
443 * Are we polling for incoming messages right now?
444 */
445 int in_receive;
446};
447
448/**
449 * Cleanup lookup handle 245 * Cleanup lookup handle
450 * @param handle Handle to clean up 246 * @param handle Handle to clean up
451 */ 247 */
@@ -656,6 +452,8 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
656 GNUNET_free (tmp); 452 GNUNET_free (tmp);
657 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it); 453 GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
658} 454}
455
456
659static void 457static void
660add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, 458add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
661 const char *url, 459 const char *url,
@@ -729,58 +527,12 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
729 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); 527 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
730 handle->idp = GNUNET_RECLAIM_connect (cfg); 528 handle->idp = GNUNET_RECLAIM_connect (cfg);
731 exp = GNUNET_TIME_UNIT_HOURS; 529 exp = GNUNET_TIME_UNIT_HOURS;
732 /*New */ 530 handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
733 struct GNUNET_RECLAIM_Handle *h = handle->idp; 531 identity_priv,
734 struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey = identity_priv; 532 attribute,
735 /*struct GNUNET_RECLAIM_ATTESTATION_Claim *attr = attribute;*/ 533 &exp,
736 struct GNUNET_TIME_Relative *exp_interval = &exp; 534 &finished_cont,
737 /*GNUNET_RECLAIM_ContinuationWithStatus cont = &finished_cont;*/ 535 handle);
738 void *cont_cls = handle;
739
740 struct AttributeStoreHandle *ash;
741 struct GNUNET_GNSRECORD_Data rd[1];
742 char *buf;
743 char *label;
744 size_t buf_size;
745 struct IdpClient *idp = cont_cls;
746 struct GNUNET_NAMESTORE_Handle *nsh;
747 nsh = GNUNET_NAMESTORE_connect (cfg);
748 if (NULL == nsh)
749 {
750 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
751 "error connecting to namestore");
752 }
753 ash = GNUNET_new (struct AttributeStoreHandle);
754 ash->identity = *pkey;
755 ash->r_id = h->r_id_gen++;
756 ash->exp.rel_value_us = exp_interval->rel_value_us;
757 ash->attest = attribute;
758 ash->client = idp;
759 buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest);
760 buf = GNUNET_malloc (buf_size);
761 // Give the ash a new id if unset
762 if (0 == ash->attest->id)
763 ash->attest->id
764 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
765 GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf);
766 label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
767 sizeof(uint64_t));
768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
769
770 rd[0].data_size = buf_size;
771 rd[0].data = buf;
772 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
773 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
774 rd[0].expiration_time = ash->exp.rel_value_us;
775 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
776 &ash->identity,
777 label,
778 1,
779 rd,
780 &finished_cont,
781 ash);
782 GNUNET_free (buf);
783 GNUNET_free (label);
784 GNUNET_JSON_parse_free (attrspec); 536 GNUNET_JSON_parse_free (attrspec);
785} 537}
786/*Placeholder*/ 538/*Placeholder*/
@@ -800,81 +552,9 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
800 const char *url, 552 const char *url,
801 void *cls) 553 void *cls)
802{ 554{
803 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 555 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting Attestations not supported\n");
804 struct RequestHandle *handle = cls; 556 GNUNET_SCHEDULER_add_now (&do_error, cls);
805 struct GNUNET_RECLAIM_ATTESTATION_Claim attr; 557 return;
806 struct EgoEntry *ego_entry;
807 char *identity_id_str;
808 char *identity;
809 char *id;
810
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
812 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
813 handle->url))
814 {
815 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
816 GNUNET_SCHEDULER_add_now (&do_error, handle);
817 return;
818 }
819 identity_id_str =
820 strdup (handle->url + strlen (
821 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1);
822 identity = strtok (identity_id_str, "/");
823 id = strtok (NULL, "/");
824 if ((NULL == identity) || (NULL == id))
825 {
826 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
827 GNUNET_free (identity_id_str);
828 GNUNET_SCHEDULER_add_now (&do_error, handle);
829 return;
830 }
831
832 for (ego_entry = handle->ego_head; NULL != ego_entry;
833 ego_entry = ego_entry->next)
834 if (0 == strcmp (identity, ego_entry->identifier))
835 break;
836 handle->resp_object = json_array ();
837 if (NULL == ego_entry)
838 {
839 // Done
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
841 GNUNET_free (identity_id_str);
842 GNUNET_SCHEDULER_add_now (&return_response, handle);
843 return;
844 }
845 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
846 handle->idp = GNUNET_RECLAIM_connect (cfg);
847 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim));
848 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t));
849 attr.name = "";
850
851 struct GNUNET_RECLAIM_Handle *h = handle->idp;
852 struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey = priv_key;
853
854 struct AttributeDeleteHandle *adh;
855 struct IdpClient *idp = handle;
856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
857 struct GNUNET_NAMESTORE_Handle *nsh;
858 nsh = GNUNET_NAMESTORE_connect (cfg);
859 adh = GNUNET_new (struct AttributeDeleteHandle);
860 adh->attest = &attr;
861 adh->r_id = h->r_id_gen++;
862 adh->identity = *pkey;
863 adh->label = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id,
864 sizeof(uint64_t));
865 /*GNUNET_SERVICE_client_continue (idp->client);*/
866 adh->client = idp;
867 /*GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);*/
868 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
869 &adh->identity,
870 adh->label,
871 0,
872 NULL,
873 &delete_finished_cb,
874 adh);
875
876
877 GNUNET_free (identity_id_str);
878} 558}
879 559
880/** 560/**
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index 7d4d7588a..988650450 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -925,6 +925,52 @@ GNUNET_RECLAIM_attribute_delete (
925 return op; 925 return op;
926} 926}
927 927
928/**
929 * Store an attestation. If the attestation is already present,
930 * it is replaced with the new attestation.
931 *
932 * @param h handle to the re:claimID service
933 * @param pkey private key of the identity
934 * @param attr the attestation value
935 * @param exp_interval the relative expiration interval for the attestation
936 * @param cont continuation to call when done
937 * @param cont_cls closure for @a cont
938 * @return handle to abort the request
939 */
940struct GNUNET_RECLAIM_Operation *
941GNUNET_RECLAIM_attestation_store (
942 struct GNUNET_RECLAIM_Handle *h,
943 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
944 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
945 const struct GNUNET_TIME_Relative *exp_interval,
946 GNUNET_RECLAIM_ContinuationWithStatus cont,
947 void *cont_cls)
948{
949 struct GNUNET_RECLAIM_Operation *op;
950 struct AttributeStoreMessage *sam;
951 size_t attr_len;
952
953 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
954 op->h = h;
955 op->as_cb = cont;
956 op->cls = cont_cls;
957 op->r_id = h->r_id_gen++;
958 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
959 attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr);
960 op->env = GNUNET_MQ_msg_extra (sam,
961 attr_len,
962 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE);
963 sam->identity = *pkey;
964 sam->id = htonl (op->r_id);
965 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
966
967 GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &sam[1]);
968
969 sam->attr_len = htons (attr_len);
970 if (NULL != h->mq)
971 GNUNET_MQ_send_copy (h->mq, op->env);
972 return op;
973}
928 974
929/** 975/**
930 * List all attributes for a local identity. 976 * List all attributes for a local identity.