gnunet-service-abd.c 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011-2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file abd/gnunet-service-abd.c
  18. * @brief GNUnet Credential Service (main service)
  19. * @author Martin Schanzenbach
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "abd.h"
  24. #include "abd_serialization.h"
  25. #include "gnunet_abd_service.h"
  26. #include "gnunet_protocols.h"
  27. #include "gnunet_signatures.h"
  28. #include "gnunet_statistics_service.h"
  29. #include <gnunet_dnsparser_lib.h>
  30. #include <gnunet_gns_service.h>
  31. #include <gnunet_gnsrecord_lib.h>
  32. #include <gnunet_identity_service.h>
  33. #include <gnunet_namestore_service.h>
  34. #define GNUNET_ABD_MAX_LENGTH 255
  35. struct VerifyRequestHandle;
  36. struct DelegationSetQueueEntry;
  37. struct DelegationChainEntry
  38. {
  39. /**
  40. * DLL
  41. */
  42. struct DelegationChainEntry *next;
  43. /**
  44. * DLL
  45. */
  46. struct DelegationChainEntry *prev;
  47. /**
  48. * The issuer
  49. */
  50. struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
  51. /**
  52. * The subject
  53. */
  54. struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
  55. /**
  56. * The issued attribute
  57. */
  58. char *issuer_attribute;
  59. /**
  60. * The delegated attribute
  61. */
  62. char *subject_attribute;
  63. };
  64. /**
  65. * DLL for record
  66. */
  67. struct DelegateRecordEntry
  68. {
  69. /**
  70. * DLL
  71. */
  72. struct DelegateRecordEntry *next;
  73. /**
  74. * DLL
  75. */
  76. struct DelegateRecordEntry *prev;
  77. /**
  78. * Number of references in delegation chains
  79. */
  80. uint32_t refcount;
  81. /**
  82. * Payload
  83. */
  84. struct GNUNET_ABD_Delegate *delegate;
  85. };
  86. /**
  87. * DLL used for delegations
  88. * Used for OR delegations
  89. */
  90. struct DelegationQueueEntry
  91. {
  92. /**
  93. * DLL
  94. */
  95. struct DelegationQueueEntry *next;
  96. /**
  97. * DLL
  98. */
  99. struct DelegationQueueEntry *prev;
  100. /**
  101. * Parent set
  102. */
  103. struct DelegationSetQueueEntry *parent_set;
  104. /**
  105. * Required solutions
  106. */
  107. uint32_t required_solutions;
  108. };
  109. /**
  110. * DLL for delegation sets
  111. * Used for AND delegation set
  112. */
  113. struct DelegationSetQueueEntry
  114. {
  115. /**
  116. * DLL
  117. */
  118. struct DelegationSetQueueEntry *next;
  119. /**
  120. * DLL
  121. */
  122. struct DelegationSetQueueEntry *prev;
  123. /**
  124. * GNS handle
  125. */
  126. struct GNUNET_GNS_LookupRequest *lookup_request;
  127. /**
  128. * Verify handle
  129. */
  130. struct VerifyRequestHandle *handle;
  131. /**
  132. * Parent attribute delegation
  133. */
  134. struct DelegationQueueEntry *parent;
  135. /**
  136. * Issuer key
  137. */
  138. struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
  139. /**
  140. * Queue entries of this set
  141. */
  142. struct DelegationQueueEntry *queue_entries_head;
  143. /**
  144. * Queue entries of this set
  145. */
  146. struct DelegationQueueEntry *queue_entries_tail;
  147. /**
  148. * Parent QueueEntry
  149. */
  150. struct DelegationQueueEntry *parent_queue_entry;
  151. /**
  152. * Issuer attribute delegated to
  153. */
  154. char *issuer_attribute;
  155. /**
  156. * The current attribute to look up
  157. */
  158. char *lookup_attribute;
  159. /**
  160. * Trailing attribute context
  161. */
  162. char *attr_trailer;
  163. /**
  164. * Still to resolve delegation as string
  165. */
  166. char *unresolved_attribute_delegation;
  167. /**
  168. * The delegation chain entry
  169. */
  170. struct DelegationChainEntry *delegation_chain_entry;
  171. /**
  172. * True if added by backward resolution
  173. */
  174. bool from_bw;
  175. };
  176. /**
  177. * Handle to a lookup operation from api
  178. */
  179. struct VerifyRequestHandle
  180. {
  181. /**
  182. * True if created by a collect request.
  183. */
  184. bool is_collect;
  185. /**
  186. * We keep these in a DLL.
  187. */
  188. struct VerifyRequestHandle *next;
  189. /**
  190. * We keep these in a DLL.
  191. */
  192. struct VerifyRequestHandle *prev;
  193. /**
  194. * Handle to the requesting client
  195. */
  196. struct GNUNET_SERVICE_Client *client;
  197. /**
  198. * Size of delegation tree
  199. */
  200. uint32_t delegation_chain_size;
  201. /**
  202. * Children of this attribute
  203. */
  204. struct DelegationChainEntry *delegation_chain_head;
  205. /**
  206. * Children of this attribute
  207. */
  208. struct DelegationChainEntry *delegation_chain_tail;
  209. /**
  210. * List for bidirectional matching
  211. */
  212. struct DelegationSetQueueEntry *dsq_head;
  213. /**
  214. * List for bidirectional matching
  215. */
  216. struct DelegationSetQueueEntry *dsq_tail;
  217. /**
  218. * Issuer public key
  219. */
  220. struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
  221. /**
  222. * Issuer attribute
  223. */
  224. char *issuer_attribute;
  225. /**
  226. * Subject public key
  227. */
  228. struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
  229. /**
  230. * Delegate DLL
  231. */
  232. struct DelegateRecordEntry *del_chain_head;
  233. /**
  234. * Delegate DLL
  235. */
  236. struct DelegateRecordEntry *del_chain_tail;
  237. /**
  238. * Delegate DLL size
  239. */
  240. uint32_t del_chain_size;
  241. /**
  242. * Current Delegation Pointer
  243. */
  244. struct DelegationQueueEntry *current_delegation;
  245. /**
  246. * request id
  247. */
  248. uint32_t request_id;
  249. /**
  250. * Pending lookups
  251. */
  252. uint64_t pending_lookups;
  253. /**
  254. * Direction of the resolution algo
  255. */
  256. enum GNUNET_ABD_AlgoDirectionFlags resolution_algo;
  257. /**
  258. * Delegate iterator for lookup
  259. */
  260. struct GNUNET_NAMESTORE_QueueEntry *dele_qe;
  261. };
  262. /**
  263. * Head of the DLL.
  264. */
  265. static struct VerifyRequestHandle *vrh_head = NULL;
  266. /**
  267. * Tail of the DLL.
  268. */
  269. static struct VerifyRequestHandle *vrh_tail = NULL;
  270. /**
  271. * Handle to the statistics service
  272. */
  273. static struct GNUNET_STATISTICS_Handle *statistics;
  274. /**
  275. * Handle to GNS service.
  276. */
  277. static struct GNUNET_GNS_Handle *gns;
  278. /**
  279. * Handle to namestore service
  280. */
  281. static struct GNUNET_NAMESTORE_Handle *namestore;
  282. static void
  283. print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
  284. {
  285. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  286. "%s %s.%s <- %s.%s\n",
  287. text,
  288. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  289. &dsentry->delegation_chain_entry->issuer_key),
  290. dsentry->delegation_chain_entry->issuer_attribute,
  291. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  292. &dsentry->delegation_chain_entry->subject_key),
  293. dsentry->delegation_chain_entry->subject_attribute);
  294. }
  295. static void
  296. cleanup_dsq_entry (struct DelegationSetQueueEntry *ds_entry)
  297. {
  298. GNUNET_free (ds_entry->issuer_key);
  299. GNUNET_free (ds_entry->issuer_attribute);
  300. GNUNET_free (ds_entry->attr_trailer);
  301. // those fields are only set/used in bw search
  302. if (ds_entry->from_bw)
  303. {
  304. GNUNET_free (ds_entry->lookup_attribute);
  305. GNUNET_free (ds_entry->unresolved_attribute_delegation);
  306. }
  307. if (NULL != ds_entry->lookup_request)
  308. {
  309. GNUNET_GNS_lookup_cancel (ds_entry->lookup_request);
  310. ds_entry->lookup_request = NULL;
  311. }
  312. if (NULL != ds_entry->delegation_chain_entry)
  313. {
  314. GNUNET_free (
  315. ds_entry->delegation_chain_entry->subject_attribute);
  316. GNUNET_free (ds_entry->delegation_chain_entry->issuer_attribute);
  317. GNUNET_free (ds_entry->delegation_chain_entry);
  318. }
  319. // Free DQ entries
  320. for (struct DelegationQueueEntry *dq_entry = ds_entry->queue_entries_head;
  321. NULL != ds_entry->queue_entries_head;
  322. dq_entry = ds_entry->queue_entries_head)
  323. {
  324. GNUNET_CONTAINER_DLL_remove (ds_entry->queue_entries_head,
  325. ds_entry->queue_entries_tail,
  326. dq_entry);
  327. GNUNET_free (dq_entry);
  328. }
  329. GNUNET_free (ds_entry);
  330. }
  331. static void
  332. cleanup_handle (struct VerifyRequestHandle *vrh)
  333. {
  334. struct DelegateRecordEntry *del_entry;
  335. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up...\n");
  336. if (NULL != vrh->dsq_head)
  337. {
  338. for (struct DelegationSetQueueEntry *ds_entry = vrh->dsq_head; NULL !=
  339. vrh->dsq_head;
  340. ds_entry = vrh->dsq_head)
  341. {
  342. GNUNET_CONTAINER_DLL_remove (vrh->dsq_head, vrh->dsq_tail, ds_entry);
  343. cleanup_dsq_entry (ds_entry);
  344. }
  345. }
  346. if (NULL != vrh->del_chain_head)
  347. {
  348. for (del_entry = vrh->del_chain_head; NULL != vrh->del_chain_head;
  349. del_entry = vrh->del_chain_head)
  350. {
  351. GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head,
  352. vrh->del_chain_tail,
  353. del_entry);
  354. GNUNET_free (del_entry->delegate);
  355. GNUNET_free (del_entry);
  356. }
  357. }
  358. GNUNET_free (vrh->issuer_attribute);
  359. GNUNET_free (vrh);
  360. }
  361. static void
  362. shutdown_task (void *cls)
  363. {
  364. struct VerifyRequestHandle *vrh;
  365. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n");
  366. while (NULL != (vrh = vrh_head))
  367. {
  368. // ABD_resolver_lookup_cancel (clh->lookup);
  369. GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
  370. cleanup_handle (vrh);
  371. }
  372. if (NULL != gns)
  373. {
  374. GNUNET_GNS_disconnect (gns);
  375. gns = NULL;
  376. }
  377. if (NULL != namestore)
  378. {
  379. GNUNET_NAMESTORE_disconnect (namestore);
  380. namestore = NULL;
  381. }
  382. if (NULL != statistics)
  383. {
  384. GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
  385. statistics = NULL;
  386. }
  387. }
  388. static void
  389. send_intermediate_response (struct VerifyRequestHandle *vrh, struct
  390. DelegationChainEntry *ch_entry, bool is_bw)
  391. {
  392. struct DelegationChainIntermediateMessage *rmsg;
  393. struct GNUNET_MQ_Envelope *env;
  394. struct GNUNET_ABD_Delegation *dd;
  395. size_t size;
  396. // Don't report immediate results during collect
  397. if (vrh->is_collect)
  398. return;
  399. dd = GNUNET_new (struct GNUNET_ABD_Delegation);
  400. dd->issuer_key = ch_entry->issuer_key;
  401. dd->subject_key = ch_entry->subject_key;
  402. dd->issuer_attribute = ch_entry->issuer_attribute;
  403. dd->issuer_attribute_len = strlen (ch_entry->issuer_attribute) + 1;
  404. dd->subject_attribute_len = 0;
  405. dd->subject_attribute = NULL;
  406. if (NULL != ch_entry->subject_attribute)
  407. {
  408. dd->subject_attribute = ch_entry->subject_attribute;
  409. dd->subject_attribute_len = strlen (ch_entry->subject_attribute) + 1;
  410. }
  411. size = GNUNET_ABD_delegation_chain_get_size (1,
  412. dd,
  413. 0,
  414. NULL);
  415. env = GNUNET_MQ_msg_extra (rmsg,
  416. size,
  417. GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT);
  418. // Assign id so that client can find associated request
  419. rmsg->id = vrh->request_id;
  420. rmsg->is_bw = htons (is_bw);
  421. rmsg->size = htonl (size);
  422. GNUNET_assert (
  423. -1 != GNUNET_ABD_delegation_chain_serialize (1,
  424. dd,
  425. 0,
  426. NULL,
  427. size,
  428. (char *) &rmsg[1]));
  429. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
  430. }
  431. static void
  432. send_lookup_response (struct VerifyRequestHandle *vrh)
  433. {
  434. struct GNUNET_MQ_Envelope *env;
  435. struct DelegationChainResultMessage *rmsg;
  436. struct DelegationChainEntry *dce;
  437. struct GNUNET_ABD_Delegation dd[vrh->delegation_chain_size];
  438. struct GNUNET_ABD_Delegate dele[vrh->del_chain_size];
  439. struct DelegateRecordEntry *del;
  440. struct DelegateRecordEntry *tmp;
  441. size_t size;
  442. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response\n");
  443. dce = vrh->delegation_chain_head;
  444. for (uint32_t i = 0; i < vrh->delegation_chain_size; i++)
  445. {
  446. dd[i].issuer_key = dce->issuer_key;
  447. dd[i].subject_key = dce->subject_key;
  448. dd[i].issuer_attribute = dce->issuer_attribute;
  449. dd[i].issuer_attribute_len = strlen (dce->issuer_attribute) + 1;
  450. dd[i].subject_attribute_len = 0;
  451. dd[i].subject_attribute = NULL;
  452. if (NULL != dce->subject_attribute)
  453. {
  454. dd[i].subject_attribute = dce->subject_attribute;
  455. dd[i].subject_attribute_len = strlen (dce->subject_attribute) + 1;
  456. }
  457. dce = dce->next;
  458. }
  459. // Remove all not needed credentials
  460. for (del = vrh->del_chain_head; NULL != del;)
  461. {
  462. if (del->refcount > 0)
  463. {
  464. del = del->next;
  465. continue;
  466. }
  467. tmp = del;
  468. del = del->next;
  469. GNUNET_CONTAINER_DLL_remove (vrh->del_chain_head, vrh->del_chain_tail, tmp);
  470. GNUNET_free (tmp->delegate);
  471. GNUNET_free (tmp);
  472. vrh->del_chain_size--;
  473. }
  474. // Get serialized record data
  475. // Append at the end of rmsg
  476. del = vrh->del_chain_head;
  477. for (uint32_t i = 0; i < vrh->del_chain_size; i++)
  478. {
  479. dele[i].issuer_key = del->delegate->issuer_key;
  480. dele[i].subject_key = del->delegate->subject_key;
  481. dele[i].issuer_attribute_len = strlen (del->delegate->issuer_attribute) + 1;
  482. dele[i].issuer_attribute = del->delegate->issuer_attribute;
  483. dele[i].subject_attribute_len = del->delegate->subject_attribute_len;
  484. dele[i].subject_attribute = del->delegate->subject_attribute;
  485. dele[i].expiration = del->delegate->expiration;
  486. dele[i].signature = del->delegate->signature;
  487. del = del->next;
  488. }
  489. size =
  490. GNUNET_ABD_delegation_chain_get_size (vrh->delegation_chain_size,
  491. dd,
  492. vrh->del_chain_size,
  493. dele);
  494. env = GNUNET_MQ_msg_extra (rmsg,
  495. size,
  496. GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT);
  497. // Assign id so that client can find associated request
  498. rmsg->id = vrh->request_id;
  499. rmsg->d_count = htonl (vrh->delegation_chain_size);
  500. rmsg->c_count = htonl (vrh->del_chain_size);
  501. if (0 < vrh->del_chain_size)
  502. rmsg->del_found = htonl (GNUNET_YES);
  503. else
  504. rmsg->del_found = htonl (GNUNET_NO);
  505. GNUNET_assert (
  506. -1 !=
  507. GNUNET_ABD_delegation_chain_serialize (vrh->delegation_chain_size,
  508. dd,
  509. vrh->del_chain_size,
  510. dele,
  511. size,
  512. (char *) &rmsg[1]));
  513. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
  514. GNUNET_CONTAINER_DLL_remove (vrh_head, vrh_tail, vrh);
  515. cleanup_handle (vrh);
  516. GNUNET_STATISTICS_update (statistics,
  517. "Completed verifications",
  518. 1,
  519. GNUNET_NO);
  520. }
  521. static char *
  522. partial_match (char *tmp_trail,
  523. char *tmp_subattr,
  524. char *parent_trail,
  525. char *issuer_attribute)
  526. {
  527. char *saveptr1, *saveptr2;
  528. char *trail_token;
  529. char *sub_token;
  530. char *attr_trailer;
  531. // tok both, parent->attr_trailer and del->sub_attr to see how far they match,
  532. // take rest of parent trailer (only when del->sub_attr token is null), and
  533. // create new/actual trailer with del->iss_attr
  534. trail_token = strtok_r (tmp_trail, ".", &saveptr1);
  535. sub_token = strtok_r (tmp_subattr, ".", &saveptr2);
  536. while (NULL != trail_token && NULL != sub_token)
  537. {
  538. if (0 == strcmp (trail_token, sub_token))
  539. {
  540. // good, matches, remove
  541. }
  542. else
  543. {
  544. // not relevant for solving the chain, end for iteration here
  545. return NULL;
  546. }
  547. trail_token = strtok_r (NULL, ".", &saveptr1);
  548. sub_token = strtok_r (NULL, ".", &saveptr2);
  549. }
  550. // skip this entry and go to next for if:
  551. // 1. at some point the attr of the trailer and the subject dont match
  552. // 2. the trailer is NULL, but the subject has more attributes
  553. // Reason: This will lead to "startzone.attribute" but we're looking for a solution
  554. // for "<- startzone"
  555. if (NULL == trail_token)
  556. {
  557. return NULL;
  558. }
  559. // do not have to check sub_token == NULL, if both would be NULL
  560. // at the same time, the complete match part above should have triggered already
  561. // otherwise, above while only ends when sub_token == NULL
  562. GNUNET_asprintf (&attr_trailer, "%s", trail_token);
  563. trail_token = strtok_r (NULL, ".", &saveptr1);
  564. while (NULL != trail_token)
  565. {
  566. GNUNET_asprintf (&attr_trailer, "%s.%s", parent_trail, trail_token);
  567. trail_token = strtok_r (NULL, ".", &saveptr1);
  568. }
  569. GNUNET_asprintf (&attr_trailer, "%s.%s", issuer_attribute, attr_trailer);
  570. return attr_trailer;
  571. }
  572. static int
  573. handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
  574. struct DelegationSetQueueEntry *match_entry,
  575. struct VerifyRequestHandle *vrh)
  576. {
  577. struct DelegationSetQueueEntry *old_fw_parent;
  578. struct DelegationSetQueueEntry *fw_entry = actual_entry;
  579. struct DelegationSetQueueEntry *last_entry = match_entry;
  580. // parent fixing, combine backward and forward chain parts
  581. while (NULL != fw_entry->parent_queue_entry)
  582. {
  583. old_fw_parent = fw_entry->parent_queue_entry->parent_set;
  584. // set parent
  585. fw_entry->parent_queue_entry->parent_set = last_entry;
  586. last_entry = fw_entry;
  587. fw_entry = old_fw_parent;
  588. }
  589. // set last entry of chain as actual_entry
  590. // actual_entry = last_entry;
  591. // set refcount, loop all delegations
  592. for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
  593. del_entry != NULL;
  594. del_entry = del_entry->next)
  595. {
  596. if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
  597. &del_entry->delegate->issuer_key,
  598. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  599. continue;
  600. if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
  601. del_entry->delegate->issuer_attribute))
  602. continue;
  603. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found delegate.\n");
  604. // increase refcount of the start delegation
  605. del_entry->refcount++;
  606. }
  607. // backtrack
  608. for (struct DelegationSetQueueEntry *tmp_set = last_entry;
  609. NULL != tmp_set->parent_queue_entry;
  610. tmp_set = tmp_set->parent_queue_entry->parent_set)
  611. {
  612. tmp_set->parent_queue_entry->required_solutions--;
  613. // add new found entry to vrh
  614. vrh->delegation_chain_size++;
  615. GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
  616. vrh->delegation_chain_tail,
  617. tmp_set->delegation_chain_entry);
  618. // if one node on the path still needs solutions, this current
  619. // patch cannot fulfill the conditions and therefore stops here
  620. // however, it is in the vrh and can be used by the other paths
  621. // related to this path/collection/verification
  622. if (0 < tmp_set->parent_queue_entry->required_solutions)
  623. {
  624. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  625. "Chain requires more solutions, waiting...\n");
  626. return GNUNET_NO;
  627. }
  628. }
  629. return GNUNET_YES;
  630. }
  631. static void
  632. forward_resolution (void *cls,
  633. uint32_t rd_count,
  634. const struct GNUNET_GNSRECORD_Data *rd)
  635. {
  636. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
  637. struct VerifyRequestHandle *vrh;
  638. struct DelegationSetQueueEntry *current_set;
  639. struct DelegationSetQueueEntry *ds_entry;
  640. struct DelegationQueueEntry *dq_entry;
  641. current_set = cls;
  642. // set handle to NULL (as el = NULL)
  643. current_set->lookup_request = NULL;
  644. vrh = current_set->handle;
  645. vrh->pending_lookups--;
  646. // Loop record entries
  647. for (uint32_t i = 0; i < rd_count; i++)
  648. {
  649. if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
  650. continue;
  651. // Start deserialize into Delegate
  652. struct GNUNET_ABD_Delegate *del;
  653. del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
  654. // Start: Create DQ Entry
  655. dq_entry = GNUNET_new (struct DelegationQueueEntry);
  656. // AND delegations are not possible, only 1 solution
  657. dq_entry->required_solutions = 1;
  658. dq_entry->parent_set = current_set;
  659. // Insert it into the current set
  660. GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
  661. current_set->queue_entries_tail,
  662. dq_entry);
  663. // Start: Create DS Entry
  664. ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
  665. GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
  666. ds_entry->from_bw = false;
  667. // (1) A.a <- A.b.c
  668. // (2) A.b <- D.d
  669. // (3) D.d <- E
  670. // (4) E.c <- F.c
  671. // (5) F.c <- G
  672. // Possibilities:
  673. // 1. complete match: trailer = 0, validate
  674. // 2. partial match: replace
  675. // 3. new solution: replace, add trailer
  676. // At resolution chain start trailer of parent is NULL
  677. if (NULL == current_set->attr_trailer)
  678. {
  679. // for (5) F.c <- G, remember .c when going upwards
  680. ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
  681. }
  682. else
  683. {
  684. if (0 == del->subject_attribute_len)
  685. {
  686. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: New solution\n");
  687. // new solution
  688. // create new trailer del->issuer_attribute, ds_entry->attr_trailer
  689. GNUNET_asprintf (&ds_entry->attr_trailer,
  690. "%s.%s",
  691. del->issuer_attribute,
  692. current_set->attr_trailer);
  693. }
  694. else if (0 == strcmp (del->subject_attribute, current_set->attr_trailer))
  695. {
  696. // complete match
  697. // new trailer == issuer attribute (e.g. (5) to (4))
  698. ds_entry->attr_trailer = GNUNET_strdup (del->issuer_attribute);
  699. }
  700. else
  701. {
  702. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Partial match\n");
  703. // partial match
  704. char *trail = partial_match (GNUNET_strdup (current_set->attr_trailer),
  705. GNUNET_strdup (del->subject_attribute),
  706. current_set->attr_trailer,
  707. GNUNET_strdup (del->issuer_attribute));
  708. // if null: skip this record entry (reasons: mismatch or overmatch, both not relevant)
  709. if (NULL == trail)
  710. {
  711. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  712. "Entry not relevant, discarding: %s.%s <- %s.%s\n",
  713. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  714. &del->issuer_key),
  715. del->issuer_attribute,
  716. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  717. &del->subject_key),
  718. del->subject_attribute);
  719. continue;
  720. }
  721. else
  722. ds_entry->attr_trailer = trail;
  723. }
  724. }
  725. // Start: Credential Chain Entry
  726. // issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject)
  727. ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
  728. GNUNET_memcpy (ds_entry->issuer_key,
  729. &del->subject_key,
  730. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
  731. ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
  732. ds_entry->delegation_chain_entry->subject_key = del->subject_key;
  733. if (0 < del->subject_attribute_len)
  734. ds_entry->delegation_chain_entry->subject_attribute =
  735. GNUNET_strdup (del->subject_attribute);
  736. ds_entry->delegation_chain_entry->issuer_key = del->issuer_key;
  737. ds_entry->delegation_chain_entry->issuer_attribute =
  738. GNUNET_strdup (del->issuer_attribute);
  739. // Found new entry, repoting intermediate result
  740. send_intermediate_response (vrh, ds_entry->delegation_chain_entry, false);
  741. // current delegation as parent
  742. ds_entry->parent_queue_entry = dq_entry;
  743. // Check for solution
  744. // if: issuer key we looking for
  745. if (0 == memcmp (&del->issuer_key,
  746. &vrh->issuer_key,
  747. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  748. {
  749. // if: issuer attr we looking for
  750. if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
  751. {
  752. // if: complete match, meaning new trailer == issuer attr
  753. if (0 == strcmp (vrh->issuer_attribute, ds_entry->attr_trailer))
  754. {
  755. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found: Solution\n");
  756. // Add found solution into delegation_chain
  757. struct DelegationSetQueueEntry *tmp_set;
  758. for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
  759. tmp_set = tmp_set->parent_queue_entry->parent_set)
  760. {
  761. if (NULL != tmp_set->delegation_chain_entry)
  762. {
  763. vrh->delegation_chain_size++;
  764. GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
  765. vrh->delegation_chain_tail,
  766. tmp_set->delegation_chain_entry);
  767. }
  768. }
  769. // Increase refcount for this delegate
  770. for (struct DelegateRecordEntry *del_entry = vrh->del_chain_head;
  771. del_entry != NULL;
  772. del_entry = del_entry->next)
  773. {
  774. if (0 == memcmp (&del_entry->delegate->issuer_key,
  775. &vrh->delegation_chain_head->subject_key,
  776. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  777. {
  778. if (0 == strcmp (del_entry->delegate->issuer_attribute,
  779. vrh->delegation_chain_head->subject_attribute))
  780. {
  781. del_entry->refcount++;
  782. }
  783. }
  784. }
  785. send_lookup_response (vrh);
  786. return;
  787. }
  788. }
  789. }
  790. // Check for bidirectional crossmatch
  791. for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
  792. del_entry != NULL;
  793. del_entry = del_entry->next)
  794. {
  795. // only check entries not by backward algorithm
  796. if (del_entry->from_bw)
  797. {
  798. // key of list entry matches actual key
  799. if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key,
  800. &ds_entry->delegation_chain_entry->issuer_key,
  801. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  802. {
  803. // compare entry subject attributes to this trailer (iss attr + old trailer)
  804. if (0 == strcmp (del_entry->unresolved_attribute_delegation,
  805. ds_entry->attr_trailer))
  806. {
  807. print_deleset (del_entry, "Forward:");
  808. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  809. "Forward: Found match with above!\n");
  810. // one node on the path still needs solutions: return
  811. if (GNUNET_NO ==
  812. handle_bidirectional_match (ds_entry, del_entry, vrh))
  813. return;
  814. send_lookup_response (vrh);
  815. return;
  816. }
  817. }
  818. }
  819. }
  820. // Starting a new GNS lookup
  821. vrh->pending_lookups++;
  822. ds_entry->handle = vrh;
  823. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  824. "Starting to look up trailer %s in zone %s\n",
  825. ds_entry->attr_trailer,
  826. GNUNET_CRYPTO_ecdsa_public_key_to_string (&del->issuer_key));
  827. ds_entry->lookup_request =
  828. GNUNET_GNS_lookup (gns,
  829. GNUNET_GNS_EMPTY_LABEL_AT,
  830. &del->issuer_key,
  831. GNUNET_GNSRECORD_TYPE_DELEGATE,
  832. GNUNET_GNS_LO_DEFAULT,
  833. &forward_resolution,
  834. ds_entry);
  835. }
  836. if (0 == vrh->pending_lookups)
  837. {
  838. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
  839. send_lookup_response (vrh);
  840. return;
  841. }
  842. }
  843. static void
  844. backward_resolution (void *cls,
  845. uint32_t rd_count,
  846. const struct GNUNET_GNSRECORD_Data *rd)
  847. {
  848. struct VerifyRequestHandle *vrh;
  849. const struct GNUNET_ABD_DelegationRecord *sets;
  850. struct DelegateRecordEntry *del_pointer;
  851. struct DelegationSetQueueEntry *current_set;
  852. struct DelegationSetQueueEntry *ds_entry;
  853. struct DelegationSetQueueEntry *tmp_set;
  854. struct DelegationQueueEntry *dq_entry;
  855. char *expanded_attr;
  856. char *lookup_attribute;
  857. current_set = cls;
  858. current_set->lookup_request = NULL;
  859. vrh = current_set->handle;
  860. vrh->pending_lookups--;
  861. // Each OR
  862. for (uint32_t i = 0; i < rd_count; i++)
  863. {
  864. if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
  865. continue;
  866. sets = rd[i].data;
  867. struct GNUNET_ABD_DelegationSet set[ntohl (sets->set_count)];
  868. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  869. "Found new attribute delegation with %d sets. Creating new Job...\n",
  870. ntohl (sets->set_count));
  871. if (GNUNET_OK !=
  872. GNUNET_ABD_delegation_set_deserialize (GNUNET_ntohll (
  873. sets->data_size),
  874. (const char *) &sets[1],
  875. ntohl (sets->set_count),
  876. set))
  877. {
  878. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to deserialize!\n");
  879. continue;
  880. }
  881. dq_entry = GNUNET_new (struct DelegationQueueEntry);
  882. dq_entry->required_solutions = ntohl (sets->set_count);
  883. dq_entry->parent_set = current_set;
  884. GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
  885. current_set->queue_entries_tail,
  886. dq_entry);
  887. // Each AND
  888. for (uint32_t j = 0; j < ntohl (sets->set_count); j++)
  889. {
  890. ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
  891. GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
  892. ds_entry->from_bw = true;
  893. if (NULL != current_set->attr_trailer)
  894. {
  895. if (0 == set[j].subject_attribute_len)
  896. {
  897. GNUNET_asprintf (&expanded_attr, "%s", current_set->attr_trailer);
  898. }
  899. else
  900. {
  901. GNUNET_asprintf (&expanded_attr,
  902. "%s.%s",
  903. set[j].subject_attribute,
  904. current_set->attr_trailer);
  905. }
  906. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expanded to %s\n", expanded_attr);
  907. ds_entry->unresolved_attribute_delegation = expanded_attr;
  908. }
  909. else
  910. {
  911. if (0 != set[j].subject_attribute_len)
  912. {
  913. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  914. "Not Expanding %s\n",
  915. set[j].subject_attribute);
  916. ds_entry->unresolved_attribute_delegation =
  917. GNUNET_strdup (set[j].subject_attribute);
  918. }
  919. }
  920. // Add a credential chain entry
  921. ds_entry->delegation_chain_entry =
  922. GNUNET_new (struct DelegationChainEntry);
  923. ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
  924. ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
  925. GNUNET_memcpy (ds_entry->issuer_key,
  926. &set[j].subject_key,
  927. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
  928. if (0 < set[j].subject_attribute_len)
  929. ds_entry->delegation_chain_entry->subject_attribute =
  930. GNUNET_strdup (set[j].subject_attribute);
  931. ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
  932. ds_entry->delegation_chain_entry->issuer_attribute =
  933. GNUNET_strdup (current_set->lookup_attribute);
  934. // Found new entry, repoting intermediate result
  935. send_intermediate_response (vrh, ds_entry->delegation_chain_entry, true);
  936. ds_entry->parent_queue_entry = dq_entry; // current_delegation;
  937. /**
  938. * Check if this delegation already matches one of our credentials
  939. */
  940. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking for cred match\n");
  941. for (del_pointer = vrh->del_chain_head; del_pointer != NULL;
  942. del_pointer = del_pointer->next)
  943. {
  944. // If key and attribute match credential: continue and backtrack
  945. if (0 != memcmp (&set[j].subject_key,
  946. &del_pointer->delegate->issuer_key,
  947. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  948. continue;
  949. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  950. "Checking if %s matches %s\n",
  951. ds_entry->unresolved_attribute_delegation,
  952. del_pointer->delegate->issuer_attribute);
  953. if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
  954. del_pointer->delegate->issuer_attribute))
  955. continue;
  956. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found issuer\n");
  957. // increase refcount of the start delegation
  958. del_pointer->refcount++;
  959. // Backtrack
  960. for (tmp_set = ds_entry; NULL != tmp_set->parent_queue_entry;
  961. tmp_set = tmp_set->parent_queue_entry->parent_set)
  962. {
  963. tmp_set->parent_queue_entry->required_solutions--;
  964. if (NULL != tmp_set->delegation_chain_entry)
  965. {
  966. vrh->delegation_chain_size++;
  967. GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
  968. vrh->delegation_chain_tail,
  969. tmp_set->delegation_chain_entry);
  970. }
  971. if (0 < tmp_set->parent_queue_entry->required_solutions)
  972. break;
  973. }
  974. // if the break above is not called the condition of the for is met
  975. if (NULL == tmp_set->parent_queue_entry)
  976. {
  977. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All solutions found\n");
  978. // Found match
  979. send_lookup_response (vrh);
  980. return;
  981. }
  982. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not all solutions found yet.\n");
  983. continue;
  984. }
  985. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  986. "Building new lookup request from %s\n",
  987. ds_entry->unresolved_attribute_delegation);
  988. // Continue with next/new backward resolution
  989. char issuer_attribute_name[strlen (
  990. ds_entry->unresolved_attribute_delegation)
  991. + 1];
  992. strcpy (issuer_attribute_name, ds_entry->unresolved_attribute_delegation);
  993. char *next_attr = strtok (issuer_attribute_name, ".");
  994. if (NULL == next_attr)
  995. {
  996. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  997. "Failed to parse next attribute\n");
  998. continue;
  999. }
  1000. GNUNET_asprintf (&lookup_attribute, "%s", next_attr);
  1001. GNUNET_asprintf (&ds_entry->lookup_attribute, "%s", next_attr);
  1002. if (strlen (next_attr) ==
  1003. strlen (ds_entry->unresolved_attribute_delegation))
  1004. {
  1005. ds_entry->attr_trailer = NULL;
  1006. }
  1007. else
  1008. {
  1009. next_attr += strlen (next_attr) + 1;
  1010. ds_entry->attr_trailer = GNUNET_strdup (next_attr);
  1011. }
  1012. // Check for bidirectional crossmatch
  1013. for (struct DelegationSetQueueEntry *del_entry = vrh->dsq_head;
  1014. del_entry != NULL;
  1015. del_entry = del_entry->next)
  1016. {
  1017. // only check entries added by forward algorithm
  1018. if (! del_entry->from_bw)
  1019. {
  1020. // key of list entry matches actual key
  1021. if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key,
  1022. &ds_entry->delegation_chain_entry->subject_key,
  1023. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  1024. {
  1025. // compare entry subject attributes to this trailer (iss attr + old trailer)
  1026. if (0 == strcmp (del_entry->attr_trailer,
  1027. ds_entry->unresolved_attribute_delegation))
  1028. {
  1029. print_deleset (del_entry, "Backward:");
  1030. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1031. "Backward: Found match with above!\n");
  1032. // if one node on the path still needs solutions: return
  1033. if (GNUNET_NO ==
  1034. handle_bidirectional_match (del_entry, ds_entry, vrh))
  1035. break;
  1036. // Send lookup response
  1037. send_lookup_response (vrh);
  1038. return;
  1039. }
  1040. }
  1041. }
  1042. }
  1043. // Starting a new GNS lookup
  1044. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1045. "Looking up %s\n",
  1046. ds_entry->lookup_attribute);
  1047. if (NULL != ds_entry->attr_trailer)
  1048. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1049. "%s still to go...\n",
  1050. ds_entry->attr_trailer);
  1051. vrh->pending_lookups++;
  1052. ds_entry->handle = vrh;
  1053. ds_entry->lookup_request =
  1054. GNUNET_GNS_lookup (gns,
  1055. lookup_attribute,
  1056. ds_entry->issuer_key, // issuer_key,
  1057. GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
  1058. GNUNET_GNS_LO_DEFAULT,
  1059. &backward_resolution,
  1060. ds_entry);
  1061. GNUNET_free (lookup_attribute);
  1062. }
  1063. }
  1064. if (0 == vrh->pending_lookups)
  1065. {
  1066. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We are all out of attributes...\n");
  1067. send_lookup_response (vrh);
  1068. return;
  1069. }
  1070. }
  1071. /**
  1072. * Result from GNS lookup.
  1073. *
  1074. * @param cls the closure (our client lookup handle)
  1075. */
  1076. static int
  1077. delegation_chain_bw_resolution_start (void *cls)
  1078. {
  1079. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Backward Resolution...\n");
  1080. struct VerifyRequestHandle *vrh = cls;
  1081. struct DelegationSetQueueEntry *ds_entry;
  1082. struct DelegateRecordEntry *del_entry;
  1083. if (0 == vrh->del_chain_size)
  1084. {
  1085. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegates found\n");
  1086. send_lookup_response (vrh);
  1087. return 1;
  1088. }
  1089. // Pre-check with vrh->dele_chain_.. if match issuer_key
  1090. // Backward: check every cred entry if match issuer key
  1091. // otherwise: start at issuer and go down till match
  1092. // A.a <- ...
  1093. // X.x <- C
  1094. // Y.y <- C
  1095. // if not X.x or Y.y == A.a start at A
  1096. for (del_entry = vrh->del_chain_head; del_entry != NULL;
  1097. del_entry = del_entry->next)
  1098. {
  1099. if (0 != memcmp (&del_entry->delegate->issuer_key,
  1100. &vrh->issuer_key,
  1101. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  1102. continue;
  1103. if (0 !=
  1104. strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
  1105. continue;
  1106. del_entry->refcount++;
  1107. // Found match prematurely
  1108. send_lookup_response (vrh);
  1109. return 1;
  1110. }
  1111. // Check for attributes from the issuer and follow the chain
  1112. // till you get the required subject's attributes
  1113. char issuer_attribute_name[strlen (vrh->issuer_attribute) + 1];
  1114. strcpy (issuer_attribute_name, vrh->issuer_attribute);
  1115. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1116. "Looking up %s\n",
  1117. issuer_attribute_name);
  1118. ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
  1119. GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
  1120. ds_entry->from_bw = true;
  1121. ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
  1122. GNUNET_memcpy (ds_entry->issuer_key,
  1123. &vrh->issuer_key,
  1124. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
  1125. ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
  1126. ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
  1127. ds_entry->delegation_chain_entry->issuer_key = vrh->issuer_key;
  1128. ds_entry->delegation_chain_entry->issuer_attribute =
  1129. GNUNET_strdup (vrh->issuer_attribute);
  1130. ds_entry->handle = vrh;
  1131. ds_entry->lookup_attribute = GNUNET_strdup (vrh->issuer_attribute);
  1132. ds_entry->unresolved_attribute_delegation = NULL;
  1133. vrh->pending_lookups = 1;
  1134. // Start with backward resolution
  1135. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Backward Resolution\n");
  1136. ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
  1137. issuer_attribute_name,
  1138. &vrh->issuer_key, // issuer_key,
  1139. GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
  1140. GNUNET_GNS_LO_DEFAULT,
  1141. &backward_resolution,
  1142. ds_entry);
  1143. return 0;
  1144. }
  1145. static int
  1146. delegation_chain_fw_resolution_start (void *cls)
  1147. {
  1148. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Start Forward Resolution...\n");
  1149. struct VerifyRequestHandle *vrh = cls;
  1150. struct DelegationSetQueueEntry *ds_entry;
  1151. struct DelegateRecordEntry *del_entry;
  1152. // set to 0 and increase on each lookup: for fw multiple lookups (may be) started
  1153. vrh->pending_lookups = 0;
  1154. if (0 == vrh->del_chain_size)
  1155. {
  1156. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No delegations found\n");
  1157. send_lookup_response (vrh);
  1158. return 1;
  1159. }
  1160. // Pre-check with vrh->dele_chain_.. if match issuer_key
  1161. // otherwise FW: start multiple lookups for each vrh->dele_chain
  1162. // A.a <- ...
  1163. // X.x <- C
  1164. // Y.y <- C
  1165. // if not X.x or Y.y == A.a start at X and at Y
  1166. for (del_entry = vrh->del_chain_head; del_entry != NULL;
  1167. del_entry = del_entry->next)
  1168. {
  1169. if (0 != memcmp (&del_entry->delegate->issuer_key,
  1170. &vrh->issuer_key,
  1171. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
  1172. continue;
  1173. if (0 !=
  1174. strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
  1175. continue;
  1176. del_entry->refcount++;
  1177. // Found match prematurely
  1178. send_lookup_response (vrh);
  1179. return 1;
  1180. }
  1181. // None match, therefore start for every delegation found a lookup chain
  1182. // Return and end collect process on first chain iss <-> sub found
  1183. // ds_entry created belongs to the first lookup, vrh still has the
  1184. // issuer+attr we look for
  1185. for (del_entry = vrh->del_chain_head; del_entry != NULL;
  1186. del_entry = del_entry->next)
  1187. {
  1188. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1189. "Looking for %s.%s\n",
  1190. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  1191. &del_entry->delegate->issuer_key),
  1192. del_entry->delegate->issuer_attribute);
  1193. ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
  1194. GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
  1195. ds_entry->from_bw = false;
  1196. ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
  1197. GNUNET_memcpy (ds_entry->issuer_key,
  1198. &del_entry->delegate->subject_key,
  1199. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
  1200. ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
  1201. ds_entry->delegation_chain_entry->subject_key =
  1202. del_entry->delegate->subject_key;
  1203. ds_entry->delegation_chain_entry->subject_attribute = NULL;
  1204. ds_entry->delegation_chain_entry->issuer_key =
  1205. del_entry->delegate->issuer_key;
  1206. ds_entry->delegation_chain_entry->issuer_attribute =
  1207. GNUNET_strdup (del_entry->delegate->issuer_attribute);
  1208. ds_entry->attr_trailer =
  1209. GNUNET_strdup (del_entry->delegate->issuer_attribute);
  1210. ds_entry->handle = vrh;
  1211. vrh->pending_lookups++;
  1212. // Start with forward resolution
  1213. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start Forward Resolution\n");
  1214. ds_entry->lookup_request =
  1215. GNUNET_GNS_lookup (gns,
  1216. GNUNET_GNS_EMPTY_LABEL_AT,
  1217. &del_entry->delegate->issuer_key, // issuer_key,
  1218. GNUNET_GNSRECORD_TYPE_DELEGATE,
  1219. GNUNET_GNS_LO_DEFAULT,
  1220. &forward_resolution,
  1221. ds_entry);
  1222. }
  1223. return 0;
  1224. }
  1225. static int
  1226. check_verify (void *cls, const struct VerifyMessage *v_msg)
  1227. {
  1228. size_t msg_size;
  1229. const char *attr;
  1230. msg_size = ntohs (v_msg->header.size);
  1231. if (msg_size < sizeof (struct VerifyMessage))
  1232. {
  1233. GNUNET_break (0);
  1234. return GNUNET_SYSERR;
  1235. }
  1236. if (ntohs (v_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
  1237. {
  1238. GNUNET_break (0);
  1239. return GNUNET_SYSERR;
  1240. }
  1241. attr = (const char *) &v_msg[1];
  1242. if (strlen (attr) > GNUNET_ABD_MAX_LENGTH)
  1243. {
  1244. GNUNET_break (0);
  1245. return GNUNET_SYSERR;
  1246. }
  1247. return GNUNET_OK;
  1248. }
  1249. static void
  1250. handle_verify (void *cls, const struct VerifyMessage *v_msg)
  1251. {
  1252. struct VerifyRequestHandle *vrh;
  1253. struct GNUNET_SERVICE_Client *client = cls;
  1254. struct DelegateRecordEntry *del_entry;
  1255. uint32_t delegate_count;
  1256. uint32_t delegate_data_size;
  1257. char attr[GNUNET_ABD_MAX_LENGTH + 1];
  1258. char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
  1259. char *attrptr = attr;
  1260. char *delegate_data;
  1261. const char *utf_in;
  1262. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received VERIFY message\n");
  1263. utf_in = (const char *) &v_msg[1];
  1264. GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
  1265. GNUNET_memcpy (issuer_attribute, attr, ntohs (v_msg->issuer_attribute_len));
  1266. issuer_attribute[ntohs (v_msg->issuer_attribute_len)] = '\0';
  1267. vrh = GNUNET_new (struct VerifyRequestHandle);
  1268. vrh->is_collect = false;
  1269. GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
  1270. vrh->client = client;
  1271. vrh->request_id = v_msg->id;
  1272. vrh->issuer_key = v_msg->issuer_key;
  1273. vrh->subject_key = v_msg->subject_key;
  1274. vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
  1275. vrh->resolution_algo = ntohs (v_msg->resolution_algo);
  1276. vrh->del_chain_head = NULL;
  1277. vrh->del_chain_tail = NULL;
  1278. vrh->dsq_head = NULL;
  1279. vrh->dsq_tail = NULL;
  1280. vrh->del_chain_head = NULL;
  1281. vrh->del_chain_tail = NULL;
  1282. GNUNET_SERVICE_client_continue (vrh->client);
  1283. if (0 == strlen (issuer_attribute))
  1284. {
  1285. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
  1286. send_lookup_response (vrh);
  1287. return;
  1288. }
  1289. // Parse delegates from verifaction message
  1290. delegate_count = ntohl (v_msg->d_count);
  1291. delegate_data_size = ntohs (v_msg->header.size)
  1292. - sizeof (struct VerifyMessage)
  1293. - ntohs (v_msg->issuer_attribute_len) - 1;
  1294. struct GNUNET_ABD_Delegate delegates[delegate_count];
  1295. memset (delegates,
  1296. 0,
  1297. sizeof (struct GNUNET_ABD_Delegate) * delegate_count);
  1298. delegate_data = (char *) &v_msg[1] + ntohs (v_msg->issuer_attribute_len) + 1;
  1299. if (GNUNET_OK != GNUNET_ABD_delegates_deserialize (delegate_data_size,
  1300. delegate_data,
  1301. delegate_count,
  1302. delegates))
  1303. {
  1304. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot deserialize delegates!\n");
  1305. send_lookup_response (vrh);
  1306. return;
  1307. }
  1308. // Prepare vrh delegation chain for later validation
  1309. for (uint32_t i = 0; i < delegate_count; i++)
  1310. {
  1311. del_entry = GNUNET_new (struct DelegateRecordEntry);
  1312. del_entry->delegate =
  1313. GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate)
  1314. + delegates[i].issuer_attribute_len + 1);
  1315. GNUNET_memcpy (del_entry->delegate,
  1316. &delegates[i],
  1317. sizeof (struct GNUNET_ABD_Delegate));
  1318. GNUNET_memcpy (&del_entry->delegate[1],
  1319. delegates[i].issuer_attribute,
  1320. delegates[i].issuer_attribute_len);
  1321. del_entry->delegate->issuer_attribute_len =
  1322. delegates[i].issuer_attribute_len;
  1323. del_entry->delegate->issuer_attribute = (char *) &del_entry->delegate[1];
  1324. GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
  1325. vrh->del_chain_tail,
  1326. del_entry);
  1327. vrh->del_chain_size++;
  1328. }
  1329. // Switch resolution algo
  1330. if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
  1331. GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
  1332. {
  1333. if (1 == delegation_chain_fw_resolution_start (vrh))
  1334. return;
  1335. delegation_chain_bw_resolution_start (vrh);
  1336. }
  1337. else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
  1338. {
  1339. delegation_chain_bw_resolution_start (vrh);
  1340. }
  1341. else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
  1342. {
  1343. delegation_chain_fw_resolution_start (vrh);
  1344. }
  1345. }
  1346. static void
  1347. handle_delegate_collection_error_cb (void *cls)
  1348. {
  1349. struct VerifyRequestHandle *vrh = cls;
  1350. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1351. "Got disconnected from namestore database.\n");
  1352. vrh->dele_qe = NULL;
  1353. send_lookup_response (vrh);
  1354. }
  1355. static void
  1356. delegate_collection_finished (void *cls)
  1357. {
  1358. struct VerifyRequestHandle *vrh = cls;
  1359. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done collecting delegates.\n");
  1360. // if both are set: bidirectional search, meaning start both chain resolutions
  1361. if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo &&
  1362. GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
  1363. {
  1364. // if premature match found don't start bw resolution
  1365. if (1 == delegation_chain_fw_resolution_start (vrh))
  1366. return;
  1367. delegation_chain_bw_resolution_start (vrh);
  1368. }
  1369. else if (GNUNET_ABD_FLAG_BACKWARD & vrh->resolution_algo)
  1370. {
  1371. delegation_chain_bw_resolution_start (vrh);
  1372. }
  1373. else if (GNUNET_ABD_FLAG_FORWARD & vrh->resolution_algo)
  1374. {
  1375. delegation_chain_fw_resolution_start (vrh);
  1376. }
  1377. }
  1378. static void
  1379. handle_delegate_collection_cb (void *cls,
  1380. const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
  1381. const char *label,
  1382. unsigned int rd_count,
  1383. const struct GNUNET_GNSRECORD_Data *rd)
  1384. {
  1385. struct VerifyRequestHandle *vrh = cls;
  1386. struct GNUNET_ABD_Delegate *del;
  1387. struct DelegateRecordEntry *del_entry;
  1388. int cred_record_count;
  1389. cred_record_count = 0;
  1390. vrh->dele_qe = NULL;
  1391. for (uint32_t i = 0; i < rd_count; i++)
  1392. {
  1393. if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
  1394. continue;
  1395. cred_record_count++;
  1396. del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
  1397. if (NULL == del)
  1398. {
  1399. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
  1400. continue;
  1401. }
  1402. // only add the entries that are explicitly marked as private
  1403. // and therefore symbolize the end of a chain
  1404. if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)
  1405. {
  1406. del_entry = GNUNET_new (struct DelegateRecordEntry);
  1407. del_entry->delegate = del;
  1408. GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
  1409. vrh->del_chain_tail,
  1410. del_entry);
  1411. vrh->del_chain_size++;
  1412. }
  1413. }
  1414. delegate_collection_finished (vrh);
  1415. }
  1416. static void
  1417. handle_collect (void *cls, const struct CollectMessage *c_msg)
  1418. {
  1419. char attr[GNUNET_ABD_MAX_LENGTH + 1];
  1420. char issuer_attribute[GNUNET_ABD_MAX_LENGTH + 1];
  1421. struct VerifyRequestHandle *vrh;
  1422. struct GNUNET_SERVICE_Client *client = cls;
  1423. char *attrptr = attr;
  1424. const char *utf_in;
  1425. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received COLLECT message\n");
  1426. utf_in = (const char *) &c_msg[1];
  1427. GNUNET_STRINGS_utf8_tolower (utf_in, attrptr);
  1428. GNUNET_memcpy (issuer_attribute, attr, ntohs (c_msg->issuer_attribute_len));
  1429. issuer_attribute[ntohs (c_msg->issuer_attribute_len)] = '\0';
  1430. vrh = GNUNET_new (struct VerifyRequestHandle);
  1431. vrh->is_collect = true;
  1432. GNUNET_CONTAINER_DLL_insert (vrh_head, vrh_tail, vrh);
  1433. vrh->client = client;
  1434. vrh->request_id = c_msg->id;
  1435. vrh->issuer_key = c_msg->issuer_key;
  1436. GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, &vrh->subject_key);
  1437. vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
  1438. vrh->resolution_algo = ntohs (c_msg->resolution_algo);
  1439. vrh->del_chain_head = NULL;
  1440. vrh->del_chain_tail = NULL;
  1441. vrh->dsq_head = NULL;
  1442. vrh->dsq_tail = NULL;
  1443. vrh->del_chain_head = NULL;
  1444. vrh->del_chain_tail = NULL;
  1445. if (0 == strlen (issuer_attribute))
  1446. {
  1447. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer attribute provided!\n");
  1448. send_lookup_response (vrh);
  1449. return;
  1450. }
  1451. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting delegates for subject\n");
  1452. // Get all delegates from subject
  1453. vrh->dele_qe =
  1454. GNUNET_NAMESTORE_records_lookup (namestore,
  1455. &c_msg->subject_key,
  1456. GNUNET_GNS_EMPTY_LABEL_AT,
  1457. &handle_delegate_collection_error_cb,
  1458. vrh,
  1459. &handle_delegate_collection_cb,
  1460. vrh);
  1461. GNUNET_SERVICE_client_continue (vrh->client);
  1462. }
  1463. static int
  1464. check_collect (void *cls, const struct CollectMessage *c_msg)
  1465. {
  1466. size_t msg_size;
  1467. const char *attr;
  1468. msg_size = ntohs (c_msg->header.size);
  1469. if (msg_size < sizeof (struct CollectMessage))
  1470. {
  1471. GNUNET_break (0);
  1472. return GNUNET_SYSERR;
  1473. }
  1474. if (ntohs (c_msg->issuer_attribute_len) > GNUNET_ABD_MAX_LENGTH)
  1475. {
  1476. GNUNET_break (0);
  1477. return GNUNET_SYSERR;
  1478. }
  1479. attr = (const char *) &c_msg[1];
  1480. if (('\0' != attr[msg_size - sizeof (struct CollectMessage) - 1]) ||
  1481. (strlen (attr) > GNUNET_ABD_MAX_LENGTH))
  1482. {
  1483. GNUNET_break (0);
  1484. return GNUNET_SYSERR;
  1485. }
  1486. return GNUNET_OK;
  1487. }
  1488. static void
  1489. client_disconnect_cb (void *cls,
  1490. struct GNUNET_SERVICE_Client *client,
  1491. void *app_ctx)
  1492. {
  1493. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
  1494. }
  1495. static void *
  1496. client_connect_cb (void *cls,
  1497. struct GNUNET_SERVICE_Client *client,
  1498. struct GNUNET_MQ_Handle *mq)
  1499. {
  1500. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
  1501. return client;
  1502. }
  1503. /**
  1504. * Process Credential requests.
  1505. *
  1506. * @param cls closure
  1507. * @param c configuration to use
  1508. * @param handle service handle
  1509. */
  1510. static void
  1511. run (void *cls,
  1512. const struct GNUNET_CONFIGURATION_Handle *c,
  1513. struct GNUNET_SERVICE_Handle *handle)
  1514. {
  1515. gns = GNUNET_GNS_connect (c);
  1516. if (NULL == gns)
  1517. {
  1518. fprintf (stderr, _ ("Failed to connect to GNS\n"));
  1519. }
  1520. namestore = GNUNET_NAMESTORE_connect (c);
  1521. if (NULL == namestore)
  1522. {
  1523. fprintf (stderr, _ ("Failed to connect to namestore\n"));
  1524. }
  1525. statistics = GNUNET_STATISTICS_create ("abd", c);
  1526. GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
  1527. }
  1528. /**
  1529. * Define "main" method using service macro
  1530. */
  1531. GNUNET_SERVICE_MAIN (
  1532. "abd",
  1533. GNUNET_SERVICE_OPTION_NONE,
  1534. &run,
  1535. &client_connect_cb,
  1536. &client_disconnect_cb,
  1537. NULL,
  1538. GNUNET_MQ_hd_var_size (verify,
  1539. GNUNET_MESSAGE_TYPE_ABD_VERIFY,
  1540. struct VerifyMessage,
  1541. NULL),
  1542. GNUNET_MQ_hd_var_size (collect,
  1543. GNUNET_MESSAGE_TYPE_ABD_COLLECT,
  1544. struct CollectMessage,
  1545. NULL),
  1546. GNUNET_MQ_handler_end ());
  1547. /* end of gnunet-service-abd.c */