1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168 |
- #define HS_SERVICE_PRIVATE
- #include "core/or/or.h"
- #include "app/config/config.h"
- #include "app/config/statefile.h"
- #include "core/mainloop/connection.h"
- #include "core/mainloop/mainloop.h"
- #include "core/or/circuitbuild.h"
- #include "core/or/circuitlist.h"
- #include "core/or/circuituse.h"
- #include "core/or/relay.h"
- #include "feature/client/circpathbias.h"
- #include "feature/dirclient/dirclient.h"
- #include "feature/dircommon/directory.h"
- #include "feature/hs_common/shared_random_client.h"
- #include "feature/keymgt/loadkey.h"
- #include "feature/nodelist/describe.h"
- #include "feature/nodelist/networkstatus.h"
- #include "feature/nodelist/nickname.h"
- #include "feature/nodelist/node_select.h"
- #include "feature/nodelist/nodelist.h"
- #include "feature/rend/rendservice.h"
- #include "lib/crypt_ops/crypto_ope.h"
- #include "lib/crypt_ops/crypto_rand.h"
- #include "lib/crypt_ops/crypto_rand.h"
- #include "lib/crypt_ops/crypto_util.h"
- #include "feature/hs/hs_circuit.h"
- #include "feature/hs/hs_common.h"
- #include "feature/hs/hs_config.h"
- #include "feature/hs/hs_control.h"
- #include "feature/hs/hs_descriptor.h"
- #include "feature/hs/hs_ident.h"
- #include "feature/hs/hs_intropoint.h"
- #include "feature/hs/hs_service.h"
- #include "feature/hs/hs_stats.h"
- #include "feature/dircommon/dir_connection_st.h"
- #include "core/or/edge_connection_st.h"
- #include "core/or/extend_info_st.h"
- #include "feature/nodelist/networkstatus_st.h"
- #include "feature/nodelist/node_st.h"
- #include "core/or/origin_circuit_st.h"
- #include "app/config/or_state_st.h"
- #include "feature/nodelist/routerstatus_st.h"
- #include "lib/encoding/confline.h"
- #include "lib/crypt_ops/crypto_format.h"
- #include "trunnel/ed25519_cert.h"
- #include "trunnel/hs/cell_common.h"
- #include "trunnel/hs/cell_establish_intro.h"
- #ifdef HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #define FOR_EACH_SERVICE_BEGIN(var) \
- STMT_BEGIN \
- hs_service_t **var##_iter, *var; \
- HT_FOREACH(var##_iter, hs_service_ht, hs_service_map) { \
- var = *var##_iter;
- #define FOR_EACH_SERVICE_END } STMT_END ;
- #define FOR_EACH_DESCRIPTOR_BEGIN(service, var) \
- STMT_BEGIN \
- hs_service_descriptor_t *var; \
- for (int var ## _loop_idx = 0; var ## _loop_idx < 2; \
- ++var ## _loop_idx) { \
- (var ## _loop_idx == 0) ? (var = service->desc_current) : \
- (var = service->desc_next); \
- if (var == NULL) continue;
- #define FOR_EACH_DESCRIPTOR_END } STMT_END ;
- static const char fname_keyfile_prefix[] = "hs_ed25519";
- static const char dname_client_pubkeys[] = "authorized_clients";
- static const char fname_hostname[] = "hostname";
- static const char address_tld[] = "onion";
- static smartlist_t *hs_service_staging_list;
- static int consider_republishing_hs_descriptors = 0;
- static int load_client_keys(hs_service_t *service);
- static void set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc,
- time_t now, bool is_current);
- static int build_service_desc_superencrypted(const hs_service_t *service,
- hs_service_descriptor_t *desc);
- static void move_descriptors(hs_service_t *src, hs_service_t *dst);
- static int service_encode_descriptor(const hs_service_t *service,
- const hs_service_descriptor_t *desc,
- const ed25519_keypair_t *signing_kp,
- char **encoded_out);
- static inline int
- hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second)
- {
- tor_assert(first);
- tor_assert(second);
-
- return ed25519_pubkey_eq(&first->keys.identity_pk,
- &second->keys.identity_pk);
- }
- static inline unsigned int
- hs_service_ht_hash(const hs_service_t *service)
- {
- tor_assert(service);
- return (unsigned int) siphash24g(service->keys.identity_pk.pubkey,
- sizeof(service->keys.identity_pk.pubkey));
- }
- static struct hs_service_ht *hs_service_map;
- HT_PROTOTYPE(hs_service_ht,
- hs_service_t,
- hs_service_node,
- hs_service_ht_hash,
- hs_service_ht_eq)
- HT_GENERATE2(hs_service_ht, hs_service_t, hs_service_node,
- hs_service_ht_hash, hs_service_ht_eq,
- 0.6, tor_reallocarray, tor_free_)
- STATIC hs_service_t *
- find_service(hs_service_ht *map, const ed25519_public_key_t *pk)
- {
- hs_service_t dummy_service;
- tor_assert(map);
- tor_assert(pk);
- memset(&dummy_service, 0, sizeof(dummy_service));
- ed25519_pubkey_copy(&dummy_service.keys.identity_pk, pk);
- return HT_FIND(hs_service_ht, map, &dummy_service);
- }
- STATIC int
- register_service(hs_service_ht *map, hs_service_t *service)
- {
- tor_assert(map);
- tor_assert(service);
- tor_assert(!ed25519_public_key_is_zero(&service->keys.identity_pk));
- if (find_service(map, &service->keys.identity_pk)) {
-
- return -1;
- }
-
- HT_INSERT(hs_service_ht, map, service);
-
- if (map == hs_service_map) {
- hs_service_map_has_changed();
- }
- return 0;
- }
- STATIC void
- remove_service(hs_service_ht *map, hs_service_t *service)
- {
- hs_service_t *elm;
- tor_assert(map);
-
- if (BUG(service == NULL) ||
- BUG(ed25519_public_key_is_zero(&service->keys.identity_pk))) {
- return;
- }
- elm = HT_REMOVE(hs_service_ht, map, service);
- if (elm) {
- tor_assert(elm == service);
- } else {
- log_warn(LD_BUG, "Could not find service in the global map "
- "while removing service %s",
- escaped(service->config.directory_path));
- }
-
- if (map == hs_service_map) {
- hs_service_map_has_changed();
- }
- }
- static void
- set_service_default_config(hs_service_config_t *c,
- const or_options_t *options)
- {
- (void) options;
- tor_assert(c);
- c->ports = smartlist_new();
- c->directory_path = NULL;
- c->max_streams_per_rdv_circuit = 0;
- c->max_streams_close_circuit = 0;
- c->num_intro_points = NUM_INTRO_POINTS_DEFAULT;
- c->allow_unknown_ports = 0;
- c->is_single_onion = 0;
- c->dir_group_readable = 0;
- c->is_ephemeral = 0;
- }
- STATIC void
- service_clear_config(hs_service_config_t *config)
- {
- if (config == NULL) {
- return;
- }
- tor_free(config->directory_path);
- if (config->ports) {
- SMARTLIST_FOREACH(config->ports, rend_service_port_config_t *, p,
- rend_service_port_config_free(p););
- smartlist_free(config->ports);
- }
- if (config->clients) {
- SMARTLIST_FOREACH(config->clients, hs_service_authorized_client_t *, p,
- service_authorized_client_free(p));
- smartlist_free(config->clients);
- }
- memset(config, 0, sizeof(*config));
- }
- static const char *
- describe_intro_point(const hs_service_intro_point_t *ip)
- {
-
- static char buf[HEX_DIGEST_LEN + 2];
- const char *legacy_id = NULL;
- SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers,
- const hs_desc_link_specifier_t *, lspec) {
- if (lspec->type == LS_LEGACY_ID) {
- legacy_id = (const char *) lspec->u.legacy_id;
- break;
- }
- } SMARTLIST_FOREACH_END(lspec);
-
- buf[0] = '$';
- if (legacy_id) {
- base16_encode(buf + 1, HEX_DIGEST_LEN + 1, legacy_id, DIGEST_LEN);
- }
- return buf;
- }
- static int32_t
- get_intro_point_min_introduce2(void)
- {
-
- return networkstatus_get_param(NULL, "hs_intro_min_introduce2",
- INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS,
- 0, INT32_MAX);
- }
- static int32_t
- get_intro_point_max_introduce2(void)
- {
-
- return networkstatus_get_param(NULL, "hs_intro_max_introduce2",
- INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS,
- 0, INT32_MAX);
- }
- static int32_t
- get_intro_point_min_lifetime(void)
- {
- #define MIN_INTRO_POINT_LIFETIME_TESTING 10
- if (get_options()->TestingTorNetwork) {
- return MIN_INTRO_POINT_LIFETIME_TESTING;
- }
-
- return networkstatus_get_param(NULL, "hs_intro_min_lifetime",
- INTRO_POINT_LIFETIME_MIN_SECONDS,
- 0, INT32_MAX);
- }
- static int32_t
- get_intro_point_max_lifetime(void)
- {
- #define MAX_INTRO_POINT_LIFETIME_TESTING 30
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_LIFETIME_TESTING;
- }
-
- return networkstatus_get_param(NULL, "hs_intro_max_lifetime",
- INTRO_POINT_LIFETIME_MAX_SECONDS,
- 0, INT32_MAX);
- }
- static int32_t
- get_intro_point_num_extra(void)
- {
-
- return networkstatus_get_param(NULL, "hs_intro_num_extra",
- NUM_INTRO_POINTS_EXTRA, 0, 128);
- }
- static int
- ht_free_service_(struct hs_service_t *service, void *data)
- {
- (void) data;
- hs_service_free(service);
-
- return 1;
- }
- static void
- service_free_all(void)
- {
- if (hs_service_map) {
-
- hs_service_ht_HT_FOREACH_FN(hs_service_map, ht_free_service_, NULL);
- HT_CLEAR(hs_service_ht, hs_service_map);
- tor_free(hs_service_map);
- hs_service_map = NULL;
- }
- if (hs_service_staging_list) {
-
- SMARTLIST_FOREACH(hs_service_staging_list, hs_service_t *, s,
- hs_service_free(s));
- smartlist_free(hs_service_staging_list);
- hs_service_staging_list = NULL;
- }
- }
- STATIC void
- service_intro_point_free_(hs_service_intro_point_t *ip)
- {
- if (!ip) {
- return;
- }
- memwipe(&ip->auth_key_kp, 0, sizeof(ip->auth_key_kp));
- memwipe(&ip->enc_key_kp, 0, sizeof(ip->enc_key_kp));
- crypto_pk_free(ip->legacy_key);
- replaycache_free(ip->replay_cache);
- hs_intropoint_clear(&ip->base);
- tor_free(ip);
- }
- static void
- service_intro_point_free_void(void *obj)
- {
- service_intro_point_free_(obj);
- }
- STATIC hs_service_intro_point_t *
- service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy,
- unsigned int supports_ed25519_link_handshake_any)
- {
- hs_desc_link_specifier_t *ls;
- hs_service_intro_point_t *ip;
- ip = tor_malloc_zero(sizeof(*ip));
-
- ed25519_keypair_generate(&ip->auth_key_kp, 0);
- {
- int32_t min_introduce2_cells = get_intro_point_min_introduce2();
- int32_t max_introduce2_cells = get_intro_point_max_introduce2();
- if (BUG(max_introduce2_cells < min_introduce2_cells)) {
- goto err;
- }
- ip->introduce2_max = crypto_rand_int_range(min_introduce2_cells,
- max_introduce2_cells);
- }
- {
- int32_t intro_point_min_lifetime = get_intro_point_min_lifetime();
- int32_t intro_point_max_lifetime = get_intro_point_max_lifetime();
- if (BUG(intro_point_max_lifetime < intro_point_min_lifetime)) {
- goto err;
- }
- ip->time_to_expire = approx_time() +
- crypto_rand_int_range(intro_point_min_lifetime,intro_point_max_lifetime);
- }
- ip->replay_cache = replaycache_new(0, 0);
-
- ip->base.link_specifiers = smartlist_new();
-
- curve25519_keypair_generate(&ip->enc_key_kp, 0);
-
- if (is_legacy) {
- ip->base.is_only_legacy = 1;
-
- ip->legacy_key = crypto_pk_new();
- if (crypto_pk_generate_key(ip->legacy_key) < 0) {
- goto err;
- }
- if (crypto_pk_get_digest(ip->legacy_key,
- (char *) ip->legacy_key_digest) < 0) {
- goto err;
- }
- }
- if (ei == NULL) {
- goto done;
- }
-
- ls = hs_desc_link_specifier_new(ei, LS_IPV4);
-
- if (BUG(!ls)) {
- goto err;
- }
- smartlist_add(ip->base.link_specifiers, ls);
- ls = hs_desc_link_specifier_new(ei, LS_LEGACY_ID);
-
- if (BUG(!ls)) {
- goto err;
- }
- smartlist_add(ip->base.link_specifiers, ls);
-
- if (supports_ed25519_link_handshake_any) {
- ls = hs_desc_link_specifier_new(ei, LS_ED25519_ID);
- if (ls) {
- smartlist_add(ip->base.link_specifiers, ls);
- }
- }
-
-
- memcpy(&ip->onion_key, &ei->curve25519_onion_key, sizeof(ip->onion_key));
- done:
- return ip;
- err:
- service_intro_point_free(ip);
- return NULL;
- }
- STATIC void
- service_intro_point_add(digest256map_t *map, hs_service_intro_point_t *ip)
- {
- hs_service_intro_point_t *old_ip_entry;
- tor_assert(map);
- tor_assert(ip);
- old_ip_entry = digest256map_set(map, ip->auth_key_kp.pubkey.pubkey, ip);
-
- tor_assert_nonfatal(!old_ip_entry);
- }
- STATIC void
- service_intro_point_remove(const hs_service_t *service,
- const hs_service_intro_point_t *ip)
- {
- tor_assert(service);
- tor_assert(ip);
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
-
- digest256map_remove(desc->intro_points.map,
- ip->auth_key_kp.pubkey.pubkey);
- } FOR_EACH_DESCRIPTOR_END;
- }
- STATIC hs_service_intro_point_t *
- service_intro_point_find(const hs_service_t *service,
- const ed25519_public_key_t *auth_key)
- {
- hs_service_intro_point_t *ip = NULL;
- tor_assert(service);
- tor_assert(auth_key);
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- if ((ip = digest256map_get(desc->intro_points.map,
- auth_key->pubkey)) != NULL) {
- break;
- }
- } FOR_EACH_DESCRIPTOR_END;
- return ip;
- }
- STATIC hs_service_descriptor_t *
- service_desc_find_by_intro(const hs_service_t *service,
- const hs_service_intro_point_t *ip)
- {
- hs_service_descriptor_t *descp = NULL;
- tor_assert(service);
- tor_assert(ip);
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- if (digest256map_get(desc->intro_points.map,
- ip->auth_key_kp.pubkey.pubkey)) {
- descp = desc;
- break;
- }
- } FOR_EACH_DESCRIPTOR_END;
- return descp;
- }
- STATIC void
- get_objects_from_ident(const hs_ident_circuit_t *ident,
- hs_service_t **service, hs_service_intro_point_t **ip,
- hs_service_descriptor_t **desc)
- {
- hs_service_t *s;
- tor_assert(ident);
-
- s = find_service(hs_service_map, &ident->identity_pk);
- if (s && service) {
- *service = s;
- }
-
- if (s && ip) {
- *ip = service_intro_point_find(s, &ident->intro_auth_pk);
- }
-
- if (s && ip && *ip && desc) {
- *desc = service_desc_find_by_intro(s, *ip);
- }
- }
- static hs_desc_link_specifier_t *
- get_link_spec_by_type(const hs_service_intro_point_t *ip, uint8_t type)
- {
- hs_desc_link_specifier_t *lnk_spec = NULL;
- tor_assert(ip);
- SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers,
- hs_desc_link_specifier_t *, ls) {
- if (ls->type == type) {
- lnk_spec = ls;
- goto end;
- }
- } SMARTLIST_FOREACH_END(ls);
- end:
- return lnk_spec;
- }
- STATIC const node_t *
- get_node_from_intro_point(const hs_service_intro_point_t *ip)
- {
- const hs_desc_link_specifier_t *ls;
- tor_assert(ip);
- ls = get_link_spec_by_type(ip, LS_LEGACY_ID);
- if (BUG(!ls)) {
- return NULL;
- }
-
- return node_get_by_id((const char *) ls->u.legacy_id);
- }
- static extend_info_t *
- get_extend_info_from_intro_point(const hs_service_intro_point_t *ip,
- unsigned int direct_conn)
- {
- extend_info_t *info = NULL;
- const node_t *node;
- tor_assert(ip);
- node = get_node_from_intro_point(ip);
- if (node == NULL) {
-
- goto end;
- }
-
- info = extend_info_from_node(node, direct_conn);
- end:
- return info;
- }
- static unsigned int
- count_desc_circuit_established(const hs_service_descriptor_t *desc)
- {
- unsigned int count = 0;
- tor_assert(desc);
- DIGEST256MAP_FOREACH(desc->intro_points.map, key,
- const hs_service_intro_point_t *, ip) {
- count += ip->circuit_established;
- } DIGEST256MAP_FOREACH_END;
- return count;
- }
- static void
- close_directory_connections(const hs_service_t *service,
- const hs_service_descriptor_t *desc)
- {
- unsigned int count = 0;
- smartlist_t *dir_conns;
- tor_assert(service);
- tor_assert(desc);
-
- dir_conns = connection_list_by_type_purpose(CONN_TYPE_DIR,
- DIR_PURPOSE_UPLOAD_HSDESC);
- SMARTLIST_FOREACH_BEGIN(dir_conns, connection_t *, conn) {
- dir_connection_t *dir_conn = TO_DIR_CONN(conn);
- if (ed25519_pubkey_eq(&dir_conn->hs_ident->identity_pk,
- &service->keys.identity_pk) &&
- ed25519_pubkey_eq(&dir_conn->hs_ident->blinded_pk,
- &desc->blinded_kp.pubkey)) {
- connection_mark_for_close(conn);
- count++;
- continue;
- }
- } SMARTLIST_FOREACH_END(conn);
- log_info(LD_REND, "Closed %u active service directory connections for "
- "descriptor %s of service %s",
- count, safe_str_client(ed25519_fmt(&desc->blinded_kp.pubkey)),
- safe_str_client(service->onion_address));
-
- smartlist_free(dir_conns);
- }
- static void
- close_service_rp_circuits(hs_service_t *service)
- {
- origin_circuit_t *ocirc = NULL;
- tor_assert(service);
-
- while ((ocirc = circuit_get_next_service_rp_circ(ocirc))) {
-
- if (ocirc->hs_ident != NULL &&
- ed25519_pubkey_eq(ô->hs_ident->identity_pk,
- &service->keys.identity_pk)) {
-
- circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
- }
- }
- }
- static void
- close_intro_circuits(hs_service_intropoints_t *intro_points)
- {
- tor_assert(intro_points);
- DIGEST256MAP_FOREACH(intro_points->map, key,
- const hs_service_intro_point_t *, ip) {
- origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
- if (ocirc) {
-
- circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
- }
- } DIGEST256MAP_FOREACH_END;
- }
- static void
- close_service_intro_circuits(hs_service_t *service)
- {
- tor_assert(service);
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- close_intro_circuits(&desc->intro_points);
- } FOR_EACH_DESCRIPTOR_END;
- }
- static void
- close_service_circuits(hs_service_t *service)
- {
- tor_assert(service);
-
- if (BUG(service->config.version < HS_VERSION_THREE)) {
- return;
- }
-
- close_service_intro_circuits(service);
-
- close_service_rp_circuits(service);
- }
- static void
- move_ephemeral_services(hs_service_ht *src, hs_service_ht *dst)
- {
- hs_service_t **iter, **next;
- tor_assert(src);
- tor_assert(dst);
-
- for (iter = HT_START(hs_service_ht, src); iter != NULL; iter = next) {
- hs_service_t *s = *iter;
- if (!s->config.is_ephemeral) {
-
- next = HT_NEXT(hs_service_ht, src, iter);
- continue;
- }
-
- next = HT_NEXT_RMV(hs_service_ht, src, iter);
- if (register_service(dst, s) < 0) {
- log_warn(LD_BUG, "Ephemeral service key is already being used. "
- "Skipping.");
- }
- }
- }
- static const char *
- service_escaped_dir(const hs_service_t *s)
- {
- return (s->config.is_ephemeral) ? "[EPHEMERAL]" :
- escaped(s->config.directory_path);
- }
- static void
- move_hs_state(hs_service_t *src_service, hs_service_t *dst_service)
- {
- tor_assert(src_service);
- tor_assert(dst_service);
- hs_service_state_t *src = &src_service->state;
- hs_service_state_t *dst = &dst_service->state;
-
- dst->intro_circ_retry_started_time = src->intro_circ_retry_started_time;
- dst->num_intro_circ_launched = src->num_intro_circ_launched;
-
- if (dst->replay_cache_rend_cookie != NULL) {
- replaycache_free(dst->replay_cache_rend_cookie);
- }
- dst->replay_cache_rend_cookie = src->replay_cache_rend_cookie;
- dst->next_rotation_time = src->next_rotation_time;
- src->replay_cache_rend_cookie = NULL;
- }
- static void
- register_all_services(void)
- {
- struct hs_service_ht *new_service_map;
- tor_assert(hs_service_staging_list);
-
- new_service_map = tor_malloc_zero(sizeof(*new_service_map));
- HT_INIT(hs_service_ht, new_service_map);
-
- move_ephemeral_services(hs_service_map, new_service_map);
- SMARTLIST_FOREACH_BEGIN(hs_service_staging_list, hs_service_t *, snew) {
- hs_service_t *s;
-
- s = find_service(hs_service_map, &snew->keys.identity_pk);
- if (s) {
-
- move_descriptors(s, snew);
- move_hs_state(s, snew);
-
- remove_service(hs_service_map, s);
- hs_service_free(s);
- }
-
- if (BUG(register_service(new_service_map, snew) < 0)) {
-
- log_warn(LD_BUG, "Unable to register service with directory %s",
- service_escaped_dir(snew));
- SMARTLIST_DEL_CURRENT(hs_service_staging_list, snew);
- hs_service_free(snew);
- }
- } SMARTLIST_FOREACH_END(snew);
-
- FOR_EACH_SERVICE_BEGIN(service) {
- close_service_circuits(service);
- } FOR_EACH_SERVICE_END;
-
- smartlist_clear(hs_service_staging_list);
- service_free_all();
- hs_service_map = new_service_map;
-
- hs_service_map_has_changed();
- }
- STATIC int
- write_address_to_file(const hs_service_t *service, const char *fname_)
- {
- int ret = -1;
- char *fname = NULL;
- char *addr_buf = NULL;
- tor_assert(service);
- tor_assert(fname_);
-
- tor_asprintf(&addr_buf, "%s.%s\n", service->onion_address, address_tld);
-
- fname = hs_path_from_filename(service->config.directory_path, fname_);
- if (write_str_to_file(fname, addr_buf, 0) < 0) {
- log_warn(LD_REND, "Could not write onion address to hostname file %s",
- escaped(fname));
- goto end;
- }
- #ifndef _WIN32
- if (service->config.dir_group_readable) {
-
- if (chmod(fname, S_IRUSR | S_IWUSR | S_IRGRP) < 0) {
- log_warn(LD_FS, "Unable to make onion service hostname file %s "
- "group-readable.", escaped(fname));
- }
- }
- #endif
-
- ret = 0;
- end:
- tor_free(fname);
- tor_free(addr_buf);
- return ret;
- }
- static int
- load_service_keys(hs_service_t *service)
- {
- int ret = -1;
- char *fname = NULL;
- ed25519_keypair_t *kp;
- const hs_service_config_t *config;
- tor_assert(service);
- config = &service->config;
-
- if (hs_check_service_private_dir(get_options()->User,
- config->directory_path,
- config->dir_group_readable, 1) < 0) {
- goto end;
- }
-
- fname = hs_path_from_filename(config->directory_path, fname_keyfile_prefix);
-
- kp = ed_key_init_from_file(fname, INIT_ED_KEY_SPLIT, LOG_INFO, NULL, 0, 0,
- 0, NULL, NULL);
- if (!kp) {
- log_info(LD_REND, "Unable to load keys from %s. Generating it...", fname);
-
- uint32_t key_flags = INIT_ED_KEY_CREATE | INIT_ED_KEY_EXTRA_STRONG |
- INIT_ED_KEY_SPLIT;
- kp = ed_key_init_from_file(fname, key_flags, LOG_WARN, NULL, 0, 0, 0,
- NULL, NULL);
- if (!kp) {
- log_warn(LD_REND, "Unable to generate keys and save in %s.", fname);
- goto end;
- }
- }
-
- ed25519_pubkey_copy(&service->keys.identity_pk, &kp->pubkey);
- memcpy(&service->keys.identity_sk, &kp->seckey,
- sizeof(service->keys.identity_sk));
-
- ed25519_keypair_free(kp);
-
- tor_assert(service->config.version <= UINT8_MAX);
- hs_build_address(&service->keys.identity_pk,
- (uint8_t) service->config.version,
- service->onion_address);
-
- if (write_address_to_file(service, fname_hostname) < 0) {
- goto end;
- }
-
- if (load_client_keys(service) < 0) {
- goto end;
- }
-
- ret = 0;
- end:
- tor_free(fname);
- return ret;
- }
- STATIC int
- client_filename_is_valid(const char *filename)
- {
- int ret = 1;
- const char *valid_extension = ".auth";
- tor_assert(filename);
-
- if (!strcmpend(filename, valid_extension) &&
- strlen(filename) != strlen(valid_extension)) {
- ret = 1;
- } else {
- ret = 0;
- }
- return ret;
- }
- STATIC hs_service_authorized_client_t *
- parse_authorized_client(const char *client_key_str)
- {
- char *auth_type = NULL;
- char *key_type = NULL;
- char *pubkey_b32 = NULL;
- hs_service_authorized_client_t *client = NULL;
- smartlist_t *fields = smartlist_new();
- tor_assert(client_key_str);
- smartlist_split_string(fields, client_key_str, ":",
- SPLIT_SKIP_SPACE, 0);
-
- if (smartlist_len(fields) != 3) {
- log_warn(LD_REND, "Unknown format of client authorization file.");
- goto err;
- }
- auth_type = smartlist_get(fields, 0);
- key_type = smartlist_get(fields, 1);
- pubkey_b32 = smartlist_get(fields, 2);
-
- if (strcmp(auth_type, "descriptor")) {
- log_warn(LD_REND, "Client authorization auth type '%s' not supported.",
- auth_type);
- goto err;
- }
-
- if (strcmp(key_type, "x25519")) {
- log_warn(LD_REND, "Client authorization key type '%s' not supported.",
- key_type);
- goto err;
- }
-
- if (strlen(pubkey_b32) != BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)) {
- log_warn(LD_REND, "Client authorization encoded base32 public key "
- "length is invalid: %s", pubkey_b32);
- goto err;
- }
- client = tor_malloc_zero(sizeof(hs_service_authorized_client_t));
- if (base32_decode((char *) client->client_pk.public_key,
- sizeof(client->client_pk.public_key),
- pubkey_b32, strlen(pubkey_b32)) < 0) {
- log_warn(LD_REND, "Client authorization public key cannot be decoded: %s",
- pubkey_b32);
- goto err;
- }
-
- goto done;
- err:
- service_authorized_client_free(client);
- done:
-
- if (pubkey_b32) {
- memwipe(pubkey_b32, 0, strlen(pubkey_b32));
- }
- tor_assert(fields);
- SMARTLIST_FOREACH(fields, char *, s, tor_free(s));
- smartlist_free(fields);
- return client;
- }
- static int
- load_client_keys(hs_service_t *service)
- {
- int ret = -1;
- char *client_key_str = NULL;
- char *client_key_file_path = NULL;
- char *client_keys_dir_path = NULL;
- hs_service_config_t *config;
- smartlist_t *file_list = NULL;
- tor_assert(service);
- config = &service->config;
-
- client_keys_dir_path = hs_path_from_filename(config->directory_path,
- dname_client_pubkeys);
- if (BUG(hs_check_service_private_dir(get_options()->User,
- client_keys_dir_path,
- config->dir_group_readable, 1) < 0)) {
- goto end;
- }
-
- if (config->clients) {
- SMARTLIST_FOREACH(config->clients, hs_service_authorized_client_t *, p,
- service_authorized_client_free(p));
- smartlist_free(config->clients);
- }
- config->clients = smartlist_new();
- file_list = tor_listdir(client_keys_dir_path);
- if (file_list == NULL) {
- log_warn(LD_REND, "Client authorization directory %s can't be listed.",
- client_keys_dir_path);
- goto end;
- }
- SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
- hs_service_authorized_client_t *client = NULL;
- log_info(LD_REND, "Loading a client authorization key file %s...",
- filename);
- if (!client_filename_is_valid(filename)) {
- log_warn(LD_REND, "Client authorization unrecognized filename %s. "
- "File must end in .auth. Ignoring.", filename);
- continue;
- }
-
- client_key_file_path = hs_path_from_filename(client_keys_dir_path,
- filename);
- client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
-
- tor_free(client_key_file_path);
-
- if (!client_key_str) {
- log_warn(LD_REND, "Client authorization file %s can't be read. "
- "Corrupted or verify permission? Ignoring.",
- client_key_file_path);
- continue;
- }
- client = parse_authorized_client(client_key_str);
-
- memwipe(client_key_str, 0, strlen(client_key_str));
- tor_free(client_key_str);
- if (client) {
- smartlist_add(config->clients, client);
- log_info(LD_REND, "Loaded a client authorization key file %s.",
- filename);
- }
- } SMARTLIST_FOREACH_END(filename);
-
- if (smartlist_len(config->clients) > 0) {
- config->is_client_auth_enabled = 1;
- }
-
- ret = 0;
- end:
- if (client_key_str) {
- memwipe(client_key_str, 0, strlen(client_key_str));
- }
- if (file_list) {
- SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
- smartlist_free(file_list);
- }
- tor_free(client_key_str);
- tor_free(client_key_file_path);
- tor_free(client_keys_dir_path);
- return ret;
- }
- STATIC void
- service_authorized_client_free_(hs_service_authorized_client_t *client)
- {
- if (!client) {
- return;
- }
- memwipe(&client->client_pk, 0, sizeof(client->client_pk));
- tor_free(client);
- }
- STATIC void
- service_descriptor_free_(hs_service_descriptor_t *desc)
- {
- if (!desc) {
- return;
- }
- hs_descriptor_free(desc->desc);
- memwipe(&desc->signing_kp, 0, sizeof(desc->signing_kp));
- memwipe(&desc->blinded_kp, 0, sizeof(desc->blinded_kp));
-
- digest256map_free(desc->intro_points.map, service_intro_point_free_void);
- digestmap_free(desc->intro_points.failed_id, tor_free_);
- if (desc->previous_hsdirs) {
- SMARTLIST_FOREACH(desc->previous_hsdirs, char *, s, tor_free(s));
- smartlist_free(desc->previous_hsdirs);
- }
- crypto_ope_free(desc->ope_cipher);
- tor_free(desc);
- }
- STATIC hs_service_descriptor_t *
- service_descriptor_new(void)
- {
- hs_service_descriptor_t *sdesc = tor_malloc_zero(sizeof(*sdesc));
- sdesc->desc = tor_malloc_zero(sizeof(hs_descriptor_t));
-
- sdesc->intro_points.map = digest256map_new();
- sdesc->intro_points.failed_id = digestmap_new();
- sdesc->previous_hsdirs = smartlist_new();
- return sdesc;
- }
- static hs_service_authorized_client_t *
- service_authorized_client_dup(const hs_service_authorized_client_t *client)
- {
- hs_service_authorized_client_t *client_dup = NULL;
- tor_assert(client);
- client_dup = tor_malloc_zero(sizeof(hs_service_authorized_client_t));
-
- memcpy(client_dup->client_pk.public_key,
- client->client_pk.public_key,
- CURVE25519_PUBKEY_LEN);
- return client_dup;
- }
- static int
- service_authorized_client_cmp(const hs_service_authorized_client_t *client1,
- const hs_service_authorized_client_t *client2)
- {
- tor_assert(client1);
- tor_assert(client2);
-
- return tor_memcmp(client1->client_pk.public_key,
- client2->client_pk.public_key,
- CURVE25519_PUBKEY_LEN);
- }
- static int
- compare_service_authorzized_client_(const void **_a, const void **_b)
- {
- const hs_service_authorized_client_t *a = *_a, *b = *_b;
- return service_authorized_client_cmp(a, b);
- }
- STATIC int
- service_authorized_client_config_equal(const hs_service_config_t *config1,
- const hs_service_config_t *config2)
- {
- int ret = 0;
- int i;
- smartlist_t *sl1 = smartlist_new();
- smartlist_t *sl2 = smartlist_new();
- tor_assert(config1);
- tor_assert(config2);
- tor_assert(config1->clients);
- tor_assert(config2->clients);
-
- if (smartlist_len(config1->clients) != smartlist_len(config2->clients)) {
- goto done;
- }
-
- SMARTLIST_FOREACH(config1->clients,
- hs_service_authorized_client_t *, client,
- smartlist_add(sl1, service_authorized_client_dup(client)));
- SMARTLIST_FOREACH(config2->clients,
- hs_service_authorized_client_t *, client,
- smartlist_add(sl2, service_authorized_client_dup(client)));
- smartlist_sort(sl1, compare_service_authorzized_client_);
- smartlist_sort(sl2, compare_service_authorzized_client_);
- for (i = 0; i < smartlist_len(sl1); i++) {
-
- if (service_authorized_client_cmp(smartlist_get(sl1, i),
- smartlist_get(sl2, i))) {
- goto done;
- }
- }
-
- ret = 1;
- done:
- if (sl1) {
- SMARTLIST_FOREACH(sl1, hs_service_authorized_client_t *, p,
- service_authorized_client_free(p));
- smartlist_free(sl1);
- }
- if (sl2) {
- SMARTLIST_FOREACH(sl2, hs_service_authorized_client_t *, p,
- service_authorized_client_free(p));
- smartlist_free(sl2);
- }
- return ret;
- }
- static void
- move_descriptors(hs_service_t *src, hs_service_t *dst)
- {
- tor_assert(src);
- tor_assert(dst);
- if (src->desc_current) {
-
- if (BUG(dst->desc_current)) {
- service_descriptor_free(dst->desc_current);
- }
- dst->desc_current = src->desc_current;
- src->desc_current = NULL;
- }
- if (src->desc_next) {
-
- if (BUG(dst->desc_next)) {
- service_descriptor_free(dst->desc_next);
- }
- dst->desc_next = src->desc_next;
- src->desc_next = NULL;
- }
-
- int client_auth_changed =
- !service_authorized_client_config_equal(&src->config, &dst->config);
- if (client_auth_changed && dst->desc_current) {
-
- hs_desc_superencrypted_data_free_contents(
- &dst->desc_current->desc->superencrypted_data);
- if (build_service_desc_superencrypted(dst, dst->desc_current) < 0) {
- goto err;
- }
- service_desc_schedule_upload(dst->desc_current, time(NULL), 1);
- }
- if (client_auth_changed && dst->desc_next) {
-
- hs_desc_superencrypted_data_free_contents(
- &dst->desc_next->desc->superencrypted_data);
- if (build_service_desc_superencrypted(dst, dst->desc_next) < 0) {
- goto err;
- }
- service_desc_schedule_upload(dst->desc_next, time(NULL), 1);
- }
- return;
- err:
-
- service_descriptor_free(dst->desc_current);
- service_descriptor_free(dst->desc_next);
- }
- static void
- remove_expired_failing_intro(hs_service_t *service, time_t now)
- {
- tor_assert(service);
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- DIGESTMAP_FOREACH_MODIFY(desc->intro_points.failed_id, key, time_t *, t) {
- time_t failure_time = *t;
- if ((failure_time + INTRO_CIRC_RETRY_PERIOD) <= now) {
- MAP_DEL_CURRENT(key);
- tor_free(t);
- }
- } DIGESTMAP_FOREACH_END;
- } FOR_EACH_DESCRIPTOR_END;
- }
- static void
- setup_intro_point_exclude_list(const hs_service_descriptor_t *desc,
- smartlist_t *node_list)
- {
- tor_assert(desc);
- tor_assert(node_list);
- DIGESTMAP_FOREACH(desc->intro_points.failed_id, key, time_t *, t) {
- (void) t;
- const node_t *node = node_get_by_id(key);
- if (node) {
- smartlist_add(node_list, (void *) node);
- }
- } DIGESTMAP_FOREACH_END;
- }
- static void
- remember_failing_intro_point(const hs_service_intro_point_t *ip,
- hs_service_descriptor_t *desc, time_t now)
- {
- time_t *time_of_failure, *prev_ptr;
- const hs_desc_link_specifier_t *legacy_ls;
- tor_assert(ip);
- tor_assert(desc);
- time_of_failure = tor_malloc_zero(sizeof(time_t));
- *time_of_failure = now;
- legacy_ls = get_link_spec_by_type(ip, LS_LEGACY_ID);
- tor_assert(legacy_ls);
- prev_ptr = digestmap_set(desc->intro_points.failed_id,
- (const char *) legacy_ls->u.legacy_id,
- time_of_failure);
- tor_free(prev_ptr);
- }
- static void
- link_specifier_copy(hs_desc_link_specifier_t *dst,
- const hs_desc_link_specifier_t *src)
- {
- tor_assert(dst);
- tor_assert(src);
- memcpy(dst, src, sizeof(hs_desc_link_specifier_t));
- }
- static int
- setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
- const hs_service_intro_point_t *ip,
- time_t now, hs_desc_intro_point_t *desc_ip)
- {
- int ret = -1;
- time_t nearest_hour = now - (now % 3600);
- tor_assert(signing_kp);
- tor_assert(ip);
- tor_assert(desc_ip);
-
- memcpy(&desc_ip->onion_key, &ip->onion_key, sizeof(desc_ip->onion_key));
-
- desc_ip->auth_key_cert = tor_cert_create(signing_kp,
- CERT_TYPE_AUTH_HS_IP_KEY,
- &ip->auth_key_kp.pubkey,
- nearest_hour,
- HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
- if (desc_ip->auth_key_cert == NULL) {
- log_warn(LD_REND, "Unable to create intro point auth-key certificate");
- goto done;
- }
-
- SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers,
- const hs_desc_link_specifier_t *, ls) {
- hs_desc_link_specifier_t *copy = tor_malloc_zero(sizeof(*copy));
- link_specifier_copy(copy, ls);
- smartlist_add(desc_ip->link_specifiers, copy);
- } SMARTLIST_FOREACH_END(ls);
-
- if (ip->base.is_only_legacy) {
- desc_ip->legacy.key = crypto_pk_dup_key(ip->legacy_key);
-
- ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
- &signing_kp->pubkey,
- desc_ip->legacy.key,
- nearest_hour + HS_DESC_CERT_LIFETIME,
- &desc_ip->legacy.cert.encoded);
- if (cert_len < 0) {
- log_warn(LD_REND, "Unable to create enc key legacy cross cert.");
- goto done;
- }
- desc_ip->legacy.cert.len = cert_len;
- }
-
- {
- ed25519_public_key_t ed25519_pubkey;
-
- memcpy(&desc_ip->enc_key, &ip->enc_key_kp.pubkey,
- sizeof(desc_ip->enc_key));
-
- ed25519_public_key_from_curve25519_public_key(&ed25519_pubkey,
- &ip->enc_key_kp.pubkey,
- 0);
- desc_ip->enc_key_cert = tor_cert_create(signing_kp,
- CERT_TYPE_CROSS_HS_IP_KEYS,
- &ed25519_pubkey, nearest_hour,
- HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
- if (desc_ip->enc_key_cert == NULL) {
- log_warn(LD_REND, "Unable to create enc key curve25519 cross cert.");
- goto done;
- }
- }
-
- ret = 0;
- done:
- return ret;
- }
- static void
- build_desc_intro_points(const hs_service_t *service,
- hs_service_descriptor_t *desc, time_t now)
- {
- hs_desc_encrypted_data_t *encrypted;
- tor_assert(service);
- tor_assert(desc);
-
- encrypted = &desc->desc->encrypted_data;
-
- hs_descriptor_clear_intro_points(desc->desc);
- DIGEST256MAP_FOREACH(desc->intro_points.map, key,
- const hs_service_intro_point_t *, ip) {
- hs_desc_intro_point_t *desc_ip = hs_desc_intro_point_new();
- if (setup_desc_intro_point(&desc->signing_kp, ip, now, desc_ip) < 0) {
- hs_desc_intro_point_free(desc_ip);
- continue;
- }
-
- smartlist_add(encrypted->intro_points, desc_ip);
- } DIGEST256MAP_FOREACH_END;
- }
- static void
- build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
- {
- hs_desc_plaintext_data_t *plaintext;
- tor_assert(desc);
- tor_assert(desc->desc);
-
- plaintext = &desc->desc->plaintext_data;
-
- tor_cert_free(plaintext->signing_key_cert);
-
- plaintext->signing_key_cert =
- tor_cert_create(&desc->blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
- &desc->signing_kp.pubkey, now, HS_DESC_CERT_LIFETIME,
- CERT_FLAG_INCLUDE_SIGNING_KEY);
-
- tor_assert_nonfatal(plaintext->signing_key_cert);
- }
- static int
- build_service_desc_encrypted(const hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- hs_desc_encrypted_data_t *encrypted;
- tor_assert(service);
- tor_assert(desc);
- encrypted = &desc->desc->encrypted_data;
- encrypted->create2_ntor = 1;
- encrypted->single_onion_service = service->config.is_single_onion;
-
- if (encrypted->intro_points == NULL) {
- encrypted->intro_points = smartlist_new();
- }
-
-
- encrypted->intro_auth_types = NULL;
- return 0;
- }
- static int
- build_service_desc_superencrypted(const hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- const hs_service_config_t *config;
- int i;
- hs_desc_superencrypted_data_t *superencrypted;
- tor_assert(service);
- tor_assert(desc);
- superencrypted = &desc->desc->superencrypted_data;
- config = &service->config;
-
- if (BUG(!curve25519_public_key_is_ok(&desc->auth_ephemeral_kp.pubkey))) {
- return -1;
- }
- memcpy(&superencrypted->auth_ephemeral_pubkey,
- &desc->auth_ephemeral_kp.pubkey,
- sizeof(curve25519_public_key_t));
-
- if (BUG(tor_mem_is_zero((char*)desc->desc->subcredential, DIGEST256_LEN))) {
- return -1;
- }
-
- superencrypted->clients = smartlist_new();
-
- if (config->is_client_auth_enabled) {
- SMARTLIST_FOREACH_BEGIN(config->clients,
- hs_service_authorized_client_t *, client) {
- hs_desc_authorized_client_t *desc_client;
- desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
-
- hs_desc_build_authorized_client(desc->desc->subcredential,
- &client->client_pk,
- &desc->auth_ephemeral_kp.seckey,
- desc->descriptor_cookie, desc_client);
- smartlist_add(superencrypted->clients, desc_client);
- } SMARTLIST_FOREACH_END(client);
- }
-
- int num_clients = smartlist_len(superencrypted->clients);
- int num_clients_to_add;
- if (num_clients == 0) {
- num_clients_to_add = HS_DESC_AUTH_CLIENT_MULTIPLE;
- } else if (num_clients % HS_DESC_AUTH_CLIENT_MULTIPLE == 0) {
- num_clients_to_add = 0;
- } else {
- num_clients_to_add =
- HS_DESC_AUTH_CLIENT_MULTIPLE
- - (num_clients % HS_DESC_AUTH_CLIENT_MULTIPLE);
- }
- for (i = 0; i < num_clients_to_add; i++) {
- hs_desc_authorized_client_t *desc_client =
- hs_desc_build_fake_authorized_client();
- smartlist_add(superencrypted->clients, desc_client);
- }
-
- smartlist_shuffle(superencrypted->clients);
- return 0;
- }
- static void
- build_service_desc_plaintext(const hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- hs_desc_plaintext_data_t *plaintext;
- tor_assert(service);
- tor_assert(desc);
- tor_assert(!tor_mem_is_zero((char *) &desc->blinded_kp,
- sizeof(desc->blinded_kp)));
- tor_assert(!tor_mem_is_zero((char *) &desc->signing_kp,
- sizeof(desc->signing_kp)));
-
- hs_get_subcredential(&service->keys.identity_pk, &desc->blinded_kp.pubkey,
- desc->desc->subcredential);
- plaintext = &desc->desc->plaintext_data;
- plaintext->version = service->config.version;
- plaintext->lifetime_sec = HS_DESC_DEFAULT_LIFETIME;
-
- ed25519_pubkey_copy(&plaintext->signing_pubkey, &desc->signing_kp.pubkey);
- ed25519_pubkey_copy(&plaintext->blinded_pubkey, &desc->blinded_kp.pubkey);
-
- build_desc_signing_key_cert(desc, approx_time());
- }
- static crypto_ope_t *
- generate_ope_cipher_for_desc(const hs_service_descriptor_t *hs_desc)
- {
-
- uint8_t key[DIGEST256_LEN];
- crypto_digest_t *digest = crypto_digest256_new(DIGEST_SHA3_256);
- const char ope_key_prefix[] = "rev-counter-generation";
- const ed25519_secret_key_t *eph_privkey = &hs_desc->blinded_kp.seckey;
- crypto_digest_add_bytes(digest, ope_key_prefix, sizeof(ope_key_prefix));
- crypto_digest_add_bytes(digest, (char*)eph_privkey->seckey,
- sizeof(eph_privkey->seckey));
- crypto_digest_get_digest(digest, (char *)key, sizeof(key));
- crypto_digest_free(digest);
- return crypto_ope_new(key);
- }
- static int
- build_service_desc_keys(const hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- int ret = -1;
- ed25519_keypair_t kp;
- tor_assert(desc);
- tor_assert(!tor_mem_is_zero((char *) &service->keys.identity_pk,
- ED25519_PUBKEY_LEN));
-
-
- memcpy(&kp.pubkey, &service->keys.identity_pk, sizeof(kp.pubkey));
- memcpy(&kp.seckey, &service->keys.identity_sk, sizeof(kp.seckey));
-
- hs_build_blinded_keypair(&kp, NULL, 0, desc->time_period_num,
- &desc->blinded_kp);
-
- memwipe(&kp, 0, sizeof(kp));
-
- log_info(LD_GENERAL,
- "Getting OPE for TP#%u", (unsigned) desc->time_period_num);
- tor_assert_nonfatal(!desc->ope_cipher);
- desc->ope_cipher = generate_ope_cipher_for_desc(desc);
-
- if (ed25519_keypair_generate(&desc->signing_kp, 0) < 0) {
- log_warn(LD_REND, "Can't generate descriptor signing keypair for "
- "service %s",
- safe_str_client(service->onion_address));
- goto end;
- }
-
- if (curve25519_keypair_generate(&desc->auth_ephemeral_kp, 0) < 0) {
- log_warn(LD_REND, "Can't generate auth ephemeral keypair for "
- "service %s",
- safe_str_client(service->onion_address));
- goto end;
- }
-
- crypto_strongest_rand(desc->descriptor_cookie,
- sizeof(desc->descriptor_cookie));
-
- ret = 0;
- end:
- return ret;
- }
- static void
- build_service_descriptor(hs_service_t *service, uint64_t time_period_num,
- hs_service_descriptor_t **desc_out)
- {
- char *encoded_desc;
- hs_service_descriptor_t *desc;
- tor_assert(service);
- tor_assert(desc_out);
- desc = service_descriptor_new();
-
- desc->time_period_num = time_period_num;
-
- if (build_service_desc_keys(service, desc) < 0) {
- goto err;
- }
-
- build_service_desc_plaintext(service, desc);
-
- if (build_service_desc_superencrypted(service, desc) < 0) {
- goto err;
- }
-
- if (build_service_desc_encrypted(service, desc) < 0) {
- goto err;
- }
-
- if (BUG(service_encode_descriptor(service, desc, &desc->signing_kp,
- &encoded_desc) < 0)) {
- goto err;
- }
- tor_free(encoded_desc);
-
- *desc_out = desc;
-
- hs_control_desc_event_created(service->onion_address,
- &desc->blinded_kp.pubkey);
- return;
- err:
- service_descriptor_free(desc);
- }
- static void
- build_descriptors_for_new_service(hs_service_t *service, time_t now)
- {
- uint64_t current_desc_tp, next_desc_tp;
- tor_assert(service);
-
- tor_assert(!service->desc_current);
- tor_assert(!service->desc_next);
-
- if (hs_in_period_between_tp_and_srv(NULL, now)) {
-
- current_desc_tp = hs_get_previous_time_period_num(0);
- next_desc_tp = hs_get_time_period_num(0);
- } else {
-
- current_desc_tp = hs_get_time_period_num(0);
- next_desc_tp = hs_get_next_time_period_num(0);
- }
-
- build_service_descriptor(service, current_desc_tp, &service->desc_current);
- build_service_descriptor(service, next_desc_tp, &service->desc_next);
- log_info(LD_REND, "Hidden service %s has just started. Both descriptors "
- "built. Now scheduled for upload.",
- safe_str_client(service->onion_address));
- }
- STATIC void
- build_all_descriptors(time_t now)
- {
- FOR_EACH_SERVICE_BEGIN(service) {
-
- if (service->desc_current == NULL && service->desc_next == NULL) {
- build_descriptors_for_new_service(service, now);
- continue;
- }
-
- if (BUG(service->desc_current == NULL)) {
- continue;
- }
- if (service->desc_next == NULL) {
- build_service_descriptor(service, hs_get_next_time_period_num(0),
- &service->desc_next);
- log_info(LD_REND, "Hidden service %s next descriptor successfully "
- "built. Now scheduled for upload.",
- safe_str_client(service->onion_address));
- }
- } FOR_EACH_DESCRIPTOR_END;
- }
- static hs_service_intro_point_t *
- pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
- {
- const node_t *node;
- extend_info_t *info = NULL;
- hs_service_intro_point_t *ip = NULL;
-
- router_crn_flags_t flags = CRN_NEED_UPTIME | CRN_NEED_DESC;
-
- router_crn_flags_t direct_flags = flags | CRN_PREF_ADDR | CRN_DIRECT_CONN;
- node = router_choose_random_node(exclude_nodes, get_options()->ExcludeNodes,
- direct_conn ? direct_flags : flags);
-
- if (!node) {
- goto err;
- }
-
- smartlist_add(exclude_nodes, (void *) node);
-
- info = extend_info_from_node(node, 0);
- if (BUG(info == NULL)) {
- goto err;
- }
-
- if (!node_supports_ed25519_link_authentication(node, 0)) {
- tor_assert_nonfatal(ed25519_public_key_is_zero(&info->ed_identity));
- } else {
-
- tor_assert_nonfatal(!ed25519_public_key_is_zero(&info->ed_identity));
- }
-
- ip = service_intro_point_new(info, !node_supports_ed25519_hs_intro(node),
- node_supports_ed25519_link_authentication(node,
- 0));
- if (ip == NULL) {
- goto err;
- }
- log_info(LD_REND, "Picked intro point: %s", extend_info_describe(info));
- extend_info_free(info);
- return ip;
- err:
- service_intro_point_free(ip);
- extend_info_free(info);
- return NULL;
- }
- static unsigned int
- pick_needed_intro_points(hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- int i = 0, num_needed_ip;
- smartlist_t *exclude_nodes = smartlist_new();
- tor_assert(service);
- tor_assert(desc);
-
- num_needed_ip = service->config.num_intro_points -
- digest256map_size(desc->intro_points.map);
- if (BUG(num_needed_ip < 0)) {
-
- goto done;
- }
-
- if (digest256map_size(desc->intro_points.map) == 0) {
- num_needed_ip += get_intro_point_num_extra();
- }
-
- DIGEST256MAP_FOREACH(desc->intro_points.map, key,
- hs_service_intro_point_t *, ip) {
- const node_t *intro_node = get_node_from_intro_point(ip);
- if (intro_node) {
- smartlist_add(exclude_nodes, (void*)intro_node);
- }
- } DIGEST256MAP_FOREACH_END;
-
- setup_intro_point_exclude_list(desc, exclude_nodes);
- for (i = 0; i < num_needed_ip; i++) {
- hs_service_intro_point_t *ip;
-
- ip = pick_intro_point(service->config.is_single_onion, exclude_nodes);
- if (ip == NULL) {
-
- log_info(LD_REND, "Unable to find a suitable node to be an "
- "introduction point for service %s.",
- safe_str_client(service->onion_address));
- goto done;
- }
-
- service_intro_point_add(desc->intro_points.map, ip);
- }
-
- desc->missing_intro_points = 0;
-
- done:
-
- smartlist_free(exclude_nodes);
- return i;
- }
- static void
- service_desc_clear_previous_hsdirs(hs_service_descriptor_t *desc)
- {
- if (BUG(!desc->previous_hsdirs)) {
- return;
- }
- SMARTLIST_FOREACH(desc->previous_hsdirs, char*, s, tor_free(s));
- smartlist_clear(desc->previous_hsdirs);
- }
- static void
- service_desc_note_upload(hs_service_descriptor_t *desc, const node_t *hsdir)
- {
- char b64_digest[BASE64_DIGEST_LEN+1] = {0};
- digest_to_base64(b64_digest, hsdir->identity);
- if (BUG(!desc->previous_hsdirs)) {
- return;
- }
- if (!smartlist_contains_string(desc->previous_hsdirs, b64_digest)) {
- smartlist_add_strdup(desc->previous_hsdirs, b64_digest);
- }
- }
- STATIC void
- service_desc_schedule_upload(hs_service_descriptor_t *desc,
- time_t now,
- int descriptor_changed)
- {
- desc->next_upload_time = now;
-
- if (descriptor_changed) {
- service_desc_clear_previous_hsdirs(desc);
- }
- }
- static void
- update_service_descriptor_intro_points(hs_service_t *service,
- hs_service_descriptor_t *desc, time_t now)
- {
- unsigned int num_intro_points;
- tor_assert(service);
- tor_assert(desc);
- tor_assert(desc->desc);
- num_intro_points = digest256map_size(desc->intro_points.map);
-
- if (num_intro_points < service->config.num_intro_points) {
- unsigned int num_new_intro_points = pick_needed_intro_points(service,
- desc);
- if (num_new_intro_points != 0) {
- log_info(LD_REND, "Service %s just picked %u intro points and wanted "
- "%u for %s descriptor. It currently has %d intro "
- "points. Launching ESTABLISH_INTRO circuit shortly.",
- safe_str_client(service->onion_address),
- num_new_intro_points,
- service->config.num_intro_points - num_intro_points,
- (desc == service->desc_current) ? "current" : "next",
- num_intro_points);
-
- service_desc_schedule_upload(desc, now, 1);
- }
-
- if ((num_new_intro_points + num_intro_points) <
- service->config.num_intro_points) {
- desc->missing_intro_points = 1;
- }
- }
- }
- STATIC void
- update_all_descriptors_intro_points(time_t now)
- {
- FOR_EACH_SERVICE_BEGIN(service) {
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- update_service_descriptor_intro_points(service, desc, now);
- } FOR_EACH_DESCRIPTOR_END;
- } FOR_EACH_SERVICE_END;
- }
- STATIC int
- intro_point_should_expire(const hs_service_intro_point_t *ip,
- time_t now)
- {
- tor_assert(ip);
- if (ip->introduce2_count >= ip->introduce2_max) {
- goto expired;
- }
- if (ip->time_to_expire <= now) {
- goto expired;
- }
-
- return 0;
- expired:
- return 1;
- }
- static void
- cleanup_intro_points(hs_service_t *service, time_t now)
- {
-
- smartlist_t *ips_to_free = smartlist_new();
- tor_assert(service);
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
-
- DIGEST256MAP_FOREACH_MODIFY(desc->intro_points.map, key,
- hs_service_intro_point_t *, ip) {
- const node_t *node = get_node_from_intro_point(ip);
- int has_expired = intro_point_should_expire(ip, now);
-
- if (has_expired || node == NULL ||
- ip->circuit_retries > MAX_INTRO_POINT_CIRCUIT_RETRIES) {
- log_info(LD_REND, "Intro point %s%s (retried: %u times). "
- "Removing it.",
- describe_intro_point(ip),
- has_expired ? " has expired" :
- (node == NULL) ? " fell off the consensus" : "",
- ip->circuit_retries);
-
- if (ip->circuit_retries > MAX_INTRO_POINT_CIRCUIT_RETRIES) {
- remember_failing_intro_point(ip, desc, approx_time());
- }
-
- MAP_DEL_CURRENT(key);
- smartlist_add(ips_to_free, ip);
- }
- } DIGEST256MAP_FOREACH_END;
- } FOR_EACH_DESCRIPTOR_END;
-
- SMARTLIST_FOREACH_BEGIN(ips_to_free, hs_service_intro_point_t *, ip) {
-
-
- origin_circuit_t *ocirc = hs_circ_service_get_intro_circ(ip);
- if (ocirc && !TO_CIRCUIT(ocirc)->marked_for_close) {
- circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
- }
-
- service_intro_point_free(ip);
- } SMARTLIST_FOREACH_END(ip);
- smartlist_free(ips_to_free);
- }
- static void
- set_rotation_time(hs_service_t *service)
- {
- tor_assert(service);
- service->state.next_rotation_time =
- sr_state_get_start_time_of_current_protocol_run() +
- sr_state_get_protocol_run_duration();
- {
- char fmt_time[ISO_TIME_LEN + 1];
- format_local_iso_time(fmt_time, service->state.next_rotation_time);
- log_info(LD_REND, "Next descriptor rotation time set to %s for %s",
- fmt_time, safe_str_client(service->onion_address));
- }
- }
- static unsigned int
- should_rotate_descriptors(hs_service_t *service, time_t now)
- {
- const networkstatus_t *ns;
- tor_assert(service);
- ns = networkstatus_get_live_consensus(now);
- if (ns == NULL) {
- goto no_rotation;
- }
- if (ns->valid_after >= service->state.next_rotation_time) {
-
- if (BUG(service->desc_current == NULL || service->desc_next == NULL)) {
- log_warn(LD_BUG, "Service descriptor is NULL (%p/%p). Next rotation "
- "time is %ld (now: %ld). Valid after time from "
- "consensus is %ld",
- service->desc_current, service->desc_next,
- (long)service->state.next_rotation_time,
- (long)now,
- (long)ns->valid_after);
- goto no_rotation;
- }
- goto rotation;
- }
- no_rotation:
- return 0;
- rotation:
- return 1;
- }
- static void
- rotate_service_descriptors(hs_service_t *service)
- {
- if (service->desc_current) {
-
- close_intro_circuits(&service->desc_current->intro_points);
-
- service_descriptor_free(service->desc_current);
- }
-
- service->desc_current = service->desc_next;
- service->desc_next = NULL;
-
- set_rotation_time(service);
- }
- STATIC void
- rotate_all_descriptors(time_t now)
- {
-
- FOR_EACH_SERVICE_BEGIN(service) {
-
- if (!should_rotate_descriptors(service, now)) {
- continue;
- }
- log_info(LD_REND, "Time to rotate our descriptors (%p / %p) for %s",
- service->desc_current, service->desc_next,
- safe_str_client(service->onion_address));
- rotate_service_descriptors(service);
- } FOR_EACH_SERVICE_END;
- }
- STATIC void
- run_housekeeping_event(time_t now)
- {
-
- FOR_EACH_SERVICE_BEGIN(service) {
-
- if (service->state.next_rotation_time == 0) {
-
- set_rotation_time(service);
- }
-
- cleanup_intro_points(service, now);
-
- remove_expired_failing_intro(service, now);
-
- } FOR_EACH_SERVICE_END;
- }
- static void
- run_build_descriptor_event(time_t now)
- {
-
-
-
- rotate_all_descriptors(now);
-
- build_all_descriptors(now);
-
- update_all_descriptors_intro_points(now);
- }
- static void
- launch_intro_point_circuits(hs_service_t *service)
- {
- tor_assert(service);
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
-
- unsigned int direct_conn = service->config.is_single_onion;
- DIGEST256MAP_FOREACH_MODIFY(desc->intro_points.map, key,
- hs_service_intro_point_t *, ip) {
- extend_info_t *ei;
-
- if (hs_circ_service_get_intro_circ(ip)) {
- continue;
- }
- ei = get_extend_info_from_intro_point(ip, direct_conn);
- if (ei == NULL) {
-
- MAP_DEL_CURRENT(key);
- service_intro_point_free(ip);
- continue;
- }
-
- ip->circuit_retries++;
- if (hs_circ_launch_intro_point(service, ip, ei) < 0) {
- log_info(LD_REND, "Unable to launch intro circuit to node %s "
- "for service %s.",
- safe_str_client(extend_info_describe(ei)),
- safe_str_client(service->onion_address));
-
- }
- extend_info_free(ei);
- } DIGEST256MAP_FOREACH_END;
- } FOR_EACH_DESCRIPTOR_END;
- }
- static unsigned int
- get_max_intro_circ_per_period(const hs_service_t *service)
- {
- unsigned int count = 0;
- unsigned int multiplier = 0;
- unsigned int num_wanted_ip;
- tor_assert(service);
- tor_assert(service->config.num_intro_points <=
- HS_CONFIG_V3_MAX_INTRO_POINTS);
- #define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1
- if (get_options()->TestingTorNetwork) {
- return MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING;
- }
- num_wanted_ip = service->config.num_intro_points;
-
- count += (num_wanted_ip + get_intro_point_num_extra());
-
- count += (num_wanted_ip * MAX_INTRO_POINT_CIRCUIT_RETRIES);
-
- multiplier += (service->desc_current) ? 1 : 0;
- multiplier += (service->desc_next) ? 1 : 0;
- return (count * multiplier);
- }
- STATIC int
- can_service_launch_intro_circuit(hs_service_t *service, time_t now)
- {
- tor_assert(service);
-
- if (now > (service->state.intro_circ_retry_started_time +
- INTRO_CIRC_RETRY_PERIOD)) {
- service->state.intro_circ_retry_started_time = now;
- service->state.num_intro_circ_launched = 0;
- goto allow;
- }
-
- if (service->state.num_intro_circ_launched <=
- get_max_intro_circ_per_period(service)) {
- goto allow;
- }
-
- {
- char *msg;
- time_t elapsed_time = now - service->state.intro_circ_retry_started_time;
- static ratelim_t rlimit = RATELIM_INIT(INTRO_CIRC_RETRY_PERIOD);
- if ((msg = rate_limit_log(&rlimit, now))) {
- log_info(LD_REND, "Hidden service %s exceeded its circuit launch limit "
- "of %u per %d seconds. It launched %u circuits in "
- "the last %ld seconds. Will retry in %ld seconds.",
- safe_str_client(service->onion_address),
- get_max_intro_circ_per_period(service),
- INTRO_CIRC_RETRY_PERIOD,
- service->state.num_intro_circ_launched,
- (long int) elapsed_time,
- (long int) (INTRO_CIRC_RETRY_PERIOD - elapsed_time));
- tor_free(msg);
- }
- }
-
- return 0;
- allow:
- return 1;
- }
- static void
- run_build_circuit_event(time_t now)
- {
-
- if (router_have_consensus_path() == CONSENSUS_PATH_UNKNOWN ||
- !have_completed_a_circuit()) {
- return;
- }
-
- if (rend_num_services() > 0) {
- rend_consider_services_intro_points(now);
- }
-
- FOR_EACH_SERVICE_BEGIN(service) {
-
- if (can_service_launch_intro_circuit(service, now)) {
-
- launch_intro_point_circuits(service);
-
- }
- } FOR_EACH_SERVICE_END;
- }
- static void
- upload_descriptor_to_hsdir(const hs_service_t *service,
- hs_service_descriptor_t *desc, const node_t *hsdir)
- {
- char *encoded_desc = NULL;
- tor_assert(service);
- tor_assert(desc);
- tor_assert(hsdir);
-
- if (!get_options()->PublishHidServDescriptors) {
- log_info(LD_REND, "Service %s not publishing descriptor. "
- "PublishHidServDescriptors is set to 1.",
- safe_str_client(service->onion_address));
- goto end;
- }
-
- if (BUG(service_encode_descriptor(service, desc, &desc->signing_kp,
- &encoded_desc) < 0)) {
- goto end;
- }
-
- hs_service_upload_desc_to_dir(encoded_desc, service->config.version,
- &service->keys.identity_pk,
- &desc->blinded_kp.pubkey, hsdir->rs);
-
- service_desc_note_upload(desc, hsdir);
-
- {
- int is_next_desc = (service->desc_next == desc);
- const uint8_t *idx = (is_next_desc) ? hsdir->hsdir_index.store_second:
- hsdir->hsdir_index.store_first;
- char *blinded_pubkey_log_str =
- tor_strdup(hex_str((char*)&desc->blinded_kp.pubkey.pubkey, 32));
- log_info(LD_REND, "Service %s %s descriptor of revision %" PRIu64
- " initiated upload request to %s with index %s (%s)",
- safe_str_client(service->onion_address),
- (is_next_desc) ? "next" : "current",
- desc->desc->plaintext_data.revision_counter,
- safe_str_client(node_describe(hsdir)),
- safe_str_client(hex_str((const char *) idx, 32)),
- safe_str_client(blinded_pubkey_log_str));
- tor_free(blinded_pubkey_log_str);
-
- hs_control_desc_event_upload(service->onion_address, hsdir->identity,
- &desc->blinded_kp.pubkey, idx);
- }
- end:
- tor_free(encoded_desc);
- return;
- }
- static void
- set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now,
- bool is_current)
- {
- uint64_t rev_counter = 0;
-
- time_t srv_start = 0;
-
- if (is_current) {
- srv_start = sr_state_get_start_time_of_previous_protocol_run();
- } else {
- srv_start = sr_state_get_start_time_of_current_protocol_run();
- }
- log_info(LD_REND, "Setting rev counter for TP #%u: "
- "SRV started at %d, now %d (%s)",
- (unsigned) hs_desc->time_period_num, (int)srv_start,
- (int)now, is_current ? "current" : "next");
- tor_assert_nonfatal(now >= srv_start);
-
- time_t seconds_since_start_of_srv = now - srv_start;
-
- seconds_since_start_of_srv++;
-
- if (BUG(seconds_since_start_of_srv > OPE_INPUT_MAX)) {
- seconds_since_start_of_srv = OPE_INPUT_MAX;
- }
-
- tor_assert(hs_desc->ope_cipher);
- rev_counter = crypto_ope_encrypt(hs_desc->ope_cipher,
- (int) seconds_since_start_of_srv);
-
- tor_assert_nonfatal(rev_counter < CRYPTO_OPE_ERROR);
- log_info(LD_REND, "Encrypted revision counter %d to %ld",
- (int) seconds_since_start_of_srv, (long int) rev_counter);
- hs_desc->desc->plaintext_data.revision_counter = rev_counter;
- }
- STATIC void
- upload_descriptor_to_all(const hs_service_t *service,
- hs_service_descriptor_t *desc)
- {
- smartlist_t *responsible_dirs = NULL;
- tor_assert(service);
- tor_assert(desc);
-
- close_directory_connections(service, desc);
-
- responsible_dirs = smartlist_new();
-
- hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num,
- service->desc_next == desc, 0, responsible_dirs);
-
- service_desc_clear_previous_hsdirs(desc);
-
- SMARTLIST_FOREACH_BEGIN(responsible_dirs, const routerstatus_t *,
- hsdir_rs) {
- const node_t *hsdir_node = node_get_by_id(hsdir_rs->identity_digest);
-
- tor_assert(hsdir_node);
-
- upload_descriptor_to_hsdir(service, desc, hsdir_node);
- } SMARTLIST_FOREACH_END(hsdir_rs);
-
- desc->next_upload_time =
- (time(NULL) + crypto_rand_int_range(HS_SERVICE_NEXT_UPLOAD_TIME_MIN,
- HS_SERVICE_NEXT_UPLOAD_TIME_MAX));
- {
- char fmt_next_time[ISO_TIME_LEN+1];
- format_local_iso_time(fmt_next_time, desc->next_upload_time);
- log_debug(LD_REND, "Service %s set to upload a descriptor at %s",
- safe_str_client(service->onion_address), fmt_next_time);
- }
- smartlist_free(responsible_dirs);
- return;
- }
- STATIC int
- service_desc_hsdirs_changed(const hs_service_t *service,
- const hs_service_descriptor_t *desc)
- {
- int should_reupload = 0;
- smartlist_t *responsible_dirs = smartlist_new();
-
- if (!desc->previous_hsdirs || !smartlist_len(desc->previous_hsdirs)) {
- goto done;
- }
-
- hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num,
- service->desc_next == desc, 0, responsible_dirs);
-
- SMARTLIST_FOREACH_BEGIN(responsible_dirs, const routerstatus_t *, hsdir_rs) {
- char b64_digest[BASE64_DIGEST_LEN+1] = {0};
- digest_to_base64(b64_digest, hsdir_rs->identity_digest);
- if (!smartlist_contains_string(desc->previous_hsdirs, b64_digest)) {
- should_reupload = 1;
- break;
- }
- } SMARTLIST_FOREACH_END(hsdir_rs);
- done:
- smartlist_free(responsible_dirs);
- return should_reupload;
- }
- static int
- should_service_upload_descriptor(const hs_service_t *service,
- const hs_service_descriptor_t *desc, time_t now)
- {
- unsigned int num_intro_points;
- tor_assert(service);
- tor_assert(desc);
-
- if (desc->missing_intro_points) {
- num_intro_points = digest256map_size(desc->intro_points.map);
- } else {
- num_intro_points = service->config.num_intro_points;
- }
-
- if (desc->missing_intro_points && num_intro_points == 0) {
- goto cannot;
- }
-
- if (count_desc_circuit_established(desc) != num_intro_points) {
- goto cannot;
- }
-
- if (desc->next_upload_time > now) {
- goto cannot;
- }
-
- if (!networkstatus_get_live_consensus(now)) {
- goto cannot;
- }
-
- if (!router_have_minimum_dir_info()) {
- goto cannot;
- }
-
- return 1;
- cannot:
- return 0;
- }
- static void
- refresh_service_descriptor(const hs_service_t *service,
- hs_service_descriptor_t *desc, time_t now)
- {
-
-
- build_desc_signing_key_cert(desc, now);
-
- build_desc_intro_points(service, desc, now);
-
- set_descriptor_revision_counter(desc, now, service->desc_current == desc);
- }
- STATIC void
- run_upload_descriptor_event(time_t now)
- {
-
- if (rend_num_services() > 0) {
- rend_consider_services_upload(now);
- rend_consider_descriptor_republication();
- }
-
- FOR_EACH_SERVICE_BEGIN(service) {
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
-
- if (consider_republishing_hs_descriptors &&
- service_desc_hsdirs_changed(service, desc)) {
- service_desc_schedule_upload(desc, now, 0);
- }
-
- if (!should_service_upload_descriptor(service, desc, now)) {
- continue;
- }
- log_info(LD_REND, "Initiating upload for hidden service %s descriptor "
- "for service %s with %u/%u introduction points%s.",
- (desc == service->desc_current) ? "current" : "next",
- safe_str_client(service->onion_address),
- digest256map_size(desc->intro_points.map),
- service->config.num_intro_points,
- (desc->missing_intro_points) ? " (couldn't pick more)" : "");
-
- refresh_service_descriptor(service, desc, now);
-
- upload_descriptor_to_all(service, desc);
- } FOR_EACH_DESCRIPTOR_END;
- } FOR_EACH_SERVICE_END;
-
- consider_republishing_hs_descriptors = 0;
- }
- static void
- service_intro_circ_has_opened(origin_circuit_t *circ)
- {
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- hs_service_descriptor_t *desc = NULL;
- tor_assert(circ);
-
- if (BUG(!circ->cpath)) {
- return;
- }
- if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)) {
- return;
- }
- if (BUG(!circ->hs_ident)) {
- return;
- }
-
- get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
- if (service == NULL) {
- log_warn(LD_REND, "Unknown service identity key %s on the introduction "
- "circuit %u. Can't find onion service.",
- safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
- TO_CIRCUIT(circ)->n_circ_id);
- goto err;
- }
- if (ip == NULL) {
- log_warn(LD_REND, "Unknown introduction point auth key on circuit %u "
- "for service %s",
- TO_CIRCUIT(circ)->n_circ_id,
- safe_str_client(service->onion_address));
- goto err;
- }
-
- tor_assert(desc);
- if (hs_circ_service_intro_has_opened(service, ip, desc, circ)) {
-
- service_intro_point_remove(service, ip);
- service_intro_point_free(ip);
- }
- goto done;
- err:
-
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NOSUCHSERVICE);
- done:
- return;
- }
- static void
- service_rendezvous_circ_has_opened(origin_circuit_t *circ)
- {
- hs_service_t *service = NULL;
- tor_assert(circ);
- tor_assert(circ->cpath);
-
- tor_assert(circ->hs_ident);
- tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
-
- TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
- pathbias_count_use_attempt(circ);
-
- get_objects_from_ident(circ->hs_ident, &service, NULL, NULL);
- if (service == NULL) {
- log_warn(LD_REND, "Unknown service identity key %s on the rendezvous "
- "circuit %u with cookie %s. Can't find onion service.",
- safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
- TO_CIRCUIT(circ)->n_circ_id,
- hex_str((const char *) circ->hs_ident->rendezvous_cookie,
- REND_COOKIE_LEN));
- goto err;
- }
-
- hs_circ_service_rp_has_opened(service, circ);
- goto done;
- err:
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NOSUCHSERVICE);
- done:
- return;
- }
- static int
- service_handle_intro_established(origin_circuit_t *circ,
- const uint8_t *payload,
- size_t payload_len)
- {
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- tor_assert(circ);
- tor_assert(payload);
- tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
-
- get_objects_from_ident(circ->hs_ident, &service, &ip, NULL);
-
- if (service == NULL) {
- log_warn(LD_REND, "Unknown service identity key %s on the introduction "
- "circuit %u. Can't find onion service.",
- safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
- TO_CIRCUIT(circ)->n_circ_id);
- goto err;
- }
- if (ip == NULL) {
-
- log_warn(LD_REND, "Introduction circuit established without an intro "
- "point object on circuit %u for service %s",
- TO_CIRCUIT(circ)->n_circ_id,
- safe_str_client(service->onion_address));
- goto err;
- }
-
- if (hs_circ_handle_intro_established(service, ip, circ, payload,
- payload_len) < 0) {
- goto err;
- }
-
- ip->circuit_established = 1;
- log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
- "on circuit %u for service %s",
- TO_CIRCUIT(circ)->n_circ_id,
- safe_str_client(service->onion_address));
- return 0;
- err:
- return -1;
- }
- static int
- service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
- size_t payload_len)
- {
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- hs_service_descriptor_t *desc = NULL;
- tor_assert(circ);
- tor_assert(payload);
- tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
-
- get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
-
- if (service == NULL) {
- log_warn(LD_BUG, "Unknown service identity key %s when handling "
- "an INTRODUCE2 cell on circuit %u",
- safe_str_client(ed25519_fmt(&circ->hs_ident->identity_pk)),
- TO_CIRCUIT(circ)->n_circ_id);
- goto err;
- }
- if (ip == NULL) {
-
- log_warn(LD_BUG, "Unknown introduction auth key when handling "
- "an INTRODUCE2 cell on circuit %u for service %s",
- TO_CIRCUIT(circ)->n_circ_id,
- safe_str_client(service->onion_address));
- goto err;
- }
-
- tor_assert(desc);
-
- if (hs_circ_handle_introduce2(service, circ, ip, desc->desc->subcredential,
- payload, payload_len) < 0) {
- goto err;
- }
- return 0;
- err:
- return -1;
- }
- static void
- service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
- {
- const char *s_dir;
- char fname[128] = {0};
- tor_assert(service);
- tor_assert(list);
-
- s_dir = service->config.directory_path;
-
- smartlist_add(list, hs_path_from_filename(s_dir, fname_hostname));
-
- tor_snprintf(fname, sizeof(fname), "%s_secret_key", fname_keyfile_prefix);
- smartlist_add(list, hs_path_from_filename(s_dir, fname));
- tor_snprintf(fname, sizeof(fname), "%s_public_key", fname_keyfile_prefix);
- smartlist_add(list, hs_path_from_filename(s_dir, fname));
- }
- static int
- service_key_on_disk(const char *directory_path)
- {
- int ret = 0;
- char *fname;
- ed25519_keypair_t *kp = NULL;
- tor_assert(directory_path);
-
- fname = hs_path_from_filename(directory_path, fname_keyfile_prefix);
- kp = ed_key_init_from_file(fname, INIT_ED_KEY_SPLIT,
- LOG_DEBUG, NULL, 0, 0, 0, NULL, NULL);
- if (kp) {
- ret = 1;
- }
- ed25519_keypair_free(kp);
- tor_free(fname);
- return ret;
- }
- static int
- service_encode_descriptor(const hs_service_t *service,
- const hs_service_descriptor_t *desc,
- const ed25519_keypair_t *signing_kp,
- char **encoded_out)
- {
- int ret;
- const uint8_t *descriptor_cookie = NULL;
- tor_assert(service);
- tor_assert(desc);
- tor_assert(encoded_out);
-
- if (service->config.is_client_auth_enabled) {
- descriptor_cookie = desc->descriptor_cookie;
- }
- ret = hs_desc_encode_descriptor(desc->desc, signing_kp,
- descriptor_cookie, encoded_out);
- return ret;
- }
- void
- hs_service_map_has_changed(void)
- {
-
- rescan_periodic_events(get_options());
- }
- void
- hs_service_upload_desc_to_dir(const char *encoded_desc,
- const uint8_t version,
- const ed25519_public_key_t *identity_pk,
- const ed25519_public_key_t *blinded_pk,
- const routerstatus_t *hsdir_rs)
- {
- char version_str[4] = {0};
- directory_request_t *dir_req;
- hs_ident_dir_conn_t ident;
- tor_assert(encoded_desc);
- tor_assert(identity_pk);
- tor_assert(blinded_pk);
- tor_assert(hsdir_rs);
-
- memset(&ident, 0, sizeof(ident));
- hs_ident_dir_conn_init(identity_pk, blinded_pk, &ident);
-
- tor_snprintf(version_str, sizeof(version_str), "%u", version);
-
- dir_req = directory_request_new(DIR_PURPOSE_UPLOAD_HSDESC);
- directory_request_set_routerstatus(dir_req, hsdir_rs);
- directory_request_set_indirection(dir_req, DIRIND_ANONYMOUS);
- directory_request_set_resource(dir_req, version_str);
- directory_request_set_payload(dir_req, encoded_desc,
- strlen(encoded_desc));
-
- directory_request_upload_set_hs_ident(dir_req, &ident);
-
- directory_initiate_request(dir_req);
- directory_request_free(dir_req);
- }
- hs_service_add_ephemeral_status_t
- hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports,
- int max_streams_per_rdv_circuit,
- int max_streams_close_circuit, char **address_out)
- {
- hs_service_add_ephemeral_status_t ret;
- hs_service_t *service = NULL;
- tor_assert(sk);
- tor_assert(ports);
- tor_assert(address_out);
- service = hs_service_new(get_options());
-
- service->config.version = HS_VERSION_THREE;
- service->config.max_streams_per_rdv_circuit = max_streams_per_rdv_circuit;
- service->config.max_streams_close_circuit = !!max_streams_close_circuit;
- service->config.is_ephemeral = 1;
- smartlist_free(service->config.ports);
- service->config.ports = ports;
-
- memcpy(&service->keys.identity_sk, sk, sizeof(service->keys.identity_sk));
- if (ed25519_public_key_generate(&service->keys.identity_pk,
- &service->keys.identity_sk) < 0) {
- log_warn(LD_CONFIG, "Unable to generate ed25519 public key"
- "for v3 service.");
- ret = RSAE_BADPRIVKEY;
- goto err;
- }
-
- if (smartlist_len(service->config.ports) == 0) {
- log_warn(LD_CONFIG, "At least one VIRTPORT/TARGET must be specified "
- "for v3 service.");
- ret = RSAE_BADVIRTPORT;
- goto err;
- }
-
- hs_build_address(&service->keys.identity_pk,
- (uint8_t) service->config.version,
- service->onion_address);
-
- if (BUG(register_service(hs_service_map, service) < 0)) {
- log_warn(LD_CONFIG, "Onion Service private key collides with an "
- "existing v3 service.");
- ret = RSAE_ADDREXISTS;
- goto err;
- }
- log_info(LD_CONFIG, "Added ephemeral v3 onion service: %s",
- safe_str_client(service->onion_address));
- *address_out = tor_strdup(service->onion_address);
- ret = RSAE_OKAY;
- goto end;
- err:
- hs_service_free(service);
- end:
- memwipe(sk, 0, sizeof(ed25519_secret_key_t));
- tor_free(sk);
- return ret;
- }
- int
- hs_service_del_ephemeral(const char *address)
- {
- uint8_t version;
- ed25519_public_key_t pk;
- hs_service_t *service = NULL;
- tor_assert(address);
- if (hs_parse_address(address, &pk, NULL, &version) < 0) {
- log_warn(LD_CONFIG, "Requested malformed v3 onion address for removal.");
- goto err;
- }
- if (version != HS_VERSION_THREE) {
- log_warn(LD_CONFIG, "Requested version of onion address for removal "
- "is not supported.");
- goto err;
- }
- service = find_service(hs_service_map, &pk);
- if (service == NULL) {
- log_warn(LD_CONFIG, "Requested non-existent v3 hidden service for "
- "removal.");
- goto err;
- }
- if (!service->config.is_ephemeral) {
- log_warn(LD_CONFIG, "Requested non-ephemeral v3 hidden service for "
- "removal.");
- goto err;
- }
-
- close_service_circuits(service);
- remove_service(hs_service_map, service);
- hs_service_free(service);
- log_info(LD_CONFIG, "Removed ephemeral v3 hidden service: %s",
- safe_str_client(address));
- return 0;
- err:
- return -1;
- }
- char *
- hs_service_lookup_current_desc(const ed25519_public_key_t *pk)
- {
- const hs_service_t *service;
- tor_assert(pk);
- service = find_service(hs_service_map, pk);
- if (service && service->desc_current) {
- char *encoded_desc = NULL;
-
- service_encode_descriptor(service,
- service->desc_current,
- &service->desc_current->signing_kp,
- &encoded_desc);
- return encoded_desc;
- }
- return NULL;
- }
- unsigned int
- hs_service_get_num_services(void)
- {
- if (hs_service_map == NULL) {
- return 0;
- }
- return HT_SIZE(hs_service_map);
- }
- void
- hs_service_intro_circ_has_closed(origin_circuit_t *circ)
- {
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- hs_service_descriptor_t *desc = NULL;
- tor_assert(circ);
- if (circ->hs_ident == NULL) {
-
- goto end;
- }
- get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
- if (service == NULL) {
-
- log_info(LD_REND, "Unable to find any hidden service associated "
- "identity key %s on intro circuit %u.",
- ed25519_fmt(&circ->hs_ident->identity_pk),
- TO_CIRCUIT(circ)->n_circ_id);
- goto end;
- }
- if (ip == NULL) {
-
- goto end;
- }
-
- tor_assert(desc);
-
- ip->circuit_established = 0;
- end:
- return;
- }
- int
- hs_service_set_conn_addr_port(const origin_circuit_t *circ,
- edge_connection_t *conn)
- {
- hs_service_t *service = NULL;
- tor_assert(circ);
- tor_assert(conn);
- tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
- tor_assert(circ->hs_ident);
- get_objects_from_ident(circ->hs_ident, &service, NULL, NULL);
- if (service == NULL) {
- log_warn(LD_REND, "Unable to find any hidden service associated "
- "identity key %s on rendezvous circuit %u.",
- ed25519_fmt(&circ->hs_ident->identity_pk),
- TO_CIRCUIT(circ)->n_circ_id);
-
- goto err_close;
- }
-
- if (service->config.max_streams_per_rdv_circuit > 0 &&
- (circ->hs_ident->num_rdv_streams >=
- service->config.max_streams_per_rdv_circuit)) {
- #define MAX_STREAM_WARN_INTERVAL 600
- static struct ratelim_t stream_ratelim =
- RATELIM_INIT(MAX_STREAM_WARN_INTERVAL);
- log_fn_ratelim(&stream_ratelim, LOG_WARN, LD_REND,
- "Maximum streams per circuit limit reached on "
- "rendezvous circuit %u for service %s. Circuit has "
- "%" PRIu64 " out of %" PRIu64 " streams. %s.",
- TO_CIRCUIT(circ)->n_circ_id,
- service->onion_address,
- circ->hs_ident->num_rdv_streams,
- service->config.max_streams_per_rdv_circuit,
- service->config.max_streams_close_circuit ?
- "Closing circuit" : "Ignoring open stream request");
- if (service->config.max_streams_close_circuit) {
-
- goto err_close;
- }
-
- goto err_no_close;
- }
-
- if (hs_set_conn_addr_port(service->config.ports, conn) < 0) {
- log_info(LD_REND, "No virtual port mapping exists for port %d for "
- "hidden service %s.",
- TO_CONN(conn)->port, service->onion_address);
- if (service->config.allow_unknown_ports) {
-
- goto err_close;
- }
-
- goto err_no_close;
- }
-
- return 0;
- err_close:
-
- return -2;
- err_no_close:
-
- return -1;
- }
- hs_circuit_id_protocol_t
- hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
- {
- hs_service_t *service = find_service(hs_service_map, pk);
- if (!service) {
- return HS_CIRCUIT_ID_PROTOCOL_NONE;
- }
- return service->config.circuit_id_protocol;
- }
- void
- hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
- smartlist_t *dir_list)
- {
- tor_assert(file_list);
- tor_assert(dir_list);
-
- rend_services_add_filenames_to_lists(file_list, dir_list);
-
- FOR_EACH_SERVICE_BEGIN(service) {
-
- if (service->config.is_ephemeral) {
- continue;
- }
- service_add_fnames_to_list(service, file_list);
- smartlist_add_strdup(dir_list, service->config.directory_path);
- smartlist_add_strdup(dir_list, dname_client_pubkeys);
- } FOR_EACH_DESCRIPTOR_END;
- }
- void
- hs_service_dir_info_changed(void)
- {
- if (hs_service_get_num_services() > 0) {
-
- static struct ratelim_t dir_info_changed_ratelim = RATELIM_INIT(30 * 60);
- log_fn_ratelim(&dir_info_changed_ratelim, LOG_INFO, LD_REND,
- "New dirinfo arrived: consider reuploading descriptor");
- consider_republishing_hs_descriptors = 1;
- }
- }
- int
- hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload,
- size_t payload_len)
- {
- int ret = -1;
- tor_assert(circ);
- tor_assert(payload);
-
- if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_INTRO) {
- log_warn(LD_PROTOCOL, "Received an INTRODUCE2 cell on a "
- "non introduction circuit of purpose %d",
- TO_CIRCUIT(circ)->purpose);
- goto done;
- }
- if (circ->hs_ident) {
- ret = service_handle_introduce2(circ, payload, payload_len);
- hs_stats_note_introduce2_cell(1);
- } else {
- ret = rend_service_receive_introduction(circ, payload, payload_len);
- hs_stats_note_introduce2_cell(0);
- }
- done:
- return ret;
- }
- int
- hs_service_receive_intro_established(origin_circuit_t *circ,
- const uint8_t *payload,
- size_t payload_len)
- {
- int ret = -1;
- tor_assert(circ);
- tor_assert(payload);
- if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
- log_warn(LD_PROTOCOL, "Received an INTRO_ESTABLISHED cell on a "
- "non introduction circuit of purpose %d",
- TO_CIRCUIT(circ)->purpose);
- goto err;
- }
-
- if (circ->hs_ident) {
- ret = service_handle_intro_established(circ, payload, payload_len);
- } else {
- ret = rend_service_intro_established(circ, payload, payload_len);
- }
- if (ret < 0) {
- goto err;
- }
- return 0;
- err:
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
- return -1;
- }
- void
- hs_service_circuit_has_opened(origin_circuit_t *circ)
- {
- tor_assert(circ);
-
- switch (TO_CIRCUIT(circ)->purpose) {
- case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
- if (circ->hs_ident) {
- service_intro_circ_has_opened(circ);
- } else {
- rend_service_intro_has_opened(circ);
- }
- break;
- case CIRCUIT_PURPOSE_S_CONNECT_REND:
- if (circ->hs_ident) {
- service_rendezvous_circ_has_opened(circ);
- } else {
- rend_service_rendezvous_has_opened(circ);
- }
- break;
- default:
- tor_assert(0);
- }
- }
- int
- hs_service_get_version_from_key(const hs_service_t *service)
- {
- int version = -1;
- const char *directory_path;
- tor_assert(service);
-
- directory_path = service->config.directory_path;
-
- if (service_key_on_disk(directory_path)) {
- version = HS_VERSION_THREE;
- goto end;
- }
-
- if (rend_service_key_on_disk(directory_path)) {
- version = HS_VERSION_TWO;
- goto end;
- }
- end:
- return version;
- }
- int
- hs_service_load_all_keys(void)
- {
-
- if (rend_num_services() != 0) {
- if (rend_service_load_all_keys(NULL) < 0) {
- goto err;
- }
- }
-
- SMARTLIST_FOREACH_BEGIN(hs_service_staging_list, hs_service_t *, service) {
-
- if (service->config.is_ephemeral) {
- continue;
- }
- log_info(LD_REND, "Loading v3 onion service keys from %s",
- service_escaped_dir(service));
- if (load_service_keys(service) < 0) {
- goto err;
- }
- } SMARTLIST_FOREACH_END(service);
-
- register_all_services();
-
- return 0;
- err:
- return -1;
- }
- void
- hs_service_stage_services(const smartlist_t *service_list)
- {
- tor_assert(service_list);
-
- if (hs_service_staging_list == NULL) {
- hs_service_staging_list = smartlist_new();
- }
-
- smartlist_add_all(hs_service_staging_list, service_list);
- }
- hs_service_t *
- hs_service_new(const or_options_t *options)
- {
- hs_service_t *service = tor_malloc_zero(sizeof(hs_service_t));
-
- set_service_default_config(&service->config, options);
-
- service->config.version = HS_SERVICE_DEFAULT_VERSION;
-
- service->state.replay_cache_rend_cookie =
- replaycache_new(REND_REPLAY_TIME_INTERVAL, REND_REPLAY_TIME_INTERVAL);
- return service;
- }
- void
- hs_service_free_(hs_service_t *service)
- {
- if (service == NULL) {
- return;
- }
-
- FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- service_descriptor_free(desc);
- } FOR_EACH_DESCRIPTOR_END;
-
- service_clear_config(&service->config);
-
- if (service->state.replay_cache_rend_cookie) {
- replaycache_free(service->state.replay_cache_rend_cookie);
- }
-
- memwipe(&service->keys.identity_sk, 0, sizeof(service->keys.identity_sk));
- tor_free(service);
- }
- void
- hs_service_run_scheduled_events(time_t now)
- {
-
- run_housekeeping_event(now);
-
-
- run_build_descriptor_event(now);
-
- run_build_circuit_event(now);
-
- run_upload_descriptor_event(now);
- }
- void
- hs_service_init(void)
- {
-
- tor_assert(!hs_service_map);
- tor_assert(!hs_service_staging_list);
-
- rend_service_init();
- hs_service_map = tor_malloc_zero(sizeof(struct hs_service_ht));
- HT_INIT(hs_service_ht, hs_service_map);
- hs_service_staging_list = smartlist_new();
- }
- void
- hs_service_free_all(void)
- {
- rend_service_free_all();
- service_free_all();
- }
- #ifdef TOR_UNIT_TESTS
- STATIC unsigned int
- get_hs_service_map_size(void)
- {
- return HT_SIZE(hs_service_map);
- }
- STATIC int
- get_hs_service_staging_list_size(void)
- {
- return smartlist_len(hs_service_staging_list);
- }
- STATIC hs_service_ht *
- get_hs_service_map(void)
- {
- return hs_service_map;
- }
- STATIC hs_service_t *
- get_first_service(void)
- {
- hs_service_t **obj = HT_START(hs_service_ht, hs_service_map);
- if (obj == NULL) {
- return NULL;
- }
- return *obj;
- }
- #endif
|