aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim')
-rw-r--r--src/reclaim/gnunet-reclaim.c14
-rw-r--r--src/reclaim/gnunet-service-reclaim.c903
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c260
-rw-r--r--src/reclaim/json_reclaim.c221
-rw-r--r--src/reclaim/json_reclaim.h19
-rw-r--r--src/reclaim/oidc_helper.c126
-rw-r--r--src/reclaim/oidc_helper.h2
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c6
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c236
-rw-r--r--src/reclaim/plugin_rest_reclaim.c867
-rw-r--r--src/reclaim/reclaim.h39
-rw-r--r--src/reclaim/reclaim_api.c418
12 files changed, 2929 insertions, 182 deletions
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
index 58f8cd6e2..5f9170f05 100644
--- a/src/reclaim/gnunet-reclaim.c
+++ b/src/reclaim/gnunet-reclaim.c
@@ -226,7 +226,9 @@ store_attr_cont (void *cls, int32_t success, const char *emsg)
226static void 226static void
227process_attrs (void *cls, 227process_attrs (void *cls,
228 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 228 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
229 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 229 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
230 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
231 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
230{ 232{
231 char *value_str; 233 char *value_str;
232 char *id; 234 char *id;
@@ -253,7 +255,7 @@ process_attrs (void *cls,
253 attr->name, 255 attr->name,
254 value_str, 256 value_str,
255 attr_type, 257 attr_type,
256 attr->version, 258 attr->flag,
257 id); 259 id);
258 GNUNET_free (id); 260 GNUNET_free (id);
259} 261}
@@ -445,7 +447,9 @@ iter_finished (void *cls)
445static void 447static void
446iter_cb (void *cls, 448iter_cb (void *cls,
447 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 449 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
448 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 450 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
451 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
452 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
449{ 453{
450 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; 454 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
451 char *attrs_tmp; 455 char *attrs_tmp;
@@ -480,7 +484,7 @@ iter_cb (void *cls,
480 attr->type, 484 attr->type,
481 attr->data, 485 attr->data,
482 attr->data_size); 486 attr->data_size);
483 le->claim->version = attr->version; 487 le->claim->flag = attr->flag;
484 le->claim->id = attr->id; 488 le->claim->id = attr->id;
485 GNUNET_CONTAINER_DLL_insert (attr_list->list_head, 489 GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
486 attr_list->list_tail, 490 attr_list->list_tail,
@@ -514,7 +518,7 @@ iter_cb (void *cls,
514 attr->name, 518 attr->name,
515 attr_str, 519 attr_str,
516 attr_type, 520 attr_type,
517 attr->version, 521 attr->flag,
518 id); 522 id);
519 GNUNET_free (id); 523 GNUNET_free (id);
520 } 524 }
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
index a83ea05a6..556006af0 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -266,6 +266,15 @@ struct AttributeDeleteHandle
266 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; 266 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
267 267
268 /** 268 /**
269 * The attestation to delete
270 */
271 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
272
273 /**
274 * The reference to delete
275 */
276 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
277 /**
269 * Tickets to update 278 * Tickets to update
270 */ 279 */
271 struct TicketRecordsEntry *tickets_to_update_head; 280 struct TicketRecordsEntry *tickets_to_update_head;
@@ -328,6 +337,16 @@ struct AttributeStoreHandle
328 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; 337 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
329 338
330 /** 339 /**
340 * The attestation to store
341 */
342 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
343
344 /**
345 * The reference to store
346 */
347 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
348
349 /**
331 * The attribute expiration interval 350 * The attribute expiration interval
332 */ 351 */
333 struct GNUNET_TIME_Relative exp; 352 struct GNUNET_TIME_Relative exp;
@@ -459,6 +478,10 @@ cleanup_adh (struct AttributeDeleteHandle *adh)
459 GNUNET_free (adh->label); 478 GNUNET_free (adh->label);
460 if (NULL != adh->claim) 479 if (NULL != adh->claim)
461 GNUNET_free (adh->claim); 480 GNUNET_free (adh->claim);
481 if (NULL != adh->attest)
482 GNUNET_free (adh->attest);
483 if (NULL != adh->reference)
484 GNUNET_free (adh->reference);
462 while (NULL != (le = adh->tickets_to_update_head)) 485 while (NULL != (le = adh->tickets_to_update_head))
463 { 486 {
464 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head, 487 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
@@ -486,6 +509,10 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
486 GNUNET_NAMESTORE_cancel (ash->ns_qe); 509 GNUNET_NAMESTORE_cancel (ash->ns_qe);
487 if (NULL != ash->claim) 510 if (NULL != ash->claim)
488 GNUNET_free (ash->claim); 511 GNUNET_free (ash->claim);
512 if (NULL != ash->attest)
513 GNUNET_free (ash->attest);
514 if (NULL != ash->reference)
515 GNUNET_free (ash->reference);
489 GNUNET_free (ash); 516 GNUNET_free (ash);
490} 517}
491 518
@@ -1023,6 +1050,478 @@ handle_attribute_store_message (void *cls,
1023 1050
1024 1051
1025/** 1052/**
1053 * Attestation store result handler
1054 *
1055 * @param cls our attribute store handle
1056 * @param success GNUNET_OK if successful
1057 * @param emsg error message (NULL if success=GNUNET_OK)
1058 */
1059static void
1060attest_store_cont (void *cls, int32_t success, const char *emsg)
1061{
1062 struct AttributeStoreHandle *ash = cls;
1063 struct GNUNET_MQ_Envelope *env;
1064 struct SuccessResultMessage *acr_msg;
1065
1066 ash->ns_qe = NULL;
1067 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1068 ash->client->store_op_tail,
1069 ash);
1070
1071 if (GNUNET_SYSERR == success)
1072 {
1073 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1074 "Failed to store attestation %s\n",
1075 emsg);
1076 cleanup_as_handle (ash);
1077 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1078 return;
1079 }
1080
1081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1082 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1083 acr_msg->id = htonl (ash->r_id);
1084 acr_msg->op_result = htonl (GNUNET_OK);
1085 GNUNET_MQ_send (ash->client->mq, env);
1086 cleanup_as_handle (ash);
1087}
1088
1089/**
1090 * Send a reference error response
1091 *
1092 * @param ash our attribute store handle
1093 * @param success the success status
1094 */
1095static void
1096send_ref_error (struct AttributeStoreHandle *ash)
1097{
1098 struct GNUNET_MQ_Envelope *env;
1099 struct SuccessResultMessage *acr_msg;
1100
1101 ash->ns_qe = NULL;
1102 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1103 ash->client->store_op_tail,
1104 ash);
1105
1106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1107 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1108 acr_msg->id = htonl (ash->r_id);
1109 acr_msg->op_result = htonl (GNUNET_SYSERR);
1110 GNUNET_MQ_send (ash->client->mq, env);
1111 cleanup_as_handle (ash);
1112}
1113
1114/**
1115 * Error looking up potential attestation. Abort.
1116 *
1117 * @param cls our attribute store handle
1118 */
1119static void
1120attest_error (void *cls)
1121{
1122 struct AttributeStoreHandle *ash = cls;
1123 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1124 "Failed to check for existing Attestation\n");
1125 cleanup_as_handle (ash);
1126 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1127 return;
1128}
1129
1130/**
1131* Check for existing record before storing reference
1132*
1133* @param cls our attribute store handle
1134* @param zone zone we are iterating
1135* @param label label of the records
1136* @param rd_count record count
1137* @param rd records
1138*/
1139static void
1140attest_add_cb (void *cls,
1141 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1142 const char *label,
1143 unsigned int rd_count,
1144 const struct GNUNET_GNSRECORD_Data *rd)
1145{
1146 struct AttributeStoreHandle *ash = cls;
1147 char *buf;
1148 size_t buf_size;
1149 buf_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (ash->attest);
1150 buf = GNUNET_malloc (buf_size);
1151 GNUNET_RECLAIM_ATTESTATION_serialize (ash->attest, buf);
1152 if (0 == rd_count )
1153 {
1154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155 "Storing new Attestation\n");
1156 struct GNUNET_GNSRECORD_Data rd_new[1];
1157 rd_new[0].data_size = buf_size;
1158 rd_new[0].data = buf;
1159 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
1160 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1161 rd_new[0].expiration_time = ash->exp.rel_value_us;
1162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1163 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1164 &ash->identity,
1165 label,
1166 1,
1167 rd_new,
1168 &attest_store_cont,
1169 ash);
1170 GNUNET_free (buf);
1171 return;
1172 }
1173 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1174 {
1175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1176 "Existing Attestation location is not an Attestation\n");
1177 send_ref_error (ash);
1178 return;
1179 }
1180 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1181 for (int i = 0; i<rd_count; i++)
1182 {
1183 rd_new[i] = rd[i];
1184 }
1185 rd_new[0].data_size = buf_size;
1186 rd_new[0].data = buf;
1187 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR;
1188 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1189 rd_new[0].expiration_time = ash->exp.rel_value_us;
1190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1191 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1192 &ash->identity,
1193 label,
1194 rd_count,
1195 rd_new,
1196 &attest_store_cont,
1197 ash);
1198 GNUNET_free (buf);
1199}
1200
1201/**
1202 * Add a new attestation
1203 *
1204 * @param cls the AttributeStoreHandle
1205 */
1206static void
1207attest_store_task (void *cls)
1208{
1209 struct AttributeStoreHandle *ash = cls;
1210 char *label;
1211
1212 // Give the ash a new id if unset
1213 if (0 == ash->attest->id)
1214 ash->attest->id
1215 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1216 label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
1217 sizeof(uint64_t));
1218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1219 "Looking up existing data under label %s\n", label);
1220// Test for the content of the existing ID
1221 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1222 &ash->identity,
1223 label,
1224 &attest_error,
1225 ash,
1226 &attest_add_cb,
1227 ash);
1228 GNUNET_free (label);
1229}
1230
1231/**
1232 * Check an attestation store message
1233 *
1234 * @param cls unused
1235 * @param sam the message to check
1236 */
1237static int
1238check_attestation_store_message (void *cls,
1239 const struct AttributeStoreMessage *sam)
1240{
1241 uint16_t size;
1242
1243 size = ntohs (sam->header.size);
1244 if (size <= sizeof(struct AttributeStoreMessage))
1245 {
1246 GNUNET_break (0);
1247 return GNUNET_SYSERR;
1248 }
1249 return GNUNET_OK;
1250}
1251
1252/**
1253* Handle an attestation store message
1254*
1255* @param cls our client
1256* @param sam the message to handle
1257*/
1258static void
1259handle_attestation_store_message (void *cls,
1260 const struct AttributeStoreMessage *sam)
1261{
1262 struct AttributeStoreHandle *ash;
1263 struct IdpClient *idp = cls;
1264 size_t data_len;
1265
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
1267
1268 data_len = ntohs (sam->attr_len);
1269
1270 ash = GNUNET_new (struct AttributeStoreHandle);
1271 ash->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &sam[1],
1272 data_len);
1273
1274 ash->r_id = ntohl (sam->id);
1275 ash->identity = sam->identity;
1276 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1277 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1278
1279 GNUNET_SERVICE_client_continue (idp->client);
1280 ash->client = idp;
1281 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1282 GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
1283}
1284
1285/**
1286 * Error looking up potential reference value. Abort.
1287 *
1288 * @param cls our attribute store handle
1289 */
1290static void
1291ref_error (void *cls)
1292{
1293 struct AttributeStoreHandle *ash = cls;
1294 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1295 "Failed to find Attestation entry for Attestation reference\n");
1296 cleanup_as_handle (ash);
1297 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1298 return;
1299}
1300
1301/**
1302 * Error looking up potential reference value. Abort.
1303 *
1304 * @param cls our attribute delete handle
1305 */
1306static void
1307ref_del_error (void *cls)
1308{
1309 struct AttributeDeleteHandle *adh = cls;
1310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1311 "Failed to find Attestation entry for Attestation reference\n");
1312 cleanup_adh (adh);
1313 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1314 return;
1315}
1316/**
1317* Reference store result handler
1318*
1319* @param cls our attribute store handle
1320* @param success GNUNET_OK if successful
1321* @param emsg error message (NULL if success=GNUNET_OK)
1322*/
1323static void
1324reference_store_cont (void *cls, int32_t success, const char *emsg)
1325{
1326 struct AttributeStoreHandle *ash = cls;
1327 struct GNUNET_MQ_Envelope *env;
1328 struct SuccessResultMessage *acr_msg;
1329
1330 ash->ns_qe = NULL;
1331 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1332 ash->client->store_op_tail,
1333 ash);
1334
1335 if (GNUNET_SYSERR == success)
1336 {
1337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1338 "Failed to store reference %s\n",
1339 emsg);
1340 cleanup_as_handle (ash);
1341 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1342 return;
1343 }
1344
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1346 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1347 acr_msg->id = htonl (ash->r_id);
1348 acr_msg->op_result = htonl (GNUNET_OK);
1349 GNUNET_MQ_send (ash->client->mq, env);
1350 cleanup_as_handle (ash);
1351}
1352
1353
1354/**
1355* Check for existing record before storing reference
1356*
1357* @param cls our attribute store handle
1358* @param zone zone we are iterating
1359* @param label label of the records
1360* @param rd_count record count
1361* @param rd records
1362*/
1363static void
1364ref_add_cb (void *cls,
1365 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1366 const char *label,
1367 unsigned int rd_count,
1368 const struct GNUNET_GNSRECORD_Data *rd)
1369{
1370 struct AttributeStoreHandle *ash = cls;
1371 char *buf;
1372 size_t buf_size;
1373 buf_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (ash->reference);
1374 buf = GNUNET_malloc (buf_size);
1375 GNUNET_RECLAIM_ATTESTATION_REF_serialize (ash->reference, buf);
1376 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
1377 char *data_tmp;
1378 if (0 == rd_count )
1379 {
1380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1381 "Failed to find Attestation entry for Attestation reference\n");
1382 send_ref_error (ash);
1383 return;
1384 }
1385 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1386 {
1387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1388 "Intended Reference storage location is not an attestation\n");
1389 send_ref_error (ash);
1390 return;
1391 }
1392 struct GNUNET_GNSRECORD_Data rd_new[rd_count + 1];
1393 int i;
1394 for (i = 0; i<rd_count; i++)
1395 {
1396 data_tmp = GNUNET_malloc (rd[i].data_size);
1397 GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
1398 ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, htons (
1399 rd[i].data_size));
1400 rd_new[i] = rd[i];
1401 if ((strcmp (ash->reference->name,ref->name) == 0)&&
1402 (strcmp (ash->reference->reference_value,ref->reference_value)==0) )
1403 {
1404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1405 "Reference already stored\n");
1406 reference_store_cont (ash,GNUNET_OK, NULL);
1407 return;
1408 }
1409 }
1410 rd_new[rd_count].data_size = buf_size;
1411 rd_new[rd_count].data = buf;
1412 rd_new[rd_count].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE;
1413 rd_new[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1414 rd_new[rd_count].expiration_time = ash->exp.rel_value_us;
1415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1416 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1417 &ash->identity,
1418 label,
1419 rd_count + 1,
1420 rd_new,
1421 &reference_store_cont,
1422 ash);
1423 GNUNET_free (buf);
1424}
1425
1426/**
1427 * Add a new reference
1428 *
1429 * @param cls the AttributeStoreHandle
1430 */
1431static void
1432reference_store_task (void *cls)
1433{
1434 struct AttributeStoreHandle *ash = cls;
1435 char *label;
1436
1437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing reference\n");
1438
1439 // Give the ash a new id if unset
1440 if (0 == ash->reference->id)
1441 {
1442 if (0 == ash->reference->id_attest)
1443 {
1444 ash->reference->id = GNUNET_CRYPTO_random_u64 (
1445 GNUNET_CRYPTO_QUALITY_STRONG,
1446 UINT64_MAX);
1447 }
1448 else
1449 {
1450 ash->reference->id = ash->reference->id_attest;
1451 }
1452 }
1453
1454 label = GNUNET_STRINGS_data_to_string_alloc (&ash->reference->id,
1455 sizeof(uint64_t));
1456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 "Looking up existing data under label %s\n", label);
1458// Test for the content of the existing ID
1459
1460 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1461 &ash->identity,
1462 label,
1463 &ref_error,
1464 ash,
1465 &ref_add_cb,
1466 ash);
1467 GNUNET_free (label);
1468}
1469
1470/**
1471 * Check an attestation reference store message
1472 *
1473 * @param cls unused
1474 * @param sam the message to check
1475 */
1476static int
1477check_reference_store_message (void *cls,
1478 const struct
1479 AttributeStoreMessage *sam)
1480{
1481 uint16_t size;
1482
1483 size = ntohs (sam->header.size);
1484 if (size <= sizeof(struct AttributeStoreMessage))
1485 {
1486 GNUNET_break (0);
1487 return GNUNET_SYSERR;
1488 }
1489 return GNUNET_OK;
1490}
1491
1492
1493/**
1494 * Handle an attestation reference store message
1495 *
1496 * @param cls our client
1497 * @param sam the message to handle
1498 */
1499static void
1500handle_reference_store_message (void *cls,
1501 const struct AttributeStoreMessage *sam)
1502{
1503 struct AttributeStoreHandle *ash;
1504 struct IdpClient *idp = cls;
1505 size_t data_len;
1506
1507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_STORE message\n");
1508
1509 data_len = ntohs (sam->attr_len);
1510 ash = GNUNET_new (struct AttributeStoreHandle);
1511 ash->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &sam[1],
1512 data_len);
1513 ash->r_id = ntohl (sam->id);
1514 ash->identity = sam->identity;
1515 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1516 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1517
1518
1519 GNUNET_SERVICE_client_continue (idp->client);
1520 ash->client = idp;
1521 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1522 GNUNET_SCHEDULER_add_now (&reference_store_task, ash);
1523}
1524/**
1026 * Send a deletion success response 1525 * Send a deletion success response
1027 * 1526 *
1028 * @param adh our attribute deletion handle 1527 * @param adh our attribute deletion handle
@@ -1066,15 +1565,21 @@ ticket_iter (void *cls,
1066 struct AttributeDeleteHandle *adh = cls; 1565 struct AttributeDeleteHandle *adh = cls;
1067 struct TicketRecordsEntry *le; 1566 struct TicketRecordsEntry *le;
1068 int has_changed = GNUNET_NO; 1567 int has_changed = GNUNET_NO;
1069
1070 for (int i = 0; i < rd_count; i++) 1568 for (int i = 0; i < rd_count; i++)
1071 { 1569 {
1072 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type) 1570 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1073 continue; 1571 continue;
1074 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))) 1572 if (adh->claim != NULL)
1075 continue; 1573 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
1574 continue;
1575 if (adh->attest != NULL)
1576 if (0 != memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t)))
1577 continue;
1578 if (adh->reference != NULL)
1579 if (0 != memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t)))
1580 continue;
1076 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1077 "Attribute to delete found (%s)\n", 1582 "Attribute or Attestation/Reference to delete found (%s)\n",
1078 adh->label); 1583 adh->label);
1079 has_changed = GNUNET_YES; 1584 has_changed = GNUNET_YES;
1080 break; 1585 break;
@@ -1136,7 +1641,7 @@ update_tickets (void *cls)
1136 if (NULL == adh->tickets_to_update_head) 1641 if (NULL == adh->tickets_to_update_head)
1137 { 1642 {
1138 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1643 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1139 "Finished updatding tickets, success\n"); 1644 "Finished updating tickets, success\n");
1140 send_delete_response (adh, GNUNET_OK); 1645 send_delete_response (adh, GNUNET_OK);
1141 cleanup_adh (adh); 1646 cleanup_adh (adh);
1142 return; 1647 return;
@@ -1164,9 +1669,18 @@ update_tickets (void *cls)
1164 int j = 0; 1669 int j = 0;
1165 for (int i = 0; i < le->rd_count; i++) 1670 for (int i = 0; i < le->rd_count; i++)
1166 { 1671 {
1167 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type) 1672 if (adh->claim != NULL)
1168 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))) 1673 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1169 continue; 1674 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t))))
1675 continue;
1676 if (adh->attest != NULL)
1677 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1678 && (0 == memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t))))
1679 continue;
1680 if (adh->reference != NULL)
1681 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1682 && (0 == memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t))))
1683 continue;
1170 rd_new[j] = rd[i]; 1684 rd_new[j] = rd[i];
1171 j++; 1685 j++;
1172 } 1686 }
@@ -1192,7 +1706,6 @@ static void
1192ticket_iter_fin (void *cls) 1706ticket_iter_fin (void *cls)
1193{ 1707{
1194 struct AttributeDeleteHandle *adh = cls; 1708 struct AttributeDeleteHandle *adh = cls;
1195
1196 adh->ns_it = NULL; 1709 adh->ns_it = NULL;
1197 GNUNET_SCHEDULER_add_now (&update_tickets, adh); 1710 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1198} 1711}
@@ -1309,6 +1822,8 @@ handle_attribute_delete_message (void *cls,
1309 adh = GNUNET_new (struct AttributeDeleteHandle); 1822 adh = GNUNET_new (struct AttributeDeleteHandle);
1310 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &dam[1], 1823 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &dam[1],
1311 data_len); 1824 data_len);
1825 adh->reference = NULL;
1826 adh->attest = NULL;
1312 1827
1313 adh->r_id = ntohl (dam->id); 1828 adh->r_id = ntohl (dam->id);
1314 adh->identity = dam->identity; 1829 adh->identity = dam->identity;
@@ -1326,6 +1841,256 @@ handle_attribute_delete_message (void *cls,
1326 adh); 1841 adh);
1327} 1842}
1328 1843
1844/**
1845 * Attestation deleted callback
1846 *
1847 * @param cls our handle
1848 * @param success success status
1849 * @param emsg error message (NULL if success=GNUNET_OK)
1850 */
1851static void
1852attest_delete_cont (void *cls, int32_t success, const char *emsg)
1853{
1854 struct AttributeDeleteHandle *adh = cls;
1855
1856 adh->ns_qe = NULL;
1857 if (GNUNET_SYSERR == success)
1858 {
1859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1860 "Error deleting attestation %s\n",
1861 adh->label);
1862 send_delete_response (adh, GNUNET_SYSERR);
1863 cleanup_adh (adh);
1864 return;
1865 }
1866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1867 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1868}
1869
1870/**
1871 * Check attestation delete message format
1872 *
1873 * @cls unused
1874 * @dam message to check
1875 */
1876static int
1877check_attestation_delete_message (void *cls,
1878 const struct AttributeDeleteMessage *dam)
1879{
1880 uint16_t size;
1881
1882 size = ntohs (dam->header.size);
1883 if (size <= sizeof(struct AttributeDeleteMessage))
1884 {
1885 GNUNET_break (0);
1886 return GNUNET_SYSERR;
1887 }
1888 return GNUNET_OK;
1889}
1890
1891
1892/**
1893 * Handle attestation deletion
1894 *
1895 * @param cls our client
1896 * @param dam deletion message
1897 */
1898static void
1899handle_attestation_delete_message (void *cls,
1900 const struct AttributeDeleteMessage *dam)
1901{
1902 struct AttributeDeleteHandle *adh;
1903 struct IdpClient *idp = cls;
1904 size_t data_len;
1905
1906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
1907
1908 data_len = ntohs (dam->attr_len);
1909
1910 adh = GNUNET_new (struct AttributeDeleteHandle);
1911 adh->attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &dam[1],
1912 data_len);
1913 adh->reference = NULL;
1914 adh->claim = NULL;
1915
1916 adh->r_id = ntohl (dam->id);
1917 adh->identity = dam->identity;
1918 adh->label
1919 = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id, sizeof(uint64_t));
1920 GNUNET_SERVICE_client_continue (idp->client);
1921 adh->client = idp;
1922 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1923 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1924 &adh->identity,
1925 adh->label,
1926 0,
1927 NULL,
1928 &attest_delete_cont,
1929 adh);
1930}
1931
1932
1933
1934/**
1935* Reference deleted callback
1936*
1937* @param cls our handle
1938* @param success success status
1939* @param emsg error message (NULL if success=GNUNET_OK)
1940*/
1941static void
1942reference_delete_cont (void *cls, int32_t success, const char *emsg)
1943{
1944 struct AttributeDeleteHandle *adh = cls;
1945
1946 adh->ns_qe = NULL;
1947 if (GNUNET_SYSERR == success)
1948 {
1949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1950 "Error deleting reference %s\n",
1951 adh->label);
1952 send_delete_response (adh, GNUNET_SYSERR);
1953 cleanup_adh (adh);
1954 return;
1955 }
1956 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1957 //GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1958 send_delete_response (adh, GNUNET_OK);
1959 cleanup_adh (adh);
1960 return;
1961}
1962
1963static void
1964ref_del_cb (void *cls,
1965 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1966 const char *label,
1967 unsigned int rd_count,
1968 const struct GNUNET_GNSRECORD_Data *rd)
1969{
1970
1971 struct AttributeDeleteHandle *adh = cls;
1972 char *data_tmp;
1973 struct GNUNET_GNSRECORD_Data rd_new[rd_count - 1];
1974 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
1975 size_t attr_len;
1976
1977 if (0 == rd_count )
1978 {
1979 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1980 "Failed to find Attestation entry for Attestation reference\n");
1981 cleanup_adh (adh);
1982 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1983 return;
1984 }
1985 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
1986 {
1987 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1988 "Intended Reference location is not an attestation\n");
1989 cleanup_adh (adh);
1990 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1991 return;
1992 }
1993 rd_new[0] = rd[0];
1994 int i;
1995 int j = 1;
1996 for (i = 1; i<rd_count; i++)
1997 {
1998 data_tmp = GNUNET_malloc (rd[i].data_size);
1999 GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2000 attr_len = htons (rd[i].data_size);
2001 ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, attr_len);
2002 if (NULL == ref )
2003 {
2004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2005 "Unable to parse attestation reference from %s\n",
2006 data_tmp);
2007 rd_new[j] = rd[i];
2008 j += 1;
2009 continue;
2010 }
2011 if ((strcmp (adh->reference->name,ref->name) == 0)&&
2012 (strcmp (adh->reference->reference_value,ref->reference_value)==0) )
2013 {
2014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2015 "Found reference to delete.\n");
2016 }
2017 else
2018 {
2019 rd_new[j] = rd[i];
2020 j += 1;
2021 }
2022 GNUNET_free (data_tmp);
2023 }
2024 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
2025 &adh->identity,
2026 label,
2027 j,
2028 rd_new,
2029 &reference_delete_cont,
2030 adh);
2031}
2032
2033/**
2034 * Check an attestation reference delete message
2035 *
2036 * @param cls unused
2037 * @param sam the message to check
2038 */
2039static int
2040check_reference_delete_message (void *cls,
2041 const struct AttributeDeleteMessage *dam)
2042{
2043 uint16_t size;
2044
2045 size = ntohs (dam->header.size);
2046 if (size <= sizeof(struct AttributeDeleteMessage))
2047 {
2048 GNUNET_break (0);
2049 return GNUNET_SYSERR;
2050 }
2051 return GNUNET_OK;
2052}
2053
2054/**
2055 * Handle reference deletion
2056 *
2057 * @param cls our client
2058 * @param dam deletion message
2059 */
2060static void
2061handle_reference_delete_message (void *cls,
2062 const struct AttributeDeleteMessage *dam)
2063{
2064 struct AttributeDeleteHandle *adh;
2065 struct IdpClient *idp = cls;
2066 size_t data_len;
2067
2068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_DELETE message\n");
2069 data_len = ntohs (dam->attr_len);
2070 adh = GNUNET_new (struct AttributeDeleteHandle);
2071 adh->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &dam[1],
2072 data_len);
2073 adh->attest = NULL;
2074 adh->claim = NULL;
2075
2076 adh->r_id = ntohl (dam->id);
2077 adh->identity = dam->identity;
2078 adh->label
2079 = GNUNET_STRINGS_data_to_string_alloc (&adh->reference->id,
2080 sizeof(uint64_t));
2081 GNUNET_SERVICE_client_continue (idp->client);
2082 adh->client = idp;
2083 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
2084 adh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
2085 &adh->identity,
2086 adh->label,
2087 &ref_del_error,
2088 adh,
2089 &ref_del_cb,
2090 adh);
2091}
2092
2093
1329 2094
1330/************************************************* 2095/*************************************************
1331* Attrubute iteration 2096* Attrubute iteration
@@ -1372,7 +2137,7 @@ attr_iter_error (void *cls)
1372 2137
1373 2138
1374/** 2139/**
1375 * Got record. Return if it is an attribute. 2140 * Got record. Return if it is an attribute or attestation/reference.
1376 * 2141 *
1377 * @param cls our attribute iterator 2142 * @param cls our attribute iterator
1378 * @param zone zone we are iterating 2143 * @param zone zone we are iterating
@@ -1388,35 +2153,103 @@ attr_iter_cb (void *cls,
1388 const struct GNUNET_GNSRECORD_Data *rd) 2153 const struct GNUNET_GNSRECORD_Data *rd)
1389{ 2154{
1390 struct AttributeIterator *ai = cls; 2155 struct AttributeIterator *ai = cls;
1391 struct AttributeResultMessage *arm;
1392 struct GNUNET_MQ_Envelope *env; 2156 struct GNUNET_MQ_Envelope *env;
1393 char *data_tmp; 2157 char *data_tmp;
1394 2158
1395 if (rd_count != 1) 2159 if (rd_count == 0)
1396 { 2160 {
1397 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); 2161 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1398 return; 2162 return;
1399 } 2163 }
2164 if (rd_count > 1)
2165 {
2166 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[0].record_type)
2167 {
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2169 "Found Ticket. Ignoring.\n");
2170 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2171 return;
2172 }
2173 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
2174 {
2175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2176 "Non-Attestation record with multiple entries found: %u\n",
2177 rd[0].record_type);
2178 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2179 return;
2180 }
2181 }
1400 2182
1401 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) 2183 for (int i = 0; i<rd_count; i++)
1402 { 2184 {
1403 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); 2185 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd[i].record_type) &&
1404 return; 2186 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[i].record_type) &&
2187 (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE != rd[i].record_type))
2188 {
2189 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2190 return;
2191 }
2192
2193 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type )
2194 {
2195 struct AttributeResultMessage *arm;
2196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
2197 label);
2198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2199 "Sending ATTRIBUTE_RESULT message\n");
2200 env = GNUNET_MQ_msg_extra (arm,
2201 rd[i].data_size,
2202 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
2203 arm->id = htonl (ai->request_id);
2204 arm->attr_len = htons (rd[i].data_size);
2205 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
2206 data_tmp = (char *) &arm[1];
2207 GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2208 GNUNET_MQ_send (ai->client->mq, env);
2209 }
2210 else
2211 {
2212 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type )
2213 {
2214 struct AttributeResultMessage *arm;
2215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
2216 label);
2217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2218 "Sending ATTESTATION_RESULT message\n");
2219 env = GNUNET_MQ_msg_extra (arm,
2220 rd[i].data_size,
2221 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
2222 arm->id = htonl (ai->request_id);
2223 arm->attr_len = htons (rd[i].data_size);
2224 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
2225 data_tmp = (char *) &arm[1];
2226 GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2227 GNUNET_MQ_send (ai->client->mq, env);
2228 }
2229 else
2230 {
2231 struct ReferenceResultMessage *rrm;
2232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found reference under: %s\n",
2233 label);
2234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2235 "Sending REFERENCE_RESULT message\n");
2236 env = GNUNET_MQ_msg_extra (rrm,
2237 rd[i].data_size + rd[0].data_size,
2238 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT);
2239 rrm->id = htonl (ai->request_id);
2240 rrm->attest_len = htons (rd[0].data_size);
2241 rrm->ref_len = htons (rd[i].data_size);
2242 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &rrm->identity);
2243 data_tmp = (char *) &rrm[1];
2244 GNUNET_memcpy (data_tmp, rd[0].data, rd[0].data_size);
2245 data_tmp += rd[0].data_size;
2246 GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
2247 GNUNET_MQ_send (ai->client->mq, env);
2248 }
2249 }
1405 } 2250 }
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1408 env = GNUNET_MQ_msg_extra (arm,
1409 rd->data_size,
1410 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1411 arm->id = htonl (ai->request_id);
1412 arm->attr_len = htons (rd->data_size);
1413 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1414 data_tmp = (char *) &arm[1];
1415 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1416 GNUNET_MQ_send (ai->client->mq, env);
1417} 2251}
1418 2252
1419
1420/** 2253/**
1421 * Iterate over zone to get attributes 2254 * Iterate over zone to get attributes
1422 * 2255 *
@@ -1742,10 +2575,26 @@ GNUNET_SERVICE_MAIN (
1742 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE, 2575 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1743 struct AttributeStoreMessage, 2576 struct AttributeStoreMessage,
1744 NULL), 2577 NULL),
2578 GNUNET_MQ_hd_var_size (attestation_store_message,
2579 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
2580 struct AttributeStoreMessage,
2581 NULL),
1745 GNUNET_MQ_hd_var_size (attribute_delete_message, 2582 GNUNET_MQ_hd_var_size (attribute_delete_message,
1746 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE, 2583 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1747 struct AttributeDeleteMessage, 2584 struct AttributeDeleteMessage,
1748 NULL), 2585 NULL),
2586 GNUNET_MQ_hd_var_size (attestation_delete_message,
2587 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
2588 struct AttributeDeleteMessage,
2589 NULL),
2590 GNUNET_MQ_hd_var_size (reference_store_message,
2591 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE,
2592 struct AttributeStoreMessage,
2593 NULL),
2594 GNUNET_MQ_hd_var_size (reference_delete_message,
2595 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE,
2596 struct AttributeDeleteMessage,
2597 NULL),
1749 GNUNET_MQ_hd_fixed_size ( 2598 GNUNET_MQ_hd_fixed_size (
1750 iteration_start, 2599 iteration_start,
1751 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START, 2600 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
index 4d1a26333..b022225b8 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -667,8 +667,7 @@ rvk_move_attr_cb (void *cls,
667 const struct GNUNET_GNSRECORD_Data *rd) 667 const struct GNUNET_GNSRECORD_Data *rd)
668{ 668{
669 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; 669 struct RECLAIM_TICKETS_RevokeHandle *rvk = cls;
670 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim; 670 struct GNUNET_GNSRECORD_Data new_rd[rd_count];
671 struct GNUNET_GNSRECORD_Data new_rd;
672 struct RevokedAttributeEntry *le; 671 struct RevokedAttributeEntry *le;
673 char *new_label; 672 char *new_label;
674 char *attr_data; 673 char *attr_data;
@@ -677,7 +676,7 @@ rvk_move_attr_cb (void *cls,
677 if (0 == rd_count) 676 if (0 == rd_count)
678 { 677 {
679 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 678 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
680 "The attribute %s no longer exists!\n", 679 "The claim %s no longer exists!\n",
681 label); 680 label);
682 le = rvk->move_attr; 681 le = rvk->move_attr;
683 rvk->move_attr = le->next; 682 rvk->move_attr = le->next;
@@ -686,32 +685,82 @@ rvk_move_attr_cb (void *cls,
686 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk); 685 GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk);
687 return; 686 return;
688 } 687 }
689 /** find a new place for this attribute **/ 688 rvk->move_attr->new_id =GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
690 rvk->move_attr->new_id = 689 new_label=NULL;
691 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); 690 attr_data=NULL;
692 new_rd = *rd; 691 //new_rd = *rd;
693 claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size); 692 for (int i = 0; i < rd_count; i++)
694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 693 {
695 "Attribute to update: Name=%s, ID=%" PRIu64 "\n", 694 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type)
696 claim->name, 695 {
697 claim->id); 696 /** find a new place for this attribute **/
698 claim->id = rvk->move_attr->new_id; 697 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
699 new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (claim); 698 claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd[i].data, rd[i].data_size);
700 attr_data = GNUNET_malloc (rd->data_size); 699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
701 new_rd.data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize (claim, attr_data); 700 "Attribute to update: Name=%s, ID=%" PRIu64 "\n",
702 new_rd.data = attr_data; 701 claim->name,
703 new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, 702 claim->id);
704 sizeof(uint64_t)); 703 claim->id = rvk->move_attr->new_id;
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label); 704 new_rd[i].data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (claim);
705 attr_data = GNUNET_malloc (rd[i].data_size);
706 new_rd[i].data_size = GNUNET_RECLAIM_ATTRIBUTE_serialize (claim, attr_data);
707 new_rd[i].data = attr_data;
708 new_rd[i].record_type = rd[i].record_type;
709 new_rd[i].flags = rd[i].flags;
710 new_rd[i].expiration_time = rd[i].expiration_time;
711 new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
712 sizeof(uint64_t));
713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
714 GNUNET_free (claim);
715 } else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type)
716 {
717 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
718 attest=GNUNET_RECLAIM_ATTESTATION_deserialize(rd[i].data, rd[i].data_size);
719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
720 "Attestation to update: Name=%s, ID=%" PRIu64 "\n",
721 attest->name,
722 attest->id);
723 attest->id = rvk->move_attr->new_id;
724 new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attest);
725 attr_data = GNUNET_malloc (rd[i].data_size);
726 new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_serialize (attest, attr_data);
727 new_rd[i].data = attr_data;
728 new_rd[i].record_type = rd[i].record_type;
729 new_rd[i].flags = rd[i].flags;
730 new_rd[i].expiration_time = rd[i].expiration_time;
731 new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, sizeof(uint64_t));
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation %s\n", new_label);
733 GNUNET_free (attest);
734 } else if (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE == rd[i].record_type)
735 {
736 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
737 reference=GNUNET_RECLAIM_ATTESTATION_REF_deserialize(rd[i].data, rd[i].data_size);
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739 "Reference to update: Name=%s, ID=%" PRIu64 "\n",
740 reference->name,
741 reference->id);
742 reference->id = rvk->move_attr->new_id;
743 reference->id_attest = rvk->move_attr->new_id;
744 new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (reference);
745 attr_data = GNUNET_malloc (rd[i].data_size);
746 new_rd[i].data_size = GNUNET_RECLAIM_ATTESTATION_REF_serialize (reference, attr_data);
747 new_rd[i].data = attr_data;
748 new_label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, sizeof(uint64_t));
749 new_rd[i].record_type = rd[i].record_type;
750 new_rd[i].flags = rd[i].flags;
751 new_rd[i].expiration_time = rd[i].expiration_time;
752 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference %s\n", new_label);
753 GNUNET_free (reference);
754 }
755 }
706 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, 756 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
707 &rvk->identity, 757 &rvk->identity,
708 new_label, 758 new_label,
709 1, 759 rd_count,
710 &new_rd, 760 new_rd,
711 &move_attr_finished, 761 &move_attr_finished,
712 rvk); 762 rvk);
713 GNUNET_free (new_label); 763 GNUNET_free (new_label);
714 GNUNET_free (claim);
715 GNUNET_free (attr_data); 764 GNUNET_free (attr_data);
716} 765}
717 766
@@ -745,7 +794,7 @@ move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk)
745 } 794 }
746 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id, 795 label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id,
747 sizeof(uint64_t)); 796 sizeof(uint64_t));
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving attribute %s\n", label); 797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label);
749 798
750 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, 799 rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
751 &rvk->identity, 800 &rvk->identity,
@@ -982,21 +1031,70 @@ process_parallel_lookup_result (void *cls,
982 1031
983 1032
984 GNUNET_free (parallel_lookup); 1033 GNUNET_free (parallel_lookup);
985 if (1 != rd_count) 1034 if (0 == rd_count)
986 GNUNET_break (0); // FIXME: We should never find this. 1035 GNUNET_break (0);
987 if (rd->record_type == GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR) 1036 // REMARK: It is possible now to find rd_count > 1
1037 for (int i = 0; i < rd_count; i++)
988 { 1038 {
989 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); 1039 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR == rd[i].record_type)
990 attr_le->claim = 1040 {
991 GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd->data, rd->data_size); 1041 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
992 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, 1042 attr_le->claim =
993 cth->attrs->list_tail, 1043 GNUNET_RECLAIM_ATTRIBUTE_deserialize (rd[i].data, rd[i].data_size);
994 attr_le); 1044 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
995 } 1045 cth->attrs->list_tail,
1046 attr_le);
1047 attr_le->reference = NULL;
1048 attr_le->attest = NULL;
1049 }
1050 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type)
1051 {
1052 /**Ignore all plain attestations
1053 *attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1054 *attr_le->attest =
1055 * GNUNET_RECLAIM_ATTESTATION_deserialize (rd[i].data, rd[i].data_size);
1056 *GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1057 * cth->attrs->list_tail,
1058 * attr_le);
1059 */
1060 continue;
1061 }
1062 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE == rd[i].record_type)
1063 {
1064 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *attr_le2;
1065 attr_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1066 attr_le2 = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1067 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[0].record_type)
1068 {
1069 attr_le->attest = GNUNET_RECLAIM_ATTESTATION_deserialize (rd[0].data,
1070 rd[0].
1071 data_size);
1072 attr_le2->reference =
1073 GNUNET_RECLAIM_ATTESTATION_REF_deserialize (rd[i].data,
1074 rd[i].data_size);
1075 attr_le->claim = NULL;
1076 attr_le->reference = NULL;
1077 attr_le2->claim = NULL;
1078 attr_le2->attest = NULL;
1079 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1080 cth->attrs->list_tail,
1081 attr_le);
1082 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1083 cth->attrs->list_tail,
1084 attr_le2);
1085 }
1086 else
1087 {
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 "Parallel Lookup of Reference without Attestation");
1090 continue;
1091 }
996 1092
1093
1094 }
1095 }
997 if (NULL != cth->parallel_lookups_head) 1096 if (NULL != cth->parallel_lookups_head)
998 return; // Wait for more 1097 return; // Wait for more
999
1000 /* Else we are done */ 1098 /* Else we are done */
1001 cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL); 1099 cth->cb (cth->cb_cls, &cth->ticket.identity, cth->attrs, GNUNET_OK, NULL);
1002 cleanup_cth (cth); 1100 cleanup_cth (cth);
@@ -1076,7 +1174,7 @@ lookup_authz_cb (void *cls,
1076 GNUNET_GNS_lookup (gns, 1174 GNUNET_GNS_lookup (gns,
1077 lbl, 1175 lbl,
1078 &cth->ticket.identity, 1176 &cth->ticket.identity,
1079 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR, 1177 GNUNET_GNSRECORD_TYPE_ANY,
1080 GNUNET_GNS_LO_DEFAULT, 1178 GNUNET_GNS_LO_DEFAULT,
1081 &process_parallel_lookup_result, 1179 &process_parallel_lookup_result,
1082 parallel_lookup); 1180 parallel_lookup);
@@ -1223,6 +1321,7 @@ issue_ticket (struct TicketIssueHandle *ih)
1223 char *label; 1321 char *label;
1224 size_t list_len = 1; 1322 size_t list_len = 1;
1225 int i; 1323 int i;
1324 char *attest_string;
1226 1325
1227 for (le = ih->attrs->list_head; NULL != le; le = le->next) 1326 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1228 list_len++; 1327 list_len++;
@@ -1232,8 +1331,51 @@ issue_ticket (struct TicketIssueHandle *ih)
1232 i = 0; 1331 i = 0;
1233 for (le = ih->attrs->list_head; NULL != le; le = le->next) 1332 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1234 { 1333 {
1235 attrs_record[i].data = &le->claim->id; 1334 if (NULL != le->claim)
1236 attrs_record[i].data_size = sizeof(le->claim->id); 1335 {
1336 attrs_record[i].data = &le->claim->id;
1337 attrs_record[i].data_size = sizeof(le->claim->id);
1338 }
1339 else if (NULL != le->attest)
1340 {
1341 // REMARK: Since we only store IDs, the references are irrelevant
1342 int j = 0;
1343 GNUNET_asprintf (&attest_string,"%d",le->attest->id);
1344 while (j<i)
1345 {
1346 if (0 == strcmp (attest_string,GNUNET_STRINGS_data_to_string_alloc (
1347 attrs_record[j].data, attrs_record[j].data_size)))
1348 break;
1349 j++;
1350 }
1351 if (j < i)
1352 {
1353 list_len--;
1354 continue;
1355 }
1356 attrs_record[i].data = &le->attest->id;
1357 attrs_record[i].data_size = sizeof(le->attest->id);
1358 }
1359 else if (NULL != le->reference)
1360 {
1361 list_len--;
1362 continue;
1363 /*
1364 int j = 0;
1365 GNUNET_asprintf (&attest_string,"%d",le->attest->id);
1366 while (j<i)
1367 {
1368 if (strcmp(attest_string, GNUNET_STRINGS_data_to_string_alloc (
1369 attrs_record[j].data, attrs_record[j].data_size)))
1370 break;
1371 j++;
1372 }
1373 if (j < i)
1374 continue;
1375 attrs_record[i].data = &le->reference->id;
1376 attrs_record[i].data_size = sizeof(le->reference->id);
1377 */
1378 }
1237 /** 1379 /**
1238 * FIXME: Should this be the attribute expiration time or ticket 1380 * FIXME: Should this be the attribute expiration time or ticket
1239 * refresh interval? Probably min(attrs.expiration) 1381 * refresh interval? Probably min(attrs.expiration)
@@ -1344,14 +1486,34 @@ filter_tickets_cb (void *cls,
1344 for (le = tih->attrs->list_head; NULL != le; le = le->next) 1486 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1345 { 1487 {
1346 // cmp attr_ref id with requested attr id 1488 // cmp attr_ref id with requested attr id
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1489 if (NULL !=le->claim)
1348 " %" PRIu64 "\n %" PRIu64 "\n", 1490 {
1349 *((uint64_t *) rd[i].data), 1491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1350 le->claim->id); 1492 " %" PRIu64 "\n %" PRIu64 "\n",
1351 1493 *((uint64_t *) rd[i].data),
1494 le->claim->id);
1495 if (0 == memcmp (rd[i].data, &le->claim->id, sizeof(uint64_t)))
1496 found_attrs_cnt++;
1497 }
1498 else if (NULL !=le->attest)
1499 {
1500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1501 " %" PRIu64 "\n %" PRIu64 "\n",
1502 *((uint64_t *) rd[i].data),
1503 le->attest->id);
1504 if (0 == memcmp (rd[i].data, &le->attest->id, sizeof(uint64_t)))
1505 found_attrs_cnt++;
1506 }
1507 else if (NULL != le->reference)
1508 {
1509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1510 " %" PRIu64 "\n %" PRIu64 "\n",
1511 *((uint64_t *) rd[i].data),
1512 le->reference->id);
1513 if (0 == memcmp (rd[i].data, &le->reference->id, sizeof(uint64_t)))
1514 found_attrs_cnt++;
1515 }
1352 1516
1353 if (0 == memcmp (rd[i].data, &le->claim->id, sizeof(uint64_t)))
1354 found_attrs_cnt++;
1355 } 1517 }
1356 } 1518 }
1357 1519
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c
index e029fdfb6..a464a9088 100644
--- a/src/reclaim/json_reclaim.c
+++ b/src/reclaim/json_reclaim.c
@@ -48,6 +48,7 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
48 const char *val_str = NULL; 48 const char *val_str = NULL;
49 const char *type_str = NULL; 49 const char *type_str = NULL;
50 const char *id_str = NULL; 50 const char *id_str = NULL;
51 const char *flag_str = NULL;
51 char *data; 52 char *data;
52 int unpack_state; 53 int unpack_state;
53 uint32_t type; 54 uint32_t type;
@@ -63,7 +64,7 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
63 } 64 }
64 // interpret single attribute 65 // interpret single attribute
65 unpack_state = json_unpack (root, 66 unpack_state = json_unpack (root,
66 "{s:s, s?s, s:s, s:s!}", 67 "{s:s, s?s, s:s, s:s, s?s!}",
67 "name", 68 "name",
68 &name_str, 69 &name_str,
69 "id", 70 "id",
@@ -71,7 +72,9 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
71 "type", 72 "type",
72 &type_str, 73 &type_str,
73 "value", 74 "value",
74 &val_str); 75 &val_str,
76 "flag",
77 &flag_str);
75 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) || 78 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
76 (NULL == type_str)) 79 (NULL == type_str))
77 { 80 {
@@ -264,3 +267,217 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
264 *ticket = NULL; 267 *ticket = NULL;
265 return ret; 268 return ret;
266} 269}
270
271/**
272 * Parse given JSON object to an attestation claim
273 *
274 * @param cls closure, NULL
275 * @param root the json object representing data
276 * @param spec where to write the data
277 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
278 */
279static int
280parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
281{
282 struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
283 const char *name_str = NULL;
284 const char *val_str = NULL;
285 const char *type_str = NULL;
286 const char *id_str = NULL;
287 char *data;
288 int unpack_state;
289 uint32_t type;
290 size_t data_size;
291
292 GNUNET_assert (NULL != root);
293
294 if (! json_is_object (root))
295 {
296 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297 "Error json is not array nor object!\n");
298 return GNUNET_SYSERR;
299 }
300 // interpret single attribute
301 unpack_state = json_unpack (root,
302 "{s:s, s?s, s:s, s:s!}",
303 "name",
304 &name_str,
305 "id",
306 &id_str,
307 "type",
308 &type_str,
309 "value",
310 &val_str);
311 if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) ||
312 (NULL == type_str))
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
315 "Error json object has a wrong format!\n");
316 return GNUNET_SYSERR;
317 }
318 type = GNUNET_RECLAIM_ATTESTATION_typename_to_number (type_str);
319 if (GNUNET_SYSERR ==
320 (GNUNET_RECLAIM_ATTESTATION_string_to_value (type,
321 val_str,
322 (void **) &data,
323 &data_size)))
324 {
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attestation value invalid!\n");
326 return GNUNET_SYSERR;
327 }
328 attr = GNUNET_RECLAIM_ATTESTATION_claim_new (name_str, type, data, data_size);
329 if ((NULL == id_str) || (0 == strlen (id_str)))
330 attr->id = 0;
331 else
332 GNUNET_STRINGS_string_to_data (id_str,
333 strlen (id_str),
334 &attr->id,
335 sizeof(uint64_t));
336
337 *(struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr = attr;
338 return GNUNET_OK;
339}
340
341/**
342 * Cleanup data left from parsing RSA public key.
343 *
344 * @param cls closure, NULL
345 * @param[out] spec where to free the data
346 */
347static void
348clean_attest (void *cls, struct GNUNET_JSON_Specification *spec)
349{
350 struct GNUNET_RECLAIM_ATTESTATION_Claim **attr;
351
352 attr = (struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr;
353 if (NULL != *attr)
354 {
355 GNUNET_free (*attr);
356 *attr = NULL;
357 }
358}
359/**
360 * JSON Specification for Reclaim attestation claims.
361 *
362 * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill
363 * @return JSON Specification
364 */
365struct GNUNET_JSON_Specification
366GNUNET_RECLAIM_JSON_spec_claim_attest (struct
367 GNUNET_RECLAIM_ATTESTATION_Claim **attr)
368{
369 struct GNUNET_JSON_Specification ret = { .parser = &parse_attest,
370 .cleaner = &clean_attest,
371 .cls = NULL,
372 .field = NULL,
373 .ptr = attr,
374 .ptr_size = 0,
375 .size_ptr = NULL };
376
377 *attr = NULL;
378 return ret;
379}
380
381/**
382 * Parse given JSON object to an attestation claim
383 *
384 * @param cls closure, NULL
385 * @param root the json object representing data
386 * @param spec where to write the data
387 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
388 */
389static int
390parse_attest_ref (void *cls, json_t *root, struct
391 GNUNET_JSON_Specification *spec)
392{
393 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
394 const char *name_str = NULL;
395 const char *ref_val_str = NULL;
396 const char *ref_id_str = NULL;
397 const char *id_str = NULL;
398 int unpack_state;
399
400 GNUNET_assert (NULL != root);
401
402 if (! json_is_object (root))
403 {
404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
405 "Error json is not array nor object!\n");
406 return GNUNET_SYSERR;
407 }
408 // interpret single reference
409 unpack_state = json_unpack (root,
410 "{s:s, s?s, s:s, s:s!}",
411 "name",
412 &name_str,
413 "id",
414 &id_str,
415 "ref_id",
416 &ref_id_str,
417 "ref_value",
418 &ref_val_str);
419 if ((0 != unpack_state) || (NULL == name_str) || (NULL == ref_val_str) ||
420 (NULL == ref_id_str))
421 {
422 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
423 "Error json object has a wrong format!\n");
424 return GNUNET_SYSERR;
425 }
426
427 attr = GNUNET_RECLAIM_ATTESTATION_reference_new (name_str, ref_val_str);
428
429 attr->id = 0;
430
431 if ((NULL == ref_id_str) || (0 == strlen (ref_id_str)))
432 attr->id_attest = 0;
433 else
434 GNUNET_STRINGS_string_to_data (ref_id_str,
435 strlen (ref_id_str),
436 &attr->id_attest,
437 sizeof(uint64_t));
438
439 *(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **) spec->ptr = attr;
440 return GNUNET_OK;
441}
442
443/**
444 * Cleanup data left from parsing RSA public key.
445 *
446 * @param cls closure, NULL
447 * @param[out] spec where to free the data
448 */
449static void
450clean_attest_ref (void *cls, struct GNUNET_JSON_Specification *spec)
451{
452 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **attr;
453
454 attr = (struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **) spec->ptr;
455 if (NULL != *attr)
456 {
457 GNUNET_free (*attr);
458 *attr = NULL;
459 }
460}
461
462/**
463 * JSON Specification for Reclaim attestation references.
464 *
465 * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_REFERENCE to fill
466 * @return JSON Specification
467 */
468struct GNUNET_JSON_Specification
469GNUNET_RECLAIM_JSON_spec_claim_attest_ref (struct
470 GNUNET_RECLAIM_ATTESTATION_REFERENCE
471 **attr)
472{
473 struct GNUNET_JSON_Specification ret = { .parser = &parse_attest_ref,
474 .cleaner = &clean_attest_ref,
475 .cls = NULL,
476 .field = NULL,
477 .ptr = attr,
478 .ptr_size = 0,
479 .size_ptr = NULL };
480
481 *attr = NULL;
482 return ret;
483} \ No newline at end of file
diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h
index 3fd26167f..9e6479e5e 100644
--- a/src/reclaim/json_reclaim.h
+++ b/src/reclaim/json_reclaim.h
@@ -46,3 +46,22 @@ GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_ATTRIBUTE_Claim **attr);
46 */ 46 */
47struct GNUNET_JSON_Specification 47struct GNUNET_JSON_Specification
48GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket); 48GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket);
49
50/**
51 * JSON Specification for Reclaim attestation claims.
52 *
53 * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill
54 * @return JSON Specification
55 */
56struct GNUNET_JSON_Specification
57GNUNET_RECLAIM_JSON_spec_claim_attest (struct
58 GNUNET_RECLAIM_ATTESTATION_Claim **attr);
59
60 /**
61 * JSON Specification for Reclaim attestation references.
62 *
63 * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_REFERENCE to fill
64 * @return JSON Specification
65 */
66 struct GNUNET_JSON_Specification
67 GNUNET_RECLAIM_JSON_spec_claim_attest_ref(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE **attr);
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index 1c3d65f35..2ce462854 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -118,7 +118,7 @@ fix_base64 (char *str)
118char * 118char *
119OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 119OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
120 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 120 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
121 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, 121 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
122 const struct GNUNET_TIME_Relative *expiration_time, 122 const struct GNUNET_TIME_Relative *expiration_time,
123 const char *nonce, 123 const char *nonce,
124 const char *secret_key) 124 const char *secret_key)
@@ -131,13 +131,22 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
131 char *subject; 131 char *subject;
132 char *header; 132 char *header;
133 char *body_str; 133 char *body_str;
134 char *aggr_names_str;
135 char *aggr_sources_str;
136 char *aggr_sources_jwt_str;
137 char *source_name;
134 char *result; 138 char *result;
135 char *header_base64; 139 char *header_base64;
136 char *body_base64; 140 char *body_base64;
137 char *signature_target; 141 char *signature_target;
138 char *signature_base64; 142 char *signature_base64;
139 char *attr_val_str; 143 char *attr_val_str;
144 char *attest_val_str;
140 json_t *body; 145 json_t *body;
146 json_t *aggr_names;
147 json_t *aggr_sources;
148 json_t *aggr_sources_jwt;
149 uint64_t attest_arr[GNUNET_RECLAIM_ATTRIBUTE_list_count_attest (attrs)];
141 150
142 // iat REQUIRED time now 151 // iat REQUIRED time now
143 time_now = GNUNET_TIME_absolute_get (); 152 time_now = GNUNET_TIME_absolute_get ();
@@ -156,6 +165,8 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
156 GNUNET_CRYPTO_EcdsaPublicKey)); 165 GNUNET_CRYPTO_EcdsaPublicKey));
157 header = create_jwt_header (); 166 header = create_jwt_header ();
158 body = json_object (); 167 body = json_object ();
168 aggr_names = json_object ();
169 aggr_sources = json_object ();
159 170
160 // iss REQUIRED case sensitive server uri with https 171 // iss REQUIRED case sensitive server uri with https
161 // The issuer is the local reclaim instance (e.g. 172 // The issuer is the local reclaim instance (e.g.
@@ -180,18 +191,111 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
180 // nonce 191 // nonce
181 if (NULL != nonce) 192 if (NULL != nonce)
182 json_object_set_new (body, "nonce", json_string (nonce)); 193 json_object_set_new (body, "nonce", json_string (nonce));
183 194 int i = 0;
195 attest_val_str = NULL;
196 aggr_names_str = NULL;
197 aggr_sources_str = NULL;
198 aggr_sources_jwt_str = NULL;
199 source_name = NULL;
184 for (le = attrs->list_head; NULL != le; le = le->next) 200 for (le = attrs->list_head; NULL != le; le = le->next)
185 { 201 {
186 attr_val_str = 202
187 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type, 203 if (le->claim != NULL)
188 le->claim->data, 204 {
189 le->claim->data_size); 205
190 json_object_set_new (body, le->claim->name, json_string (attr_val_str)); 206 attr_val_str =
191 GNUNET_free (attr_val_str); 207 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
208 le->claim->data,
209 le->claim->data_size);
210 json_object_set_new (body, le->claim->name, json_string (attr_val_str));
211 GNUNET_free (attr_val_str);
212 }
213 else if (NULL != le->reference)
214 {
215 // Check if attest is there
216 int j = 0;
217 while (j<i)
218 {
219 if (attest_arr[j] == le->reference->id_attest)
220 break;
221 j++;
222 }
223 if (j==i)
224 {
225 // Attest not yet existent. Append to the end of the list
226 GNUNET_CONTAINER_DLL_remove (attrs->list_head, attrs->list_tail, le);
227 GNUNET_CONTAINER_DLL_insert_tail (attrs->list_head, attrs->list_tail,
228 le);
229 continue;
230 }
231 else
232 {
233 // Attestation is existing, hence take the respective source str
234 GNUNET_asprintf (&source_name,
235 "src%d",
236 j);
237 json_object_set_new (aggr_names, le->reference->name, json_string (
238 source_name));
239 }
240
241 }
242 else if (NULL != le->attest)
243 {
244 // We assume that at max 99 different attestations
245 int j = 0;
246 while (j<i)
247 {
248 if (attest_arr[j] == le->attest->id)
249 break;
250 j++;
251 }
252 if (j==i)
253 {
254 // New Attestation
255 attest_arr[i] = le->attest->id;
256 GNUNET_asprintf (&source_name,
257 "src%d",
258 i);
259 aggr_sources_jwt = json_object ();
260 attest_val_str = GNUNET_RECLAIM_ATTESTATION_value_to_string (
261 le->attest->type, le->attest->data, le->attest->data_size);
262 json_object_set_new (aggr_sources_jwt, "JWT",json_string (
263 attest_val_str) );
264 aggr_sources_jwt_str = json_dumps (aggr_sources_jwt, JSON_INDENT (0)
265 | JSON_COMPACT);
266 json_object_set_new (aggr_sources, source_name,json_string (
267 aggr_sources_jwt_str));
268 i++;
269 }
270 else
271 {
272 // Attestation already existent. Ignore
273 continue;
274 }
275
276 }
277 }
278 if (NULL != attest_val_str)
279 GNUNET_free (attest_val_str);
280 if (NULL != source_name)
281 GNUNET_free (source_name);
282 if (0!=i)
283 {
284 aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
285 aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
286 | JSON_COMPACT);
287 json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
288 json_object_set_new (body, "_claim_sources", json_string (
289 aggr_sources_str));
192 } 290 }
291
292 json_decref (aggr_names);
293 json_decref (aggr_sources);
294 json_decref (aggr_sources_jwt);
295
193 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT); 296 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
194 json_decref (body); 297 json_decref (body);
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
195 299
196 GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64); 300 GNUNET_STRINGS_base64_encode (header, strlen (header), &header_base64);
197 fix_base64 (header_base64); 301 fix_base64 (header_base64);
@@ -226,6 +330,12 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
226 GNUNET_free (signature_target); 330 GNUNET_free (signature_target);
227 GNUNET_free (header); 331 GNUNET_free (header);
228 GNUNET_free (body_str); 332 GNUNET_free (body_str);
333 if (NULL != aggr_sources_str)
334 GNUNET_free (aggr_sources_str);
335 if (NULL != aggr_names_str)
336 GNUNET_free (aggr_names_str);
337 if (NULL != aggr_sources_jwt_str)
338 GNUNET_free (aggr_sources_jwt_str);
229 GNUNET_free (signature_base64); 339 GNUNET_free (signature_base64);
230 GNUNET_free (body_base64); 340 GNUNET_free (body_base64);
231 GNUNET_free (header_base64); 341 GNUNET_free (header_base64);
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 1774618e8..a7072755b 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -51,7 +51,7 @@
51char* 51char*
52OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 52OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
53 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 53 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
54 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, 54 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
55 const struct GNUNET_TIME_Relative *expiration_time, 55 const struct GNUNET_TIME_Relative *expiration_time,
56 const char *nonce, 56 const char *nonce,
57 const char *secret_key); 57 const char *secret_key);
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
index d530ef01d..f7145a272 100644
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ b/src/reclaim/plugin_gnsrecord_reclaim.c
@@ -54,6 +54,8 @@ value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF: 54 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF:
55 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 55 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
56 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER: 56 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
57 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR:
58 case GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE:
57 return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 59 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
58 60
59 default: 61 default:
@@ -93,6 +95,8 @@ string_to_value (void *cls, uint32_t type, const char *s, void **data,
93 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF: 95 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF:
94 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER: 96 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
95 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 97 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
98 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR:
99 case GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE:
96 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size); 100 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
97 101
98 default: 102 default:
@@ -112,10 +116,12 @@ static struct
112} name_map[] = { 116} name_map[] = {
113 { "RECLAIM_ATTR", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR }, 117 { "RECLAIM_ATTR", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR },
114 { "RECLAIM_ATTR_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF }, 118 { "RECLAIM_ATTR_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF },
119 { "RECLAIM_ATTEST", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR },
115 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER }, 120 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
116 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT }, 121 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
117 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT }, 122 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
118 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET }, 123 { "RECLAIM_TICKET", GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET },
124 { "RECLAIM_REFERENCE", GNUNET_GNSRECORD_TYPE_RECLAIM_REFERENCE },
119 { NULL, UINT32_MAX } 125 { NULL, UINT32_MAX }
120}; 126};
121 127
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 92a1de621..741094f21 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -120,6 +120,11 @@
120#define OIDC_NONCE_KEY "nonce" 120#define OIDC_NONCE_KEY "nonce"
121 121
122/** 122/**
123 * OIDC claims key
124 */
125#define OIDC_CLAIMS_KEY "claims"
126
127/**
123 * OIDC PKCE code challenge 128 * OIDC PKCE code challenge
124 */ 129 */
125#define OIDC_CODE_CHALLENGE_KEY "code_challenge" 130#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
@@ -291,6 +296,11 @@ struct OIDC_Variables
291 char *nonce; 296 char *nonce;
292 297
293 /** 298 /**
299 * The OIDC claims
300 */
301 char *claims;
302
303 /**
294 * The OIDC response type 304 * The OIDC response type
295 */ 305 */
296 char *response_type; 306 char *response_type;
@@ -560,7 +570,12 @@ cleanup_handle (struct RequestHandle *handle)
560 { 570 {
561 claim_tmp = claim_entry; 571 claim_tmp = claim_entry;
562 claim_entry = claim_entry->next; 572 claim_entry = claim_entry->next;
563 GNUNET_free (claim_tmp->claim); 573 if (NULL != claim_tmp->claim)
574 GNUNET_free (claim_tmp->claim);
575 if (NULL != claim_tmp->attest)
576 GNUNET_free (claim_tmp->attest);
577 if (NULL != claim_tmp->reference)
578 GNUNET_free (claim_tmp->reference);
564 GNUNET_free (claim_tmp); 579 GNUNET_free (claim_tmp);
565 } 580 }
566 GNUNET_free (handle->attr_list); 581 GNUNET_free (handle->attr_list);
@@ -697,7 +712,7 @@ return_userinfo_response (void *cls)
697 struct MHD_Response *resp; 712 struct MHD_Response *resp;
698 713
699 result_str = json_dumps (handle->oidc->response, 0); 714 result_str = json_dumps (handle->oidc->response, 0);
700 715 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str);
701 resp = GNUNET_REST_create_response (result_str); 716 resp = GNUNET_REST_create_response (result_str);
702 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 717 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
703 GNUNET_free (result_str); 718 GNUNET_free (result_str);
@@ -838,7 +853,7 @@ login_redirect (void *cls)
838 &login_base_url)) 853 &login_base_url))
839 { 854 {
840 GNUNET_asprintf (&new_redirect, 855 GNUNET_asprintf (&new_redirect,
841 "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", 856 "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
842 login_base_url, 857 login_base_url,
843 OIDC_RESPONSE_TYPE_KEY, 858 OIDC_RESPONSE_TYPE_KEY,
844 handle->oidc->response_type, 859 handle->oidc->response_type,
@@ -854,7 +869,10 @@ login_redirect (void *cls)
854 (NULL != handle->oidc->code_challenge) ? 869 (NULL != handle->oidc->code_challenge) ?
855 handle->oidc->code_challenge : "", 870 handle->oidc->code_challenge : "",
856 OIDC_NONCE_KEY, 871 OIDC_NONCE_KEY,
857 (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); 872 (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
873 OIDC_CLAIMS_KEY,
874 (NULL != handle->oidc->claims) ? handle->oidc->claims :
875 "");
858 resp = GNUNET_REST_create_response (""); 876 resp = GNUNET_REST_create_response ("");
859 MHD_add_response_header (resp, "Location", new_redirect); 877 MHD_add_response_header (resp, "Location", new_redirect);
860 GNUNET_free (login_base_url); 878 GNUNET_free (login_base_url);
@@ -973,12 +991,14 @@ oidc_collect_finished_cb (void *cls)
973 991
974 992
975/** 993/**
976 * Collects all attributes for an ego if in scope parameter 994 * Collects all attributes/references for an ego if in scope parameter
977 */ 995 */
978static void 996static void
979oidc_attr_collect (void *cls, 997oidc_attr_collect (void *cls,
980 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 998 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
981 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 999 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1000 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1001 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
982{ 1002{
983 struct RequestHandle *handle = cls; 1003 struct RequestHandle *handle = cls;
984 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; 1004 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
@@ -986,39 +1006,92 @@ oidc_attr_collect (void *cls,
986 char *scope_variable; 1006 char *scope_variable;
987 char delimiter[] = " "; 1007 char delimiter[] = " ";
988 1008
989 if ((NULL == attr->name) || (NULL == attr->data)) 1009 if ((NULL == attr) && (NULL == reference))
990 { 1010 {
991 GNUNET_RECLAIM_get_attributes_next (handle->attr_it); 1011 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
992 return; 1012 return;
993 } 1013 }
994 1014 if (NULL != reference)
995 scope_variables = GNUNET_strdup (handle->oidc->scope);
996 scope_variable = strtok (scope_variables, delimiter);
997 while (NULL != scope_variable)
998 {
999 if (0 == strcmp (attr->name, scope_variable))
1000 break;
1001 scope_variable = strtok (NULL, delimiter);
1002 }
1003 if (NULL == scope_variable)
1004 { 1015 {
1005 GNUNET_RECLAIM_get_attributes_next (handle->attr_it); 1016 if ((NULL == reference->name) || (NULL == reference->reference_value))
1017 {
1018 return;
1019 }
1020 scope_variables = GNUNET_strdup (handle->oidc->scope);
1021 scope_variable = strtok (scope_variables, delimiter);
1022 while (NULL != scope_variable)
1023 {
1024 if (0 == strcmp (reference->name, scope_variable))
1025 break;
1026 scope_variable = strtok (NULL, delimiter);
1027 }
1028 if (NULL == scope_variable)
1029 {
1030 GNUNET_free (scope_variables);
1031 return;
1032 }
1006 GNUNET_free (scope_variables); 1033 GNUNET_free (scope_variables);
1007 return; 1034 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le2;
1035 le2 = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1036 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1037 le->claim = NULL;
1038 le->reference = NULL;
1039 le->attest = GNUNET_RECLAIM_ATTESTATION_claim_new (attest->name,
1040 attest->type,
1041 attest->data,
1042 attest->data_size);
1043 le->attest->id = attest->id;
1044 le2->attest = NULL;
1045 le2->claim = NULL;
1046 le2->reference = GNUNET_RECLAIM_ATTESTATION_reference_new (reference->name,
1047 reference->
1048 reference_value);
1049 le2->reference->id = reference->id;
1050 le2->reference->id_attest = reference->id_attest;
1051 GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
1052 handle->attr_list->list_tail,
1053 le);
1054 GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
1055 handle->attr_list->list_tail,
1056 le2);
1057 }
1058 else if (NULL != attr)
1059 {
1060 if ((NULL == attr->name) || (NULL == attr->data))
1061 {
1062 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1063 return;
1064 }
1065 scope_variables = GNUNET_strdup (handle->oidc->scope);
1066 scope_variable = strtok (scope_variables, delimiter);
1067 while (NULL != scope_variable)
1068 {
1069 if (0 == strcmp (attr->name, scope_variable))
1070 break;
1071 scope_variable = strtok (NULL, delimiter);
1072 }
1073 if (NULL == scope_variable)
1074 {
1075 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1076 GNUNET_free (scope_variables);
1077 return;
1078 }
1079 GNUNET_free (scope_variables);
1080 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1081 le->reference = NULL;
1082 le->attest = NULL;
1083 le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
1084 attr->type,
1085 attr->data,
1086 attr->data_size);
1087 le->claim->id = attr->id;
1088 le->claim->flag = attr->flag;
1089
1090 GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
1091 handle->attr_list->list_tail,
1092 le);
1093 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1008 } 1094 }
1009 GNUNET_free (scope_variables);
1010
1011 le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
1012 le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name,
1013 attr->type,
1014 attr->data,
1015 attr->data_size);
1016 le->claim->id = attr->id;
1017 le->claim->version = attr->version;
1018 GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
1019 handle->attr_list->list_tail,
1020 le);
1021 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1022} 1095}
1023 1096
1024 1097
@@ -1304,6 +1377,9 @@ build_authz_response (void *cls)
1304 // OPTIONAL value: nonce 1377 // OPTIONAL value: nonce
1305 handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY); 1378 handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1306 1379
1380 // OPTIONAL value: claims
1381 handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1382
1307 // TODO check other values if needed 1383 // TODO check other values if needed
1308 number_of_ignored_parameter = 1384 number_of_ignored_parameter =
1309 sizeof(OIDC_ignored_parameter_array) / sizeof(char *); 1385 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
@@ -1454,6 +1530,9 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1454 handle->ego_entry = handle->ego_tail; 1530 handle->ego_entry = handle->ego_tail;
1455 } 1531 }
1456 } 1532 }
1533 handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n",GNUNET_strdup (
1535 handle->oidc->scope));
1457 if (NULL == handle->tld) 1536 if (NULL == handle->tld)
1458 GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle); 1537 GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle);
1459 if (NULL == handle->tld) 1538 if (NULL == handle->tld)
@@ -1857,28 +1936,97 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1857 1936
1858 1937
1859/** 1938/**
1860 * Collects claims and stores them in handle 1939 * Collects claims and stores them in handle
1861 */ 1940 */
1862static void 1941static void
1863consume_ticket (void *cls, 1942consume_ticket (void *cls,
1864 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 1943 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1865 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 1944 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1945 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1946 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
1866{ 1947{
1867 struct RequestHandle *handle = cls; 1948 struct RequestHandle *handle = cls;
1868 char *tmp_value;
1869 json_t *value;
1870
1871 if (NULL == identity) 1949 if (NULL == identity)
1872 { 1950 {
1873 GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); 1951 GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
1874 return; 1952 return;
1875 } 1953 }
1876 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, 1954 if (NULL != attr)
1877 attr->data, 1955 {
1878 attr->data_size); 1956 char *tmp_value;
1879 value = json_string (tmp_value); 1957 json_t *value;
1880 json_object_set_new (handle->oidc->response, attr->name, value); 1958 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
1881 GNUNET_free (tmp_value); 1959 attr->data,
1960 attr->data_size);
1961 value = json_string (tmp_value);
1962 json_object_set_new (handle->oidc->response, attr->name, value);
1963 GNUNET_free (tmp_value);
1964 }
1965 else if ((NULL != attest) && (NULL != reference))
1966 {
1967 json_t *claim_sources;
1968 json_t *claim_sources_jwt;
1969 json_t *claim_names;
1970 char *attest_val_str;
1971 claim_sources=json_object_get(handle->oidc->response,"_claim_sources");
1972 claim_names=json_object_get(handle->oidc->response,"_claim_names");
1973 attest_val_str = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
1974 attest->data,
1975 attest->
1976 data_size);
1977 if ((NULL == claim_sources) && (NULL == claim_names) )
1978 {
1979 claim_sources = json_object ();
1980 claim_names = json_object ();
1981 }
1982 char *source_name;
1983 int i = 0;
1984 GNUNET_asprintf (&source_name,"src%d",i);
1985 while (NULL != (claim_sources_jwt = json_object_get (claim_sources,
1986 source_name)))
1987 {
1988 if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt,
1989 "JWT")),
1990 attest_val_str))
1991 {
1992 // Adapt only the claim names
1993 json_object_set_new (claim_names, reference->name, json_string (
1994 source_name));
1995 json_object_set (handle->oidc->response, "_claim_names",claim_names);
1996 handle->oidc->response = json_deep_copy(handle->oidc->response);
1997 break;
1998 }
1999 i++;
2000 GNUNET_asprintf (&source_name,"src%d",i);
2001 }
2002
2003 // Create new one
2004 if (NULL == claim_sources_jwt)
2005 {
2006 claim_sources_jwt = json_object ();
2007 // Set the JWT for names
2008 json_object_set_new (claim_names, reference->name, json_string (
2009 source_name));
2010 // Set the JWT for the inner source
2011 json_object_set_new (claim_sources_jwt, "JWT", json_string (
2012 attest_val_str));
2013 // Set the JWT for the source
2014 json_object_set_new (claim_sources, source_name,claim_sources_jwt);
2015 // Set as claims
2016 json_object_set (handle->oidc->response, "_claim_names", claim_names);
2017 json_object_set (handle->oidc->response, "_claim_sources",claim_sources);
2018 handle->oidc->response = json_deep_copy(handle->oidc->response);
2019 }
2020
2021 json_decref (claim_sources);
2022 json_decref (claim_names);
2023 json_decref (claim_sources_jwt);
2024 GNUNET_free (attest_val_str);
2025 }
2026 else
2027 {
2028 // REMARK: We should not find any claim, one of attest/ref is NULL
2029 }
1882} 2030}
1883 2031
1884 2032
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index 9a75b2d16..dcda75b65 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -37,7 +37,6 @@
37#include "gnunet_rest_plugin.h" 37#include "gnunet_rest_plugin.h"
38#include "gnunet_signatures.h" 38#include "gnunet_signatures.h"
39#include "json_reclaim.h" 39#include "json_reclaim.h"
40
41/** 40/**
42 * REST root namespace 41 * REST root namespace
43 */ 42 */
@@ -49,6 +48,11 @@
49#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes" 48#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
50 49
51/** 50/**
51 * Attestation namespace
52 */
53#define GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE "/reclaim/attestation"
54
55/**
52 * Ticket namespace 56 * Ticket namespace
53 */ 57 */
54#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets" 58#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
@@ -272,6 +276,8 @@ cleanup_handle (struct RequestHandle *handle)
272 claim_tmp = claim_entry; 276 claim_tmp = claim_entry;
273 claim_entry = claim_entry->next; 277 claim_entry = claim_entry->next;
274 GNUNET_free (claim_tmp->claim); 278 GNUNET_free (claim_tmp->claim);
279 GNUNET_free (claim_tmp->attest);
280 GNUNET_free (claim_tmp->reference);
275 GNUNET_free (claim_tmp); 281 GNUNET_free (claim_tmp);
276 } 282 }
277 GNUNET_free (handle->attr_list); 283 GNUNET_free (handle->attr_list);
@@ -360,6 +366,21 @@ finished_cont (void *cls, int32_t success, const char *emsg)
360 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 366 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
361} 367}
362 368
369static void
370delete_finished_cb (void *cls, int32_t success, const char *emsg)
371{
372 struct RequestHandle *handle = cls;
373 struct MHD_Response *resp;
374
375 resp = GNUNET_REST_create_response (emsg);
376 if (GNUNET_OK != success)
377 {
378 GNUNET_SCHEDULER_add_now (&do_error, handle);
379 return;
380 }
381 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
382 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
383}
363 384
364/** 385/**
365 * Return attributes for identity 386 * Return attributes for identity
@@ -434,6 +455,661 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
434} 455}
435 456
436 457
458static void
459add_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
460 const char *url,
461 void *cls)
462{
463 struct RequestHandle *handle = cls;
464 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
465 const char *identity;
466 struct EgoEntry *ego_entry;
467 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attribute;
468 struct GNUNET_TIME_Relative exp;
469 char term_data[handle->rest_handle->data_size + 1];
470 json_t *data_json;
471 json_error_t err;
472 struct GNUNET_JSON_Specification attrspec[] =
473 { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attribute),
474 GNUNET_JSON_spec_end () };
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Adding an attestation reference for %s.\n",
477 handle->url);
478 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
479 "reference/") + 1 >= strlen (
480 handle->url))
481 {
482 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
483 GNUNET_SCHEDULER_add_now (&do_error, handle);
484 return;
485 }
486 identity = handle->url + strlen (
487 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
488 + 1;
489 for (ego_entry = handle->ego_head; NULL != ego_entry;
490 ego_entry = ego_entry->next)
491 if (0 == strcmp (identity, ego_entry->identifier))
492 break;
493 if (NULL == ego_entry)
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
496 return;
497 }
498 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
499 if (0 >= handle->rest_handle->data_size)
500 {
501 GNUNET_SCHEDULER_add_now (&do_error, handle);
502 return;
503 }
504
505 term_data[handle->rest_handle->data_size] = '\0';
506 GNUNET_memcpy (term_data,
507 handle->rest_handle->data,
508 handle->rest_handle->data_size);
509 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
510 GNUNET_assert (GNUNET_OK ==
511 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
512 json_decref (data_json);
513 if (NULL == attribute)
514 {
515 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
516 "Unable to parse attestation reference from %s\n",
517 term_data);
518 GNUNET_SCHEDULER_add_now (&do_error, handle);
519 return;
520 }
521 /**
522 * New ID for attribute
523 */
524 if (0 == attribute->id)
525 attribute->id = attribute->id_attest;
526 handle->idp = GNUNET_RECLAIM_connect (cfg);
527 exp = GNUNET_TIME_UNIT_HOURS;
528 handle->idp_op = GNUNET_RECLAIM_attestation_reference_store (handle->idp,
529 identity_priv,
530 attribute,
531 &exp,
532 &finished_cont,
533 handle);
534 GNUNET_JSON_parse_free (attrspec);
535}
536
537static void
538parse_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
539 const char *url,
540 void *cls)
541{
542 struct RequestHandle *handle = cls;
543
544 char term_data[handle->rest_handle->data_size + 1];
545 json_t *data_json;
546 json_error_t err;
547 int unpack_state;
548 struct MHD_Response *resp;
549 char *val_str = NULL;
550 const char *type_str = NULL;
551 term_data[handle->rest_handle->data_size] = '\0';
552 GNUNET_memcpy (term_data,
553 handle->rest_handle->data,
554 handle->rest_handle->data_size);
555 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
556 GNUNET_assert (NULL != data_json);
557 if (! json_is_object (data_json))
558 {
559 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 "Error json is not array nor object!\n");
561 GNUNET_SCHEDULER_add_now (&do_error, handle);
562 return;
563 }
564 unpack_state = json_unpack (data_json,
565 "{s:s, s:s!}",
566 "value",
567 &val_str,
568 "type",
569 &type_str);
570 if ((0 != unpack_state) || (NULL == val_str) || (NULL == type_str))
571 {
572 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
573 "Error json object has a wrong format!\n");
574 GNUNET_SCHEDULER_add_now (&do_error, handle);
575 return;
576 }
577 if (0 == strcmp (type_str, "JWT"))
578 {
579 // The value is a JWT
580 char *decoded_jwt;
581 char delim[] = ".";
582 char *jwt_body = strtok (val_str, delim);
583 jwt_body = strtok (NULL, delim);
584 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
585 (void **) &decoded_jwt);
586 resp = GNUNET_REST_create_response (decoded_jwt);
587 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
588 GNUNET_free (decoded_jwt);
589 }
590 else
591 {
592 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
593 "Error requested parsing type not supported!\n");
594 GNUNET_SCHEDULER_add_now (&do_error, handle);
595 return;
596 }
597 cleanup_handle (handle);
598 json_decref (data_json);
599}
600
601static void
602add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
603 const char *url,
604 void *cls)
605{
606 struct RequestHandle *handle = cls;
607 /* Check for substring "reference" */
608 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
609 handle->url))
610 {
611 if ( strncmp ("reference/", (handle->url + strlen (
612 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
613 + 1), strlen (
614 "reference/")) == 0)
615 {
616 add_attestation_ref_cont (con_handle,url,cls);
617 return;
618 }
619 }
620 /* Check for substring "parse" */
621 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
622 handle->url))
623 {
624 if ( strncmp ("parse", (handle->url + strlen (
625 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
626 + 1), strlen (
627 "parse")) == 0)
628 {
629 parse_attestation_cont (con_handle,url,cls);
630 return;
631 }
632 }
633 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
634 const char *identity;
635 struct EgoEntry *ego_entry;
636 struct GNUNET_RECLAIM_ATTESTATION_Claim *attribute;
637 struct GNUNET_TIME_Relative exp;
638 char term_data[handle->rest_handle->data_size + 1];
639 json_t *data_json;
640 json_error_t err;
641 struct GNUNET_JSON_Specification attrspec[] =
642 { GNUNET_RECLAIM_JSON_spec_claim_attest (&attribute),
643 GNUNET_JSON_spec_end () };
644
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
646 "Adding an attestation for %s.\n",
647 handle->url);
648 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
649 handle->url))
650 {
651 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
652 GNUNET_SCHEDULER_add_now (&do_error, handle);
653 return;
654 }
655 identity = handle->url + strlen (
656 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
657
658 for (ego_entry = handle->ego_head; NULL != ego_entry;
659 ego_entry = ego_entry->next)
660 if (0 == strcmp (identity, ego_entry->identifier))
661 break;
662
663 if (NULL == ego_entry)
664 {
665 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Identity unknown (%s)\n", identity);
666 return;
667 }
668 identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
669
670 if (0 >= handle->rest_handle->data_size)
671 {
672 GNUNET_SCHEDULER_add_now (&do_error, handle);
673 return;
674 }
675
676 term_data[handle->rest_handle->data_size] = '\0';
677 GNUNET_memcpy (term_data,
678 handle->rest_handle->data,
679 handle->rest_handle->data_size);
680 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
681 GNUNET_assert (GNUNET_OK ==
682 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
683 json_decref (data_json);
684 if (NULL == attribute)
685 {
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 "Unable to parse attestation from %s\n",
688 term_data);
689 GNUNET_SCHEDULER_add_now (&do_error, handle);
690 return;
691 }
692 /**
693 * New ID for attribute
694 */
695 if (0 == attribute->id)
696 attribute->id =
697 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
698 handle->idp = GNUNET_RECLAIM_connect (cfg);
699 exp = GNUNET_TIME_UNIT_HOURS;
700 handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
701 identity_priv,
702 attribute,
703 &exp,
704 &finished_cont,
705 handle);
706 GNUNET_JSON_parse_free (attrspec);
707}
708
709/**
710 * Collect all references for an ego
711 *
712 */
713static void
714ref_collect (void *cls,
715 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
716 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
717 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
718 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
719{
720 struct RequestHandle *handle = cls;
721 json_t *attr_obj;
722 char *id_str;
723 char *id_attest_str;
724
725 if (NULL == reference)
726 {
727 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
728 return;
729 }
730
731 if ((NULL == reference->name) || (NULL == reference->reference_value))
732 {
733 return;
734 }
735
736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference: %s\n",
737 reference->name);
738 attr_obj = json_object ();
739 json_object_set_new (attr_obj, "name", json_string (reference->name));
740 json_object_set_new (attr_obj, "ref_value", json_string (
741 reference->reference_value));
742 id_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id,
743 sizeof(uint64_t));
744 id_attest_str = GNUNET_STRINGS_data_to_string_alloc (&reference->id_attest,
745 sizeof(uint64_t));
746 json_object_set_new (attr_obj, "id", json_string (id_str));
747 json_object_set_new (attr_obj, "ref_id", json_string (id_attest_str));
748 json_array_append (handle->resp_object, attr_obj);
749 json_decref (attr_obj);
750}
751
752/**
753 * Lists references for identity request
754 *
755 * @param con_handle the connection handle
756 * @param url the url
757 * @param cls the RequestHandle
758 */
759static void
760list_reference_cont (struct GNUNET_REST_RequestHandle *con_handle,
761 const char *url,
762 void *cls)
763{
764 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
765 struct RequestHandle *handle = cls;
766 struct EgoEntry *ego_entry;
767 char *identity;
768
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770 "Getting references for %s.\n",
771 handle->url);
772 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
773 "reference/") + 1 >= strlen (
774 handle->url))
775 {
776 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
777 GNUNET_SCHEDULER_add_now (&do_error, handle);
778 return;
779 }
780 identity = handle->url + strlen (
781 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
782 + 1;
783 for (ego_entry = handle->ego_head; NULL != ego_entry;
784 ego_entry = ego_entry->next)
785 if (0 == strcmp (identity, ego_entry->identifier))
786 break;
787 handle->resp_object = json_array ();
788
789 if (NULL == ego_entry)
790 {
791 // Done
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
793 GNUNET_SCHEDULER_add_now (&return_response, handle);
794 return;
795 }
796 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
797 handle->idp = GNUNET_RECLAIM_connect (cfg);
798 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
799 priv_key,
800 &collect_error_cb,
801 handle,
802 &ref_collect,
803 handle,
804 &collect_finished_cb,
805 handle);
806}
807
808/**
809 * Collect all attestations for an ego
810 *
811 */
812static void
813attest_collect (void *cls,
814 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
815 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
816 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
817 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
818{
819 struct RequestHandle *handle = cls;
820 json_t *attr_obj;
821 const char *type;
822 char *tmp_value;
823 char *id_str;
824
825
826 if (NULL != reference)
827 {
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Attestation Collection with Reference\n");
830 return;
831 }
832 if (NULL == attest)
833 {
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Attestation Collection with empty Attestation\n");
836 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
837 return;
838 }
839
840 if ((NULL == attest->name) || (NULL == attest->data))
841 {
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843 "Attestation Collection with empty Name/Value\n");
844 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
845 return;
846 }
847
848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n",
849 attest->name);
850
851 tmp_value = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
852 attest->data,
853 attest->data_size);
854 attr_obj = json_object ();
855 json_object_set_new (attr_obj, "value", json_string (tmp_value));
856 json_object_set_new (attr_obj, "name", json_string (attest->name));
857 type = GNUNET_RECLAIM_ATTESTATION_number_to_typename (attest->type);
858 json_object_set_new (attr_obj, "type", json_string (type));
859 id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(uint64_t));
860 json_object_set_new (attr_obj, "id", json_string (id_str));
861 json_array_append (handle->resp_object, attr_obj);
862 json_decref (attr_obj);
863 GNUNET_free (tmp_value);
864 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
865}
866
867
868/**
869 * Lists attestation for identity request
870 *
871 * @param con_handle the connection handle
872 * @param url the url
873 * @param cls the RequestHandle
874 */
875static void
876list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
877 const char *url,
878 void *cls)
879{
880 struct RequestHandle *handle = cls;
881 /* Check for substring "reference" */
882 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
883 handle->url))
884 {
885 if ( strncmp ("reference/", (handle->url + strlen (
886 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
887 + 1), strlen (
888 "reference/")) == 0)
889 {
890 list_reference_cont (con_handle,url,cls);
891 return;
892 }
893 }
894 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
895 struct EgoEntry *ego_entry;
896 char *identity;
897
898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
899 "Getting attestations for %s.\n",
900 handle->url);
901 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
902 handle->url))
903 {
904 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
905 GNUNET_SCHEDULER_add_now (&do_error, handle);
906 return;
907 }
908 identity = handle->url + strlen (
909 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1;
910
911 for (ego_entry = handle->ego_head; NULL != ego_entry;
912 ego_entry = ego_entry->next)
913 if (0 == strcmp (identity, ego_entry->identifier))
914 break;
915 handle->resp_object = json_array ();
916
917
918 if (NULL == ego_entry)
919 {
920 // Done
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
922 GNUNET_SCHEDULER_add_now (&return_response, handle);
923 return;
924 }
925 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
926 handle->idp = GNUNET_RECLAIM_connect (cfg);
927 handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
928 priv_key,
929 &collect_error_cb,
930 handle,
931 &attest_collect,
932 handle,
933 &collect_finished_cb,
934 handle);
935}
936
937/**
938 * Deletes reference from an identity
939 *
940 * @param con_handle the connection handle
941 * @param url the url
942 * @param cls the RequestHandle
943 */
944static void
945delete_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
946 const char *url,
947 void *cls)
948{
949 struct RequestHandle *handle = cls;
950 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
951 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
952 struct EgoEntry *ego_entry;
953 char *identity;
954 char *identity_id_str;
955 char *id;
956 char term_data[handle->rest_handle->data_size + 1];
957 json_t *data_json;
958 json_error_t err;
959
960 struct GNUNET_JSON_Specification attrspec[] =
961 { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attr),
962 GNUNET_JSON_spec_end () };
963 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
964 "Deleting attestation reference.\n");
965 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
966 "reference/") + 1 >= strlen (
967 handle->url))
968 {
969 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
970 GNUNET_SCHEDULER_add_now (&do_error, handle);
971 return;
972 }
973 identity_id_str = strdup (handle->url + strlen (
974 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
975 + strlen ("reference/")
976 + 1);
977 identity = strtok (identity_id_str, "/");
978 id = strtok (NULL, "/");
979
980 if ((NULL == identity) || (NULL == id))
981 {
982 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
983 GNUNET_SCHEDULER_add_now (&do_error, handle);
984 return;
985 }
986 for (ego_entry = handle->ego_head; NULL != ego_entry;
987 ego_entry = ego_entry->next)
988 if (0 == strcmp (identity, ego_entry->identifier))
989 break;
990 handle->resp_object = json_array ();
991 if (NULL == ego_entry)
992 {
993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
994 GNUNET_SCHEDULER_add_now (&return_response, handle);
995 return;
996 }
997 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
998 if (0 >= handle->rest_handle->data_size)
999 {
1000 GNUNET_SCHEDULER_add_now (&do_error, handle);
1001 return;
1002 }
1003
1004 term_data[handle->rest_handle->data_size] = '\0';
1005 GNUNET_memcpy (term_data,
1006 handle->rest_handle->data,
1007 handle->rest_handle->data_size);
1008 data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
1009 GNUNET_assert (GNUNET_OK ==
1010 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
1011 json_decref (data_json);
1012 if (NULL == attr)
1013 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Unable to parse attestation reference from %s\n",
1016 term_data);
1017 GNUNET_SCHEDULER_add_now (&do_error, handle);
1018 return;
1019 }
1020 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr->id, sizeof(uint64_t));
1021
1022 handle->idp = GNUNET_RECLAIM_connect (cfg);
1023 handle->idp_op = GNUNET_RECLAIM_attestation_reference_delete (handle->idp,
1024 priv_key,
1025 attr,
1026 &
1027 delete_finished_cb,
1028 handle);
1029 GNUNET_JSON_parse_free (attrspec);
1030}
1031
1032
1033/**
1034 * Deletes attestation from an identity
1035 *
1036 * @param con_handle the connection handle
1037 * @param url the url
1038 * @param cls the RequestHandle
1039 */
1040static void
1041delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
1042 const char *url,
1043 void *cls)
1044{
1045 struct RequestHandle *handle = cls;
1046 /* Check for substring "reference" */
1047 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
1048 handle->url))
1049 {
1050 if ( strncmp ("reference", (handle->url + strlen (
1051 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
1052 + 1), strlen (
1053 "reference")) == 0)
1054 {
1055 delete_attestation_ref_cont (con_handle,url,cls);
1056 return;
1057 }
1058 }
1059 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1060 struct GNUNET_RECLAIM_ATTESTATION_Claim attr;
1061 struct EgoEntry *ego_entry;
1062 char *identity_id_str;
1063 char *identity;
1064 char *id;
1065
1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
1067 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) >= strlen (
1068 handle->url))
1069 {
1070 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
1071 GNUNET_SCHEDULER_add_now (&do_error, handle);
1072 return;
1073 }
1074 identity_id_str =
1075 strdup (handle->url + strlen (
1076 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + 1);
1077 identity = strtok (identity_id_str, "/");
1078 id = strtok (NULL, "/");
1079 if ((NULL == identity) || (NULL == id))
1080 {
1081 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
1082 GNUNET_free (identity_id_str);
1083 GNUNET_SCHEDULER_add_now (&do_error, handle);
1084 return;
1085 }
1086
1087 for (ego_entry = handle->ego_head; NULL != ego_entry;
1088 ego_entry = ego_entry->next)
1089 if (0 == strcmp (identity, ego_entry->identifier))
1090 break;
1091 handle->resp_object = json_array ();
1092 if (NULL == ego_entry)
1093 {
1094 // Done
1095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
1096 GNUNET_free (identity_id_str);
1097 GNUNET_SCHEDULER_add_now (&return_response, handle);
1098 return;
1099 }
1100 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1101 handle->idp = GNUNET_RECLAIM_connect (cfg);
1102 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim));
1103 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(uint64_t));
1104 attr.name = "";
1105 handle->idp_op = GNUNET_RECLAIM_attestation_delete (handle->idp,
1106 priv_key,
1107 &attr,
1108 &delete_finished_cb,
1109 handle);
1110 GNUNET_free (identity_id_str);
1111}
1112
437/** 1113/**
438 * List tickets for identity request 1114 * List tickets for identity request
439 * 1115 *
@@ -568,6 +1244,72 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
568 GNUNET_JSON_parse_free (attrspec); 1244 GNUNET_JSON_parse_free (attrspec);
569} 1245}
570 1246
1247/**
1248 * Parse a JWT and return the respective claim value as Attribute
1249 *
1250 * @param attest the jwt attestation
1251 * @param claim the name of the claim in the JWT
1252 *
1253 * @return a GNUNET_RECLAIM_ATTRIBUTE_Claim, containing the new value
1254 */
1255struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
1256parse_jwt (const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1257 const char *claim)
1258{
1259 char *jwt_string;
1260 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
1261 char delim[] = ".";
1262 const char *type_str = NULL;
1263 const char *val_str = NULL;
1264 char *data;
1265 size_t data_size;
1266 uint32_t type;
1267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
1268 char *decoded_jwt;
1269 json_t *json_val;
1270 json_error_t *json_err = NULL;
1271
1272 jwt_string = GNUNET_RECLAIM_ATTESTATION_value_to_string (attest->type,
1273 attest->data,
1274 attest->data_size);
1275 char *jwt_body = strtok (jwt_string, delim);
1276 jwt_body = strtok (NULL, delim);
1277 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
1278 (void **) &decoded_jwt);
1279 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
1280 const char *key;
1281 json_t *value;
1282 json_object_foreach (json_val, key, value) {
1283 if (0 == strcasecmp (key,claim))
1284 {
1285 val_str = json_dumps (value, JSON_ENCODE_ANY);
1286 }
1287 }
1288 type_str = "String";
1289 type = GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (type_str);
1290 if (GNUNET_SYSERR ==(GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,val_str,
1291 (void **) &data,
1292 &data_size)))
1293 {
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1295 "Attribute value from JWT Parser invalid!\n");
1296 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (type,
1297 "Error: Referenced Claim Name not Found",
1298 (void **) &data,
1299 &data_size);
1300 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1301 attr->id = attest->id;
1302 attr->flag = 1;
1303 }
1304 else
1305 {
1306 attr = GNUNET_RECLAIM_ATTRIBUTE_claim_new (claim, type, data, data_size);
1307 attr->id = attest->id;
1308 attr->flag = 1;
1309 }
1310 return attr;
1311}
1312
571 1313
572/** 1314/**
573 * Collect all attributes for an ego 1315 * Collect all attributes for an ego
@@ -576,40 +1318,93 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
576static void 1318static void
577attr_collect (void *cls, 1319attr_collect (void *cls,
578 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 1320 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
579 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 1321 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1322 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1323 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
580{ 1324{
581 struct RequestHandle *handle = cls; 1325 struct RequestHandle *handle = cls;
582 json_t *attr_obj; 1326 json_t *attr_obj;
583 const char *type; 1327 const char *type;
584 char *tmp_value;
585 char *id_str; 1328 char *id_str;
586 1329
587 if ((NULL == attr->name) || (NULL == attr->data)) 1330 if ((NULL == attr) && (NULL == reference))
588 { 1331 {
1332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1333 "Attribute Collection with empty Attribute/Reference\n");
589 GNUNET_RECLAIM_get_attributes_next (handle->attr_it); 1334 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
590 return; 1335 return;
591 } 1336 }
592 1337
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name); 1338 if (NULL == attr)
594 1339 {
595 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
596 attr->data,
597 attr->data_size);
598 1340
599 attr_obj = json_object (); 1341 if ((NULL == reference->name) || (NULL == reference->reference_value))
600 json_object_set_new (attr_obj, "value", json_string (tmp_value)); 1342 {
601 json_object_set_new (attr_obj, "name", json_string (attr->name)); 1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
602 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type); 1344 "Attribute Collection with empty Reference Name/Value\n");
603 json_object_set_new (attr_obj, "type", json_string (type)); 1345 return;
604 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t)); 1346 }
605 json_object_set_new (attr_obj, "id", json_string (id_str)); 1347 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr2;
606 json_array_append (handle->resp_object, attr_obj); 1348 attr2 = parse_jwt (attest, reference->reference_value);
607 json_decref (attr_obj); 1349 if (NULL == attr2)
608 GNUNET_free (tmp_value); 1350 {
609 GNUNET_RECLAIM_get_attributes_next (handle->attr_it); 1351 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1352 "Attribute Collection with unparsed Attestation\n");
1353 return;
1354 }
1355 attr2->name = reference->name;
1356 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding reference as attribute: %s\n",
1357 reference->name);
1358 char *tmp_value;
1359 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr2->type,
1360 attr2->data,
1361 attr2->data_size);
1362 attr_obj = json_object ();
1363
1364 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1365 json_object_set_new (attr_obj, "name", json_string (attr2->name));
1366 json_object_set_new (attr_obj, "flag", json_string ("1"));
1367 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr2->type);
1368 json_object_set_new (attr_obj, "type", json_string (type));
1369 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id, sizeof(uint64_t));
1370 json_object_set_new (attr_obj, "id", json_string (id_str));
1371 json_array_append (handle->resp_object, attr_obj);
1372 json_decref (attr_obj);
1373 GNUNET_free (tmp_value);
1374 }
1375 else
1376 {
1377 if ((NULL == attr->name) || (NULL == attr->data))
1378 {
1379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1380 "Attribute Collection with empty Attribute Name/Value\n");
1381 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1382 return;
1383 }
1384 char *tmp_value;
1385 char *flag_str;
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
1387
1388 tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
1389 attr->data,
1390 attr->data_size);
1391
1392 attr_obj = json_object ();
1393 json_object_set_new (attr_obj, "value", json_string (tmp_value));
1394 json_object_set_new (attr_obj, "name", json_string (attr->name));
1395 GNUNET_asprintf (&flag_str,"%d",attr->flag);
1396 json_object_set_new (attr_obj, "flag", json_string (flag_str));
1397 type = GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (attr->type);
1398 json_object_set_new (attr_obj, "type", json_string (type));
1399 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(uint64_t));
1400 json_object_set_new (attr_obj, "id", json_string (id_str));
1401 json_array_append (handle->resp_object, attr_obj);
1402 json_decref (attr_obj);
1403 GNUNET_free (tmp_value);
1404 GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
1405 }
610} 1406}
611 1407
612
613/** 1408/**
614 * List attributes for identity request 1409 * List attributes for identity request
615 * 1410 *
@@ -665,23 +1460,6 @@ list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
665} 1460}
666 1461
667 1462
668static void
669delete_finished_cb (void *cls, int32_t success, const char *emsg)
670{
671 struct RequestHandle *handle = cls;
672 struct MHD_Response *resp;
673
674 resp = GNUNET_REST_create_response (emsg);
675 if (GNUNET_OK != success)
676 {
677 GNUNET_SCHEDULER_add_now (&do_error, handle);
678 return;
679 }
680 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
681 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
682}
683
684
685/** 1463/**
686 * List attributes for identity request 1464 * List attributes for identity request
687 * 1465 *
@@ -825,7 +1603,9 @@ revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
825static void 1603static void
826consume_cont (void *cls, 1604consume_cont (void *cls,
827 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 1605 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
828 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr) 1606 const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
1607 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest,
1608 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference)
829{ 1609{
830 struct RequestHandle *handle = cls; 1610 struct RequestHandle *handle = cls;
831 char *val_str; 1611 char *val_str;
@@ -969,6 +1749,15 @@ init_cont (struct RequestHandle *handle)
969 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, 1749 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
970 &delete_attribute_cont }, 1750 &delete_attribute_cont },
971 { MHD_HTTP_METHOD_GET, 1751 { MHD_HTTP_METHOD_GET,
1752 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1753 &list_attestation_cont },
1754 { MHD_HTTP_METHOD_POST,
1755 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1756 &add_attestation_cont },
1757 { MHD_HTTP_METHOD_DELETE,
1758 GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE,
1759 &delete_attestation_cont },
1760 { MHD_HTTP_METHOD_GET,
972 GNUNET_REST_API_NS_IDENTITY_TICKETS, 1761 GNUNET_REST_API_NS_IDENTITY_TICKETS,
973 &list_tickets_cont }, 1762 &list_tickets_cont },
974 { MHD_HTTP_METHOD_POST, 1763 { MHD_HTTP_METHOD_POST,
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
index 8e731812e..ff953a096 100644
--- a/src/reclaim/reclaim.h
+++ b/src/reclaim/reclaim.h
@@ -153,6 +153,45 @@ struct AttributeResultMessage
153 */ 153 */
154}; 154};
155 155
156/**
157 * Reference plus Attestation is returned from the idp.
158 */
159struct ReferenceResultMessage
160{
161 /**
162 * Message header
163 */
164 struct GNUNET_MessageHeader header;
165
166 /**
167 * Unique identifier for this request (for key collisions).
168 */
169 uint32_t id GNUNET_PACKED;
170
171 /**
172 * Length of serialized attestation data
173 */
174 uint16_t attest_len GNUNET_PACKED;
175
176 /**
177 * Length of serialized reference data
178 */
179 uint16_t ref_len GNUNET_PACKED;
180
181 /**
182 * always zero (for alignment)
183 */
184 uint16_t reserved GNUNET_PACKED;
185
186 /**
187 * The public key of the identity.
188 */
189 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
190
191 /* followed by:
192 * serialized reference data + attestation data
193 */
194};
156 195
157/** 196/**
158 * Start a attribute iteration for the given identity 197 * Start a attribute iteration for the given identity
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index 7d4d7588a..847abb58a 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -486,7 +486,7 @@ handle_consume_ticket_result (void *cls,
486 uint32_t r_id = ntohl (msg->id); 486 uint32_t r_id = ntohl (msg->id);
487 487
488 attrs_len = ntohs (msg->attrs_len); 488 attrs_len = ntohs (msg->attrs_len);
489 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n"); 489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
490 490
491 491
492 for (op = h->op_head; NULL != op; op = op->next) 492 for (op = h->op_head; NULL != op; op = op->next)
@@ -498,22 +498,36 @@ handle_consume_ticket_result (void *cls,
498 { 498 {
499 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs; 499 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
500 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; 500 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
501 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le2;
501 attrs = 502 attrs =
502 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &msg[1], attrs_len); 503 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &msg[1], attrs_len);
503 if (NULL != op->ar_cb) 504 if (NULL != op->ar_cb)
504 { 505 {
505 if (NULL == attrs) 506 if (NULL == attrs)
506 { 507 {
507 op->ar_cb (op->cls, &msg->identity, NULL); 508 op->ar_cb (op->cls, &msg->identity, NULL, NULL, NULL);
508 } 509 }
509 else 510 else
510 { 511 {
511 for (le = attrs->list_head; NULL != le; le = le->next) 512 for (le = attrs->list_head; NULL != le; le = le->next)
512 op->ar_cb (op->cls, &msg->identity, le->claim); 513 {
514 if (le->reference != NULL && le->attest == NULL)
515 {
516 for (le2 = attrs->list_head; NULL != le2; le2 = le2->next)
517 {
518 if (le2->attest != NULL && le2->attest->id == le->reference->id_attest)
519 {
520 op->ar_cb (op->cls, &msg->identity, le->claim, le2->attest, le->reference);
521 break;
522 }
523
524 }
525 }
526 }
513 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs); 527 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
514 attrs = NULL; 528 attrs = NULL;
515 } 529 }
516 op->ar_cb (op->cls, NULL, NULL); 530 op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
517 } 531 }
518 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); 532 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
519 free_op (op); 533 free_op (op);
@@ -597,7 +611,7 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
597 if (NULL != op) 611 if (NULL != op)
598 { 612 {
599 if (NULL != op->ar_cb) 613 if (NULL != op->ar_cb)
600 op->ar_cb (op->cls, NULL, NULL); 614 op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
601 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); 615 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
602 free_op (op); 616 free_op (op);
603 } 617 }
@@ -610,12 +624,111 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
610 if (NULL != it) 624 if (NULL != it)
611 { 625 {
612 if (NULL != it->proc) 626 if (NULL != it->proc)
613 it->proc (it->proc_cls, &msg->identity, attr); 627 it->proc (it->proc_cls, &msg->identity, attr, NULL, NULL);
628 }
629 else if (NULL != op)
630 {
631 if (NULL != op->ar_cb)
632 op->ar_cb (op->cls, &msg->identity, attr, NULL, NULL);
633 }
634 GNUNET_free (attr);
635 return;
636 }
637 GNUNET_assert (0);
638}
639
640/**
641 * Handle an incoming message of type
642 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT
643 *
644 * @param cls
645 * @param msg the message we received
646 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
647 */
648static int
649check_attestation_result (void *cls, const struct AttributeResultMessage *msg)
650{
651 size_t msg_len;
652 size_t attr_len;
653
654 msg_len = ntohs (msg->header.size);
655 attr_len = ntohs (msg->attr_len);
656 if (msg_len != sizeof(struct AttributeResultMessage) + attr_len)
657 {
658 GNUNET_break (0);
659 return GNUNET_SYSERR;
660 }
661 return GNUNET_OK;
662}
663
664
665/**
666 * Handle an incoming message of type
667 * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT
668 *
669 * @param cls
670 * @param msg the message we received
671 */
672static void
673handle_attestation_result (void *cls, const struct AttributeResultMessage *msg)
674{
675 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
676 struct GNUNET_RECLAIM_Handle *h = cls;
677 struct GNUNET_RECLAIM_AttributeIterator *it;
678 struct GNUNET_RECLAIM_Operation *op;
679 size_t attr_len;
680 uint32_t r_id = ntohl (msg->id);
681
682 attr_len = ntohs (msg->attr_len);
683 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attestation result.\n");
684
685
686 for (it = h->it_head; NULL != it; it = it->next)
687 if (it->r_id == r_id)
688 break;
689 for (op = h->op_head; NULL != op; op = op->next)
690 if (op->r_id == r_id)
691 break;
692 if ((NULL == it) && (NULL == op))
693 return;
694
695 if ((0 ==
696 (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
697 {
698 if ((NULL == it) && (NULL == op))
699 {
700 GNUNET_break (0);
701 force_reconnect (h);
702 return;
703 }
704 if (NULL != it)
705 {
706 if (NULL != it->finish_cb)
707 it->finish_cb (it->finish_cb_cls);
708 free_it (it);
709 }
710 if (NULL != op)
711 {
712 if (NULL != op->ar_cb)
713 op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
714 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
715 free_op (op);
716 }
717 return;
718 }
719
720 {
721 struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
722 attr = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &msg[1], attr_len);
723 if (NULL != it)
724 {
725 if (NULL != it->proc)
726 it->proc (it->proc_cls, &msg->identity, NULL, attr, NULL);
614 } 727 }
615 else if (NULL != op) 728 else if (NULL != op)
616 { 729 {
617 if (NULL != op->ar_cb) 730 if (NULL != op->ar_cb)
618 op->ar_cb (op->cls, &msg->identity, attr); 731 op->ar_cb (op->cls, &msg->identity, NULL, attr, NULL);
619 } 732 }
620 GNUNET_free (attr); 733 GNUNET_free (attr);
621 return; 734 return;
@@ -623,6 +736,110 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
623 GNUNET_assert (0); 736 GNUNET_assert (0);
624} 737}
625 738
739/**
740 * Handle an incoming message of type
741 * #GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT
742 *
743 * @param cls
744 * @param msg the message we received
745 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
746 */
747static int
748check_reference_result (void *cls, const struct ReferenceResultMessage *msg)
749{
750 size_t msg_len;
751 size_t attr_len;
752 size_t ref_len;
753
754 msg_len = ntohs (msg->header.size);
755 attr_len = ntohs (msg->attest_len);
756 ref_len = ntohs (msg->ref_len);
757 if (msg_len != sizeof(struct ReferenceResultMessage) + attr_len + ref_len)
758 {
759 GNUNET_break (0);
760 return GNUNET_SYSERR;
761 }
762 return GNUNET_OK;
763}
764
765/**
766* Handle an incoming message of type
767* #GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT
768*
769* @param cls
770* @param msg the message we received
771*/
772static void
773handle_reference_result (void *cls, const struct ReferenceResultMessage *msg)
774{
775 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
776 struct GNUNET_RECLAIM_Handle *h = cls;
777 struct GNUNET_RECLAIM_AttributeIterator *it;
778 struct GNUNET_RECLAIM_Operation *op;
779 size_t attest_len;
780 size_t ref_len;
781 uint32_t r_id = ntohl (msg->id);
782 attest_len = ntohs (msg->attest_len);
783 ref_len = ntohs (msg->ref_len);
784 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing reference result.\n");
785 for (it = h->it_head; NULL != it; it = it->next)
786 if (it->r_id == r_id)
787 break;
788 for (op = h->op_head; NULL != op; op = op->next)
789 if (op->r_id == r_id)
790 break;
791 if ((NULL == it) && (NULL == op))
792 return;
793
794 if ((0 ==
795 (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
796 {
797 if ((NULL == it) && (NULL == op))
798 {
799 GNUNET_break (0);
800 force_reconnect (h);
801 return;
802 }
803 if (NULL != it)
804 {
805 if (NULL != it->finish_cb)
806 it->finish_cb (it->finish_cb_cls);
807 free_it (it);
808 }
809 if (NULL != op)
810 {
811 if (NULL != op->ar_cb)
812 op->ar_cb (op->cls, NULL, NULL, NULL, NULL);
813 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
814 free_op (op);
815 }
816 return;
817 }
818
819 {
820 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
821 struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
822 attest = GNUNET_RECLAIM_ATTESTATION_deserialize ((char *) &msg[1],
823 attest_len);
824 ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &msg[1]
825 + attest_len,
826 ref_len);
827 if (NULL != it)
828 {
829 if (NULL != it->proc)
830 it->proc (it->proc_cls, &msg->identity, NULL, attest, ref);
831 }
832 else if (NULL != op)
833 {
834 if (NULL != op->ar_cb)
835 op->ar_cb (op->cls, &msg->identity, NULL, attest, ref);
836 }
837 GNUNET_free (ref);
838 GNUNET_free (attest);
839 return;
840 }
841 GNUNET_assert (0);
842}
626 843
627/** 844/**
628 * Handle an incoming message of type 845 * Handle an incoming message of type
@@ -742,6 +959,14 @@ reconnect (struct GNUNET_RECLAIM_Handle *h)
742 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT, 959 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
743 struct AttributeResultMessage, 960 struct AttributeResultMessage,
744 h), 961 h),
962 GNUNET_MQ_hd_var_size (attestation_result,
963 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT,
964 struct AttributeResultMessage,
965 h),
966 GNUNET_MQ_hd_var_size (reference_result,
967 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT,
968 struct ReferenceResultMessage,
969 h),
745 GNUNET_MQ_hd_fixed_size (ticket_result, 970 GNUNET_MQ_hd_fixed_size (ticket_result,
746 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT, 971 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
747 struct TicketResultMessage, 972 struct TicketResultMessage,
@@ -925,6 +1150,185 @@ GNUNET_RECLAIM_attribute_delete (
925 return op; 1150 return op;
926} 1151}
927 1152
1153/**
1154 * Store an attestation. If the attestation is already present,
1155 * it is replaced with the new attestation.
1156 *
1157 * @param h handle to the re:claimID service
1158 * @param pkey private key of the identity
1159 * @param attr the attestation value
1160 * @param exp_interval the relative expiration interval for the attestation
1161 * @param cont continuation to call when done
1162 * @param cont_cls closure for @a cont
1163 * @return handle to abort the request
1164 */
1165struct GNUNET_RECLAIM_Operation *
1166GNUNET_RECLAIM_attestation_store (
1167 struct GNUNET_RECLAIM_Handle *h,
1168 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1169 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
1170 const struct GNUNET_TIME_Relative *exp_interval,
1171 GNUNET_RECLAIM_ContinuationWithStatus cont,
1172 void *cont_cls)
1173{
1174 struct GNUNET_RECLAIM_Operation *op;
1175 struct AttributeStoreMessage *sam;
1176 size_t attr_len;
1177
1178 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1179 op->h = h;
1180 op->as_cb = cont;
1181 op->cls = cont_cls;
1182 op->r_id = h->r_id_gen++;
1183 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1184 attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr);
1185 op->env = GNUNET_MQ_msg_extra (sam,
1186 attr_len,
1187 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE);
1188 sam->identity = *pkey;
1189 sam->id = htonl (op->r_id);
1190 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1191
1192 GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &sam[1]);
1193
1194 sam->attr_len = htons (attr_len);
1195 if (NULL != h->mq)
1196 GNUNET_MQ_send_copy (h->mq, op->env);
1197 return op;
1198}
1199
1200/**
1201 * Delete an attestation. Tickets used to share this attestation are updated
1202 * accordingly.
1203 *
1204 * @param h handle to the re:claimID service
1205 * @param pkey Private key of the identity to add an attribute to
1206 * @param attr The attestation
1207 * @param cont Continuation to call when done
1208 * @param cont_cls Closure for @a cont
1209 * @return handle Used to to abort the request
1210 */
1211struct GNUNET_RECLAIM_Operation *
1212GNUNET_RECLAIM_attestation_delete (
1213 struct GNUNET_RECLAIM_Handle *h,
1214 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1215 const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
1216 GNUNET_RECLAIM_ContinuationWithStatus cont,
1217 void *cont_cls)
1218{
1219 struct GNUNET_RECLAIM_Operation *op;
1220 struct AttributeDeleteMessage *dam;
1221 size_t attr_len;
1222
1223 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1224 op->h = h;
1225 op->as_cb = cont;
1226 op->cls = cont_cls;
1227 op->r_id = h->r_id_gen++;
1228 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1229 attr_len = GNUNET_RECLAIM_ATTESTATION_serialize_get_size (attr);
1230 op->env = GNUNET_MQ_msg_extra (dam,
1231 attr_len,
1232 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE);
1233 dam->identity = *pkey;
1234 dam->id = htonl (op->r_id);
1235 GNUNET_RECLAIM_ATTESTATION_serialize (attr, (char *) &dam[1]);
1236
1237 dam->attr_len = htons (attr_len);
1238 if (NULL != h->mq)
1239 GNUNET_MQ_send_copy (h->mq, op->env);
1240 return op;
1241}
1242
1243/**
1244 * Store an attestation reference. If the reference is already present,
1245 * it is replaced with the new reference.
1246 *
1247 * @param h handle to the re:claimID service
1248 * @param pkey private key of the identity
1249 * @param attr the reference value
1250 * @param exp_interval the relative expiration interval for the reference
1251 * @param cont continuation to call when done
1252 * @param cont_cls closure for @a cont
1253 * @return handle to abort the request
1254 */
1255struct GNUNET_RECLAIM_Operation *
1256GNUNET_RECLAIM_attestation_reference_store (
1257 struct GNUNET_RECLAIM_Handle *h,
1258 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1259 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
1260 const struct GNUNET_TIME_Relative *exp_interval,
1261 GNUNET_RECLAIM_ContinuationWithStatus cont,
1262 void *cont_cls)
1263{
1264 struct GNUNET_RECLAIM_Operation *op;
1265 struct AttributeStoreMessage *sam;
1266 size_t attr_len;
1267 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1268 op->h = h;
1269 op->as_cb = cont;
1270 op->cls = cont_cls;
1271 op->r_id = h->r_id_gen++;
1272 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1273 attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (attr);
1274 op->env = GNUNET_MQ_msg_extra (sam,
1275 attr_len,
1276 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE);
1277 sam->identity = *pkey;
1278 sam->id = htonl (op->r_id);
1279 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1280
1281 GNUNET_RECLAIM_ATTESTATION_REF_serialize (attr, (char *) &sam[1]);
1282
1283 sam->attr_len = htons (attr_len);
1284 if (NULL != h->mq)
1285 GNUNET_MQ_send_copy (h->mq, op->env);
1286 return op;
1287}
1288
1289/**
1290 * Delete an attestation reference. Tickets used to share this reference are updated
1291 * accordingly.
1292 *
1293 * @param h handle to the re:claimID service
1294 * @param pkey Private key of the identity to delete the reference from
1295 * @param attr The reference
1296 * @param cont Continuation to call when done
1297 * @param cont_cls Closure for @a cont
1298 * @return handle Used to to abort the request
1299 */
1300struct GNUNET_RECLAIM_Operation *
1301GNUNET_RECLAIM_attestation_reference_delete (
1302 struct GNUNET_RECLAIM_Handle *h,
1303 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1304 const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
1305 GNUNET_RECLAIM_ContinuationWithStatus cont,
1306 void *cont_cls)
1307{
1308
1309 struct GNUNET_RECLAIM_Operation *op;
1310 struct AttributeDeleteMessage *dam;
1311 size_t attr_len;
1312
1313 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1314 op->h = h;
1315 op->as_cb = cont;
1316 op->cls = cont_cls;
1317 op->r_id = h->r_id_gen++;
1318 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1319 attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (attr);
1320 op->env = GNUNET_MQ_msg_extra (dam,
1321 attr_len,
1322 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE);
1323 dam->identity = *pkey;
1324 dam->id = htonl (op->r_id);
1325 GNUNET_RECLAIM_ATTESTATION_REF_serialize (attr, (char *) &dam[1]);
1326
1327 dam->attr_len = htons (attr_len);
1328 if (NULL != h->mq)
1329 GNUNET_MQ_send_copy (h->mq, op->env);
1330 return op;
1331}
928 1332
929/** 1333/**
930 * List all attributes for a local identity. 1334 * List all attributes for a local identity.