12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2011-2013 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file abd/gnunet-service-abd.c
- * @brief GNUnet Credential Service (main service)
- * @author Martin Schanzenbach
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "abd.h"
- #include "abd_serialization.h"
- #include "gnunet_abd_service.h"
- #include "gnunet_protocols.h"
- #include "gnunet_signatures.h"
- #include "gnunet_statistics_service.h"
- #include <gnunet_dnsparser_lib.h>
- #include <gnunet_gns_service.h>
- #include <gnunet_gnsrecord_lib.h>
- #include <gnunet_identity_service.h>
- #include <gnunet_namestore_service.h>
- #define GNUNET_ABD_MAX_LENGTH 255
- struct VerifyRequestHandle;
- struct DelegationSetQueueEntry;
- struct DelegationChainEntry
- {
- /**
- * DLL
- */
- struct DelegationChainEntry *next;
- /**
- * DLL
- */
- struct DelegationChainEntry *prev;
- /**
- * The issuer
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
- /**
- * The subject
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
- /**
- * The issued attribute
- */
- char *issuer_attribute;
- /**
- * The delegated attribute
- */
- char *subject_attribute;
- };
- /**
- * DLL for record
- */
- struct DelegateRecordEntry
- {
- /**
- * DLL
- */
- struct DelegateRecordEntry *next;
- /**
- * DLL
- */
- struct DelegateRecordEntry *prev;
- /**
- * Number of references in delegation chains
- */
- uint32_t refcount;
- /**
- * Payload
- */
- struct GNUNET_ABD_Delegate *delegate;
- };
- /**
- * DLL used for delegations
- * Used for OR delegations
- */
- struct DelegationQueueEntry
- {
- /**
- * DLL
- */
- struct DelegationQueueEntry *next;
- /**
- * DLL
- */
- struct DelegationQueueEntry *prev;
- /**
- * Parent set
- */
- struct DelegationSetQueueEntry *parent_set;
- /**
- * Required solutions
- */
- uint32_t required_solutions;
- };
- /**
- * DLL for delegation sets
- * Used for AND delegation set
- */
- struct DelegationSetQueueEntry
- {
- /**
- * DLL
- */
- struct DelegationSetQueueEntry *next;
- /**
- * DLL
- */
- struct DelegationSetQueueEntry *prev;
- /**
- * GNS handle
- */
- struct GNUNET_GNS_LookupRequest *lookup_request;
- /**
- * Verify handle
- */
- struct VerifyRequestHandle *handle;
- /**
- * Parent attribute delegation
- */
- struct DelegationQueueEntry *parent;
- /**
- * Issuer key
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
- /**
- * Queue entries of this set
- */
- struct DelegationQueueEntry *queue_entries_head;
- /**
- * Queue entries of this set
- */
- struct DelegationQueueEntry *queue_entries_tail;
- /**
- * Parent QueueEntry
- */
- struct DelegationQueueEntry *parent_queue_entry;
- /**
- * Issuer attribute delegated to
- */
- char *issuer_attribute;
- /**
- * The current attribute to look up
- */
- char *lookup_attribute;
- /**
- * Trailing attribute context
- */
- char *attr_trailer;
- /**
- * Still to resolve delegation as string
- */
- char *unresolved_attribute_delegation;
- /**
- * The delegation chain entry
- */
- struct DelegationChainEntry *delegation_chain_entry;
- /**
- * True if added by backward resolution
- */
- bool from_bw;
- };
- /**
- * Handle to a lookup operation from api
- */
- struct VerifyRequestHandle
- {
- /**
- * True if created by a collect request.
- */
- bool is_collect;
- /**
- * We keep these in a DLL.
- */
- struct VerifyRequestHandle *next;
- /**
- * We keep these in a DLL.
- */
- struct VerifyRequestHandle *prev;
- /**
- * Handle to the requesting client
- */
- struct GNUNET_SERVICE_Client *client;
- /**
- * Size of delegation tree
- */
- uint32_t delegation_chain_size;
- /**
- * Children of this attribute
- */
- struct DelegationChainEntry *delegation_chain_head;
- /**
- * Children of this attribute
- */
- struct DelegationChainEntry *delegation_chain_tail;
- /**
- * List for bidirectional matching
- */
- struct DelegationSetQueueEntry *dsq_head;
- /**
- * List for bidirectional matching
- */
- struct DelegationSetQueueEntry *dsq_tail;
- /**
- * Issuer public key
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
- /**
- * Issuer attribute
- */
- char *issuer_attribute;
- /**
- * Subject public key
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
- /**
- * Delegate DLL
- */
- struct DelegateRecordEntry *del_chain_head;
- /**
- * Delegate DLL
- */
- struct DelegateRecordEntry *del_chain_tail;
- /**
- * Delegate DLL size
- */
- uint32_t del_chain_size;
- /**
- * Current Delegation Pointer
- */
- struct DelegationQueueEntry *current_delegation;
- /**
- * request id
- */
- uint32_t request_id;
- /**
- * Pending lookups
- */
- uint64_t pending_lookups;
- /**
- * Direction of the resolution algo
- */
- enum GNUNET_ABD_AlgoDirectionFlags resolution_algo;
- /**
- * Delegate iterator for lookup
- */
- struct GNUNET_NAMESTORE_QueueEntry *dele_qe;
- };
- /**
- * Head of the DLL.
- */
- static struct VerifyRequestHandle *vrh_head = NULL;
- /**
- * Tail of the DLL.
- */
- static struct VerifyRequestHandle *vrh_tail = NULL;
- /**
- * Handle to the statistics service
- */
- static struct GNUNET_STATISTICS_Handle *statistics;
- /**
- * Handle to GNS service.
- */
- static struct GNUNET_GNS_Handle *gns;
- /**
- * Handle to namestore service
- */
- static struct GNUNET_NAMESTORE_Handle *namestore;
- static void
- print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s %s.%s <- %s.%s\n",
- text,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
- &dsentry->delegation_chain_entry->issuer_key),
- dsentry->delegation_chain_entry->issuer_attribute,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
- &dsentry->delegation_chain_entry->subject_key),
- dsentry->delegation_chain_entry->subject_attribute);
- }
- static void
- cleanup_dsq_entry (struct DelegationSetQueueEntry *ds_entry)
- {
- GNUNET_free (ds_entry->issuer_key);
- GNUNET_free (ds_entry->issuer_attribute);
- GNUNET_free (ds_entry->attr_trailer);
- // those fields are only set/used in bw search
- if (ds_entry->from_bw)
- {
- GNUNET_free (ds_entry->lookup_attribute);
- GNUNET_free (ds_entry->unresolved_attribute_delegation);
- }
- if (NULL != ds_entry->lookup_request)
- {
- GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
- ds_entry->lookup_request = NULL;
- }
- if (NULL != ds_entry->delegation_chain_entry)
- {
- GNUNET_free (
- ds_entry->delegation_chain_entry->subject_attribute);
- GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
- GNUNET_free (ds_entry->delegation_chain_entry);
- }
- // Free DQ entries
- for (struct DelegationQueueEntry *dq_entry = ds_entry->queue_entries_head;
- NULL != ds_entry->queue_entries_head;
- dq_entry = ds_entry->queue_entries_head)
- {
- GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
- ds_entry->queue_entries_tail,
- dq_entry);
- GNUNET_free (dq_entry);
- }
- GNUNET_free (ds_entry);
- }
- static void
- cleanup_handle (struct VerifyRequestHandle *vrh)
- {
- struct DelegateRecordEntry *del_entry;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n");
- if (NULL != vrh->dsq_head)
- {
- for (struct DelegationSetQueueEntry *ds_entry = vrh->dsq_head; NULL !=
- vrh->dsq_head;
- ds_entry = vrh->dsq_head)
- {
- GNUNET_CONTAINER_DLL_remove (vrh->dsq_head, vrh->dsq_tail, ds_entry);
- cleanup_dsq_entry (ds_entry);
- }
- }
- if (NULL != vrh->del_chain_head)
- {
- for (del_entry = vrh->del_chain_head; NULL != vrh->del_chain_head;
- del_entry = vrh->del_chain_head)
- {
- GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head,
- vrh->del_chain_tail,
- del_entry);
- GNUNET_free (del_entry->delegate);
- GNUNET_free (del_entry);
- }
- }
- GNUNET_free (vrh->issuer_attribute);
- GNUNET_free (vrh);
- }
- static void
- shutdown_task (void *cls)
- {
- struct VerifyRequestHandle *vrh;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n");
- while (NULL != (vrh = vrh_head))
- {
- // ABD_resolver_lookup_cancel (clh->lookup);
- GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
- cleanup_handle (vrh);
- }
- if (NULL != gns)
- {
- GNUNET_GNS_disconnect (gns);
- gns = NULL;
- }
- if (NULL != namestore)
- {
- GNUNET_NAMESTORE_disconnect (namestore);
- namestore = NULL;
- }
- if (NULL != statistics)
- {
- GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
- statistics = NULL;
- }
- }
- static void
- send_intermediate_response (struct VerifyRequestHandle *vrh, struct
- DelegationChainEntry *ch_entry, bool is_bw)
- {
- struct DelegationChainIntermediateMessage *rmsg;
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_ABD_Delegation *dd;
- size_t size;
- // Don't report immediate results during collect
- if (vrh->is_collect)
- return;
- dd = GNUNET_new (struct GNUNET_ABD_Delegation);
- dd->issuer_key = ch_entry->issuer_key;
- dd->subject_key = ch_entry->subject_key;
- dd->issuer_attribute = ch_entry->issuer_attribute;
- dd->issuer_attribute_len = strlen (ch_entry->issuer_attribute) + 1;
- dd->subject_attribute_len = 0;
- dd->subject_attribute = NULL;
- if (NULL != ch_entry->subject_attribute)
- {
- dd->subject_attribute = ch_entry->subject_attribute;
- dd->subject_attribute_len = strlen (ch_entry->subject_attribute) + 1;
- }
- size = GNUNET_ABD_delegation_chain_get_size (1,
- dd,
- 0,
- NULL);
- env = GNUNET_MQ_msg_extra (rmsg,
- size,
- GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT);
- // Assign id so that client can find associated request
- rmsg->id = vrh->request_id;
- rmsg->is_bw = htons (is_bw);
- rmsg->size = htonl (size);
- GNUNET_assert (
- -1 != GNUNET_ABD_delegation_chain_serialize (1,
- dd,
- 0,
- NULL,
- size,
- (char *) &rmsg[1]));
- GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
- }
- static void
- send_lookup_response (struct VerifyRequestHandle *vrh)
- {
- struct GNUNET_MQ_Envelope *env;
- struct DelegationChainResultMessage *rmsg;
- struct DelegationChainEntry *dce;
- struct GNUNET_ABD_Delegation dd[vrh->delegation_chain_size];
- struct GNUNET_ABD_Delegate dele[vrh->del_chain_size];
- struct DelegateRecordEntry *del;
- struct DelegateRecordEntry *tmp;
- size_t size;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n");
- dce = vrh->delegation_chain_head;
- for (uint32_t i = 0; i < vrh->delegation_chain_size; i++)
- {
- dd[i].issuer_key = dce->issuer_key;
- dd[i].subject_key = dce->subject_key;
- dd[i].issuer_attribute = dce->issuer_attribute;
- dd[i].issuer_attribute_len = strlen (dce->issuer_attribute) + 1;
- dd[i].subject_attribute_len = 0;
- dd[i].subject_attribute = NULL;
- if (NULL != dce->subject_attribute)
- {
- dd[i].subject_attribute = dce->subject_attribute;
- dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1;
- }
- dce = dce->next;
- }
- // Remove all not needed credentials
- for (del = vrh->del_chain_head; NULL != del;)
- {
- if (del->refcount > 0)
- {
- del = del->next;
- continue;
- }
- tmp = del;
- del = del->next;
- GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp);
- GNUNET_free (tmp->delegate);
- GNUNET_free (tmp);
- vrh->del_chain_size--;
- }
- // Get serialized record data
- // Append at the end of rmsg
- del = vrh->del_chain_head;
- for (uint32_t i = 0; i < vrh->del_chain_size; i++)
- {
- dele[i].issuer_key = del->delegate->issuer_key;
- dele[i].subject_key = del->delegate->subject_key;
- dele[i].issuer_attribute_len = strlen (del->delegate->issuer_attribute) + 1;
- dele[i].issuer_attribute = del->delegate->issuer_attribute;
- dele[i].subject_attribute_len = del->delegate->subject_attribute_len;
- dele[i].subject_attribute = del->delegate->subject_attribute;
- dele[i].expiration = del->delegate->expiration;
- dele[i].signature = del->delegate->signature;
- del = del->next;
- }
- size =
- GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size,
- dd,
- vrh->del_chain_size,
- dele);
- env = GNUNET_MQ_msg_extra (rmsg,
- size,
- GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT);
- // Assign id so that client can find associated request
- rmsg->id = vrh->request_id;
- rmsg->d_count = htonl (vrh->delegation_chain_size);
- rmsg->c_count = htonl (vrh->del_chain_size);
- if (0 < vrh->del_chain_size)
- rmsg->del_found = htonl (GNUNET_YES);
- else
- rmsg->del_found = htonl (GNUNET_NO);
- GNUNET_assert (
- -1 !=
- GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size,
- dd,
- vrh->del_chain_size,
- dele,
- size,
- (char *) &rmsg[1]));
- GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
- GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
- cleanup_handle (vrh);
- GNUNET_STATISTICS_update (statistics,
- "Completed verifications",
- 1,
- GNUNET_NO);
- }
- static char *
- partial_match (char *tmp_trail,
- char *tmp_subattr,
- char *parent_trail,
- char *issuer_attribute)
- {
- char *saveptr1, *saveptr2;
- char *trail_token;
- char *sub_token;
- char *attr_trailer;
- // tok both, parent->attr_trailer and del->sub_attr to see how far they match,
- // take rest of parent trailer (only when del->sub_attr token is null), and
- // create new/actual trailer with del->iss_attr
- trail_token = strtok_r (tmp_trail, ".", &saveptr1);
- sub_token = strtok_r (tmp_subattr, ".", &saveptr2);
- while (NULL != trail_token && NULL != sub_token)
- {
- if (0 == strcmp (trail_token, sub_token))
- {
- // good, matches, remove
- }
- else
- {
- // not relevant for solving the chain, end for iteration here
- return NULL;
- }
- trail_token = strtok_r (NULL, ".", &saveptr1);
- sub_token = strtok_r (NULL, ".", &saveptr2);
- }
- // skip this entry and go to next for if:
- // 1. at some point the attr of the trailer and the subject dont match
- // 2. the trailer is NULL, but the subject has more attributes
- // Reason: This will lead to "startzone.attribute" but we're looking for a solution
- // for "<- startzone"
- if (NULL == trail_token)
- {
- return NULL;
- }
- // do not have to check sub_token == NULL, if both would be NULL
- // at the same time, the complete match part above should have triggered already
- // otherwise, above while only ends when sub_token == NULL
- GNUNET_asprintf (&attr_trailer, "%s", trail_token);
- trail_token = strtok_r (NULL, ".", &saveptr1);
- while (NULL != trail_token)
- {
- GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token);
- trail_token = strtok_r (NULL, ".", &saveptr1);
- }
- GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer);
- return attr_trailer;
- }
- static int
- handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
- struct DelegationSetQueueEntry *match_entry,
- struct VerifyRequestHandle *vrh)
- {
- struct DelegationSetQueueEntry *old_fw_parent;
- struct DelegationSetQueueEntry *fw_entry = actual_entry;
- struct DelegationSetQueueEntry *last_entry = match_entry;
- // parent fixing, combine backward and forward chain parts
- while (NULL != fw_entry->parent_queue_entry)
- {
- old_fw_parent = fw_entry->parent_queue_entry->parent_set;
- // set parent
- fw_entry->parent_queue_entry->parent_set = last_entry;
- last_entry = fw_entry;
- fw_entry = old_fw_parent;
- }
- // set last entry of chain as actual_entry
- // actual_entry = last_entry;
- // set refcount, loop all delegations
- for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
- del_entry != NULL;
- del_entry = del_entry->next)
- {
- if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
- &del_entry->delegate->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- continue;
- if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
- del_entry->delegate->issuer_attribute))
- continue;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n");
- // increase refcount of the start delegation
- del_entry->refcount++;
- }
- // backtrack
- for (struct DelegationSetQueueEntry *tmp_set = last_entry;
- NULL != tmp_set->parent_queue_entry;
- tmp_set = tmp_set->parent_queue_entry->parent_set)
- {
- tmp_set->parent_queue_entry->required_solutions--;
- // add new found entry to vrh
- vrh->delegation_chain_size++;
- GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
- vrh->delegation_chain_tail,
- tmp_set->delegation_chain_entry);
- // if one node on the path still needs solutions, this current
- // patch cannot fulfill the conditions and therefore stops here
- // however, it is in the vrh and can be used by the other paths
- // related to this path/collection/verification
- if (0 < tmp_set->parent_queue_entry->required_solutions)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Chain requires more solutions, waiting...\n");
- return GNUNET_NO;
- }
- }
- return GNUNET_YES;
- }
- static void
- forward_resolution (void *cls,
- uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
- struct VerifyRequestHandle *vrh;
- struct DelegationSetQueueEntry *current_set;
- struct DelegationSetQueueEntry *ds_entry;
- struct DelegationQueueEntry *dq_entry;
- current_set = cls;
- // set handle to NULL (as el = NULL)
- current_set->lookup_request = NULL;
- vrh = current_set->handle;
- vrh->pending_lookups--;
- // Loop record entries
- for (uint32_t i = 0; i < rd_count; i++)
- {
- if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
- continue;
- // Start deserialize into Delegate
- struct GNUNET_ABD_Delegate *del;
- del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
- // Start: Create DQ Entry
- dq_entry = GNUNET_new (struct DelegationQueueEntry);
- // AND delegations are not possible, only 1 solution
- dq_entry->required_solutions = 1;
- dq_entry->parent_set = current_set;
- // Insert it into the current set
- GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
- current_set->queue_entries_tail,
- dq_entry);
- // Start: Create DS Entry
- ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
- GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
- ds_entry->from_bw = false;
- // (1) A.a <- A.b.c
- // (2) A.b <- D.d
- // (3) D.d <- E
- // (4) E.c <- F.c
- // (5) F.c <- G
- // Possibilities:
- // 1. complete match: trailer = 0, validate
- // 2. partial match: replace
- // 3. new solution: replace, add trailer
- // At resolution chain start trailer of parent is NULL
- if (NULL == current_set->attr_trailer)
- {
- // for (5) F.c <- G, remember .c when going upwards
- ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
- }
- else
- {
- if (0 == del->subject_attribute_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n");
- // new solution
- // create new trailer del->issuer_attribute, ds_entry->attr_trailer
- GNUNET_asprintf (&ds_entry->attr_trailer,
- "%s.%s",
- del->issuer_attribute,
- current_set->attr_trailer);
- }
- else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer))
- {
- // complete match
- // new trailer == issuer attribute (e.g. (5) to (4))
- ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n");
- // partial match
- char *trail = partial_match (GNUNET_strdup (current_set->attr_trailer),
- GNUNET_strdup (del->subject_attribute),
- current_set->attr_trailer,
- GNUNET_strdup (del->issuer_attribute));
- // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
- if (NULL == trail)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Entry not relevant, discarding: %s.%s <- %s.%s\n",
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
- &del->issuer_key),
- del->issuer_attribute,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
- &del->subject_key),
- del->subject_attribute);
- continue;
- }
- else
- ds_entry->attr_trailer = trail;
- }
- }
- // Start: Credential Chain Entry
- // issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject)
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (ds_entry->issuer_key,
- &del->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
- ds_entry->delegation_chain_entry->subject_key = del->subject_key;
- if (0 < del->subject_attribute_len)
- ds_entry->delegation_chain_entry->subject_attribute =
- GNUNET_strdup (del->subject_attribute);
- ds_entry->delegation_chain_entry->issuer_key = del->issuer_key;
- ds_entry->delegation_chain_entry->issuer_attribute =
- GNUNET_strdup (del->issuer_attribute);
- // Found new entry, repoting intermediate result
- send_intermediate_response (vrh, ds_entry->delegation_chain_entry, false);
- // current delegation as parent
- ds_entry->parent_queue_entry = dq_entry;
- // Check for solution
- // if: issuer key we looking for
- if (0 == memcmp (&del->issuer_key,
- &vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- // if: issuer attr we looking for
- if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
- {
- // if: complete match, meaning new trailer == issuer attr
- if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n");
- // Add found solution into delegation_chain
- struct DelegationSetQueueEntry *tmp_set;
- for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
- tmp_set = tmp_set->parent_queue_entry->parent_set)
- {
- if (NULL != tmp_set->delegation_chain_entry)
- {
- vrh->delegation_chain_size++;
- GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
- vrh->delegation_chain_tail,
- tmp_set->delegation_chain_entry);
- }
- }
- // Increase refcount for this delegate
- for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
- del_entry != NULL;
- del_entry = del_entry->next)
- {
- if (0 == memcmp (&del_entry->delegate->issuer_key,
- &vrh->delegation_chain_head->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- if (0 == strcmp (del_entry->delegate->issuer_attribute,
- vrh->delegation_chain_head->subject_attribute))
- {
- del_entry->refcount++;
- }
- }
- }
- send_lookup_response (vrh);
- return;
- }
- }
- }
- // Check for bidirectional crossmatch
- for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
- del_entry != NULL;
- del_entry = del_entry->next)
- {
- // only check entries not by backward algorithm
- if (del_entry->from_bw)
- {
- // key of list entry matches actual key
- if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key,
- &ds_entry->delegation_chain_entry->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- // compare entry subject attributes to this trailer (iss attr + old trailer)
- if (0 == strcmp (del_entry->unresolved_attribute_delegation,
- ds_entry->attr_trailer))
- {
- print_deleset (del_entry, "Forward:");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Forward: Found match with above!\n");
- // one node on the path still needs solutions: return
- if (GNUNET_NO ==
- handle_bidirectional_match (ds_entry, del_entry, vrh))
- return;
- send_lookup_response (vrh);
- return;
- }
- }
- }
- }
- // Starting a new GNS lookup
- vrh->pending_lookups++;
- ds_entry->handle = vrh;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Starting to look up trailer %s in zone %s\n",
- ds_entry->attr_trailer,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&del->issuer_key));
- ds_entry->lookup_request =
- GNUNET_GNS_lookup (gns,
- GNUNET_GNS_EMPTY_LABEL_AT,
- &del->issuer_key,
- GNUNET_GNSRECORD_TYPE_DELEGATE,
- GNUNET_GNS_LO_DEFAULT,
- &forward_resolution,
- ds_entry);
- }
- if (0 == vrh->pending_lookups)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
- send_lookup_response (vrh);
- return;
- }
- }
- static void
- backward_resolution (void *cls,
- uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
- {
- struct VerifyRequestHandle *vrh;
- const struct GNUNET_ABD_DelegationRecord *sets;
- struct DelegateRecordEntry *del_pointer;
- struct DelegationSetQueueEntry *current_set;
- struct DelegationSetQueueEntry *ds_entry;
- struct DelegationSetQueueEntry *tmp_set;
- struct DelegationQueueEntry *dq_entry;
- char *expanded_attr;
- char *lookup_attribute;
- current_set = cls;
- current_set->lookup_request = NULL;
- vrh = current_set->handle;
- vrh->pending_lookups--;
- // Each OR
- for (uint32_t i = 0; i < rd_count; i++)
- {
- if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
- continue;
- sets = rd[i].data;
- struct GNUNET_ABD_DelegationSet set[ntohl (sets->set_count)];
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Found new attribute delegation with %d sets. Creating new Job...\n",
- ntohl (sets->set_count));
- if (GNUNET_OK !=
- GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll (
- sets->data_size),
- (const char *) &sets[1],
- ntohl (sets->set_count),
- set))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n");
- continue;
- }
- dq_entry = GNUNET_new (struct DelegationQueueEntry);
- dq_entry->required_solutions = ntohl (sets->set_count);
- dq_entry->parent_set = current_set;
- GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
- current_set->queue_entries_tail,
- dq_entry);
- // Each AND
- for (uint32_t j = 0; j < ntohl (sets->set_count); j++)
- {
- ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
- GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
- ds_entry->from_bw = true;
- if (NULL != current_set->attr_trailer)
- {
- if (0 == set[j].subject_attribute_len)
- {
- GNUNET_asprintf (&expanded_attr, "%s", current_set->attr_trailer);
- }
- else
- {
- GNUNET_asprintf (&expanded_attr,
- "%s.%s",
- set[j].subject_attribute,
- current_set->attr_trailer);
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expanded to %s\n", expanded_attr);
- ds_entry->unresolved_attribute_delegation = expanded_attr;
- }
- else
- {
- if (0 != set[j].subject_attribute_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Not Expanding %s\n",
- set[j].subject_attribute);
- ds_entry->unresolved_attribute_delegation =
- GNUNET_strdup (set[j].subject_attribute);
- }
- }
- // Add a credential chain entry
- ds_entry->delegation_chain_entry =
- GNUNET_new (struct DelegationChainEntry);
- ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (ds_entry->issuer_key,
- &set[j].subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- if (0 < set[j].subject_attribute_len)
- ds_entry->delegation_chain_entry->subject_attribute =
- GNUNET_strdup (set[j].subject_attribute);
- ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
- ds_entry->delegation_chain_entry->issuer_attribute =
- GNUNET_strdup (current_set->lookup_attribute);
- // Found new entry, repoting intermediate result
- send_intermediate_response (vrh, ds_entry->delegation_chain_entry, true);
- ds_entry->parent_queue_entry = dq_entry; // current_delegation;
- /**
- * Check if this delegation already matches one of our credentials
- */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n");
- for (del_pointer = vrh->del_chain_head; del_pointer != NULL;
- del_pointer = del_pointer->next)
- {
- // If key and attribute match credential: continue and backtrack
- if (0 != memcmp (&set[j].subject_key,
- &del_pointer->delegate->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- continue;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Checking if %s matches %s\n",
- ds_entry->unresolved_attribute_delegation,
- del_pointer->delegate->issuer_attribute);
- if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
- del_pointer->delegate->issuer_attribute))
- continue;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n");
- // increase refcount of the start delegation
- del_pointer->refcount++;
- // Backtrack
- for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
- tmp_set = tmp_set->parent_queue_entry->parent_set)
- {
- tmp_set->parent_queue_entry->required_solutions--;
- if (NULL != tmp_set->delegation_chain_entry)
- {
- vrh->delegation_chain_size++;
- GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
- vrh->delegation_chain_tail,
- tmp_set->delegation_chain_entry);
- }
- if (0 < tmp_set->parent_queue_entry->required_solutions)
- break;
- }
- // if the break above is not called the condition of the for is met
- if (NULL == tmp_set->parent_queue_entry)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All solutions found\n");
- // Found match
- send_lookup_response (vrh);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not all solutions found yet.\n");
- continue;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Building new lookup request from %s\n",
- ds_entry->unresolved_attribute_delegation);
- // Continue with next/new backward resolution
- char issuer_attribute_name[strlen (
- ds_entry->unresolved_attribute_delegation)
- + 1];
- strcpy (issuer_attribute_name, ds_entry->unresolved_attribute_delegation);
- char *next_attr = strtok (issuer_attribute_name, ".");
- if (NULL == next_attr)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse next attribute\n");
- continue;
- }
- GNUNET_asprintf (&lookup_attribute, "%s", next_attr);
- GNUNET_asprintf (&ds_entry->lookup_attribute, "%s", next_attr);
- if (strlen (next_attr) ==
- strlen (ds_entry->unresolved_attribute_delegation))
- {
- ds_entry->attr_trailer = NULL;
- }
- else
- {
- next_attr += strlen (next_attr) + 1;
- ds_entry->attr_trailer = GNUNET_strdup (next_attr);
- }
- // Check for bidirectional crossmatch
- for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
- del_entry != NULL;
- del_entry = del_entry->next)
- {
- // only check entries added by forward algorithm
- if (! del_entry->from_bw)
- {
- // key of list entry matches actual key
- if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key,
- &ds_entry->delegation_chain_entry->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- {
- // compare entry subject attributes to this trailer (iss attr + old trailer)
- if (0 == strcmp (del_entry->attr_trailer,
- ds_entry->unresolved_attribute_delegation))
- {
- print_deleset (del_entry, "Backward:");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Backward: Found match with above!\n");
- // if one node on the path still needs solutions: return
- if (GNUNET_NO ==
- handle_bidirectional_match (del_entry, ds_entry, vrh))
- break;
- // Send lookup response
- send_lookup_response (vrh);
- return;
- }
- }
- }
- }
- // Starting a new GNS lookup
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Looking up %s\n",
- ds_entry->lookup_attribute);
- if (NULL != ds_entry->attr_trailer)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s still to go...\n",
- ds_entry->attr_trailer);
- vrh->pending_lookups++;
- ds_entry->handle = vrh;
- ds_entry->lookup_request =
- GNUNET_GNS_lookup (gns,
- lookup_attribute,
- ds_entry->issuer_key, // issuer_key,
- GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
- GNUNET_GNS_LO_DEFAULT,
- &backward_resolution,
- ds_entry);
- GNUNET_free (lookup_attribute);
- }
- }
- if (0 == vrh->pending_lookups)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
- send_lookup_response (vrh);
- return;
- }
- }
- /**
- * Result from GNS lookup.
- *
- * @param cls the closure (our client lookup handle)
- */
- static int
- delegation_chain_bw_resolution_start (void *cls)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n");
- struct VerifyRequestHandle *vrh = cls;
- struct DelegationSetQueueEntry *ds_entry;
- struct DelegateRecordEntry *del_entry;
- if (0 == vrh->del_chain_size)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n");
- send_lookup_response (vrh);
- return 1;
- }
- // Pre-check with vrh->dele_chain_.. if match issuer_key
- // Backward: check every cred entry if match issuer key
- // otherwise: start at issuer and go down till match
- // A.a <- ...
- // X.x <- C
- // Y.y <- C
- // if not X.x or Y.y == A.a start at A
- for (del_entry = vrh->del_chain_head; del_entry != NULL;
- del_entry = del_entry->next)
- {
- if (0 != memcmp (&del_entry->delegate->issuer_key,
- &vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- continue;
- if (0 !=
- strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
- continue;
- del_entry->refcount++;
- // Found match prematurely
- send_lookup_response (vrh);
- return 1;
- }
- // Check for attributes from the issuer and follow the chain
- // till you get the required subject's attributes
- char issuer_attribute_name[strlen (vrh->issuer_attribute) + 1];
- strcpy (issuer_attribute_name, vrh->issuer_attribute);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Looking up %s\n",
- issuer_attribute_name);
- ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
- GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
- ds_entry->from_bw = true;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (ds_entry->issuer_key,
- &vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
- ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
- ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key;
- ds_entry->delegation_chain_entry->issuer_attribute =
- GNUNET_strdup (vrh->issuer_attribute);
- ds_entry->handle = vrh;
- ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
- ds_entry->unresolved_attribute_delegation = NULL;
- vrh->pending_lookups = 1;
- // Start with backward resolution
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n");
- ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
- issuer_attribute_name,
- &vrh->issuer_key, // issuer_key,
- GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
- GNUNET_GNS_LO_DEFAULT,
- &backward_resolution,
- ds_entry);
- return 0;
- }
- static int
- delegation_chain_fw_resolution_start (void *cls)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n");
- struct VerifyRequestHandle *vrh = cls;
- struct DelegationSetQueueEntry *ds_entry;
- struct DelegateRecordEntry *del_entry;
- // set to 0 and increase on each lookup: for fw multiple lookups (may be) started
- vrh->pending_lookups = 0;
- if (0 == vrh->del_chain_size)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n");
- send_lookup_response (vrh);
- return 1;
- }
- // Pre-check with vrh->dele_chain_.. if match issuer_key
- // otherwise FW: start multiple lookups for each vrh->dele_chain
- // A.a <- ...
- // X.x <- C
- // Y.y <- C
- // if not X.x or Y.y == A.a start at X and at Y
- for (del_entry = vrh->del_chain_head; del_entry != NULL;
- del_entry = del_entry->next)
- {
- if (0 != memcmp (&del_entry->delegate->issuer_key,
- &vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
- continue;
- if (0 !=
- strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
- continue;
- del_entry->refcount++;
- // Found match prematurely
- send_lookup_response (vrh);
- return 1;
- }
- // None match, therefore start for every delegation found a lookup chain
- // Return and end collect process on first chain iss <-> sub found
- // ds_entry created belongs to the first lookup, vrh still has the
- // issuer+attr we look for
- for (del_entry = vrh->del_chain_head; del_entry != NULL;
- del_entry = del_entry->next)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Looking for %s.%s\n",
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
- &del_entry->delegate->issuer_key),
- del_entry->delegate->issuer_attribute);
- ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
- GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
- ds_entry->from_bw = false;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
- GNUNET_memcpy (ds_entry->issuer_key,
- &del_entry->delegate->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
- ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
- ds_entry->delegation_chain_entry->subject_key =
- del_entry->delegate->subject_key;
- ds_entry->delegation_chain_entry->subject_attribute = NULL;
- ds_entry->delegation_chain_entry->issuer_key =
- del_entry->delegate->issuer_key;
- ds_entry->delegation_chain_entry->issuer_attribute =
- GNUNET_strdup (del_entry->delegate->issuer_attribute);
- ds_entry->attr_trailer =
- GNUNET_strdup (del_entry->delegate->issuer_attribute);
- ds_entry->handle = vrh;
- vrh->pending_lookups++;
- // Start with forward resolution
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n");
- ds_entry->lookup_request =
- GNUNET_GNS_lookup (gns,
- GNUNET_GNS_EMPTY_LABEL_AT,
- &del_entry->delegate->issuer_key, // issuer_key,
- GNUNET_GNSRECORD_TYPE_DELEGATE,
- GNUNET_GNS_LO_DEFAULT,
- &forward_resolution,
- ds_entry);
- }
- return 0;
- }
- static int
- check_verify (void *cls, const struct VerifyMessage *v_msg)
- {
- size_t msg_size;
- const char *attr;
- msg_size = ntohs (v_msg->header.size);
- if (msg_size < sizeof (struct VerifyMessage))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (ntohs (v_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- attr = (const char *) &v_msg[1];
- if (strlen (attr) > GNUNET_ABD_MAX_LENGTH)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- static void
- handle_verify (void *cls, const struct VerifyMessage *v_msg)
- {
- struct VerifyRequestHandle *vrh;
- struct GNUNET_SERVICE_Client *client = cls;
- struct DelegateRecordEntry *del_entry;
- uint32_t delegate_count;
- uint32_t delegate_data_size;
- char attr[GNUNET_ABD_MAX_LENGTH + 1];
- char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
- char *attrptr = attr;
- char *delegate_data;
- const char *utf_in;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received VERIFY message\n");
- utf_in = (const char *) &v_msg[1];
- GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
- GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
- issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
- vrh = GNUNET_new (struct VerifyRequestHandle);
- vrh->is_collect = false;
- GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
- vrh->client = client;
- vrh->request_id = v_msg->id;
- vrh->issuer_key = v_msg->issuer_key;
- vrh->subject_key = v_msg->subject_key;
- vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
- vrh->resolution_algo = ntohs (v_msg->resolution_algo);
- vrh->del_chain_head = NULL;
- vrh->del_chain_tail = NULL;
- vrh->dsq_head = NULL;
- vrh->dsq_tail = NULL;
- vrh->del_chain_head = NULL;
- vrh->del_chain_tail = NULL;
- GNUNET_SERVICE_client_continue (vrh->client);
- if (0 == strlen (issuer_attribute))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
- send_lookup_response (vrh);
- return;
- }
- // Parse delegates from verifaction message
- delegate_count = ntohl (v_msg->d_count);
- delegate_data_size = ntohs (v_msg->header.size)
- - sizeof (struct VerifyMessage)
- - ntohs (v_msg->issuer_attribute_len) - 1;
- struct GNUNET_ABD_Delegate delegates[delegate_count];
- memset (delegates,
- 0,
- sizeof (struct GNUNET_ABD_Delegate) * delegate_count);
- delegate_data = (char *) &v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
- if (GNUNET_OK != GNUNET_ABD_delegates_deserialize (delegate_data_size,
- delegate_data,
- delegate_count,
- delegates))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n");
- send_lookup_response (vrh);
- return;
- }
- // Prepare vrh delegation chain for later validation
- for (uint32_t i = 0; i < delegate_count; i++)
- {
- del_entry = GNUNET_new (struct DelegateRecordEntry);
- del_entry->delegate =
- GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate)
- + delegates[i].issuer_attribute_len + 1);
- GNUNET_memcpy (del_entry->delegate,
- &delegates[i],
- sizeof (struct GNUNET_ABD_Delegate));
- GNUNET_memcpy (&del_entry->delegate[1],
- delegates[i].issuer_attribute,
- delegates[i].issuer_attribute_len);
- del_entry->delegate->issuer_attribute_len =
- delegates[i].issuer_attribute_len;
- del_entry->delegate->issuer_attribute = (char *) &del_entry->delegate[1];
- GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
- vrh->del_chain_tail,
- del_entry);
- vrh->del_chain_size++;
- }
- // Switch resolution algo
- if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
- GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
- {
- if (1 == delegation_chain_fw_resolution_start (vrh))
- return;
- delegation_chain_bw_resolution_start (vrh);
- }
- else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
- {
- delegation_chain_bw_resolution_start (vrh);
- }
- else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
- {
- delegation_chain_fw_resolution_start (vrh);
- }
- }
- static void
- handle_delegate_collection_error_cb (void *cls)
- {
- struct VerifyRequestHandle *vrh = cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got disconnected from namestore database.\n");
- vrh->dele_qe = NULL;
- send_lookup_response (vrh);
- }
- static void
- delegate_collection_finished (void *cls)
- {
- struct VerifyRequestHandle *vrh = cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n");
- // if both are set: bidirectional search, meaning start both chain resolutions
- if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
- GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
- {
- // if premature match found don't start bw resolution
- if (1 == delegation_chain_fw_resolution_start (vrh))
- return;
- delegation_chain_bw_resolution_start (vrh);
- }
- else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
- {
- delegation_chain_bw_resolution_start (vrh);
- }
- else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
- {
- delegation_chain_fw_resolution_start (vrh);
- }
- }
- static void
- handle_delegate_collection_cb (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
- const char *label,
- unsigned int rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
- {
- struct VerifyRequestHandle *vrh = cls;
- struct GNUNET_ABD_Delegate *del;
- struct DelegateRecordEntry *del_entry;
- int cred_record_count;
- cred_record_count = 0;
- vrh->dele_qe = NULL;
- for (uint32_t i = 0; i < rd_count; i++)
- {
- if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
- continue;
- cred_record_count++;
- del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
- if (NULL == del)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
- continue;
- }
- // only add the entries that are explicitly marked as private
- // and therefore symbolize the end of a chain
- if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)
- {
- del_entry = GNUNET_new (struct DelegateRecordEntry);
- del_entry->delegate = del;
- GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
- vrh->del_chain_tail,
- del_entry);
- vrh->del_chain_size++;
- }
- }
- delegate_collection_finished (vrh);
- }
- static void
- handle_collect (void *cls, const struct CollectMessage *c_msg)
- {
- char attr[GNUNET_ABD_MAX_LENGTH + 1];
- char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
- struct VerifyRequestHandle *vrh;
- struct GNUNET_SERVICE_Client *client = cls;
- char *attrptr = attr;
- const char *utf_in;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received COLLECT message\n");
- utf_in = (const char *) &c_msg[1];
- GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
- GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
- issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
- vrh = GNUNET_new (struct VerifyRequestHandle);
- vrh->is_collect = true;
- GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
- vrh->client = client;
- vrh->request_id = c_msg->id;
- vrh->issuer_key = c_msg->issuer_key;
- GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, &vrh->subject_key);
- vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
- vrh->resolution_algo = ntohs (c_msg->resolution_algo);
- vrh->del_chain_head = NULL;
- vrh->del_chain_tail = NULL;
- vrh->dsq_head = NULL;
- vrh->dsq_tail = NULL;
- vrh->del_chain_head = NULL;
- vrh->del_chain_tail = NULL;
- if (0 == strlen (issuer_attribute))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
- send_lookup_response (vrh);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n");
- // Get all delegates from subject
- vrh->dele_qe =
- GNUNET_NAMESTORE_records_lookup (namestore,
- &c_msg->subject_key,
- GNUNET_GNS_EMPTY_LABEL_AT,
- &handle_delegate_collection_error_cb,
- vrh,
- &handle_delegate_collection_cb,
- vrh);
- GNUNET_SERVICE_client_continue (vrh->client);
- }
- static int
- check_collect (void *cls, const struct CollectMessage *c_msg)
- {
- size_t msg_size;
- const char *attr;
- msg_size = ntohs (c_msg->header.size);
- if (msg_size < sizeof (struct CollectMessage))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (ntohs (c_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- attr = (const char *) &c_msg[1];
- if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
- (strlen (attr) > GNUNET_ABD_MAX_LENGTH))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- static void
- client_disconnect_cb (void *cls,
- struct GNUNET_SERVICE_Client *client,
- void *app_ctx)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
- }
- static void *
- client_connect_cb (void *cls,
- struct GNUNET_SERVICE_Client *client,
- struct GNUNET_MQ_Handle *mq)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
- return client;
- }
- /**
- * Process Credential requests.
- *
- * @param cls closure
- * @param c configuration to use
- * @param handle service handle
- */
- static void
- run (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_SERVICE_Handle *handle)
- {
- gns = GNUNET_GNS_connect (c);
- if (NULL == gns)
- {
- fprintf (stderr, _ ("Failed to connect to GNS\n"));
- }
- namestore = GNUNET_NAMESTORE_connect (c);
- if (NULL == namestore)
- {
- fprintf (stderr, _ ("Failed to connect to namestore\n"));
- }
- statistics = GNUNET_STATISTICS_create ("abd", c);
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
- }
- /**
- * Define "main" method using service macro
- */
- GNUNET_SERVICE_MAIN (
- "abd",
- GNUNET_SERVICE_OPTION_NONE,
- &run,
- &client_connect_cb,
- &client_disconnect_cb,
- NULL,
- GNUNET_MQ_hd_var_size (verify,
- GNUNET_MESSAGE_TYPE_ABD_VERIFY,
- struct VerifyMessage,
- NULL),
- GNUNET_MQ_hd_var_size (collect,
- GNUNET_MESSAGE_TYPE_ABD_COLLECT,
- struct CollectMessage,
- NULL),
- GNUNET_MQ_handler_end ());
- /* end of gnunet-service-abd.c */
|