WebServiceZonesApi.cs 208 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using DnsServerCore.Auth;
  16. using DnsServerCore.Dns;
  17. using DnsServerCore.Dns.Dnssec;
  18. using DnsServerCore.Dns.ResourceRecords;
  19. using DnsServerCore.Dns.ZoneManagers;
  20. using DnsServerCore.Dns.Zones;
  21. using Microsoft.AspNetCore.Http;
  22. using System;
  23. using System.Collections.Generic;
  24. using System.IO;
  25. using System.Net;
  26. using System.Text;
  27. using System.Text.Json;
  28. using System.Threading.Tasks;
  29. using TechnitiumLibrary;
  30. using TechnitiumLibrary.Net;
  31. using TechnitiumLibrary.Net.Dns;
  32. using TechnitiumLibrary.Net.Dns.ResourceRecords;
  33. namespace DnsServerCore
  34. {
  35. class WebServiceZonesApi
  36. {
  37. #region variables
  38. static readonly char[] _commaSeparator = new char[] { ',' };
  39. static readonly char[] _pipeSeparator = new char[] { '|' };
  40. static readonly char[] _commaSpaceSeparator = new char[] { ',', ' ' };
  41. static readonly char[] _newLineSeparator = new char[] { '\r', '\n' };
  42. readonly DnsWebService _dnsWebService;
  43. uint _defaultRecordTtl = 3600;
  44. #endregion
  45. #region constructor
  46. public WebServiceZonesApi(DnsWebService dnsWebService)
  47. {
  48. _dnsWebService = dnsWebService;
  49. }
  50. #endregion
  51. #region static
  52. public static void WriteRecordsAsJson(List<DnsResourceRecord> records, Utf8JsonWriter jsonWriter, bool authoritativeZoneRecords, AuthZoneInfo zoneInfo = null)
  53. {
  54. if (records is null)
  55. {
  56. jsonWriter.WritePropertyName("records");
  57. jsonWriter.WriteStartArray();
  58. jsonWriter.WriteEndArray();
  59. return;
  60. }
  61. records.Sort();
  62. Dictionary<string, Dictionary<DnsResourceRecordType, List<DnsResourceRecord>>> groupedByDomainRecords = DnsResourceRecord.GroupRecords(records);
  63. jsonWriter.WritePropertyName("records");
  64. jsonWriter.WriteStartArray();
  65. foreach (KeyValuePair<string, Dictionary<DnsResourceRecordType, List<DnsResourceRecord>>> groupedByTypeRecords in groupedByDomainRecords)
  66. {
  67. foreach (KeyValuePair<DnsResourceRecordType, List<DnsResourceRecord>> groupedRecords in groupedByTypeRecords.Value)
  68. {
  69. foreach (DnsResourceRecord record in groupedRecords.Value)
  70. WriteRecordAsJson(record, jsonWriter, authoritativeZoneRecords, zoneInfo);
  71. }
  72. }
  73. jsonWriter.WriteEndArray();
  74. }
  75. #endregion
  76. #region private
  77. private static void WriteRecordAsJson(DnsResourceRecord record, Utf8JsonWriter jsonWriter, bool authoritativeZoneRecords, AuthZoneInfo zoneInfo = null)
  78. {
  79. jsonWriter.WriteStartObject();
  80. jsonWriter.WriteString("name", record.Name);
  81. if (DnsClient.TryConvertDomainNameToUnicode(record.Name, out string idn))
  82. jsonWriter.WriteString("nameIdn", idn);
  83. jsonWriter.WriteString("type", record.Type.ToString());
  84. if (authoritativeZoneRecords)
  85. {
  86. GenericRecordInfo authRecordInfo = record.GetAuthGenericRecordInfo();
  87. jsonWriter.WriteNumber("ttl", record.TTL);
  88. jsonWriter.WriteBoolean("disabled", authRecordInfo.Disabled);
  89. string comments = authRecordInfo.Comments;
  90. if (!string.IsNullOrEmpty(comments))
  91. jsonWriter.WriteString("comments", comments);
  92. }
  93. else
  94. {
  95. if (record.IsStale)
  96. jsonWriter.WriteString("ttl", "0 (0 sec)");
  97. else
  98. jsonWriter.WriteString("ttl", record.TTL + " (" + WebUtilities.GetFormattedTime((int)record.TTL) + ")");
  99. }
  100. jsonWriter.WritePropertyName("rData");
  101. jsonWriter.WriteStartObject();
  102. switch (record.Type)
  103. {
  104. case DnsResourceRecordType.A:
  105. {
  106. if (record.RDATA is DnsARecordData rdata)
  107. {
  108. jsonWriter.WriteString("ipAddress", rdata.Address.ToString());
  109. }
  110. else
  111. {
  112. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  113. jsonWriter.WriteString("data", record.RDATA.ToString());
  114. }
  115. }
  116. break;
  117. case DnsResourceRecordType.NS:
  118. {
  119. if (record.RDATA is DnsNSRecordData rdata)
  120. {
  121. jsonWriter.WriteString("nameServer", rdata.NameServer.Length == 0 ? "." : rdata.NameServer);
  122. if (DnsClient.TryConvertDomainNameToUnicode(rdata.NameServer, out string nameServerIdn))
  123. jsonWriter.WriteString("nameServerIdn", nameServerIdn);
  124. if (!authoritativeZoneRecords)
  125. {
  126. if (rdata.IsParentSideTtlSet)
  127. jsonWriter.WriteString("parentSideTtl", rdata.ParentSideTtl + " (" + WebUtilities.GetFormattedTime((int)rdata.ParentSideTtl) + ")");
  128. }
  129. }
  130. else
  131. {
  132. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  133. jsonWriter.WriteString("data", record.RDATA.ToString());
  134. }
  135. }
  136. break;
  137. case DnsResourceRecordType.CNAME:
  138. {
  139. if (record.RDATA is DnsCNAMERecordData rdata)
  140. {
  141. jsonWriter.WriteString("cname", rdata.Domain.Length == 0 ? "." : rdata.Domain);
  142. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Domain, out string cnameIdn))
  143. jsonWriter.WriteString("cnameIdn", cnameIdn);
  144. }
  145. else
  146. {
  147. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  148. jsonWriter.WriteString("data", record.RDATA.ToString());
  149. }
  150. }
  151. break;
  152. case DnsResourceRecordType.SOA:
  153. {
  154. if (record.RDATA is DnsSOARecordData rdata)
  155. {
  156. jsonWriter.WriteString("primaryNameServer", rdata.PrimaryNameServer);
  157. if (DnsClient.TryConvertDomainNameToUnicode(rdata.PrimaryNameServer, out string primaryNameServerIdn))
  158. jsonWriter.WriteString("primaryNameServerIdn", primaryNameServerIdn);
  159. jsonWriter.WriteString("responsiblePerson", rdata.ResponsiblePerson);
  160. jsonWriter.WriteNumber("serial", rdata.Serial);
  161. jsonWriter.WriteNumber("refresh", rdata.Refresh);
  162. jsonWriter.WriteNumber("retry", rdata.Retry);
  163. jsonWriter.WriteNumber("expire", rdata.Expire);
  164. jsonWriter.WriteNumber("minimum", rdata.Minimum);
  165. }
  166. else
  167. {
  168. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  169. jsonWriter.WriteString("data", record.RDATA.ToString());
  170. }
  171. if (authoritativeZoneRecords)
  172. {
  173. SOARecordInfo authRecordInfo = record.GetAuthSOARecordInfo();
  174. if ((zoneInfo is not null) && (zoneInfo.Type == AuthZoneType.Primary))
  175. jsonWriter.WriteBoolean("useSerialDateScheme", authRecordInfo.UseSoaSerialDateScheme);
  176. IReadOnlyList<NameServerAddress> primaryNameServers = authRecordInfo.PrimaryNameServers;
  177. if (primaryNameServers is not null)
  178. {
  179. string primaryAddresses = null;
  180. foreach (NameServerAddress primaryNameServer in primaryNameServers)
  181. {
  182. if (primaryAddresses == null)
  183. primaryAddresses = primaryNameServer.OriginalAddress;
  184. else
  185. primaryAddresses = primaryAddresses + ", " + primaryNameServer.OriginalAddress;
  186. }
  187. jsonWriter.WriteString("primaryAddresses", primaryAddresses);
  188. }
  189. if (authRecordInfo.ZoneTransferProtocol != DnsTransportProtocol.Udp)
  190. jsonWriter.WriteString("zoneTransferProtocol", authRecordInfo.ZoneTransferProtocol.ToString());
  191. if (!string.IsNullOrEmpty(authRecordInfo.TsigKeyName))
  192. jsonWriter.WriteString("tsigKeyName", authRecordInfo.TsigKeyName);
  193. }
  194. }
  195. break;
  196. case DnsResourceRecordType.PTR:
  197. {
  198. if (record.RDATA is DnsPTRRecordData rdata)
  199. {
  200. jsonWriter.WriteString("ptrName", rdata.Domain.Length == 0 ? "." : rdata.Domain);
  201. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Domain, out string ptrNameIdn))
  202. jsonWriter.WriteString("ptrNameIdn", ptrNameIdn);
  203. }
  204. else
  205. {
  206. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  207. jsonWriter.WriteString("data", record.RDATA.ToString());
  208. }
  209. }
  210. break;
  211. case DnsResourceRecordType.MX:
  212. {
  213. if (record.RDATA is DnsMXRecordData rdata)
  214. {
  215. jsonWriter.WriteNumber("preference", rdata.Preference);
  216. jsonWriter.WriteString("exchange", rdata.Exchange.Length == 0 ? "." : rdata.Exchange);
  217. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Exchange, out string exchangeIdn))
  218. jsonWriter.WriteString("exchangeIdn", exchangeIdn);
  219. }
  220. else
  221. {
  222. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  223. jsonWriter.WriteString("data", record.RDATA.ToString());
  224. }
  225. }
  226. break;
  227. case DnsResourceRecordType.TXT:
  228. {
  229. if (record.RDATA is DnsTXTRecordData rdata)
  230. {
  231. jsonWriter.WriteString("text", rdata.GetText());
  232. jsonWriter.WriteBoolean("splitText", rdata.CharacterStrings.Count > 1);
  233. jsonWriter.WriteStartArray("characterStrings");
  234. foreach (string characterString in rdata.CharacterStrings)
  235. jsonWriter.WriteStringValue(characterString);
  236. jsonWriter.WriteEndArray();
  237. }
  238. else
  239. {
  240. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  241. jsonWriter.WriteString("data", record.RDATA.ToString());
  242. }
  243. }
  244. break;
  245. case DnsResourceRecordType.AAAA:
  246. {
  247. if (record.RDATA is DnsAAAARecordData rdata)
  248. {
  249. jsonWriter.WriteString("ipAddress", rdata.Address.ToString());
  250. }
  251. else
  252. {
  253. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  254. jsonWriter.WriteString("data", record.RDATA.ToString());
  255. }
  256. }
  257. break;
  258. case DnsResourceRecordType.SRV:
  259. {
  260. if (record.RDATA is DnsSRVRecordData rdata)
  261. {
  262. jsonWriter.WriteNumber("priority", rdata.Priority);
  263. jsonWriter.WriteNumber("weight", rdata.Weight);
  264. jsonWriter.WriteNumber("port", rdata.Port);
  265. jsonWriter.WriteString("target", rdata.Target.Length == 0 ? "." : rdata.Target);
  266. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Target, out string targetIdn))
  267. jsonWriter.WriteString("targetIdn", targetIdn);
  268. }
  269. else
  270. {
  271. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  272. jsonWriter.WriteString("data", record.RDATA.ToString());
  273. }
  274. }
  275. break;
  276. case DnsResourceRecordType.NAPTR:
  277. {
  278. if (record.RDATA is DnsNAPTRRecordData rdata)
  279. {
  280. jsonWriter.WriteNumber("order", rdata.Order);
  281. jsonWriter.WriteNumber("preference", rdata.Preference);
  282. jsonWriter.WriteString("flags", rdata.Flags);
  283. jsonWriter.WriteString("services", rdata.Services);
  284. jsonWriter.WriteString("regexp", rdata.Regexp);
  285. jsonWriter.WriteString("replacement", rdata.Replacement.Length == 0 ? "." : rdata.Replacement);
  286. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Replacement, out string replacementIdn))
  287. jsonWriter.WriteString("replacementIdn", replacementIdn);
  288. }
  289. else
  290. {
  291. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  292. jsonWriter.WriteString("data", record.RDATA.ToString());
  293. }
  294. }
  295. break;
  296. case DnsResourceRecordType.DNAME:
  297. {
  298. if (record.RDATA is DnsDNAMERecordData rdata)
  299. {
  300. jsonWriter.WriteString("dname", rdata.Domain.Length == 0 ? "." : rdata.Domain);
  301. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Domain, out string dnameIdn))
  302. jsonWriter.WriteString("dnameIdn", dnameIdn);
  303. }
  304. else
  305. {
  306. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  307. jsonWriter.WriteString("data", record.RDATA.ToString());
  308. }
  309. }
  310. break;
  311. case DnsResourceRecordType.DS:
  312. {
  313. if (record.RDATA is DnsDSRecordData rdata)
  314. {
  315. jsonWriter.WriteNumber("keyTag", rdata.KeyTag);
  316. jsonWriter.WriteString("algorithm", rdata.Algorithm.ToString());
  317. jsonWriter.WriteString("digestType", rdata.DigestType.ToString());
  318. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.Digest));
  319. }
  320. else
  321. {
  322. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  323. jsonWriter.WriteString("data", record.RDATA.ToString());
  324. }
  325. }
  326. break;
  327. case DnsResourceRecordType.SSHFP:
  328. {
  329. if (record.RDATA is DnsSSHFPRecordData rdata)
  330. {
  331. jsonWriter.WriteString("algorithm", rdata.Algorithm.ToString());
  332. jsonWriter.WriteString("fingerprintType", rdata.FingerprintType.ToString());
  333. jsonWriter.WriteString("fingerprint", Convert.ToHexString(rdata.Fingerprint));
  334. }
  335. else
  336. {
  337. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  338. jsonWriter.WriteString("data", record.RDATA.ToString());
  339. }
  340. }
  341. break;
  342. case DnsResourceRecordType.RRSIG:
  343. {
  344. if (record.RDATA is DnsRRSIGRecordData rdata)
  345. {
  346. jsonWriter.WriteString("typeCovered", rdata.TypeCovered.ToString());
  347. jsonWriter.WriteString("algorithm", rdata.Algorithm.ToString());
  348. jsonWriter.WriteNumber("labels", rdata.Labels);
  349. jsonWriter.WriteNumber("originalTtl", rdata.OriginalTtl);
  350. jsonWriter.WriteString("signatureExpiration", DateTime.UnixEpoch.AddSeconds(rdata.SignatureExpiration));
  351. jsonWriter.WriteString("signatureInception", DateTime.UnixEpoch.AddSeconds(rdata.SignatureInception));
  352. jsonWriter.WriteNumber("keyTag", rdata.KeyTag);
  353. jsonWriter.WriteString("signersName", rdata.SignersName.Length == 0 ? "." : rdata.SignersName);
  354. jsonWriter.WriteString("signature", Convert.ToBase64String(rdata.Signature));
  355. }
  356. else
  357. {
  358. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  359. jsonWriter.WriteString("data", record.RDATA.ToString());
  360. }
  361. }
  362. break;
  363. case DnsResourceRecordType.NSEC:
  364. {
  365. if (record.RDATA is DnsNSECRecordData rdata)
  366. {
  367. jsonWriter.WriteString("nextDomainName", rdata.NextDomainName);
  368. jsonWriter.WritePropertyName("types");
  369. jsonWriter.WriteStartArray();
  370. foreach (DnsResourceRecordType type in rdata.Types)
  371. jsonWriter.WriteStringValue(type.ToString());
  372. jsonWriter.WriteEndArray();
  373. }
  374. else
  375. {
  376. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  377. jsonWriter.WriteString("data", record.RDATA.ToString());
  378. }
  379. }
  380. break;
  381. case DnsResourceRecordType.DNSKEY:
  382. {
  383. if (record.RDATA is DnsDNSKEYRecordData rdata)
  384. {
  385. jsonWriter.WriteString("flags", rdata.Flags.ToString());
  386. jsonWriter.WriteNumber("protocol", rdata.Protocol);
  387. jsonWriter.WriteString("algorithm", rdata.Algorithm.ToString());
  388. jsonWriter.WriteString("publicKey", rdata.PublicKey.ToString());
  389. jsonWriter.WriteNumber("computedKeyTag", rdata.ComputedKeyTag);
  390. if (authoritativeZoneRecords)
  391. {
  392. if ((zoneInfo is not null) && (zoneInfo.Type == AuthZoneType.Primary))
  393. {
  394. IReadOnlyCollection<DnssecPrivateKey> dnssecPrivateKeys = zoneInfo.DnssecPrivateKeys;
  395. if (dnssecPrivateKeys is not null)
  396. {
  397. foreach (DnssecPrivateKey dnssecPrivateKey in dnssecPrivateKeys)
  398. {
  399. if (dnssecPrivateKey.KeyTag == rdata.ComputedKeyTag)
  400. {
  401. jsonWriter.WriteString("dnsKeyState", dnssecPrivateKey.State.ToString());
  402. if ((dnssecPrivateKey.KeyType == DnssecPrivateKeyType.KeySigningKey) && (dnssecPrivateKey.State == DnssecPrivateKeyState.Published))
  403. jsonWriter.WriteString("dnsKeyStateReadyBy", (zoneInfo.ApexZone as PrimaryZone).GetDnsKeyStateReadyBy(dnssecPrivateKey));
  404. break;
  405. }
  406. }
  407. }
  408. }
  409. if (rdata.Flags.HasFlag(DnsDnsKeyFlag.SecureEntryPoint))
  410. {
  411. jsonWriter.WritePropertyName("computedDigests");
  412. jsonWriter.WriteStartArray();
  413. {
  414. jsonWriter.WriteStartObject();
  415. jsonWriter.WriteString("digestType", "SHA256");
  416. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.CreateDS(record.Name, DnssecDigestType.SHA256).Digest));
  417. jsonWriter.WriteEndObject();
  418. }
  419. {
  420. jsonWriter.WriteStartObject();
  421. jsonWriter.WriteString("digestType", "SHA384");
  422. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.CreateDS(record.Name, DnssecDigestType.SHA384).Digest));
  423. jsonWriter.WriteEndObject();
  424. }
  425. jsonWriter.WriteEndArray();
  426. }
  427. }
  428. }
  429. else
  430. {
  431. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  432. jsonWriter.WriteString("data", record.RDATA.ToString());
  433. }
  434. }
  435. break;
  436. case DnsResourceRecordType.NSEC3:
  437. {
  438. if (record.RDATA is DnsNSEC3RecordData rdata)
  439. {
  440. jsonWriter.WriteString("hashAlgorithm", rdata.HashAlgorithm.ToString());
  441. jsonWriter.WriteString("flags", rdata.Flags.ToString());
  442. jsonWriter.WriteNumber("iterations", rdata.Iterations);
  443. jsonWriter.WriteString("salt", Convert.ToHexString(rdata.Salt));
  444. jsonWriter.WriteString("nextHashedOwnerName", rdata.NextHashedOwnerName);
  445. jsonWriter.WritePropertyName("types");
  446. jsonWriter.WriteStartArray();
  447. foreach (DnsResourceRecordType type in rdata.Types)
  448. jsonWriter.WriteStringValue(type.ToString());
  449. jsonWriter.WriteEndArray();
  450. }
  451. else
  452. {
  453. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  454. jsonWriter.WriteString("data", record.RDATA.ToString());
  455. }
  456. }
  457. break;
  458. case DnsResourceRecordType.NSEC3PARAM:
  459. {
  460. if (record.RDATA is DnsNSEC3PARAMRecordData rdata)
  461. {
  462. jsonWriter.WriteString("hashAlgorithm", rdata.HashAlgorithm.ToString());
  463. jsonWriter.WriteString("flags", rdata.Flags.ToString());
  464. jsonWriter.WriteNumber("iterations", rdata.Iterations);
  465. jsonWriter.WriteString("salt", Convert.ToHexString(rdata.Salt));
  466. }
  467. else
  468. {
  469. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  470. jsonWriter.WriteString("data", record.RDATA.ToString());
  471. }
  472. }
  473. break;
  474. case DnsResourceRecordType.TLSA:
  475. {
  476. if (record.RDATA is DnsTLSARecordData rdata)
  477. {
  478. jsonWriter.WriteString("certificateUsage", rdata.CertificateUsage.ToString().Replace('_', '-'));
  479. jsonWriter.WriteString("selector", rdata.Selector.ToString());
  480. jsonWriter.WriteString("matchingType", rdata.MatchingType.ToString().Replace('_', '-'));
  481. jsonWriter.WriteString("certificateAssociationData", Convert.ToHexString(rdata.CertificateAssociationData));
  482. }
  483. else
  484. {
  485. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  486. jsonWriter.WriteString("data", record.RDATA.ToString());
  487. }
  488. }
  489. break;
  490. case DnsResourceRecordType.ZONEMD:
  491. {
  492. if (record.RDATA is DnsZONEMDRecordData rdata)
  493. {
  494. jsonWriter.WriteNumber("serial", rdata.Serial);
  495. jsonWriter.WriteString("scheme", rdata.Scheme.ToString());
  496. jsonWriter.WriteString("hashAlgorithm", rdata.HashAlgorithm.ToString());
  497. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.Digest));
  498. }
  499. else
  500. {
  501. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  502. jsonWriter.WriteString("data", record.RDATA.ToString());
  503. }
  504. }
  505. break;
  506. case DnsResourceRecordType.SVCB:
  507. case DnsResourceRecordType.HTTPS:
  508. {
  509. if (record.RDATA is DnsSVCBRecordData rdata)
  510. {
  511. jsonWriter.WriteNumber("svcPriority", rdata.SvcPriority);
  512. jsonWriter.WriteString("svcTargetName", rdata.TargetName);
  513. jsonWriter.WritePropertyName("svcParams");
  514. jsonWriter.WriteStartObject();
  515. foreach (KeyValuePair<DnsSvcParamKey, DnsSvcParamValue> svcParam in rdata.SvcParams)
  516. jsonWriter.WriteString(svcParam.Key.ToString().ToLower().Replace('_', '-'), svcParam.Value.ToString());
  517. jsonWriter.WriteEndObject();
  518. if (authoritativeZoneRecords)
  519. {
  520. SVCBRecordInfo rrInfo = record.GetAuthSVCBRecordInfo();
  521. jsonWriter.WriteBoolean("autoIpv4Hint", rrInfo.AutoIpv4Hint);
  522. jsonWriter.WriteBoolean("autoIpv6Hint", rrInfo.AutoIpv6Hint);
  523. }
  524. }
  525. else
  526. {
  527. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  528. jsonWriter.WriteString("data", record.RDATA.ToString());
  529. }
  530. }
  531. break;
  532. case DnsResourceRecordType.URI:
  533. {
  534. if (record.RDATA is DnsURIRecordData rdata)
  535. {
  536. jsonWriter.WriteNumber("priority", rdata.Priority);
  537. jsonWriter.WriteNumber("weight", rdata.Weight);
  538. jsonWriter.WriteString("uri", rdata.Uri.AbsoluteUri);
  539. }
  540. else
  541. {
  542. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  543. jsonWriter.WriteString("data", record.RDATA.ToString());
  544. }
  545. }
  546. break;
  547. case DnsResourceRecordType.CAA:
  548. {
  549. if (record.RDATA is DnsCAARecordData rdata)
  550. {
  551. jsonWriter.WriteNumber("flags", rdata.Flags);
  552. jsonWriter.WriteString("tag", rdata.Tag);
  553. jsonWriter.WriteString("value", rdata.Value);
  554. }
  555. else
  556. {
  557. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  558. jsonWriter.WriteString("data", record.RDATA.ToString());
  559. }
  560. }
  561. break;
  562. case DnsResourceRecordType.ANAME:
  563. {
  564. if (record.RDATA is DnsANAMERecordData rdata)
  565. {
  566. jsonWriter.WriteString("aname", rdata.Domain.Length == 0 ? "." : rdata.Domain);
  567. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Domain, out string anameIdn))
  568. jsonWriter.WriteString("anameIdn", anameIdn);
  569. }
  570. else
  571. {
  572. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  573. jsonWriter.WriteString("data", record.RDATA.ToString());
  574. }
  575. }
  576. break;
  577. case DnsResourceRecordType.FWD:
  578. {
  579. if (record.RDATA is DnsForwarderRecordData rdata)
  580. {
  581. jsonWriter.WriteString("protocol", rdata.Protocol.ToString());
  582. jsonWriter.WriteString("forwarder", rdata.Forwarder);
  583. jsonWriter.WriteBoolean("dnssecValidation", rdata.DnssecValidation);
  584. jsonWriter.WriteString("proxyType", rdata.ProxyType.ToString());
  585. switch (rdata.ProxyType)
  586. {
  587. case DnsForwarderRecordProxyType.Http:
  588. case DnsForwarderRecordProxyType.Socks5:
  589. jsonWriter.WriteString("proxyAddress", rdata.ProxyAddress);
  590. jsonWriter.WriteNumber("proxyPort", rdata.ProxyPort);
  591. jsonWriter.WriteString("proxyUsername", rdata.ProxyUsername);
  592. jsonWriter.WriteString("proxyPassword", rdata.ProxyPassword);
  593. break;
  594. }
  595. }
  596. }
  597. break;
  598. case DnsResourceRecordType.APP:
  599. {
  600. if (record.RDATA is DnsApplicationRecordData rdata)
  601. {
  602. jsonWriter.WriteString("appName", rdata.AppName);
  603. jsonWriter.WriteString("classPath", rdata.ClassPath);
  604. jsonWriter.WriteString("data", rdata.Data);
  605. }
  606. }
  607. break;
  608. case DnsResourceRecordType.ALIAS:
  609. {
  610. if (record.RDATA is DnsALIASRecordData rdata)
  611. {
  612. jsonWriter.WriteString("type", rdata.Type.ToString());
  613. jsonWriter.WriteString("alias", rdata.Domain.Length == 0 ? "." : rdata.Domain);
  614. if (DnsClient.TryConvertDomainNameToUnicode(rdata.Domain, out string aliasIdn))
  615. jsonWriter.WriteString("aliasIdn", aliasIdn);
  616. }
  617. else
  618. {
  619. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  620. jsonWriter.WriteString("data", record.RDATA.ToString());
  621. }
  622. }
  623. break;
  624. default:
  625. {
  626. if (record.RDATA is DnsUnknownRecordData rdata)
  627. {
  628. jsonWriter.WriteString("value", BitConverter.ToString(rdata.DATA).Replace('-', ':'));
  629. }
  630. else
  631. {
  632. jsonWriter.WriteString("dataType", record.RDATA.GetType().Name);
  633. jsonWriter.WriteString("data", record.RDATA.ToString());
  634. }
  635. }
  636. break;
  637. }
  638. jsonWriter.WriteEndObject();
  639. jsonWriter.WriteString("dnssecStatus", record.DnssecStatus.ToString());
  640. if (authoritativeZoneRecords)
  641. {
  642. GenericRecordInfo authRecordInfo = record.GetAuthGenericRecordInfo();
  643. if (authRecordInfo is NSRecordInfo nsRecordInfo)
  644. {
  645. IReadOnlyList<DnsResourceRecord> glueRecords = nsRecordInfo.GlueRecords;
  646. if (glueRecords is not null)
  647. {
  648. jsonWriter.WritePropertyName("glueRecords");
  649. jsonWriter.WriteStartArray();
  650. foreach (DnsResourceRecord glueRecord in glueRecords)
  651. jsonWriter.WriteStringValue(glueRecord.RDATA.ToString());
  652. jsonWriter.WriteEndArray();
  653. }
  654. }
  655. jsonWriter.WriteString("lastUsedOn", authRecordInfo.LastUsedOn);
  656. }
  657. else
  658. {
  659. CacheRecordInfo cacheRecordInfo = record.GetCacheRecordInfo();
  660. IReadOnlyList<DnsResourceRecord> glueRecords = cacheRecordInfo.GlueRecords;
  661. if (glueRecords is not null)
  662. {
  663. jsonWriter.WritePropertyName("glueRecords");
  664. jsonWriter.WriteStartArray();
  665. foreach (DnsResourceRecord glueRecord in glueRecords)
  666. jsonWriter.WriteStringValue(glueRecord.RDATA.ToString());
  667. jsonWriter.WriteEndArray();
  668. }
  669. IReadOnlyList<DnsResourceRecord> rrsigRecords = cacheRecordInfo.RRSIGRecords;
  670. IReadOnlyList<DnsResourceRecord> nsecRecords = cacheRecordInfo.NSECRecords;
  671. if ((rrsigRecords is not null) || (nsecRecords is not null))
  672. {
  673. jsonWriter.WritePropertyName("dnssecRecords");
  674. jsonWriter.WriteStartArray();
  675. if (rrsigRecords is not null)
  676. {
  677. foreach (DnsResourceRecord rrsigRecord in rrsigRecords)
  678. jsonWriter.WriteStringValue(rrsigRecord.ToString());
  679. }
  680. if (nsecRecords is not null)
  681. {
  682. foreach (DnsResourceRecord nsecRecord in nsecRecords)
  683. jsonWriter.WriteStringValue(nsecRecord.ToString());
  684. }
  685. jsonWriter.WriteEndArray();
  686. }
  687. NetworkAddress eDnsClientSubnet = cacheRecordInfo.EDnsClientSubnet;
  688. if (eDnsClientSubnet is not null)
  689. jsonWriter.WriteString("eDnsClientSubnet", eDnsClientSubnet.ToString());
  690. DnsDatagramMetadata responseMetadata = cacheRecordInfo.ResponseMetadata;
  691. if (responseMetadata is not null)
  692. {
  693. jsonWriter.WritePropertyName("responseMetadata");
  694. jsonWriter.WriteStartObject();
  695. jsonWriter.WriteString("nameServer", responseMetadata.NameServer?.ToString());
  696. jsonWriter.WriteString("protocol", (responseMetadata.NameServer is null ? DnsTransportProtocol.Udp : responseMetadata.NameServer.Protocol).ToString());
  697. jsonWriter.WriteString("datagramSize", responseMetadata.DatagramSize + " bytes");
  698. jsonWriter.WriteString("roundTripTime", Math.Round(responseMetadata.RoundTripTime, 2) + " ms");
  699. jsonWriter.WriteEndObject();
  700. }
  701. jsonWriter.WriteString("lastUsedOn", cacheRecordInfo.LastUsedOn);
  702. }
  703. jsonWriter.WriteEndObject();
  704. }
  705. private static void WriteZoneInfoAsJson(AuthZoneInfo zoneInfo, Utf8JsonWriter jsonWriter)
  706. {
  707. jsonWriter.WriteStartObject();
  708. jsonWriter.WriteString("name", zoneInfo.Name);
  709. if (DnsClient.TryConvertDomainNameToUnicode(zoneInfo.Name, out string nameIdn))
  710. jsonWriter.WriteString("nameIdn", nameIdn);
  711. jsonWriter.WriteString("type", zoneInfo.Type.ToString());
  712. switch (zoneInfo.Type)
  713. {
  714. case AuthZoneType.Primary:
  715. jsonWriter.WriteBoolean("internal", zoneInfo.Internal);
  716. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  717. jsonWriter.WriteNumber("soaSerial", (zoneInfo.GetApexRecords(DnsResourceRecordType.SOA)[0].RDATA as DnsSOARecordData).Serial);
  718. if (!zoneInfo.Internal)
  719. {
  720. string[] notifyFailed = zoneInfo.NotifyFailed;
  721. jsonWriter.WriteBoolean("notifyFailed", notifyFailed.Length > 0);
  722. jsonWriter.WritePropertyName("notifyFailedFor");
  723. jsonWriter.WriteStartArray();
  724. foreach (string server in notifyFailed)
  725. jsonWriter.WriteStringValue(server);
  726. jsonWriter.WriteEndArray();
  727. }
  728. break;
  729. case AuthZoneType.Secondary:
  730. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  731. jsonWriter.WriteNumber("soaSerial", (zoneInfo.GetApexRecords(DnsResourceRecordType.SOA)[0].RDATA as DnsSOARecordData).Serial);
  732. jsonWriter.WriteString("expiry", zoneInfo.Expiry);
  733. jsonWriter.WriteBoolean("isExpired", zoneInfo.IsExpired);
  734. jsonWriter.WriteBoolean("syncFailed", zoneInfo.SyncFailed);
  735. {
  736. string[] notifyFailed = zoneInfo.NotifyFailed;
  737. jsonWriter.WriteBoolean("notifyFailed", notifyFailed.Length > 0);
  738. jsonWriter.WritePropertyName("notifyFailedFor");
  739. jsonWriter.WriteStartArray();
  740. foreach (string server in notifyFailed)
  741. jsonWriter.WriteStringValue(server);
  742. jsonWriter.WriteEndArray();
  743. }
  744. break;
  745. case AuthZoneType.Stub:
  746. jsonWriter.WriteNumber("soaSerial", (zoneInfo.GetApexRecords(DnsResourceRecordType.SOA)[0].RDATA as DnsSOARecordData).Serial);
  747. jsonWriter.WriteString("expiry", zoneInfo.Expiry);
  748. jsonWriter.WriteBoolean("isExpired", zoneInfo.IsExpired);
  749. jsonWriter.WriteBoolean("syncFailed", zoneInfo.SyncFailed);
  750. break;
  751. }
  752. jsonWriter.WriteString("lastModified", zoneInfo.LastModified);
  753. jsonWriter.WriteBoolean("disabled", zoneInfo.Disabled);
  754. jsonWriter.WriteEndObject();
  755. }
  756. private static string[] DecodeCharacterStrings(string text)
  757. {
  758. string[] characterStrings = text.Split(_newLineSeparator, StringSplitOptions.RemoveEmptyEntries);
  759. for (int i = 0; i < characterStrings.Length; i++)
  760. characterStrings[i] = Unescape(characterStrings[i]);
  761. return characterStrings;
  762. }
  763. private static string Unescape(string text)
  764. {
  765. StringBuilder sb = new StringBuilder(text.Length);
  766. for (int i = 0, j; i < text.Length; i++)
  767. {
  768. char c = text[i];
  769. if (c == '\\')
  770. {
  771. j = i + 1;
  772. if (j == text.Length)
  773. {
  774. sb.Append(c);
  775. break;
  776. }
  777. char next = text[j];
  778. switch (next)
  779. {
  780. case 'n':
  781. sb.Append('\n');
  782. break;
  783. case 'r':
  784. sb.Append('\r');
  785. break;
  786. case 't':
  787. sb.Append('\t');
  788. break;
  789. case '\\':
  790. sb.Append('\\');
  791. break;
  792. default:
  793. sb.Append(c).Append(next);
  794. break;
  795. }
  796. i++;
  797. }
  798. else
  799. {
  800. sb.Append(c);
  801. }
  802. }
  803. return sb.ToString();
  804. }
  805. private static string GetSvcbTargetName(DnsResourceRecord svcbRecord)
  806. {
  807. DnsSVCBRecordData rData = svcbRecord.RDATA as DnsSVCBRecordData;
  808. if (rData.TargetName.Length > 0)
  809. return rData.TargetName;
  810. if (rData.SvcPriority == 0) //alias mode
  811. return null;
  812. //service mode
  813. return svcbRecord.Name;
  814. }
  815. private void ResolveSvcbAutoHints(string zoneName, DnsResourceRecord svcbRecord, bool resolveIpv4Hint, bool resolveIpv6Hint, Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams, IReadOnlyCollection<DnsResourceRecord> importRecords = null)
  816. {
  817. string targetName = GetSvcbTargetName(svcbRecord);
  818. if (targetName is not null)
  819. ResolveSvcbAutoHints(zoneName, targetName, resolveIpv4Hint, resolveIpv6Hint, svcParams, importRecords);
  820. }
  821. private void ResolveSvcbAutoHints(string zoneName, string targetName, bool resolveIpv4Hint, bool resolveIpv6Hint, Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams, IReadOnlyCollection<DnsResourceRecord> importRecords = null)
  822. {
  823. if (resolveIpv4Hint)
  824. {
  825. List<IPAddress> ipv4Hint = new List<IPAddress>();
  826. IReadOnlyList<DnsResourceRecord> records = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneName, targetName, DnsResourceRecordType.A);
  827. foreach (DnsResourceRecord record in records)
  828. {
  829. if (record.GetAuthGenericRecordInfo().Disabled)
  830. continue;
  831. ipv4Hint.Add((record.RDATA as DnsARecordData).Address);
  832. }
  833. if (importRecords is not null)
  834. {
  835. foreach (DnsResourceRecord record in importRecords)
  836. {
  837. if (record.Type != DnsResourceRecordType.A)
  838. continue;
  839. if (record.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase))
  840. {
  841. IPAddress address = (record.RDATA as DnsARecordData).Address;
  842. if (!ipv4Hint.Contains(address))
  843. ipv4Hint.Add(address);
  844. }
  845. }
  846. }
  847. if (ipv4Hint.Count > 0)
  848. svcParams[DnsSvcParamKey.IPv4Hint] = new DnsSvcIPv4HintParamValue(ipv4Hint);
  849. else
  850. svcParams.Remove(DnsSvcParamKey.IPv4Hint);
  851. }
  852. if (resolveIpv6Hint)
  853. {
  854. List<IPAddress> ipv6Hint = new List<IPAddress>();
  855. IReadOnlyList<DnsResourceRecord> records = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneName, targetName, DnsResourceRecordType.AAAA);
  856. foreach (DnsResourceRecord record in records)
  857. {
  858. if (record.GetAuthGenericRecordInfo().Disabled)
  859. continue;
  860. ipv6Hint.Add((record.RDATA as DnsAAAARecordData).Address);
  861. }
  862. if (importRecords is not null)
  863. {
  864. foreach (DnsResourceRecord record in importRecords)
  865. {
  866. if (record.Type != DnsResourceRecordType.AAAA)
  867. continue;
  868. if (record.Name.Equals(targetName, StringComparison.OrdinalIgnoreCase))
  869. {
  870. IPAddress address = (record.RDATA as DnsAAAARecordData).Address;
  871. if (!ipv6Hint.Contains(address))
  872. ipv6Hint.Add(address);
  873. }
  874. }
  875. }
  876. if (ipv6Hint.Count > 0)
  877. svcParams[DnsSvcParamKey.IPv6Hint] = new DnsSvcIPv6HintParamValue(ipv6Hint);
  878. else
  879. svcParams.Remove(DnsSvcParamKey.IPv6Hint);
  880. }
  881. }
  882. private void UpdateSvcbAutoHints(string zoneName, string targetName, bool resolveIpv4Hint, bool resolveIpv6Hint)
  883. {
  884. List<DnsResourceRecord> allSvcbRecords = new List<DnsResourceRecord>();
  885. _dnsWebService.DnsServer.AuthZoneManager.ListAllZoneRecords(zoneName, [DnsResourceRecordType.SVCB, DnsResourceRecordType.HTTPS], allSvcbRecords);
  886. foreach (DnsResourceRecord record in allSvcbRecords)
  887. {
  888. SVCBRecordInfo info = record.GetAuthSVCBRecordInfo();
  889. if ((info.AutoIpv4Hint && resolveIpv4Hint) || (info.AutoIpv6Hint && resolveIpv6Hint))
  890. {
  891. string scvbTargetName = GetSvcbTargetName(record);
  892. if (targetName.Equals(scvbTargetName, StringComparison.OrdinalIgnoreCase))
  893. {
  894. DnsSVCBRecordData oldRData = record.RDATA as DnsSVCBRecordData;
  895. Dictionary<DnsSvcParamKey, DnsSvcParamValue> newSvcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(oldRData.SvcParams);
  896. ResolveSvcbAutoHints(zoneName, targetName, resolveIpv4Hint, resolveIpv6Hint, newSvcParams);
  897. DnsSVCBRecordData newRData = new DnsSVCBRecordData(oldRData.SvcPriority, oldRData.TargetName, newSvcParams);
  898. DnsResourceRecord newRecord = new DnsResourceRecord(record.Name, record.Type, record.Class, record.TTL, newRData) { Tag = record.Tag };
  899. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneName, record, newRecord);
  900. }
  901. }
  902. }
  903. }
  904. #endregion
  905. #region public
  906. public void ListZones(HttpContext context)
  907. {
  908. UserSession session = context.GetCurrentSession();
  909. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.View))
  910. throw new DnsWebServiceException("Access was denied.");
  911. HttpRequest request = context.Request;
  912. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  913. IReadOnlyList<AuthZoneInfo> zones;
  914. if (request.TryGetQueryOrForm("pageNumber", int.Parse, out int pageNumber))
  915. {
  916. int zonesPerPage = request.GetQueryOrForm("zonesPerPage", int.Parse, 10);
  917. AuthZoneManager.ZonesPage page = _dnsWebService.DnsServer.AuthZoneManager.GetZonesPage(pageNumber, zonesPerPage);
  918. zones = page.Zones;
  919. jsonWriter.WriteNumber("pageNumber", page.PageNumber);
  920. jsonWriter.WriteNumber("totalPages", page.TotalPages);
  921. jsonWriter.WriteNumber("totalZones", page.TotalZones);
  922. }
  923. else
  924. {
  925. zones = _dnsWebService.DnsServer.AuthZoneManager.GetAllZones();
  926. }
  927. jsonWriter.WritePropertyName("zones");
  928. jsonWriter.WriteStartArray();
  929. foreach (AuthZoneInfo zone in zones)
  930. {
  931. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zone.Name, session.User, PermissionFlag.View))
  932. continue;
  933. WriteZoneInfoAsJson(zone, jsonWriter);
  934. }
  935. jsonWriter.WriteEndArray();
  936. }
  937. public async Task CreateZoneAsync(HttpContext context)
  938. {
  939. UserSession session = context.GetCurrentSession();
  940. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  941. throw new DnsWebServiceException("Access was denied.");
  942. HttpRequest request = context.Request;
  943. string zoneName = request.GetQueryOrFormAlt("zone", "domain");
  944. if (zoneName.Contains('*'))
  945. throw new DnsWebServiceException("Domain name for a zone cannot contain wildcard character.");
  946. if (IPAddress.TryParse(zoneName, out IPAddress ipAddress))
  947. {
  948. zoneName = ipAddress.GetReverseDomain().ToLower();
  949. }
  950. else if (zoneName.Contains('/'))
  951. {
  952. string[] parts = zoneName.Split('/');
  953. if ((parts.Length == 2) && IPAddress.TryParse(parts[0], out ipAddress) && int.TryParse(parts[1], out int subnetMaskWidth))
  954. zoneName = Zone.GetReverseZone(ipAddress, subnetMaskWidth);
  955. }
  956. else if (zoneName.EndsWith('.'))
  957. {
  958. zoneName = zoneName.Substring(0, zoneName.Length - 1);
  959. }
  960. if (DnsClient.IsDomainNameUnicode(zoneName))
  961. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  962. AuthZoneType type = request.GetQueryOrFormEnum("type", AuthZoneType.Primary);
  963. AuthZoneInfo zoneInfo;
  964. switch (type)
  965. {
  966. case AuthZoneType.Primary:
  967. {
  968. bool useSoaSerialDateScheme = request.GetQueryOrForm("useSoaSerialDateScheme", bool.Parse, _dnsWebService.DnsServer.AuthZoneManager.UseSoaSerialDateScheme);
  969. zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(zoneName, _dnsWebService.DnsServer.ServerDomain, false, useSoaSerialDateScheme);
  970. if (zoneInfo is null)
  971. throw new DnsWebServiceException("Zone already exists: " + zoneName);
  972. //set permissions
  973. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  974. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  975. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  976. _dnsWebService._authManager.SaveConfigFile();
  977. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Authoritative primary zone was created: " + zoneName);
  978. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  979. }
  980. break;
  981. case AuthZoneType.Secondary:
  982. {
  983. string primaryNameServerAddresses = request.GetQueryOrForm("primaryNameServerAddresses", null);
  984. DnsTransportProtocol zoneTransferProtocol = request.GetQueryOrFormEnum("zoneTransferProtocol", DnsTransportProtocol.Tcp);
  985. string tsigKeyName = request.GetQueryOrForm("tsigKeyName", null);
  986. if (zoneTransferProtocol == DnsTransportProtocol.Quic)
  987. DnsWebService.ValidateQuicSupport();
  988. zoneInfo = await _dnsWebService.DnsServer.AuthZoneManager.CreateSecondaryZoneAsync(zoneName, primaryNameServerAddresses, zoneTransferProtocol, tsigKeyName);
  989. if (zoneInfo is null)
  990. throw new DnsWebServiceException("Zone already exists: " + zoneName);
  991. //set permissions
  992. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  993. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  994. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  995. _dnsWebService._authManager.SaveConfigFile();
  996. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Authoritative secondary zone was created: " + zoneName);
  997. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  998. }
  999. break;
  1000. case AuthZoneType.Stub:
  1001. {
  1002. string primaryNameServerAddresses = request.GetQueryOrForm("primaryNameServerAddresses", null);
  1003. zoneInfo = await _dnsWebService.DnsServer.AuthZoneManager.CreateStubZoneAsync(zoneName, primaryNameServerAddresses);
  1004. if (zoneInfo is null)
  1005. throw new DnsWebServiceException("Zone already exists: " + zoneName);
  1006. //set permissions
  1007. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  1008. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1009. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1010. _dnsWebService._authManager.SaveConfigFile();
  1011. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Stub zone was created: " + zoneName);
  1012. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1013. }
  1014. break;
  1015. case AuthZoneType.Forwarder:
  1016. {
  1017. DnsTransportProtocol forwarderProtocol = request.GetQueryOrFormEnum("protocol", DnsTransportProtocol.Udp);
  1018. string forwarder = request.GetQueryOrForm("forwarder");
  1019. bool dnssecValidation = request.GetQueryOrForm("dnssecValidation", bool.Parse, false);
  1020. DnsForwarderRecordProxyType proxyType = request.GetQueryOrFormEnum("proxyType", DnsForwarderRecordProxyType.DefaultProxy);
  1021. string proxyAddress = null;
  1022. ushort proxyPort = 0;
  1023. string proxyUsername = null;
  1024. string proxyPassword = null;
  1025. switch (proxyType)
  1026. {
  1027. case DnsForwarderRecordProxyType.Http:
  1028. case DnsForwarderRecordProxyType.Socks5:
  1029. proxyAddress = request.GetQueryOrForm("proxyAddress");
  1030. proxyPort = request.GetQueryOrForm("proxyPort", ushort.Parse);
  1031. proxyUsername = request.QueryOrForm("proxyUsername");
  1032. proxyPassword = request.QueryOrForm("proxyPassword");
  1033. break;
  1034. }
  1035. switch (forwarderProtocol)
  1036. {
  1037. case DnsTransportProtocol.HttpsJson:
  1038. forwarderProtocol = DnsTransportProtocol.Https;
  1039. break;
  1040. case DnsTransportProtocol.Quic:
  1041. DnsWebService.ValidateQuicSupport();
  1042. break;
  1043. }
  1044. zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreateForwarderZone(zoneName, forwarderProtocol, forwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword, null);
  1045. if (zoneInfo is null)
  1046. throw new DnsWebServiceException("Zone already exists: " + zoneName);
  1047. //set permissions
  1048. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  1049. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1050. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1051. _dnsWebService._authManager.SaveConfigFile();
  1052. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Forwarder zone was created: " + zoneName);
  1053. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1054. }
  1055. break;
  1056. default:
  1057. throw new NotSupportedException("Zone type not supported.");
  1058. }
  1059. //delete cache for this zone to allow rebuilding cache data as needed by stub or forwarder zones
  1060. _dnsWebService.DnsServer.CacheZoneManager.DeleteZone(zoneInfo.Name);
  1061. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  1062. jsonWriter.WriteString("domain", string.IsNullOrEmpty(zoneInfo.Name) ? "." : zoneInfo.Name);
  1063. }
  1064. public async Task ImportZoneAsync(HttpContext context)
  1065. {
  1066. UserSession session = context.GetCurrentSession();
  1067. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1068. throw new DnsWebServiceException("Access was denied.");
  1069. HttpRequest request = context.Request;
  1070. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1071. if (DnsClient.IsDomainNameUnicode(zoneName))
  1072. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1073. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1074. if (zoneInfo is null)
  1075. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1076. if (zoneInfo.Internal)
  1077. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1078. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  1079. throw new DnsWebServiceException("Access was denied.");
  1080. bool overwrite = request.GetQueryOrForm("overwrite", bool.Parse, true);
  1081. bool overwriteSoaSerial = request.GetQueryOrForm("overwriteSoaSerial", bool.Parse, false);
  1082. TextReader textReader;
  1083. switch (request.ContentType?.ToLowerInvariant())
  1084. {
  1085. case "application/x-www-form-urlencoded":
  1086. string zoneRecords = request.GetQueryOrForm("records");
  1087. textReader = new StringReader(zoneRecords);
  1088. break;
  1089. case "text/plain":
  1090. textReader = new StreamReader(request.Body);
  1091. break;
  1092. default:
  1093. throw new DnsWebServiceException("Content type is not supported: " + request.ContentType);
  1094. }
  1095. using TextReader zoneReader = textReader;
  1096. IReadOnlyCollection<DnsResourceRecord> records = await ZoneFile.ReadZoneFileFromAsync(zoneReader, zoneInfo.Name, _dnsWebService._zonesApi.DefaultRecordTtl);
  1097. List<DnsResourceRecord> newRecords = new List<DnsResourceRecord>(records.Count);
  1098. foreach (DnsResourceRecord record in records)
  1099. {
  1100. if (record.Class != DnsClass.IN)
  1101. throw new DnsWebServiceException("Cannot import records: only IN class is supported by the DNS server.");
  1102. switch (record.Type)
  1103. {
  1104. case DnsResourceRecordType.DNSKEY:
  1105. case DnsResourceRecordType.RRSIG:
  1106. case DnsResourceRecordType.NSEC:
  1107. case DnsResourceRecordType.NSEC3:
  1108. case DnsResourceRecordType.NSEC3PARAM:
  1109. continue; //skip DNSSEC records
  1110. case DnsResourceRecordType.SVCB:
  1111. case DnsResourceRecordType.HTTPS:
  1112. {
  1113. if (record.Tag is string comments)
  1114. {
  1115. SVCBRecordInfo rrInfo = new SVCBRecordInfo();
  1116. rrInfo.Comments = comments;
  1117. record.Tag = rrInfo;
  1118. }
  1119. if (record.RDATA is DnsSVCBRecordData rdata && (rdata.AutoIpv4Hint || rdata.AutoIpv6Hint))
  1120. {
  1121. if (rdata.AutoIpv4Hint)
  1122. record.GetAuthSVCBRecordInfo().AutoIpv4Hint = true;
  1123. if (rdata.AutoIpv6Hint)
  1124. record.GetAuthSVCBRecordInfo().AutoIpv6Hint = true;
  1125. Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(rdata.SvcParams);
  1126. DnsResourceRecord newRecord = new DnsResourceRecord(record.Name, record.Type, record.Class, record.TTL, new DnsSVCBRecordData(rdata.SvcPriority, rdata.TargetName, svcParams)) { Tag = record.Tag };
  1127. ResolveSvcbAutoHints(zoneInfo.Name, record, rdata.AutoIpv4Hint, rdata.AutoIpv6Hint, svcParams, records);
  1128. newRecords.Add(newRecord);
  1129. break;
  1130. }
  1131. newRecords.Add(record);
  1132. }
  1133. break;
  1134. default:
  1135. {
  1136. if (record.Tag is string comments)
  1137. {
  1138. GenericRecordInfo rrInfo = new GenericRecordInfo();
  1139. rrInfo.Comments = comments;
  1140. record.Tag = rrInfo;
  1141. }
  1142. newRecords.Add(record);
  1143. }
  1144. break;
  1145. }
  1146. }
  1147. _dnsWebService.DnsServer.AuthZoneManager.ImportRecords(zoneInfo.Name, newRecords, overwrite, overwriteSoaSerial);
  1148. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Total " + newRecords.Count + " record(s) were imported successfully into authoritative zone: " + zoneInfo.Name);
  1149. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1150. }
  1151. public async Task ExportZoneAsync(HttpContext context)
  1152. {
  1153. UserSession session = context.GetCurrentSession();
  1154. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.View))
  1155. throw new DnsWebServiceException("Access was denied.");
  1156. HttpRequest request = context.Request;
  1157. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1158. if (DnsClient.IsDomainNameUnicode(zoneName))
  1159. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1160. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1161. if (zoneInfo is null)
  1162. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1163. if (zoneInfo.Internal)
  1164. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1165. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
  1166. throw new DnsWebServiceException("Access was denied.");
  1167. List<DnsResourceRecord> records = new List<DnsResourceRecord>();
  1168. _dnsWebService.DnsServer.AuthZoneManager.ListAllZoneRecords(zoneInfo.Name, records);
  1169. foreach (DnsResourceRecord record in records)
  1170. {
  1171. switch (record.Type)
  1172. {
  1173. case DnsResourceRecordType.SVCB:
  1174. case DnsResourceRecordType.HTTPS:
  1175. SVCBRecordInfo info = record.GetAuthSVCBRecordInfo();
  1176. if (info.AutoIpv4Hint)
  1177. (record.RDATA as DnsSVCBRecordData).AutoIpv4Hint = true;
  1178. if (info.AutoIpv6Hint)
  1179. (record.RDATA as DnsSVCBRecordData).AutoIpv6Hint = true;
  1180. break;
  1181. }
  1182. }
  1183. HttpResponse response = context.Response;
  1184. response.ContentType = "text/plain";
  1185. response.Headers.ContentDisposition = "attachment;filename=" + (zoneInfo.Name == "." ? "root.zone" : zoneInfo.Name + ".zone");
  1186. await using (StreamWriter sW = new StreamWriter(response.Body))
  1187. {
  1188. await ZoneFile.WriteZoneFileToAsync(sW, zoneInfo.Name, records, delegate (DnsResourceRecord record)
  1189. {
  1190. if (record.Tag is null)
  1191. return null;
  1192. return record.GetAuthGenericRecordInfo().Comments;
  1193. });
  1194. }
  1195. }
  1196. public void CloneZone(HttpContext context)
  1197. {
  1198. UserSession session = context.GetCurrentSession();
  1199. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1200. throw new DnsWebServiceException("Access was denied.");
  1201. HttpRequest request = context.Request;
  1202. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1203. if (DnsClient.IsDomainNameUnicode(zoneName))
  1204. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1205. string sourceZoneName = request.GetQueryOrForm("sourceZone").TrimEnd('.');
  1206. if (DnsClient.IsDomainNameUnicode(sourceZoneName))
  1207. sourceZoneName = DnsClient.ConvertDomainNameToAscii(sourceZoneName);
  1208. AuthZoneInfo sourceZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(sourceZoneName);
  1209. if (sourceZoneInfo is null)
  1210. throw new DnsWebServiceException("No such authoritative zone was found: " + sourceZoneName);
  1211. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, sourceZoneInfo.Name, session.User, PermissionFlag.View))
  1212. throw new DnsWebServiceException("Access was denied.");
  1213. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CloneZone(zoneName, sourceZoneName);
  1214. //set permissions
  1215. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  1216. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1217. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, zoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  1218. _dnsWebService._authManager.SaveConfigFile();
  1219. //save zone
  1220. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1221. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + sourceZoneInfo.Type.ToString() + " zone '" + sourceZoneInfo.Name + "' was cloned as '" + zoneName + "' sucessfully.");
  1222. }
  1223. public void ConvertZone(HttpContext context)
  1224. {
  1225. UserSession session = context.GetCurrentSession();
  1226. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Delete))
  1227. throw new DnsWebServiceException("Access was denied.");
  1228. HttpRequest request = context.Request;
  1229. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1230. AuthZoneType type = request.GetQueryOrFormEnum<AuthZoneType>("type");
  1231. if (DnsClient.IsDomainNameUnicode(zoneName))
  1232. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1233. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1234. if (zoneInfo is null)
  1235. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1236. if (zoneInfo.Internal)
  1237. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1238. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
  1239. throw new DnsWebServiceException("Access was denied.");
  1240. _dnsWebService.DnsServer.AuthZoneManager.ConvertZoneType(zoneInfo.Name, type);
  1241. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1242. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone '" + zoneInfo.Name + "' was converted to " + type.ToString() + " zone sucessfully.");
  1243. }
  1244. public void SignPrimaryZone(HttpContext context)
  1245. {
  1246. UserSession session = context.GetCurrentSession();
  1247. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1248. throw new DnsWebServiceException("Access was denied.");
  1249. HttpRequest request = context.Request;
  1250. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1251. if (DnsClient.IsDomainNameUnicode(zoneName))
  1252. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1253. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1254. throw new DnsWebServiceException("Access was denied.");
  1255. string algorithm = request.GetQueryOrForm("algorithm");
  1256. uint dnsKeyTtl = request.GetQueryOrForm<uint>("dnsKeyTtl", uint.Parse, 24 * 60 * 60);
  1257. ushort zskRolloverDays = request.GetQueryOrForm<ushort>("zskRolloverDays", ushort.Parse, 30);
  1258. bool useNSEC3 = false;
  1259. string strNxProof = request.QueryOrForm("nxProof");
  1260. if (!string.IsNullOrEmpty(strNxProof))
  1261. {
  1262. switch (strNxProof.ToUpper())
  1263. {
  1264. case "NSEC":
  1265. useNSEC3 = false;
  1266. break;
  1267. case "NSEC3":
  1268. useNSEC3 = true;
  1269. break;
  1270. default:
  1271. throw new NotSupportedException("Non-existence proof type is not supported: " + strNxProof);
  1272. }
  1273. }
  1274. ushort iterations = 0;
  1275. byte saltLength = 0;
  1276. if (useNSEC3)
  1277. {
  1278. iterations = request.GetQueryOrForm<ushort>("iterations", ushort.Parse, 0);
  1279. saltLength = request.GetQueryOrForm<byte>("saltLength", byte.Parse, 0);
  1280. }
  1281. switch (algorithm.ToUpper())
  1282. {
  1283. case "RSA":
  1284. string hashAlgorithm = request.GetQueryOrForm("hashAlgorithm");
  1285. int kskKeySize = request.GetQueryOrForm("kskKeySize", int.Parse);
  1286. int zskKeySize = request.GetQueryOrForm("zskKeySize", int.Parse);
  1287. if (useNSEC3)
  1288. _dnsWebService.DnsServer.AuthZoneManager.SignPrimaryZoneWithRsaNSEC3(zoneName, hashAlgorithm, kskKeySize, zskKeySize, iterations, saltLength, dnsKeyTtl, zskRolloverDays);
  1289. else
  1290. _dnsWebService.DnsServer.AuthZoneManager.SignPrimaryZoneWithRsaNSEC(zoneName, hashAlgorithm, kskKeySize, zskKeySize, dnsKeyTtl, zskRolloverDays);
  1291. break;
  1292. case "ECDSA":
  1293. string curve = request.GetQueryOrForm("curve");
  1294. if (useNSEC3)
  1295. _dnsWebService.DnsServer.AuthZoneManager.SignPrimaryZoneWithEcdsaNSEC3(zoneName, curve, iterations, saltLength, dnsKeyTtl, zskRolloverDays);
  1296. else
  1297. _dnsWebService.DnsServer.AuthZoneManager.SignPrimaryZoneWithEcdsaNSEC(zoneName, curve, dnsKeyTtl, zskRolloverDays);
  1298. break;
  1299. default:
  1300. throw new NotSupportedException("Algorithm is not supported: " + algorithm);
  1301. }
  1302. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone was signed successfully: " + zoneName);
  1303. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1304. }
  1305. public void UnsignPrimaryZone(HttpContext context)
  1306. {
  1307. UserSession session = context.GetCurrentSession();
  1308. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1309. throw new DnsWebServiceException("Access was denied.");
  1310. string zoneName = context.Request.GetQueryOrForm("zone").TrimEnd('.');
  1311. if (DnsClient.IsDomainNameUnicode(zoneName))
  1312. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1313. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1314. throw new DnsWebServiceException("Access was denied.");
  1315. _dnsWebService.DnsServer.AuthZoneManager.UnsignPrimaryZone(zoneName);
  1316. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone was unsigned successfully: " + zoneName);
  1317. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1318. }
  1319. public void GetPrimaryZoneDsInfo(HttpContext context)
  1320. {
  1321. UserSession session = context.GetCurrentSession();
  1322. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.View))
  1323. throw new DnsWebServiceException("Access was denied.");
  1324. string zoneName = context.Request.GetQueryOrForm("zone").TrimEnd('.');
  1325. if (DnsClient.IsDomainNameUnicode(zoneName))
  1326. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1327. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1328. if (zoneInfo is null)
  1329. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1330. if (zoneInfo.Internal)
  1331. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1332. if (zoneInfo.Type != AuthZoneType.Primary)
  1333. throw new DnsWebServiceException("The zone must be a primary zone.");
  1334. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
  1335. throw new DnsWebServiceException("Access was denied.");
  1336. if (zoneInfo.DnssecStatus == AuthZoneDnssecStatus.Unsigned)
  1337. throw new DnsWebServiceException("The zone must be signed with DNSSEC.");
  1338. IReadOnlyList<DnsResourceRecord> dnsKeyRecords = zoneInfo.GetApexRecords(DnsResourceRecordType.DNSKEY);
  1339. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  1340. jsonWriter.WriteString("name", zoneInfo.Name);
  1341. jsonWriter.WriteString("type", zoneInfo.Type.ToString());
  1342. jsonWriter.WriteBoolean("internal", zoneInfo.Internal);
  1343. jsonWriter.WriteBoolean("disabled", zoneInfo.Disabled);
  1344. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  1345. jsonWriter.WritePropertyName("dsRecords");
  1346. jsonWriter.WriteStartArray();
  1347. foreach (DnsResourceRecord record in dnsKeyRecords)
  1348. {
  1349. if (record.RDATA is DnsDNSKEYRecordData rdata && rdata.Flags.HasFlag(DnsDnsKeyFlag.SecureEntryPoint))
  1350. {
  1351. jsonWriter.WriteStartObject();
  1352. jsonWriter.WriteNumber("keyTag", rdata.ComputedKeyTag);
  1353. IReadOnlyCollection<DnssecPrivateKey> dnssecPrivateKeys = zoneInfo.DnssecPrivateKeys;
  1354. if (dnssecPrivateKeys is not null)
  1355. {
  1356. foreach (DnssecPrivateKey dnssecPrivateKey in dnssecPrivateKeys)
  1357. {
  1358. if ((dnssecPrivateKey.KeyType == DnssecPrivateKeyType.KeySigningKey) && (dnssecPrivateKey.KeyTag == rdata.ComputedKeyTag))
  1359. {
  1360. jsonWriter.WriteString("dnsKeyState", dnssecPrivateKey.State.ToString());
  1361. if (dnssecPrivateKey.State == DnssecPrivateKeyState.Published)
  1362. jsonWriter.WriteString("dnsKeyStateReadyBy", (zoneInfo.ApexZone as PrimaryZone).GetDnsKeyStateReadyBy(dnssecPrivateKey));
  1363. break;
  1364. }
  1365. }
  1366. }
  1367. jsonWriter.WriteString("algorithm", rdata.Algorithm.ToString());
  1368. jsonWriter.WriteString("publicKey", rdata.PublicKey.ToString());
  1369. jsonWriter.WritePropertyName("digests");
  1370. jsonWriter.WriteStartArray();
  1371. {
  1372. jsonWriter.WriteStartObject();
  1373. jsonWriter.WriteString("digestType", "SHA256");
  1374. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.CreateDS(record.Name, DnssecDigestType.SHA256).Digest));
  1375. jsonWriter.WriteEndObject();
  1376. }
  1377. {
  1378. jsonWriter.WriteStartObject();
  1379. jsonWriter.WriteString("digestType", "SHA384");
  1380. jsonWriter.WriteString("digest", Convert.ToHexString(rdata.CreateDS(record.Name, DnssecDigestType.SHA384).Digest));
  1381. jsonWriter.WriteEndObject();
  1382. }
  1383. jsonWriter.WriteEndArray();
  1384. jsonWriter.WriteEndObject();
  1385. }
  1386. }
  1387. jsonWriter.WriteEndArray();
  1388. }
  1389. public void GetPrimaryZoneDnssecProperties(HttpContext context)
  1390. {
  1391. UserSession session = context.GetCurrentSession();
  1392. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1393. throw new DnsWebServiceException("Access was denied.");
  1394. string zoneName = context.Request.GetQueryOrForm("zone").TrimEnd('.');
  1395. if (DnsClient.IsDomainNameUnicode(zoneName))
  1396. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1397. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1398. if (zoneInfo is null)
  1399. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1400. if (zoneInfo.Internal)
  1401. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1402. if (zoneInfo.Type != AuthZoneType.Primary)
  1403. throw new DnsWebServiceException("The zone must be a primary zone.");
  1404. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
  1405. throw new DnsWebServiceException("Access was denied.");
  1406. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  1407. jsonWriter.WriteString("name", zoneInfo.Name);
  1408. jsonWriter.WriteString("type", zoneInfo.Type.ToString());
  1409. jsonWriter.WriteBoolean("internal", zoneInfo.Internal);
  1410. jsonWriter.WriteBoolean("disabled", zoneInfo.Disabled);
  1411. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  1412. if (zoneInfo.DnssecStatus == AuthZoneDnssecStatus.SignedWithNSEC3)
  1413. {
  1414. IReadOnlyList<DnsResourceRecord> nsec3ParamRecords = zoneInfo.GetApexRecords(DnsResourceRecordType.NSEC3PARAM);
  1415. DnsNSEC3PARAMRecordData nsec3Param = nsec3ParamRecords[0].RDATA as DnsNSEC3PARAMRecordData;
  1416. jsonWriter.WriteNumber("nsec3Iterations", nsec3Param.Iterations);
  1417. jsonWriter.WriteNumber("nsec3SaltLength", nsec3Param.Salt.Length);
  1418. }
  1419. jsonWriter.WriteNumber("dnsKeyTtl", zoneInfo.DnsKeyTtl);
  1420. jsonWriter.WritePropertyName("dnssecPrivateKeys");
  1421. jsonWriter.WriteStartArray();
  1422. IReadOnlyCollection<DnssecPrivateKey> dnssecPrivateKeys = zoneInfo.DnssecPrivateKeys;
  1423. if (dnssecPrivateKeys is not null)
  1424. {
  1425. List<DnssecPrivateKey> sortedDnssecPrivateKey = new List<DnssecPrivateKey>(dnssecPrivateKeys);
  1426. sortedDnssecPrivateKey.Sort(delegate (DnssecPrivateKey key1, DnssecPrivateKey key2)
  1427. {
  1428. int value = key1.KeyType.CompareTo(key2.KeyType);
  1429. if (value == 0)
  1430. value = key1.StateChangedOn.CompareTo(key2.StateChangedOn);
  1431. return value;
  1432. });
  1433. foreach (DnssecPrivateKey dnssecPrivateKey in sortedDnssecPrivateKey)
  1434. {
  1435. jsonWriter.WriteStartObject();
  1436. jsonWriter.WriteNumber("keyTag", dnssecPrivateKey.KeyTag);
  1437. jsonWriter.WriteString("keyType", dnssecPrivateKey.KeyType.ToString());
  1438. switch (dnssecPrivateKey.Algorithm)
  1439. {
  1440. case DnssecAlgorithm.RSAMD5:
  1441. case DnssecAlgorithm.RSASHA1:
  1442. case DnssecAlgorithm.RSASHA1_NSEC3_SHA1:
  1443. case DnssecAlgorithm.RSASHA256:
  1444. case DnssecAlgorithm.RSASHA512:
  1445. jsonWriter.WriteString("algorithm", dnssecPrivateKey.Algorithm.ToString() + " (" + (dnssecPrivateKey as DnssecRsaPrivateKey).KeySize + " bits)");
  1446. break;
  1447. default:
  1448. jsonWriter.WriteString("algorithm", dnssecPrivateKey.Algorithm.ToString());
  1449. break;
  1450. }
  1451. jsonWriter.WriteString("state", dnssecPrivateKey.State.ToString());
  1452. jsonWriter.WriteString("stateChangedOn", dnssecPrivateKey.StateChangedOn);
  1453. if ((dnssecPrivateKey.KeyType == DnssecPrivateKeyType.KeySigningKey) && (dnssecPrivateKey.State == DnssecPrivateKeyState.Published))
  1454. jsonWriter.WriteString("stateReadyBy", (zoneInfo.ApexZone as PrimaryZone).GetDnsKeyStateReadyBy(dnssecPrivateKey));
  1455. jsonWriter.WriteBoolean("isRetiring", dnssecPrivateKey.IsRetiring);
  1456. jsonWriter.WriteNumber("rolloverDays", dnssecPrivateKey.RolloverDays);
  1457. jsonWriter.WriteEndObject();
  1458. }
  1459. }
  1460. jsonWriter.WriteEndArray();
  1461. }
  1462. public void ConvertPrimaryZoneToNSEC(HttpContext context)
  1463. {
  1464. UserSession session = context.GetCurrentSession();
  1465. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1466. throw new DnsWebServiceException("Access was denied.");
  1467. string zoneName = context.Request.GetQueryOrForm("zone").TrimEnd('.');
  1468. if (DnsClient.IsDomainNameUnicode(zoneName))
  1469. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1470. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1471. throw new DnsWebServiceException("Access was denied.");
  1472. _dnsWebService.DnsServer.AuthZoneManager.ConvertPrimaryZoneToNSEC(zoneName);
  1473. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone was converted to NSEC successfully: " + zoneName);
  1474. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1475. }
  1476. public void ConvertPrimaryZoneToNSEC3(HttpContext context)
  1477. {
  1478. UserSession session = context.GetCurrentSession();
  1479. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1480. throw new DnsWebServiceException("Access was denied.");
  1481. HttpRequest request = context.Request;
  1482. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1483. if (DnsClient.IsDomainNameUnicode(zoneName))
  1484. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1485. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1486. throw new DnsWebServiceException("Access was denied.");
  1487. ushort iterations = request.GetQueryOrForm<ushort>("iterations", ushort.Parse, 0);
  1488. byte saltLength = request.GetQueryOrForm<byte>("saltLength", byte.Parse, 0);
  1489. _dnsWebService.DnsServer.AuthZoneManager.ConvertPrimaryZoneToNSEC3(zoneName, iterations, saltLength);
  1490. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone was converted to NSEC3 successfully: " + zoneName);
  1491. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1492. }
  1493. public void UpdatePrimaryZoneNSEC3Parameters(HttpContext context)
  1494. {
  1495. UserSession session = context.GetCurrentSession();
  1496. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1497. throw new DnsWebServiceException("Access was denied.");
  1498. HttpRequest request = context.Request;
  1499. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1500. if (DnsClient.IsDomainNameUnicode(zoneName))
  1501. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1502. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1503. throw new DnsWebServiceException("Access was denied.");
  1504. ushort iterations = request.GetQueryOrForm<ushort>("iterations", ushort.Parse, 0);
  1505. byte saltLength = request.GetQueryOrForm<byte>("saltLength", byte.Parse, 0);
  1506. _dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneNSEC3Parameters(zoneName, iterations, saltLength);
  1507. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone NSEC3 parameters were updated successfully: " + zoneName);
  1508. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1509. }
  1510. public void UpdatePrimaryZoneDnssecDnsKeyTtl(HttpContext context)
  1511. {
  1512. UserSession session = context.GetCurrentSession();
  1513. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1514. throw new DnsWebServiceException("Access was denied.");
  1515. HttpRequest request = context.Request;
  1516. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1517. if (DnsClient.IsDomainNameUnicode(zoneName))
  1518. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1519. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1520. throw new DnsWebServiceException("Access was denied.");
  1521. uint dnsKeyTtl = request.GetQueryOrForm("ttl", uint.Parse);
  1522. _dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneDnsKeyTtl(zoneName, dnsKeyTtl);
  1523. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone DNSKEY TTL was updated successfully: " + zoneName);
  1524. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1525. }
  1526. public void GenerateAndAddPrimaryZoneDnssecPrivateKey(HttpContext context)
  1527. {
  1528. UserSession session = context.GetCurrentSession();
  1529. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1530. throw new DnsWebServiceException("Access was denied.");
  1531. HttpRequest request = context.Request;
  1532. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1533. if (DnsClient.IsDomainNameUnicode(zoneName))
  1534. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1535. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1536. throw new DnsWebServiceException("Access was denied.");
  1537. DnssecPrivateKeyType keyType = request.GetQueryOrFormEnum<DnssecPrivateKeyType>("keyType");
  1538. ushort rolloverDays = request.GetQueryOrForm("rolloverDays", ushort.Parse, (ushort)(keyType == DnssecPrivateKeyType.ZoneSigningKey ? 30 : 0));
  1539. string algorithm = request.GetQueryOrForm("algorithm");
  1540. switch (algorithm.ToUpper())
  1541. {
  1542. case "RSA":
  1543. string hashAlgorithm = request.GetQueryOrForm("hashAlgorithm");
  1544. int keySize = request.GetQueryOrForm("keySize", int.Parse);
  1545. _dnsWebService.DnsServer.AuthZoneManager.GenerateAndAddPrimaryZoneDnssecRsaPrivateKey(zoneName, keyType, hashAlgorithm, keySize, rolloverDays);
  1546. break;
  1547. case "ECDSA":
  1548. string curve = request.GetQueryOrForm("curve");
  1549. _dnsWebService.DnsServer.AuthZoneManager.GenerateAndAddPrimaryZoneDnssecEcdsaPrivateKey(zoneName, keyType, curve, rolloverDays);
  1550. break;
  1551. default:
  1552. throw new NotSupportedException("Algorithm is not supported: " + algorithm);
  1553. }
  1554. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] DNSSEC private key was generated and added to the primary zone successfully: " + zoneName);
  1555. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1556. }
  1557. public void UpdatePrimaryZoneDnssecPrivateKey(HttpContext context)
  1558. {
  1559. UserSession session = context.GetCurrentSession();
  1560. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1561. throw new DnsWebServiceException("Access was denied.");
  1562. HttpRequest request = context.Request;
  1563. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1564. if (DnsClient.IsDomainNameUnicode(zoneName))
  1565. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1566. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1567. throw new DnsWebServiceException("Access was denied.");
  1568. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  1569. ushort rolloverDays = request.GetQueryOrForm("rolloverDays", ushort.Parse);
  1570. _dnsWebService.DnsServer.AuthZoneManager.UpdatePrimaryZoneDnssecPrivateKey(zoneName, keyTag, rolloverDays);
  1571. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Primary zone DNSSEC private key config was updated successfully: " + zoneName);
  1572. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1573. }
  1574. public void DeletePrimaryZoneDnssecPrivateKey(HttpContext context)
  1575. {
  1576. UserSession session = context.GetCurrentSession();
  1577. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1578. throw new DnsWebServiceException("Access was denied.");
  1579. HttpRequest request = context.Request;
  1580. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1581. if (DnsClient.IsDomainNameUnicode(zoneName))
  1582. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1583. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1584. throw new DnsWebServiceException("Access was denied.");
  1585. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  1586. _dnsWebService.DnsServer.AuthZoneManager.DeletePrimaryZoneDnssecPrivateKey(zoneName, keyTag);
  1587. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] DNSSEC private key was deleted from primary zone successfully: " + zoneName);
  1588. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1589. }
  1590. public void PublishAllGeneratedPrimaryZoneDnssecPrivateKeys(HttpContext context)
  1591. {
  1592. UserSession session = context.GetCurrentSession();
  1593. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1594. throw new DnsWebServiceException("Access was denied.");
  1595. string zoneName = context.Request.GetQueryOrForm("zone").TrimEnd('.');
  1596. if (DnsClient.IsDomainNameUnicode(zoneName))
  1597. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1598. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1599. throw new DnsWebServiceException("Access was denied.");
  1600. _dnsWebService.DnsServer.AuthZoneManager.PublishAllGeneratedPrimaryZoneDnssecPrivateKeys(zoneName);
  1601. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] All DNSSEC private keys from the primary zone were published successfully: " + zoneName);
  1602. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1603. }
  1604. public void RolloverPrimaryZoneDnsKey(HttpContext context)
  1605. {
  1606. UserSession session = context.GetCurrentSession();
  1607. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1608. throw new DnsWebServiceException("Access was denied.");
  1609. HttpRequest request = context.Request;
  1610. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1611. if (DnsClient.IsDomainNameUnicode(zoneName))
  1612. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1613. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1614. throw new DnsWebServiceException("Access was denied.");
  1615. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  1616. _dnsWebService.DnsServer.AuthZoneManager.RolloverPrimaryZoneDnsKey(zoneName, keyTag);
  1617. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] The DNSKEY (" + keyTag + ") from the primary zone was rolled over successfully: " + zoneName);
  1618. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1619. }
  1620. public void RetirePrimaryZoneDnsKey(HttpContext context)
  1621. {
  1622. UserSession session = context.GetCurrentSession();
  1623. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1624. throw new DnsWebServiceException("Access was denied.");
  1625. HttpRequest request = context.Request;
  1626. string zoneName = request.GetQueryOrForm("zone").TrimEnd('.');
  1627. if (DnsClient.IsDomainNameUnicode(zoneName))
  1628. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1629. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneName, session.User, PermissionFlag.Delete))
  1630. throw new DnsWebServiceException("Access was denied.");
  1631. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  1632. _dnsWebService.DnsServer.AuthZoneManager.RetirePrimaryZoneDnsKey(zoneName, keyTag);
  1633. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] The DNSKEY (" + keyTag + ") from the primary zone was retired successfully: " + zoneName);
  1634. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneName);
  1635. }
  1636. public void DeleteZone(HttpContext context)
  1637. {
  1638. UserSession session = context.GetCurrentSession();
  1639. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Delete))
  1640. throw new DnsWebServiceException("Access was denied.");
  1641. string zoneName = context.Request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1642. if (DnsClient.IsDomainNameUnicode(zoneName))
  1643. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1644. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1645. if (zoneInfo is null)
  1646. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1647. if (zoneInfo.Internal)
  1648. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1649. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
  1650. throw new DnsWebServiceException("Access was denied.");
  1651. if (!_dnsWebService.DnsServer.AuthZoneManager.DeleteZone(zoneInfo.Name))
  1652. throw new DnsWebServiceException("Failed to delete the zone: " + zoneInfo.Name);
  1653. _dnsWebService._authManager.RemoveAllPermissions(PermissionSection.Zones, zoneInfo.Name);
  1654. _dnsWebService._authManager.SaveConfigFile();
  1655. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was deleted: " + zoneName);
  1656. _dnsWebService.DnsServer.AuthZoneManager.DeleteZoneFile(zoneInfo.Name);
  1657. }
  1658. public void EnableZone(HttpContext context)
  1659. {
  1660. UserSession session = context.GetCurrentSession();
  1661. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1662. throw new DnsWebServiceException("Access was denied.");
  1663. string zoneName = context.Request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1664. if (DnsClient.IsDomainNameUnicode(zoneName))
  1665. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1666. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1667. if (zoneInfo is null)
  1668. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1669. if (zoneInfo.Internal)
  1670. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1671. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  1672. throw new DnsWebServiceException("Access was denied.");
  1673. zoneInfo.Disabled = false;
  1674. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was enabled: " + zoneInfo.Name);
  1675. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1676. //delete cache for this zone to allow rebuilding cache data as needed by stub or forwarder zones
  1677. _dnsWebService.DnsServer.CacheZoneManager.DeleteZone(zoneInfo.Name);
  1678. }
  1679. public void DisableZone(HttpContext context)
  1680. {
  1681. UserSession session = context.GetCurrentSession();
  1682. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1683. throw new DnsWebServiceException("Access was denied.");
  1684. string zoneName = context.Request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1685. if (DnsClient.IsDomainNameUnicode(zoneName))
  1686. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1687. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1688. if (zoneInfo is null)
  1689. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1690. if (zoneInfo.Internal)
  1691. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1692. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  1693. throw new DnsWebServiceException("Access was denied.");
  1694. zoneInfo.Disabled = true;
  1695. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone was disabled: " + zoneInfo.Name);
  1696. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1697. }
  1698. public void GetZoneOptions(HttpContext context)
  1699. {
  1700. UserSession session = context.GetCurrentSession();
  1701. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1702. throw new DnsWebServiceException("Access was denied.");
  1703. HttpRequest request = context.Request;
  1704. string zoneName = request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1705. if (DnsClient.IsDomainNameUnicode(zoneName))
  1706. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1707. bool includeAvailableTsigKeyNames = request.GetQueryOrForm("includeAvailableTsigKeyNames", bool.Parse, false);
  1708. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1709. if (zoneInfo is null)
  1710. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1711. if (zoneInfo.Internal)
  1712. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1713. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
  1714. throw new DnsWebServiceException("Access was denied.");
  1715. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  1716. jsonWriter.WriteString("name", zoneInfo.Name);
  1717. if (DnsClient.TryConvertDomainNameToUnicode(zoneInfo.Name, out string nameIdn))
  1718. jsonWriter.WriteString("nameIdn", nameIdn);
  1719. jsonWriter.WriteString("type", zoneInfo.Type.ToString());
  1720. switch (zoneInfo.Type)
  1721. {
  1722. case AuthZoneType.Primary:
  1723. jsonWriter.WriteBoolean("internal", zoneInfo.Internal);
  1724. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  1725. if (!zoneInfo.Internal)
  1726. {
  1727. string[] notifyFailed = zoneInfo.NotifyFailed;
  1728. jsonWriter.WriteBoolean("notifyFailed", notifyFailed.Length > 0);
  1729. jsonWriter.WritePropertyName("notifyFailedFor");
  1730. jsonWriter.WriteStartArray();
  1731. foreach (string server in notifyFailed)
  1732. jsonWriter.WriteStringValue(server);
  1733. jsonWriter.WriteEndArray();
  1734. }
  1735. break;
  1736. case AuthZoneType.Secondary:
  1737. jsonWriter.WriteString("dnssecStatus", zoneInfo.DnssecStatus.ToString());
  1738. {
  1739. string[] notifyFailed = zoneInfo.NotifyFailed;
  1740. jsonWriter.WriteBoolean("notifyFailed", notifyFailed.Length > 0);
  1741. jsonWriter.WritePropertyName("notifyFailedFor");
  1742. jsonWriter.WriteStartArray();
  1743. foreach (string server in notifyFailed)
  1744. jsonWriter.WriteStringValue(server);
  1745. jsonWriter.WriteEndArray();
  1746. }
  1747. break;
  1748. }
  1749. jsonWriter.WriteBoolean("disabled", zoneInfo.Disabled);
  1750. switch (zoneInfo.Type)
  1751. {
  1752. case AuthZoneType.Primary:
  1753. case AuthZoneType.Secondary:
  1754. jsonWriter.WriteString("zoneTransfer", zoneInfo.ZoneTransfer.ToString());
  1755. jsonWriter.WritePropertyName("zoneTransferNameServers");
  1756. {
  1757. jsonWriter.WriteStartArray();
  1758. if (zoneInfo.ZoneTransferNameServers is not null)
  1759. {
  1760. foreach (NetworkAddress networkAddress in zoneInfo.ZoneTransferNameServers)
  1761. jsonWriter.WriteStringValue(networkAddress.ToString());
  1762. }
  1763. jsonWriter.WriteEndArray();
  1764. }
  1765. jsonWriter.WritePropertyName("zoneTransferTsigKeyNames");
  1766. {
  1767. jsonWriter.WriteStartArray();
  1768. if (zoneInfo.ZoneTransferTsigKeyNames is not null)
  1769. {
  1770. foreach (KeyValuePair<string, object> tsigKeyName in zoneInfo.ZoneTransferTsigKeyNames)
  1771. jsonWriter.WriteStringValue(tsigKeyName.Key);
  1772. }
  1773. jsonWriter.WriteEndArray();
  1774. }
  1775. jsonWriter.WriteString("notify", zoneInfo.Notify.ToString());
  1776. jsonWriter.WritePropertyName("notifyNameServers");
  1777. {
  1778. jsonWriter.WriteStartArray();
  1779. if (zoneInfo.NotifyNameServers is not null)
  1780. {
  1781. foreach (IPAddress nameServer in zoneInfo.NotifyNameServers)
  1782. jsonWriter.WriteStringValue(nameServer.ToString());
  1783. }
  1784. jsonWriter.WriteEndArray();
  1785. }
  1786. break;
  1787. }
  1788. switch (zoneInfo.Type)
  1789. {
  1790. case AuthZoneType.Primary:
  1791. case AuthZoneType.Secondary:
  1792. case AuthZoneType.Forwarder:
  1793. jsonWriter.WriteString("update", zoneInfo.Update.ToString());
  1794. jsonWriter.WritePropertyName("updateIpAddresses");
  1795. {
  1796. jsonWriter.WriteStartArray();
  1797. if (zoneInfo.UpdateIpAddresses is not null)
  1798. {
  1799. foreach (NetworkAddress networkAddress in zoneInfo.UpdateIpAddresses)
  1800. jsonWriter.WriteStringValue(networkAddress.ToString());
  1801. }
  1802. jsonWriter.WriteEndArray();
  1803. }
  1804. break;
  1805. }
  1806. switch (zoneInfo.Type)
  1807. {
  1808. case AuthZoneType.Primary:
  1809. case AuthZoneType.Forwarder:
  1810. jsonWriter.WritePropertyName("updateSecurityPolicies");
  1811. {
  1812. jsonWriter.WriteStartArray();
  1813. if (zoneInfo.UpdateSecurityPolicies is not null)
  1814. {
  1815. foreach (KeyValuePair<string, IReadOnlyDictionary<string, IReadOnlyList<DnsResourceRecordType>>> updateSecurityPolicy in zoneInfo.UpdateSecurityPolicies)
  1816. {
  1817. foreach (KeyValuePair<string, IReadOnlyList<DnsResourceRecordType>> policy in updateSecurityPolicy.Value)
  1818. {
  1819. jsonWriter.WriteStartObject();
  1820. jsonWriter.WriteString("tsigKeyName", updateSecurityPolicy.Key);
  1821. jsonWriter.WriteString("domain", policy.Key);
  1822. jsonWriter.WritePropertyName("allowedTypes");
  1823. jsonWriter.WriteStartArray();
  1824. foreach (DnsResourceRecordType allowedType in policy.Value)
  1825. jsonWriter.WriteStringValue(allowedType.ToString());
  1826. jsonWriter.WriteEndArray();
  1827. jsonWriter.WriteEndObject();
  1828. }
  1829. }
  1830. }
  1831. jsonWriter.WriteEndArray();
  1832. }
  1833. break;
  1834. }
  1835. if (includeAvailableTsigKeyNames)
  1836. {
  1837. jsonWriter.WritePropertyName("availableTsigKeyNames");
  1838. {
  1839. jsonWriter.WriteStartArray();
  1840. if (_dnsWebService.DnsServer.TsigKeys is not null)
  1841. {
  1842. foreach (KeyValuePair<string, TsigKey> tsigKey in _dnsWebService.DnsServer.TsigKeys)
  1843. jsonWriter.WriteStringValue(tsigKey.Key);
  1844. }
  1845. jsonWriter.WriteEndArray();
  1846. }
  1847. }
  1848. }
  1849. public void SetZoneOptions(HttpContext context)
  1850. {
  1851. UserSession session = context.GetCurrentSession();
  1852. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1853. throw new DnsWebServiceException("Access was denied.");
  1854. HttpRequest request = context.Request;
  1855. string zoneName = request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1856. if (DnsClient.IsDomainNameUnicode(zoneName))
  1857. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1858. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1859. if (zoneInfo is null)
  1860. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1861. if (zoneInfo.Internal)
  1862. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1863. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
  1864. throw new DnsWebServiceException("Access was denied.");
  1865. if (request.TryGetQueryOrForm("disabled", bool.Parse, out bool disabled))
  1866. zoneInfo.Disabled = disabled;
  1867. switch (zoneInfo.Type)
  1868. {
  1869. case AuthZoneType.Primary:
  1870. case AuthZoneType.Secondary:
  1871. if (request.TryGetQueryOrFormEnum("zoneTransfer", out AuthZoneTransfer zoneTransfer))
  1872. zoneInfo.ZoneTransfer = zoneTransfer;
  1873. string strZoneTransferNameServers = request.QueryOrForm("zoneTransferNameServers");
  1874. if (strZoneTransferNameServers is not null)
  1875. {
  1876. if ((strZoneTransferNameServers.Length == 0) || strZoneTransferNameServers.Equals("false", StringComparison.OrdinalIgnoreCase))
  1877. zoneInfo.ZoneTransferNameServers = null;
  1878. else
  1879. zoneInfo.ZoneTransferNameServers = strZoneTransferNameServers.Split(NetworkAddress.Parse, ',');
  1880. }
  1881. string strZoneTransferTsigKeyNames = request.QueryOrForm("zoneTransferTsigKeyNames");
  1882. if (strZoneTransferTsigKeyNames is not null)
  1883. {
  1884. if ((strZoneTransferTsigKeyNames.Length == 0) || strZoneTransferTsigKeyNames.Equals("false", StringComparison.OrdinalIgnoreCase))
  1885. {
  1886. zoneInfo.ZoneTransferTsigKeyNames = null;
  1887. }
  1888. else
  1889. {
  1890. string[] strZoneTransferTsigKeyNamesParts = strZoneTransferTsigKeyNames.Split(_commaSeparator, StringSplitOptions.RemoveEmptyEntries);
  1891. Dictionary<string, object> zoneTransferTsigKeyNames = new Dictionary<string, object>(strZoneTransferTsigKeyNamesParts.Length);
  1892. for (int i = 0; i < strZoneTransferTsigKeyNamesParts.Length; i++)
  1893. zoneTransferTsigKeyNames.Add(strZoneTransferTsigKeyNamesParts[i].ToLower(), null);
  1894. zoneInfo.ZoneTransferTsigKeyNames = zoneTransferTsigKeyNames;
  1895. }
  1896. }
  1897. if (request.TryGetQueryOrFormEnum("notify", out AuthZoneNotify notify))
  1898. zoneInfo.Notify = notify;
  1899. string strNotifyNameServers = request.QueryOrForm("notifyNameServers");
  1900. if (strNotifyNameServers is not null)
  1901. {
  1902. if ((strNotifyNameServers.Length == 0) || strNotifyNameServers.Equals("false", StringComparison.OrdinalIgnoreCase))
  1903. zoneInfo.NotifyNameServers = null;
  1904. else
  1905. zoneInfo.NotifyNameServers = strNotifyNameServers.Split(IPAddress.Parse, ',');
  1906. }
  1907. break;
  1908. }
  1909. switch (zoneInfo.Type)
  1910. {
  1911. case AuthZoneType.Primary:
  1912. case AuthZoneType.Secondary:
  1913. case AuthZoneType.Forwarder:
  1914. if (request.TryGetQueryOrFormEnum("update", out AuthZoneUpdate update))
  1915. zoneInfo.Update = update;
  1916. string strUpdateIpAddresses = request.QueryOrForm("updateIpAddresses");
  1917. if (strUpdateIpAddresses is not null)
  1918. {
  1919. if ((strUpdateIpAddresses.Length == 0) || strUpdateIpAddresses.Equals("false", StringComparison.OrdinalIgnoreCase))
  1920. zoneInfo.UpdateIpAddresses = null;
  1921. else
  1922. zoneInfo.UpdateIpAddresses = strUpdateIpAddresses.Split(NetworkAddress.Parse, ',');
  1923. }
  1924. break;
  1925. }
  1926. switch (zoneInfo.Type)
  1927. {
  1928. case AuthZoneType.Primary:
  1929. case AuthZoneType.Forwarder:
  1930. string strUpdateSecurityPolicies = request.QueryOrForm("updateSecurityPolicies");
  1931. if (strUpdateSecurityPolicies is not null)
  1932. {
  1933. if ((strUpdateSecurityPolicies.Length == 0) || strUpdateSecurityPolicies.Equals("false", StringComparison.OrdinalIgnoreCase))
  1934. {
  1935. zoneInfo.UpdateSecurityPolicies = null;
  1936. }
  1937. else
  1938. {
  1939. string[] strUpdateSecurityPoliciesParts = strUpdateSecurityPolicies.Split(_pipeSeparator, StringSplitOptions.RemoveEmptyEntries);
  1940. Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<DnsResourceRecordType>>> updateSecurityPolicies = new Dictionary<string, IReadOnlyDictionary<string, IReadOnlyList<DnsResourceRecordType>>>(strUpdateSecurityPoliciesParts.Length);
  1941. for (int i = 0; i < strUpdateSecurityPoliciesParts.Length; i += 3)
  1942. {
  1943. string tsigKeyName = strUpdateSecurityPoliciesParts[i].ToLower();
  1944. string domain = strUpdateSecurityPoliciesParts[i + 1].ToLower();
  1945. string strTypes = strUpdateSecurityPoliciesParts[i + 2];
  1946. if (!domain.Equals(zoneInfo.Name, StringComparison.OrdinalIgnoreCase) && !domain.EndsWith("." + zoneInfo.Name, StringComparison.OrdinalIgnoreCase))
  1947. throw new DnsWebServiceException("Cannot set Dynamic Updates security policies: the domain '" + domain + "' must be part of the current zone.");
  1948. if (!updateSecurityPolicies.TryGetValue(tsigKeyName, out IReadOnlyDictionary<string, IReadOnlyList<DnsResourceRecordType>> policyMap))
  1949. {
  1950. policyMap = new Dictionary<string, IReadOnlyList<DnsResourceRecordType>>();
  1951. updateSecurityPolicies.Add(tsigKeyName, policyMap);
  1952. }
  1953. if (!policyMap.TryGetValue(domain, out IReadOnlyList<DnsResourceRecordType> types))
  1954. {
  1955. types = new List<DnsResourceRecordType>();
  1956. (policyMap as Dictionary<string, IReadOnlyList<DnsResourceRecordType>>).Add(domain, types);
  1957. }
  1958. foreach (string strType in strTypes.Split(_commaSpaceSeparator, StringSplitOptions.RemoveEmptyEntries))
  1959. (types as List<DnsResourceRecordType>).Add(Enum.Parse<DnsResourceRecordType>(strType, true));
  1960. }
  1961. zoneInfo.UpdateSecurityPolicies = updateSecurityPolicies;
  1962. }
  1963. }
  1964. break;
  1965. }
  1966. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] " + zoneInfo.Type.ToString() + " zone options were updated successfully: " + zoneInfo.Name);
  1967. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1968. }
  1969. public void ResyncZone(HttpContext context)
  1970. {
  1971. UserSession session = context.GetCurrentSession();
  1972. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, session.User, PermissionFlag.Modify))
  1973. throw new DnsWebServiceException("Access was denied.");
  1974. string zoneName = context.Request.GetQueryOrFormAlt("zone", "domain").TrimEnd('.');
  1975. if (DnsClient.IsDomainNameUnicode(zoneName))
  1976. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  1977. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.GetAuthZoneInfo(zoneName);
  1978. if (zoneInfo is null)
  1979. throw new DnsWebServiceException("No such authoritative zone was found: " + zoneName);
  1980. if (zoneInfo.Internal)
  1981. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  1982. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  1983. throw new DnsWebServiceException("Access was denied.");
  1984. switch (zoneInfo.Type)
  1985. {
  1986. case AuthZoneType.Secondary:
  1987. case AuthZoneType.Stub:
  1988. zoneInfo.TriggerResync();
  1989. break;
  1990. default:
  1991. throw new DnsWebServiceException("Only Secondary and Stub zones support resync.");
  1992. }
  1993. }
  1994. public void AddRecord(HttpContext context)
  1995. {
  1996. HttpRequest request = context.Request;
  1997. string domain = request.GetQueryOrForm("domain").TrimEnd('.');
  1998. if (DnsClient.IsDomainNameUnicode(domain))
  1999. domain = DnsClient.ConvertDomainNameToAscii(domain);
  2000. string zoneName = request.QueryOrForm("zone");
  2001. if (zoneName is not null)
  2002. {
  2003. zoneName = zoneName.TrimEnd('.');
  2004. if (DnsClient.IsDomainNameUnicode(zoneName))
  2005. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  2006. }
  2007. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(string.IsNullOrEmpty(zoneName) ? domain : zoneName);
  2008. if (zoneInfo is null)
  2009. throw new DnsWebServiceException("No such authoritative zone was found: " + domain);
  2010. if (zoneInfo.Internal)
  2011. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  2012. UserSession session = context.GetCurrentSession();
  2013. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  2014. throw new DnsWebServiceException("Access was denied.");
  2015. DnsResourceRecordType type = request.GetQueryOrFormEnum<DnsResourceRecordType>("type");
  2016. uint ttl = request.GetQueryOrForm("ttl", uint.Parse, _defaultRecordTtl);
  2017. bool overwrite = request.GetQueryOrForm("overwrite", bool.Parse, false);
  2018. string comments = request.QueryOrForm("comments");
  2019. DnsResourceRecord newRecord;
  2020. switch (type)
  2021. {
  2022. case DnsResourceRecordType.A:
  2023. case DnsResourceRecordType.AAAA:
  2024. {
  2025. string strIPAddress = request.GetQueryOrFormAlt("ipAddress", "value");
  2026. IPAddress ipAddress;
  2027. if (strIPAddress.Equals("request-ip-address"))
  2028. ipAddress = context.GetRemoteEndPoint().Address;
  2029. else
  2030. ipAddress = IPAddress.Parse(strIPAddress);
  2031. bool ptr = request.GetQueryOrForm("ptr", bool.Parse, false);
  2032. if (ptr)
  2033. {
  2034. string ptrDomain = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 32 : 128);
  2035. AuthZoneInfo reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(ptrDomain);
  2036. if (reverseZoneInfo is null)
  2037. {
  2038. bool createPtrZone = request.GetQueryOrForm("createPtrZone", bool.Parse, false);
  2039. if (!createPtrZone)
  2040. throw new DnsServerException("No reverse zone available to add PTR record.");
  2041. string ptrZone = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 24 : 64);
  2042. reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(ptrZone, _dnsWebService.DnsServer.ServerDomain, false);
  2043. if (reverseZoneInfo == null)
  2044. throw new DnsServerException("Failed to create reverse zone to add PTR record: " + ptrZone);
  2045. //set permissions
  2046. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  2047. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  2048. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, reverseZoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  2049. _dnsWebService._authManager.SaveConfigFile();
  2050. }
  2051. if (reverseZoneInfo.Internal)
  2052. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is an internal zone.");
  2053. if ((reverseZoneInfo.Type != AuthZoneType.Primary) && (reverseZoneInfo.Type != AuthZoneType.Forwarder))
  2054. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is not a primary or forwarder zone.");
  2055. _dnsWebService.DnsServer.AuthZoneManager.SetRecords(reverseZoneInfo.Name, ptrDomain, DnsResourceRecordType.PTR, ttl, new DnsPTRRecordData[] { new DnsPTRRecordData(domain) });
  2056. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(reverseZoneInfo.Name);
  2057. }
  2058. if (type == DnsResourceRecordType.A)
  2059. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsARecordData(ipAddress));
  2060. else
  2061. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsAAAARecordData(ipAddress));
  2062. if (!string.IsNullOrEmpty(comments))
  2063. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2064. if (overwrite)
  2065. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2066. else
  2067. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2068. bool updateSvcbHints = request.GetQueryOrForm("updateSvcbHints", bool.Parse, false);
  2069. if (updateSvcbHints)
  2070. UpdateSvcbAutoHints(zoneName, domain, type == DnsResourceRecordType.A, type == DnsResourceRecordType.AAAA);
  2071. }
  2072. break;
  2073. case DnsResourceRecordType.NS:
  2074. {
  2075. string nameServer = request.GetQueryOrFormAlt("nameServer", "value").TrimEnd('.');
  2076. string glueAddresses = request.GetQueryOrForm("glue", null);
  2077. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsNSRecordData(nameServer));
  2078. if (!string.IsNullOrEmpty(glueAddresses))
  2079. newRecord.SetGlueRecords(glueAddresses);
  2080. if (!string.IsNullOrEmpty(comments))
  2081. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2082. if (overwrite)
  2083. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2084. else
  2085. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2086. }
  2087. break;
  2088. case DnsResourceRecordType.CNAME:
  2089. {
  2090. if (!overwrite)
  2091. {
  2092. IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneInfo.Name, domain, type);
  2093. if (existingRecords.Count > 0)
  2094. throw new DnsWebServiceException("Record already exists. Use overwrite option if you wish to overwrite existing records.");
  2095. }
  2096. string cname = request.GetQueryOrFormAlt("cname", "value").TrimEnd('.');
  2097. if (cname.Equals(domain, StringComparison.OrdinalIgnoreCase))
  2098. throw new DnsWebServiceException("CNAME domain name cannot be same as that of the record name.");
  2099. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsCNAMERecordData(cname));
  2100. if (!string.IsNullOrEmpty(comments))
  2101. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2102. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2103. }
  2104. break;
  2105. case DnsResourceRecordType.PTR:
  2106. {
  2107. string ptrName = request.GetQueryOrFormAlt("ptrName", "value").TrimEnd('.');
  2108. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsPTRRecordData(ptrName));
  2109. if (!string.IsNullOrEmpty(comments))
  2110. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2111. if (overwrite)
  2112. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2113. else
  2114. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2115. }
  2116. break;
  2117. case DnsResourceRecordType.MX:
  2118. {
  2119. ushort preference = request.GetQueryOrForm("preference", ushort.Parse);
  2120. string exchange = request.GetQueryOrFormAlt("exchange", "value").TrimEnd('.');
  2121. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsMXRecordData(preference, exchange));
  2122. if (!string.IsNullOrEmpty(comments))
  2123. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2124. if (overwrite)
  2125. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2126. else
  2127. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2128. }
  2129. break;
  2130. case DnsResourceRecordType.TXT:
  2131. {
  2132. string text = request.GetQueryOrFormAlt("text", "value");
  2133. bool splitText = request.GetQueryOrForm("splitText", bool.Parse, false);
  2134. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, splitText ? new DnsTXTRecordData(DecodeCharacterStrings(text)) : new DnsTXTRecordData(text));
  2135. if (!string.IsNullOrEmpty(comments))
  2136. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2137. if (overwrite)
  2138. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2139. else
  2140. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2141. }
  2142. break;
  2143. case DnsResourceRecordType.SRV:
  2144. {
  2145. ushort priority = request.GetQueryOrForm("priority", ushort.Parse);
  2146. ushort weight = request.GetQueryOrForm("weight", ushort.Parse);
  2147. ushort port = request.GetQueryOrForm("port", ushort.Parse);
  2148. string target = request.GetQueryOrFormAlt("target", "value").TrimEnd('.');
  2149. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsSRVRecordData(priority, weight, port, target));
  2150. if (!string.IsNullOrEmpty(comments))
  2151. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2152. if (overwrite)
  2153. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2154. else
  2155. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2156. }
  2157. break;
  2158. case DnsResourceRecordType.NAPTR:
  2159. {
  2160. ushort order = request.GetQueryOrForm("naptrOrder", ushort.Parse);
  2161. ushort preference = request.GetQueryOrForm("naptrPreference", ushort.Parse);
  2162. string flags = request.GetQueryOrForm("naptrFlags", "");
  2163. string services = request.GetQueryOrForm("naptrServices", "");
  2164. string regexp = request.GetQueryOrForm("naptrRegexp", "");
  2165. string replacement = request.GetQueryOrForm("naptrReplacement", "").TrimEnd('.');
  2166. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsNAPTRRecordData(order, preference, flags, services, regexp, replacement));
  2167. if (!string.IsNullOrEmpty(comments))
  2168. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2169. if (overwrite)
  2170. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2171. else
  2172. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2173. }
  2174. break;
  2175. case DnsResourceRecordType.DNAME:
  2176. {
  2177. if (!overwrite)
  2178. {
  2179. IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneInfo.Name, domain, type);
  2180. if (existingRecords.Count > 0)
  2181. throw new DnsWebServiceException("Record already exists. Use overwrite option if you wish to overwrite existing records.");
  2182. }
  2183. string dname = request.GetQueryOrFormAlt("dname", "value").TrimEnd('.');
  2184. if (dname.EndsWith("." + domain, StringComparison.OrdinalIgnoreCase))
  2185. throw new DnsWebServiceException("DNAME domain name cannot be a sub domain of the record name.");
  2186. if (dname.Equals(domain, StringComparison.OrdinalIgnoreCase))
  2187. throw new DnsWebServiceException("DNAME domain name cannot be same as that of the record name.");
  2188. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsDNAMERecordData(dname));
  2189. if (!string.IsNullOrEmpty(comments))
  2190. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2191. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2192. }
  2193. break;
  2194. case DnsResourceRecordType.DS:
  2195. {
  2196. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  2197. DnssecAlgorithm algorithm = Enum.Parse<DnssecAlgorithm>(request.GetQueryOrForm("algorithm").Replace('-', '_'), true);
  2198. DnssecDigestType digestType = Enum.Parse<DnssecDigestType>(request.GetQueryOrForm("digestType").Replace('-', '_'), true);
  2199. byte[] digest = request.GetQueryOrFormAlt("digest", "value", Convert.FromHexString);
  2200. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsDSRecordData(keyTag, algorithm, digestType, digest));
  2201. if (!string.IsNullOrEmpty(comments))
  2202. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2203. if (overwrite)
  2204. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2205. else
  2206. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2207. }
  2208. break;
  2209. case DnsResourceRecordType.SSHFP:
  2210. {
  2211. DnsSSHFPAlgorithm sshfpAlgorithm = request.GetQueryOrFormEnum<DnsSSHFPAlgorithm>("sshfpAlgorithm");
  2212. DnsSSHFPFingerprintType sshfpFingerprintType = request.GetQueryOrFormEnum<DnsSSHFPFingerprintType>("sshfpFingerprintType");
  2213. byte[] sshfpFingerprint = request.GetQueryOrForm("sshfpFingerprint", Convert.FromHexString);
  2214. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsSSHFPRecordData(sshfpAlgorithm, sshfpFingerprintType, sshfpFingerprint));
  2215. if (!string.IsNullOrEmpty(comments))
  2216. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2217. if (overwrite)
  2218. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2219. else
  2220. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2221. }
  2222. break;
  2223. case DnsResourceRecordType.TLSA:
  2224. {
  2225. DnsTLSACertificateUsage tlsaCertificateUsage = Enum.Parse<DnsTLSACertificateUsage>(request.GetQueryOrForm("tlsaCertificateUsage").Replace('-', '_'), true);
  2226. DnsTLSASelector tlsaSelector = request.GetQueryOrFormEnum<DnsTLSASelector>("tlsaSelector");
  2227. DnsTLSAMatchingType tlsaMatchingType = Enum.Parse<DnsTLSAMatchingType>(request.GetQueryOrForm("tlsaMatchingType").Replace('-', '_'), true);
  2228. string tlsaCertificateAssociationData = request.GetQueryOrForm("tlsaCertificateAssociationData");
  2229. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsTLSARecordData(tlsaCertificateUsage, tlsaSelector, tlsaMatchingType, tlsaCertificateAssociationData));
  2230. if (!string.IsNullOrEmpty(comments))
  2231. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2232. if (overwrite)
  2233. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2234. else
  2235. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2236. }
  2237. break;
  2238. case DnsResourceRecordType.SVCB:
  2239. case DnsResourceRecordType.HTTPS:
  2240. {
  2241. ushort svcPriority = request.GetQueryOrForm("svcPriority", ushort.Parse);
  2242. string targetName = request.GetQueryOrForm("svcTargetName").TrimEnd('.');
  2243. string strSvcParams = request.GetQueryOrForm("svcParams");
  2244. bool autoIpv4Hint = request.GetQueryOrForm("autoIpv4Hint", bool.Parse, false);
  2245. bool autoIpv6Hint = request.GetQueryOrForm("autoIpv6Hint", bool.Parse, false);
  2246. Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams;
  2247. if (strSvcParams.Equals("false", StringComparison.OrdinalIgnoreCase))
  2248. {
  2249. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(0);
  2250. }
  2251. else
  2252. {
  2253. string[] strSvcParamsParts = strSvcParams.Split('|');
  2254. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(strSvcParamsParts.Length / 2);
  2255. for (int i = 0; i < strSvcParamsParts.Length; i += 2)
  2256. {
  2257. DnsSvcParamKey svcParamKey = Enum.Parse<DnsSvcParamKey>(strSvcParamsParts[i].Replace('-', '_'), true);
  2258. DnsSvcParamValue svcParamValue = DnsSvcParamValue.Parse(svcParamKey, strSvcParamsParts[i + 1]);
  2259. svcParams.Add(svcParamKey, svcParamValue);
  2260. }
  2261. }
  2262. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsSVCBRecordData(svcPriority, targetName, svcParams));
  2263. if (!string.IsNullOrEmpty(comments))
  2264. newRecord.GetAuthSVCBRecordInfo().Comments = comments;
  2265. if (autoIpv4Hint)
  2266. newRecord.GetAuthSVCBRecordInfo().AutoIpv4Hint = true;
  2267. if (autoIpv6Hint)
  2268. newRecord.GetAuthSVCBRecordInfo().AutoIpv6Hint = true;
  2269. if (autoIpv4Hint || autoIpv6Hint)
  2270. ResolveSvcbAutoHints(zoneInfo.Name, newRecord, autoIpv4Hint, autoIpv6Hint, svcParams);
  2271. if (overwrite)
  2272. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2273. else
  2274. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2275. }
  2276. break;
  2277. case DnsResourceRecordType.URI:
  2278. {
  2279. ushort priority = request.GetQueryOrForm("uriPriority", ushort.Parse);
  2280. ushort weight = request.GetQueryOrForm("uriWeight", ushort.Parse);
  2281. Uri uri = request.GetQueryOrForm("uri", delegate (string value) { return new Uri(value); });
  2282. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsURIRecordData(priority, weight, uri));
  2283. if (!string.IsNullOrEmpty(comments))
  2284. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2285. if (overwrite)
  2286. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2287. else
  2288. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2289. }
  2290. break;
  2291. case DnsResourceRecordType.CAA:
  2292. {
  2293. byte flags = request.GetQueryOrForm("flags", byte.Parse);
  2294. string tag = request.GetQueryOrForm("tag");
  2295. string value = request.GetQueryOrForm("value");
  2296. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsCAARecordData(flags, tag, value));
  2297. if (!string.IsNullOrEmpty(comments))
  2298. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2299. if (overwrite)
  2300. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2301. else
  2302. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2303. }
  2304. break;
  2305. case DnsResourceRecordType.ANAME:
  2306. {
  2307. string aname = request.GetQueryOrFormAlt("aname", "value").TrimEnd('.');
  2308. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsANAMERecordData(aname));
  2309. if (!string.IsNullOrEmpty(comments))
  2310. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2311. if (overwrite)
  2312. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2313. else
  2314. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2315. }
  2316. break;
  2317. case DnsResourceRecordType.FWD:
  2318. {
  2319. DnsTransportProtocol protocol = request.GetQueryOrFormEnum("protocol", DnsTransportProtocol.Udp);
  2320. string forwarder = request.GetQueryOrFormAlt("forwarder", "value");
  2321. bool dnssecValidation = request.GetQueryOrForm("dnssecValidation", bool.Parse, false);
  2322. DnsForwarderRecordProxyType proxyType = DnsForwarderRecordProxyType.DefaultProxy;
  2323. string proxyAddress = null;
  2324. ushort proxyPort = 0;
  2325. string proxyUsername = null;
  2326. string proxyPassword = null;
  2327. if (!forwarder.Equals("this-server"))
  2328. {
  2329. proxyType = request.GetQueryOrFormEnum("proxyType", DnsForwarderRecordProxyType.DefaultProxy);
  2330. switch (proxyType)
  2331. {
  2332. case DnsForwarderRecordProxyType.Http:
  2333. case DnsForwarderRecordProxyType.Socks5:
  2334. proxyAddress = request.GetQueryOrForm("proxyAddress");
  2335. proxyPort = request.GetQueryOrForm("proxyPort", ushort.Parse);
  2336. proxyUsername = request.QueryOrForm("proxyUsername");
  2337. proxyPassword = request.QueryOrForm("proxyPassword");
  2338. break;
  2339. }
  2340. }
  2341. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsForwarderRecordData(protocol, forwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword));
  2342. if (!string.IsNullOrEmpty(comments))
  2343. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2344. if (overwrite)
  2345. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2346. else
  2347. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2348. }
  2349. break;
  2350. case DnsResourceRecordType.APP:
  2351. {
  2352. string appName = request.GetQueryOrFormAlt("appName", "value");
  2353. string classPath = request.GetQueryOrForm("classPath");
  2354. string recordData = request.GetQueryOrForm("recordData", "");
  2355. if (!overwrite)
  2356. {
  2357. IReadOnlyList<DnsResourceRecord> existingRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(zoneInfo.Name, domain, type);
  2358. if (existingRecords.Count > 0)
  2359. throw new DnsWebServiceException("Record already exists. Use overwrite option if you wish to overwrite existing records.");
  2360. }
  2361. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsApplicationRecordData(appName, classPath, recordData));
  2362. if (!string.IsNullOrEmpty(comments))
  2363. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2364. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2365. }
  2366. break;
  2367. default:
  2368. {
  2369. string strRData = request.GetQueryOrForm("rdata");
  2370. byte[] rdata;
  2371. if (strRData.Contains(':'))
  2372. rdata = strRData.ParseColonHexString();
  2373. else
  2374. rdata = Convert.FromHexString(strRData);
  2375. newRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, DnsResourceRecord.ReadRecordDataFrom(type, rdata));
  2376. if (!string.IsNullOrEmpty(comments))
  2377. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2378. if (overwrite)
  2379. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newRecord);
  2380. else
  2381. _dnsWebService.DnsServer.AuthZoneManager.AddRecord(zoneInfo.Name, newRecord);
  2382. }
  2383. break;
  2384. }
  2385. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] New record was added to authoritative zone '" + zoneInfo.Name + "' successfully {record: " + newRecord.ToString() + "}");
  2386. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  2387. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  2388. jsonWriter.WritePropertyName("zone");
  2389. WriteZoneInfoAsJson(zoneInfo, jsonWriter);
  2390. jsonWriter.WritePropertyName("addedRecord");
  2391. WriteRecordAsJson(newRecord, jsonWriter, true, null);
  2392. }
  2393. public void GetRecords(HttpContext context)
  2394. {
  2395. HttpRequest request = context.Request;
  2396. string domain = request.GetQueryOrForm("domain").TrimEnd('.');
  2397. if (DnsClient.IsDomainNameUnicode(domain))
  2398. domain = DnsClient.ConvertDomainNameToAscii(domain);
  2399. string zoneName = request.QueryOrForm("zone");
  2400. if (zoneName is not null)
  2401. {
  2402. zoneName = zoneName.TrimEnd('.');
  2403. if (DnsClient.IsDomainNameUnicode(zoneName))
  2404. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  2405. }
  2406. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(string.IsNullOrEmpty(zoneName) ? domain : zoneName);
  2407. if (zoneInfo is null)
  2408. throw new DnsWebServiceException("No such authoritative zone was found: " + domain);
  2409. UserSession session = context.GetCurrentSession();
  2410. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.View))
  2411. throw new DnsWebServiceException("Access was denied.");
  2412. bool listZone = request.GetQueryOrForm("listZone", bool.Parse, false);
  2413. List<DnsResourceRecord> records = new List<DnsResourceRecord>();
  2414. if (listZone)
  2415. _dnsWebService.DnsServer.AuthZoneManager.ListAllZoneRecords(zoneInfo.Name, records);
  2416. else
  2417. _dnsWebService.DnsServer.AuthZoneManager.ListAllRecords(zoneInfo.Name, domain, records);
  2418. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  2419. jsonWriter.WritePropertyName("zone");
  2420. WriteZoneInfoAsJson(zoneInfo, jsonWriter);
  2421. WriteRecordsAsJson(records, jsonWriter, true, zoneInfo);
  2422. }
  2423. public void DeleteRecord(HttpContext context)
  2424. {
  2425. HttpRequest request = context.Request;
  2426. string domain = request.GetQueryOrForm("domain").TrimEnd('.');
  2427. if (DnsClient.IsDomainNameUnicode(domain))
  2428. domain = DnsClient.ConvertDomainNameToAscii(domain);
  2429. string zoneName = request.QueryOrForm("zone");
  2430. if (zoneName is not null)
  2431. {
  2432. zoneName = zoneName.TrimEnd('.');
  2433. if (DnsClient.IsDomainNameUnicode(zoneName))
  2434. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  2435. }
  2436. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(string.IsNullOrEmpty(zoneName) ? domain : zoneName);
  2437. if (zoneInfo is null)
  2438. throw new DnsWebServiceException("No such authoritative zone was found: " + domain);
  2439. if (zoneInfo.Internal)
  2440. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  2441. UserSession session = context.GetCurrentSession();
  2442. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Delete))
  2443. throw new DnsWebServiceException("Access was denied.");
  2444. DnsResourceRecordType type = request.GetQueryOrFormEnum<DnsResourceRecordType>("type");
  2445. switch (type)
  2446. {
  2447. case DnsResourceRecordType.A:
  2448. case DnsResourceRecordType.AAAA:
  2449. {
  2450. IPAddress ipAddress = IPAddress.Parse(request.GetQueryOrFormAlt("ipAddress", "value"));
  2451. if (type == DnsResourceRecordType.A)
  2452. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsARecordData(ipAddress));
  2453. else
  2454. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsAAAARecordData(ipAddress));
  2455. string ptrDomain = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 32 : 128);
  2456. AuthZoneInfo reverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(ptrDomain);
  2457. if ((reverseZoneInfo != null) && !reverseZoneInfo.Internal && (reverseZoneInfo.Type == AuthZoneType.Primary))
  2458. {
  2459. IReadOnlyList<DnsResourceRecord> ptrRecords = _dnsWebService.DnsServer.AuthZoneManager.GetRecords(reverseZoneInfo.Name, ptrDomain, DnsResourceRecordType.PTR);
  2460. if (ptrRecords.Count > 0)
  2461. {
  2462. foreach (DnsResourceRecord ptrRecord in ptrRecords)
  2463. {
  2464. if ((ptrRecord.RDATA as DnsPTRRecordData).Domain.Equals(domain, StringComparison.OrdinalIgnoreCase))
  2465. {
  2466. //delete PTR record and save reverse zone
  2467. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(reverseZoneInfo.Name, ptrDomain, DnsResourceRecordType.PTR, ptrRecord.RDATA);
  2468. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(reverseZoneInfo.Name);
  2469. break;
  2470. }
  2471. }
  2472. }
  2473. }
  2474. bool updateSvcbHints = request.GetQueryOrForm("updateSvcbHints", bool.Parse, false);
  2475. if (updateSvcbHints)
  2476. UpdateSvcbAutoHints(zoneName, domain, type == DnsResourceRecordType.A, type == DnsResourceRecordType.AAAA);
  2477. }
  2478. break;
  2479. case DnsResourceRecordType.NS:
  2480. {
  2481. string nameServer = request.GetQueryOrFormAlt("nameServer", "value").TrimEnd('.');
  2482. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsNSRecordData(nameServer, false));
  2483. }
  2484. break;
  2485. case DnsResourceRecordType.CNAME:
  2486. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
  2487. break;
  2488. case DnsResourceRecordType.PTR:
  2489. {
  2490. string ptrName = request.GetQueryOrFormAlt("ptrName", "value").TrimEnd('.');
  2491. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsPTRRecordData(ptrName));
  2492. }
  2493. break;
  2494. case DnsResourceRecordType.MX:
  2495. {
  2496. ushort preference = request.GetQueryOrForm("preference", ushort.Parse);
  2497. string exchange = request.GetQueryOrFormAlt("exchange", "value").TrimEnd('.');
  2498. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsMXRecordData(preference, exchange));
  2499. }
  2500. break;
  2501. case DnsResourceRecordType.TXT:
  2502. {
  2503. string text = request.GetQueryOrFormAlt("text", "value");
  2504. bool splitText = request.GetQueryOrForm("splitText", bool.Parse, false);
  2505. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, splitText ? new DnsTXTRecordData(DecodeCharacterStrings(text)) : new DnsTXTRecordData(text));
  2506. }
  2507. break;
  2508. case DnsResourceRecordType.SRV:
  2509. {
  2510. ushort priority = request.GetQueryOrForm("priority", ushort.Parse);
  2511. ushort weight = request.GetQueryOrForm("weight", ushort.Parse);
  2512. ushort port = request.GetQueryOrForm("port", ushort.Parse);
  2513. string target = request.GetQueryOrFormAlt("target", "value").TrimEnd('.');
  2514. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsSRVRecordData(priority, weight, port, target));
  2515. }
  2516. break;
  2517. case DnsResourceRecordType.NAPTR:
  2518. {
  2519. ushort order = request.GetQueryOrForm("naptrOrder", ushort.Parse);
  2520. ushort preference = request.GetQueryOrForm("naptrPreference", ushort.Parse);
  2521. string flags = request.GetQueryOrForm("naptrFlags", "");
  2522. string services = request.GetQueryOrForm("naptrServices", "");
  2523. string regexp = request.GetQueryOrForm("naptrRegexp", "");
  2524. string replacement = request.GetQueryOrForm("naptrReplacement", "").TrimEnd('.');
  2525. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsNAPTRRecordData(order, preference, flags, services, regexp, replacement));
  2526. }
  2527. break;
  2528. case DnsResourceRecordType.DNAME:
  2529. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
  2530. break;
  2531. case DnsResourceRecordType.DS:
  2532. {
  2533. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  2534. DnssecAlgorithm algorithm = Enum.Parse<DnssecAlgorithm>(request.GetQueryOrForm("algorithm").Replace('-', '_'), true);
  2535. DnssecDigestType digestType = Enum.Parse<DnssecDigestType>(request.GetQueryOrForm("digestType").Replace('-', '_'), true);
  2536. byte[] digest = Convert.FromHexString(request.GetQueryOrFormAlt("digest", "value"));
  2537. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsDSRecordData(keyTag, algorithm, digestType, digest));
  2538. }
  2539. break;
  2540. case DnsResourceRecordType.SSHFP:
  2541. {
  2542. DnsSSHFPAlgorithm sshfpAlgorithm = request.GetQueryOrFormEnum<DnsSSHFPAlgorithm>("sshfpAlgorithm");
  2543. DnsSSHFPFingerprintType sshfpFingerprintType = request.GetQueryOrFormEnum<DnsSSHFPFingerprintType>("sshfpFingerprintType");
  2544. byte[] sshfpFingerprint = request.GetQueryOrForm("sshfpFingerprint", Convert.FromHexString);
  2545. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsSSHFPRecordData(sshfpAlgorithm, sshfpFingerprintType, sshfpFingerprint));
  2546. }
  2547. break;
  2548. case DnsResourceRecordType.TLSA:
  2549. {
  2550. DnsTLSACertificateUsage tlsaCertificateUsage = Enum.Parse<DnsTLSACertificateUsage>(request.GetQueryOrForm("tlsaCertificateUsage").Replace('-', '_'), true);
  2551. DnsTLSASelector tlsaSelector = request.GetQueryOrFormEnum<DnsTLSASelector>("tlsaSelector");
  2552. DnsTLSAMatchingType tlsaMatchingType = Enum.Parse<DnsTLSAMatchingType>(request.GetQueryOrForm("tlsaMatchingType").Replace('-', '_'), true);
  2553. string tlsaCertificateAssociationData = request.GetQueryOrForm("tlsaCertificateAssociationData");
  2554. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsTLSARecordData(tlsaCertificateUsage, tlsaSelector, tlsaMatchingType, tlsaCertificateAssociationData));
  2555. }
  2556. break;
  2557. case DnsResourceRecordType.SVCB:
  2558. case DnsResourceRecordType.HTTPS:
  2559. {
  2560. ushort svcPriority = request.GetQueryOrForm("svcPriority", ushort.Parse);
  2561. string targetName = request.GetQueryOrForm("svcTargetName").TrimEnd('.');
  2562. string strSvcParams = request.GetQueryOrForm("svcParams");
  2563. Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams;
  2564. if (strSvcParams.Equals("false", StringComparison.OrdinalIgnoreCase))
  2565. {
  2566. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(0);
  2567. }
  2568. else
  2569. {
  2570. string[] strSvcParamsParts = strSvcParams.Split('|');
  2571. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(strSvcParamsParts.Length / 2);
  2572. for (int i = 0; i < strSvcParamsParts.Length; i += 2)
  2573. {
  2574. DnsSvcParamKey svcParamKey = Enum.Parse<DnsSvcParamKey>(strSvcParamsParts[i].Replace('-', '_'), true);
  2575. DnsSvcParamValue svcParamValue = DnsSvcParamValue.Parse(svcParamKey, strSvcParamsParts[i + 1]);
  2576. svcParams.Add(svcParamKey, svcParamValue);
  2577. }
  2578. }
  2579. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsSVCBRecordData(svcPriority, targetName, svcParams));
  2580. }
  2581. break;
  2582. case DnsResourceRecordType.URI:
  2583. {
  2584. ushort priority = request.GetQueryOrForm("uriPriority", ushort.Parse);
  2585. ushort weight = request.GetQueryOrForm("uriWeight", ushort.Parse);
  2586. Uri uri = request.GetQueryOrForm("uri", delegate (string value) { return new Uri(value); });
  2587. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsURIRecordData(priority, weight, uri));
  2588. }
  2589. break;
  2590. case DnsResourceRecordType.CAA:
  2591. {
  2592. byte flags = request.GetQueryOrForm("flags", byte.Parse);
  2593. string tag = request.GetQueryOrForm("tag");
  2594. string value = request.GetQueryOrForm("value");
  2595. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsCAARecordData(flags, tag, value));
  2596. }
  2597. break;
  2598. case DnsResourceRecordType.ANAME:
  2599. {
  2600. string aname = request.GetQueryOrFormAlt("aname", "value").TrimEnd('.');
  2601. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsANAMERecordData(aname));
  2602. }
  2603. break;
  2604. case DnsResourceRecordType.FWD:
  2605. {
  2606. DnsTransportProtocol protocol = request.GetQueryOrFormEnum("protocol", DnsTransportProtocol.Udp);
  2607. string forwarder = request.GetQueryOrFormAlt("forwarder", "value");
  2608. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsForwarderRecordData(protocol, forwarder));
  2609. }
  2610. break;
  2611. case DnsResourceRecordType.APP:
  2612. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(zoneInfo.Name, domain, type);
  2613. break;
  2614. default:
  2615. {
  2616. string strRData = request.GetQueryOrForm("rdata", string.Empty);
  2617. byte[] rdata;
  2618. if (strRData.Contains(':'))
  2619. rdata = strRData.ParseColonHexString();
  2620. else
  2621. rdata = Convert.FromHexString(strRData);
  2622. if (!_dnsWebService.DnsServer.AuthZoneManager.DeleteRecord(zoneInfo.Name, domain, type, new DnsUnknownRecordData(rdata)))
  2623. throw new DnsWebServiceException("Failed to delete the record.");
  2624. }
  2625. break;
  2626. }
  2627. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Record was deleted from authoritative zone '" + zoneInfo.Name + "' successfully {domain: " + domain + "; type: " + type + ";}");
  2628. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  2629. }
  2630. public void UpdateRecord(HttpContext context)
  2631. {
  2632. HttpRequest request = context.Request;
  2633. string domain = request.GetQueryOrForm("domain").TrimEnd('.');
  2634. if (DnsClient.IsDomainNameUnicode(domain))
  2635. domain = DnsClient.ConvertDomainNameToAscii(domain);
  2636. string zoneName = request.QueryOrForm("zone");
  2637. if (zoneName is not null)
  2638. {
  2639. zoneName = zoneName.TrimEnd('.');
  2640. if (DnsClient.IsDomainNameUnicode(zoneName))
  2641. zoneName = DnsClient.ConvertDomainNameToAscii(zoneName);
  2642. }
  2643. AuthZoneInfo zoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(string.IsNullOrEmpty(zoneName) ? domain : zoneName);
  2644. if (zoneInfo is null)
  2645. throw new DnsWebServiceException("No such authoritative zone was found: " + domain);
  2646. if (zoneInfo.Internal)
  2647. throw new DnsWebServiceException("Access was denied to manage internal DNS Server zone.");
  2648. UserSession session = context.GetCurrentSession();
  2649. if (!_dnsWebService._authManager.IsPermitted(PermissionSection.Zones, zoneInfo.Name, session.User, PermissionFlag.Modify))
  2650. throw new DnsWebServiceException("Access was denied.");
  2651. string newDomain = request.GetQueryOrForm("newDomain", domain).TrimEnd('.');
  2652. uint ttl = request.GetQueryOrForm("ttl", uint.Parse, _defaultRecordTtl);
  2653. bool disable = request.GetQueryOrForm("disable", bool.Parse, false);
  2654. string comments = request.QueryOrForm("comments");
  2655. DnsResourceRecordType type = request.GetQueryOrFormEnum<DnsResourceRecordType>("type");
  2656. DnsResourceRecord oldRecord = null;
  2657. DnsResourceRecord newRecord;
  2658. switch (type)
  2659. {
  2660. case DnsResourceRecordType.A:
  2661. case DnsResourceRecordType.AAAA:
  2662. {
  2663. IPAddress ipAddress = IPAddress.Parse(request.GetQueryOrFormAlt("ipAddress", "value"));
  2664. IPAddress newIpAddress = IPAddress.Parse(request.GetQueryOrFormAlt("newIpAddress", "newValue", ipAddress.ToString()));
  2665. bool ptr = request.GetQueryOrForm("ptr", bool.Parse, false);
  2666. if (ptr)
  2667. {
  2668. string newPtrDomain = Zone.GetReverseZone(newIpAddress, type == DnsResourceRecordType.A ? 32 : 128);
  2669. AuthZoneInfo newReverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(newPtrDomain);
  2670. if (newReverseZoneInfo is null)
  2671. {
  2672. bool createPtrZone = request.GetQueryOrForm("createPtrZone", bool.Parse, false);
  2673. if (!createPtrZone)
  2674. throw new DnsServerException("No reverse zone available to add PTR record.");
  2675. string ptrZone = Zone.GetReverseZone(newIpAddress, type == DnsResourceRecordType.A ? 24 : 64);
  2676. newReverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.CreatePrimaryZone(ptrZone, _dnsWebService.DnsServer.ServerDomain, false);
  2677. if (newReverseZoneInfo is null)
  2678. throw new DnsServerException("Failed to create reverse zone to add PTR record: " + ptrZone);
  2679. //set permissions
  2680. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, newReverseZoneInfo.Name, session.User, PermissionFlag.ViewModifyDelete);
  2681. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, newReverseZoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  2682. _dnsWebService._authManager.SetPermission(PermissionSection.Zones, newReverseZoneInfo.Name, _dnsWebService._authManager.GetGroup(Group.DNS_ADMINISTRATORS), PermissionFlag.ViewModifyDelete);
  2683. _dnsWebService._authManager.SaveConfigFile();
  2684. }
  2685. if (newReverseZoneInfo.Internal)
  2686. throw new DnsServerException("Reverse zone '" + newReverseZoneInfo.Name + "' is an internal zone.");
  2687. if ((newReverseZoneInfo.Type != AuthZoneType.Primary) && (newReverseZoneInfo.Type != AuthZoneType.Forwarder))
  2688. throw new DnsServerException("Reverse zone '" + newReverseZoneInfo.Name + "' is not a primary or forwarder zone.");
  2689. string oldPtrDomain = Zone.GetReverseZone(ipAddress, type == DnsResourceRecordType.A ? 32 : 128);
  2690. AuthZoneInfo oldReverseZoneInfo = _dnsWebService.DnsServer.AuthZoneManager.FindAuthZoneInfo(oldPtrDomain);
  2691. if ((oldReverseZoneInfo != null) && !oldReverseZoneInfo.Internal && (oldReverseZoneInfo.Type == AuthZoneType.Primary))
  2692. {
  2693. //delete old PTR record if any and save old reverse zone
  2694. _dnsWebService.DnsServer.AuthZoneManager.DeleteRecords(oldReverseZoneInfo.Name, oldPtrDomain, DnsResourceRecordType.PTR);
  2695. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(oldReverseZoneInfo.Name);
  2696. }
  2697. //add new PTR record and save reverse zone
  2698. _dnsWebService.DnsServer.AuthZoneManager.SetRecords(newReverseZoneInfo.Name, newPtrDomain, DnsResourceRecordType.PTR, ttl, new DnsPTRRecordData[] { new DnsPTRRecordData(domain) });
  2699. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(newReverseZoneInfo.Name);
  2700. }
  2701. if (type == DnsResourceRecordType.A)
  2702. {
  2703. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsARecordData(ipAddress));
  2704. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsARecordData(newIpAddress));
  2705. }
  2706. else
  2707. {
  2708. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsAAAARecordData(ipAddress));
  2709. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsAAAARecordData(newIpAddress));
  2710. }
  2711. if (disable)
  2712. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2713. if (!string.IsNullOrEmpty(comments))
  2714. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2715. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2716. bool updateSvcbHints = request.GetQueryOrForm("updateSvcbHints", bool.Parse, false);
  2717. if (updateSvcbHints)
  2718. UpdateSvcbAutoHints(zoneName, newDomain, type == DnsResourceRecordType.A, type == DnsResourceRecordType.AAAA);
  2719. }
  2720. break;
  2721. case DnsResourceRecordType.NS:
  2722. {
  2723. string nameServer = request.GetQueryOrFormAlt("nameServer", "value").TrimEnd('.');
  2724. string newNameServer = request.GetQueryOrFormAlt("newNameServer", "newValue", nameServer).TrimEnd('.');
  2725. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsNSRecordData(nameServer));
  2726. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsNSRecordData(newNameServer));
  2727. if (disable)
  2728. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2729. if (!string.IsNullOrEmpty(comments))
  2730. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2731. if (request.TryGetQueryOrForm("glue", out string glueAddresses))
  2732. newRecord.SetGlueRecords(glueAddresses);
  2733. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2734. }
  2735. break;
  2736. case DnsResourceRecordType.CNAME:
  2737. {
  2738. string cname = request.GetQueryOrFormAlt("cname", "value").TrimEnd('.');
  2739. if (cname.Equals(newDomain, StringComparison.OrdinalIgnoreCase))
  2740. throw new DnsWebServiceException("CNAME domain name cannot be same as that of the record name.");
  2741. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsCNAMERecordData(cname));
  2742. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsCNAMERecordData(cname));
  2743. if (disable)
  2744. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2745. if (!string.IsNullOrEmpty(comments))
  2746. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2747. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2748. }
  2749. break;
  2750. case DnsResourceRecordType.SOA:
  2751. {
  2752. string primaryNameServer = request.GetQueryOrForm("primaryNameServer").TrimEnd('.');
  2753. string responsiblePerson = request.GetQueryOrForm("responsiblePerson").TrimEnd('.');
  2754. uint serial = request.GetQueryOrForm("serial", uint.Parse);
  2755. uint refresh = request.GetQueryOrForm("refresh", uint.Parse);
  2756. uint retry = request.GetQueryOrForm("retry", uint.Parse);
  2757. uint expire = request.GetQueryOrForm("expire", uint.Parse);
  2758. uint minimum = request.GetQueryOrForm("minimum", uint.Parse);
  2759. DnsResourceRecord newSOARecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsSOARecordData(primaryNameServer, responsiblePerson, serial, refresh, retry, expire, minimum));
  2760. switch (zoneInfo.Type)
  2761. {
  2762. case AuthZoneType.Primary:
  2763. {
  2764. SOARecordInfo recordInfo = newSOARecord.GetAuthSOARecordInfo();
  2765. if (request.TryGetQueryOrForm("useSerialDateScheme", bool.Parse, out bool useSerialDateScheme))
  2766. recordInfo.UseSoaSerialDateScheme = useSerialDateScheme;
  2767. }
  2768. break;
  2769. case AuthZoneType.Secondary:
  2770. {
  2771. SOARecordInfo recordInfo = newSOARecord.GetAuthSOARecordInfo();
  2772. if (request.TryGetQueryOrFormEnum("zoneTransferProtocol", out DnsTransportProtocol zoneTransferProtocol))
  2773. {
  2774. if (zoneTransferProtocol == DnsTransportProtocol.Quic)
  2775. DnsWebService.ValidateQuicSupport();
  2776. recordInfo.ZoneTransferProtocol = zoneTransferProtocol;
  2777. }
  2778. if (request.TryGetQueryOrForm("primaryAddresses", out string primaryAddresses))
  2779. {
  2780. recordInfo.PrimaryNameServers = primaryAddresses.Split(delegate (string address)
  2781. {
  2782. NameServerAddress nameServer = NameServerAddress.Parse(address);
  2783. if (nameServer.Protocol != zoneTransferProtocol)
  2784. nameServer = nameServer.ChangeProtocol(zoneTransferProtocol);
  2785. return nameServer;
  2786. }, ',');
  2787. }
  2788. if (request.TryGetQueryOrForm("tsigKeyName", out string tsigKeyName))
  2789. recordInfo.TsigKeyName = tsigKeyName;
  2790. }
  2791. break;
  2792. case AuthZoneType.Stub:
  2793. {
  2794. if (request.TryGetQueryOrForm("primaryAddresses", out string primaryAddresses))
  2795. {
  2796. newSOARecord.GetAuthSOARecordInfo().PrimaryNameServers = primaryAddresses.Split(delegate (string address)
  2797. {
  2798. NameServerAddress nameServer = NameServerAddress.Parse(address);
  2799. if (nameServer.Protocol != DnsTransportProtocol.Udp)
  2800. nameServer = nameServer.ChangeProtocol(DnsTransportProtocol.Udp);
  2801. return nameServer;
  2802. }, ',');
  2803. }
  2804. }
  2805. break;
  2806. }
  2807. if (!string.IsNullOrEmpty(comments))
  2808. newSOARecord.GetAuthGenericRecordInfo().Comments = comments;
  2809. _dnsWebService.DnsServer.AuthZoneManager.SetRecord(zoneInfo.Name, newSOARecord);
  2810. newRecord = zoneInfo.GetApexRecords(DnsResourceRecordType.SOA)[0];
  2811. }
  2812. break;
  2813. case DnsResourceRecordType.PTR:
  2814. {
  2815. string ptrName = request.GetQueryOrFormAlt("ptrName", "value").TrimEnd('.');
  2816. string newPtrName = request.GetQueryOrFormAlt("newPtrName", "newValue", ptrName).TrimEnd('.');
  2817. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsPTRRecordData(ptrName));
  2818. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsPTRRecordData(newPtrName));
  2819. if (disable)
  2820. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2821. if (!string.IsNullOrEmpty(comments))
  2822. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2823. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2824. }
  2825. break;
  2826. case DnsResourceRecordType.MX:
  2827. {
  2828. ushort preference = request.GetQueryOrForm("preference", ushort.Parse);
  2829. ushort newPreference = request.GetQueryOrForm("newPreference", ushort.Parse, preference);
  2830. string exchange = request.GetQueryOrFormAlt("exchange", "value").TrimEnd('.');
  2831. string newExchange = request.GetQueryOrFormAlt("newExchange", "newValue", exchange).TrimEnd('.');
  2832. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsMXRecordData(preference, exchange));
  2833. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsMXRecordData(newPreference, newExchange));
  2834. if (disable)
  2835. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2836. if (!string.IsNullOrEmpty(comments))
  2837. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2838. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2839. }
  2840. break;
  2841. case DnsResourceRecordType.TXT:
  2842. {
  2843. string text = request.GetQueryOrFormAlt("text", "value");
  2844. string newText = request.GetQueryOrFormAlt("newText", "newValue", text);
  2845. bool splitText = request.GetQueryOrForm("splitText", bool.Parse, false);
  2846. bool newSplitText = request.GetQueryOrForm("newSplitText", bool.Parse, splitText);
  2847. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, splitText ? new DnsTXTRecordData(DecodeCharacterStrings(text)) : new DnsTXTRecordData(text));
  2848. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, newSplitText ? new DnsTXTRecordData(DecodeCharacterStrings(newText)) : new DnsTXTRecordData(newText));
  2849. if (disable)
  2850. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2851. if (!string.IsNullOrEmpty(comments))
  2852. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2853. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2854. }
  2855. break;
  2856. case DnsResourceRecordType.SRV:
  2857. {
  2858. ushort priority = request.GetQueryOrForm("priority", ushort.Parse);
  2859. ushort newPriority = request.GetQueryOrForm("newPriority", ushort.Parse, priority);
  2860. ushort weight = request.GetQueryOrForm("weight", ushort.Parse);
  2861. ushort newWeight = request.GetQueryOrForm("newWeight", ushort.Parse, weight);
  2862. ushort port = request.GetQueryOrForm("port", ushort.Parse);
  2863. ushort newPort = request.GetQueryOrForm("newPort", ushort.Parse, port);
  2864. string target = request.GetQueryOrFormAlt("target", "value").TrimEnd('.');
  2865. string newTarget = request.GetQueryOrFormAlt("newTarget", "newValue", target).TrimEnd('.');
  2866. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsSRVRecordData(priority, weight, port, target));
  2867. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsSRVRecordData(newPriority, newWeight, newPort, newTarget));
  2868. if (disable)
  2869. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2870. if (!string.IsNullOrEmpty(comments))
  2871. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2872. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2873. }
  2874. break;
  2875. case DnsResourceRecordType.NAPTR:
  2876. {
  2877. ushort order = request.GetQueryOrForm("naptrOrder", ushort.Parse);
  2878. ushort newOrder = request.GetQueryOrForm("naptrNewOrder", ushort.Parse, order);
  2879. ushort preference = request.GetQueryOrForm("naptrPreference", ushort.Parse);
  2880. ushort newPreference = request.GetQueryOrForm("naptrNewPreference", ushort.Parse, preference);
  2881. string flags = request.GetQueryOrForm("naptrFlags", "");
  2882. string newFlags = request.GetQueryOrForm("naptrNewFlags", flags);
  2883. string services = request.GetQueryOrForm("naptrServices", "");
  2884. string newServices = request.GetQueryOrForm("naptrNewServices", services);
  2885. string regexp = request.GetQueryOrForm("naptrRegexp", "");
  2886. string newRegexp = request.GetQueryOrForm("naptrNewRegexp", regexp);
  2887. string replacement = request.GetQueryOrForm("naptrReplacement", "").TrimEnd('.');
  2888. string newReplacement = request.GetQueryOrForm("naptrNewReplacement", replacement).TrimEnd('.');
  2889. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsNAPTRRecordData(order, preference, flags, services, regexp, replacement));
  2890. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsNAPTRRecordData(newOrder, newPreference, newFlags, newServices, newRegexp, newReplacement));
  2891. if (disable)
  2892. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2893. if (!string.IsNullOrEmpty(comments))
  2894. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2895. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2896. }
  2897. break;
  2898. case DnsResourceRecordType.DNAME:
  2899. {
  2900. string dname = request.GetQueryOrFormAlt("dname", "value").TrimEnd('.');
  2901. if (dname.EndsWith("." + newDomain, StringComparison.OrdinalIgnoreCase))
  2902. throw new DnsWebServiceException("DNAME domain name cannot be a sub domain of the record name.");
  2903. if (dname.Equals(newDomain, StringComparison.OrdinalIgnoreCase))
  2904. throw new DnsWebServiceException("DNAME domain name cannot be same as that of the record name.");
  2905. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsDNAMERecordData(dname));
  2906. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsDNAMERecordData(dname));
  2907. if (disable)
  2908. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2909. if (!string.IsNullOrEmpty(comments))
  2910. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2911. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2912. }
  2913. break;
  2914. case DnsResourceRecordType.DS:
  2915. {
  2916. ushort keyTag = request.GetQueryOrForm("keyTag", ushort.Parse);
  2917. ushort newKeyTag = request.GetQueryOrForm("newKeyTag", ushort.Parse, keyTag);
  2918. DnssecAlgorithm algorithm = Enum.Parse<DnssecAlgorithm>(request.GetQueryOrForm("algorithm").Replace('-', '_'), true);
  2919. DnssecAlgorithm newAlgorithm = Enum.Parse<DnssecAlgorithm>(request.GetQueryOrForm("newAlgorithm", algorithm.ToString()).Replace('-', '_'), true);
  2920. DnssecDigestType digestType = Enum.Parse<DnssecDigestType>(request.GetQueryOrForm("digestType").Replace('-', '_'), true);
  2921. DnssecDigestType newDigestType = Enum.Parse<DnssecDigestType>(request.GetQueryOrForm("newDigestType", digestType.ToString()).Replace('-', '_'), true);
  2922. byte[] digest = request.GetQueryOrFormAlt("digest", "value", Convert.FromHexString);
  2923. byte[] newDigest = request.GetQueryOrFormAlt("newDigest", "newValue", Convert.FromHexString, digest);
  2924. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsDSRecordData(keyTag, algorithm, digestType, digest));
  2925. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsDSRecordData(newKeyTag, newAlgorithm, newDigestType, newDigest));
  2926. if (disable)
  2927. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2928. if (!string.IsNullOrEmpty(comments))
  2929. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2930. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2931. }
  2932. break;
  2933. case DnsResourceRecordType.SSHFP:
  2934. {
  2935. DnsSSHFPAlgorithm sshfpAlgorithm = request.GetQueryOrFormEnum<DnsSSHFPAlgorithm>("sshfpAlgorithm");
  2936. DnsSSHFPAlgorithm newSshfpAlgorithm = request.GetQueryOrFormEnum("newSshfpAlgorithm", sshfpAlgorithm);
  2937. DnsSSHFPFingerprintType sshfpFingerprintType = request.GetQueryOrFormEnum<DnsSSHFPFingerprintType>("sshfpFingerprintType");
  2938. DnsSSHFPFingerprintType newSshfpFingerprintType = request.GetQueryOrFormEnum("newSshfpFingerprintType", sshfpFingerprintType);
  2939. byte[] sshfpFingerprint = request.GetQueryOrForm("sshfpFingerprint", Convert.FromHexString);
  2940. byte[] newSshfpFingerprint = request.GetQueryOrForm("newSshfpFingerprint", Convert.FromHexString, sshfpFingerprint);
  2941. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsSSHFPRecordData(sshfpAlgorithm, sshfpFingerprintType, sshfpFingerprint));
  2942. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsSSHFPRecordData(newSshfpAlgorithm, newSshfpFingerprintType, newSshfpFingerprint));
  2943. if (disable)
  2944. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2945. if (!string.IsNullOrEmpty(comments))
  2946. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2947. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2948. }
  2949. break;
  2950. case DnsResourceRecordType.TLSA:
  2951. {
  2952. DnsTLSACertificateUsage tlsaCertificateUsage = Enum.Parse<DnsTLSACertificateUsage>(request.GetQueryOrForm("tlsaCertificateUsage").Replace('-', '_'), true);
  2953. DnsTLSACertificateUsage newTlsaCertificateUsage = Enum.Parse<DnsTLSACertificateUsage>(request.GetQueryOrForm("newTlsaCertificateUsage", tlsaCertificateUsage.ToString()).Replace('-', '_'), true);
  2954. DnsTLSASelector tlsaSelector = request.GetQueryOrFormEnum<DnsTLSASelector>("tlsaSelector");
  2955. DnsTLSASelector newTlsaSelector = request.GetQueryOrFormEnum("newTlsaSelector", tlsaSelector);
  2956. DnsTLSAMatchingType tlsaMatchingType = Enum.Parse<DnsTLSAMatchingType>(request.GetQueryOrForm("tlsaMatchingType").Replace('-', '_'), true);
  2957. DnsTLSAMatchingType newTlsaMatchingType = Enum.Parse<DnsTLSAMatchingType>(request.GetQueryOrForm("newTlsaMatchingType", tlsaMatchingType.ToString()).Replace('-', '_'), true);
  2958. string tlsaCertificateAssociationData = request.GetQueryOrForm("tlsaCertificateAssociationData");
  2959. string newTlsaCertificateAssociationData = request.GetQueryOrForm("newTlsaCertificateAssociationData", tlsaCertificateAssociationData);
  2960. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsTLSARecordData(tlsaCertificateUsage, tlsaSelector, tlsaMatchingType, tlsaCertificateAssociationData));
  2961. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsTLSARecordData(newTlsaCertificateUsage, newTlsaSelector, newTlsaMatchingType, newTlsaCertificateAssociationData));
  2962. if (disable)
  2963. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  2964. if (!string.IsNullOrEmpty(comments))
  2965. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  2966. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  2967. }
  2968. break;
  2969. case DnsResourceRecordType.SVCB:
  2970. case DnsResourceRecordType.HTTPS:
  2971. {
  2972. ushort svcPriority = request.GetQueryOrForm("svcPriority", ushort.Parse);
  2973. ushort newSvcPriority = request.GetQueryOrForm("newSvcPriority", ushort.Parse, svcPriority);
  2974. string targetName = request.GetQueryOrForm("svcTargetName").TrimEnd('.');
  2975. string newTargetName = request.GetQueryOrForm("newSvcTargetName", targetName).TrimEnd('.');
  2976. string strSvcParams = request.GetQueryOrForm("svcParams");
  2977. string strNewSvcParams = request.GetQueryOrForm("newSvcParams", strSvcParams);
  2978. bool autoIpv4Hint = request.GetQueryOrForm("autoIpv4Hint", bool.Parse, false);
  2979. bool autoIpv6Hint = request.GetQueryOrForm("autoIpv6Hint", bool.Parse, false);
  2980. Dictionary<DnsSvcParamKey, DnsSvcParamValue> svcParams;
  2981. if (strSvcParams.Equals("false", StringComparison.OrdinalIgnoreCase))
  2982. {
  2983. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(0);
  2984. }
  2985. else
  2986. {
  2987. string[] strSvcParamsParts = strSvcParams.Split('|');
  2988. svcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(strSvcParamsParts.Length / 2);
  2989. for (int i = 0; i < strSvcParamsParts.Length; i += 2)
  2990. {
  2991. DnsSvcParamKey svcParamKey = Enum.Parse<DnsSvcParamKey>(strSvcParamsParts[i].Replace('-', '_'), true);
  2992. DnsSvcParamValue svcParamValue = DnsSvcParamValue.Parse(svcParamKey, strSvcParamsParts[i + 1]);
  2993. svcParams.Add(svcParamKey, svcParamValue);
  2994. }
  2995. }
  2996. Dictionary<DnsSvcParamKey, DnsSvcParamValue> newSvcParams;
  2997. if (strNewSvcParams.Equals("false", StringComparison.OrdinalIgnoreCase))
  2998. {
  2999. newSvcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(0);
  3000. }
  3001. else
  3002. {
  3003. string[] strSvcParamsParts = strNewSvcParams.Split('|');
  3004. newSvcParams = new Dictionary<DnsSvcParamKey, DnsSvcParamValue>(strSvcParamsParts.Length / 2);
  3005. for (int i = 0; i < strSvcParamsParts.Length; i += 2)
  3006. {
  3007. DnsSvcParamKey svcParamKey = Enum.Parse<DnsSvcParamKey>(strSvcParamsParts[i].Replace('-', '_'), true);
  3008. DnsSvcParamValue svcParamValue = DnsSvcParamValue.Parse(svcParamKey, strSvcParamsParts[i + 1]);
  3009. newSvcParams.Add(svcParamKey, svcParamValue);
  3010. }
  3011. }
  3012. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsSVCBRecordData(svcPriority, targetName, svcParams));
  3013. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsSVCBRecordData(newSvcPriority, newTargetName, newSvcParams));
  3014. if (disable)
  3015. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3016. if (!string.IsNullOrEmpty(comments))
  3017. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3018. if (autoIpv4Hint)
  3019. newRecord.GetAuthSVCBRecordInfo().AutoIpv4Hint = true;
  3020. if (autoIpv6Hint)
  3021. newRecord.GetAuthSVCBRecordInfo().AutoIpv6Hint = true;
  3022. if (autoIpv4Hint || autoIpv6Hint)
  3023. ResolveSvcbAutoHints(zoneInfo.Name, newRecord, autoIpv4Hint, autoIpv6Hint, newSvcParams);
  3024. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3025. }
  3026. break;
  3027. case DnsResourceRecordType.URI:
  3028. {
  3029. ushort priority = request.GetQueryOrForm("uriPriority", ushort.Parse);
  3030. ushort newPriority = request.GetQueryOrForm("newUriPriority", ushort.Parse, priority);
  3031. ushort weight = request.GetQueryOrForm("uriWeight", ushort.Parse);
  3032. ushort newWeight = request.GetQueryOrForm("newUriWeight", ushort.Parse, weight);
  3033. Uri uri = request.GetQueryOrForm("uri", delegate (string value) { return new Uri(value); });
  3034. Uri newUri = request.GetQueryOrForm("newUri", delegate (string value) { return new Uri(value); }, uri);
  3035. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsURIRecordData(priority, weight, uri));
  3036. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsURIRecordData(newPriority, newWeight, newUri));
  3037. if (disable)
  3038. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3039. if (!string.IsNullOrEmpty(comments))
  3040. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3041. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3042. }
  3043. break;
  3044. case DnsResourceRecordType.CAA:
  3045. {
  3046. byte flags = request.GetQueryOrForm("flags", byte.Parse);
  3047. byte newFlags = request.GetQueryOrForm("newFlags", byte.Parse, flags);
  3048. string tag = request.GetQueryOrForm("tag");
  3049. string newTag = request.GetQueryOrForm("newTag", tag);
  3050. string value = request.GetQueryOrForm("value");
  3051. string newValue = request.GetQueryOrForm("newValue", value);
  3052. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsCAARecordData(flags, tag, value));
  3053. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsCAARecordData(newFlags, newTag, newValue));
  3054. if (disable)
  3055. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3056. if (!string.IsNullOrEmpty(comments))
  3057. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3058. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3059. }
  3060. break;
  3061. case DnsResourceRecordType.ANAME:
  3062. {
  3063. string aname = request.GetQueryOrFormAlt("aname", "value").TrimEnd('.');
  3064. string newAName = request.GetQueryOrFormAlt("newAName", "newValue", aname).TrimEnd('.');
  3065. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsANAMERecordData(aname));
  3066. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsANAMERecordData(newAName));
  3067. if (disable)
  3068. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3069. if (!string.IsNullOrEmpty(comments))
  3070. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3071. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3072. }
  3073. break;
  3074. case DnsResourceRecordType.FWD:
  3075. {
  3076. DnsTransportProtocol protocol = request.GetQueryOrFormEnum("protocol", DnsTransportProtocol.Udp);
  3077. DnsTransportProtocol newProtocol = request.GetQueryOrFormEnum("newProtocol", protocol);
  3078. string forwarder = request.GetQueryOrFormAlt("forwarder", "value");
  3079. string newForwarder = request.GetQueryOrFormAlt("newForwarder", "newValue", forwarder);
  3080. bool dnssecValidation = request.GetQueryOrForm("dnssecValidation", bool.Parse, false);
  3081. DnsForwarderRecordProxyType proxyType = DnsForwarderRecordProxyType.DefaultProxy;
  3082. string proxyAddress = null;
  3083. ushort proxyPort = 0;
  3084. string proxyUsername = null;
  3085. string proxyPassword = null;
  3086. if (!newForwarder.Equals("this-server"))
  3087. {
  3088. proxyType = request.GetQueryOrFormEnum("proxyType", DnsForwarderRecordProxyType.DefaultProxy);
  3089. switch (proxyType)
  3090. {
  3091. case DnsForwarderRecordProxyType.Http:
  3092. case DnsForwarderRecordProxyType.Socks5:
  3093. proxyAddress = request.GetQueryOrForm("proxyAddress");
  3094. proxyPort = request.GetQueryOrForm("proxyPort", ushort.Parse);
  3095. proxyUsername = request.QueryOrForm("proxyUsername");
  3096. proxyPassword = request.QueryOrForm("proxyPassword");
  3097. break;
  3098. }
  3099. }
  3100. switch (newProtocol)
  3101. {
  3102. case DnsTransportProtocol.HttpsJson:
  3103. newProtocol = DnsTransportProtocol.Https;
  3104. break;
  3105. case DnsTransportProtocol.Quic:
  3106. DnsWebService.ValidateQuicSupport();
  3107. break;
  3108. }
  3109. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsForwarderRecordData(protocol, forwarder));
  3110. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, 0, new DnsForwarderRecordData(newProtocol, newForwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword));
  3111. if (disable)
  3112. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3113. if (!string.IsNullOrEmpty(comments))
  3114. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3115. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3116. }
  3117. break;
  3118. case DnsResourceRecordType.APP:
  3119. {
  3120. string appName = request.GetQueryOrFormAlt("appName", "value");
  3121. string classPath = request.GetQueryOrForm("classPath");
  3122. string recordData = request.GetQueryOrForm("recordData", "");
  3123. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsApplicationRecordData(appName, classPath, recordData));
  3124. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsApplicationRecordData(appName, classPath, recordData));
  3125. if (disable)
  3126. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3127. if (!string.IsNullOrEmpty(comments))
  3128. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3129. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3130. }
  3131. break;
  3132. default:
  3133. {
  3134. string strRData = request.GetQueryOrForm("rdata");
  3135. string strNewRData = request.GetQueryOrForm("newRData", strRData);
  3136. byte[] rdata;
  3137. if (strRData.Contains(':'))
  3138. rdata = strRData.ParseColonHexString();
  3139. else
  3140. rdata = Convert.FromHexString(strRData);
  3141. byte[] newRData;
  3142. if (strNewRData.Contains(':'))
  3143. newRData = strNewRData.ParseColonHexString();
  3144. else
  3145. newRData = Convert.FromHexString(strNewRData);
  3146. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsUnknownRecordData(rdata));
  3147. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsUnknownRecordData(newRData));
  3148. if (disable)
  3149. newRecord.GetAuthGenericRecordInfo().Disabled = true;
  3150. if (!string.IsNullOrEmpty(comments))
  3151. newRecord.GetAuthGenericRecordInfo().Comments = comments;
  3152. _dnsWebService.DnsServer.AuthZoneManager.UpdateRecord(zoneInfo.Name, oldRecord, newRecord);
  3153. }
  3154. break;
  3155. }
  3156. _dnsWebService._log.Write(context.GetRemoteEndPoint(), "[" + session.User.Username + "] Record was updated for authoritative zone '" + zoneInfo.Name + "' successfully {" + (oldRecord is null ? "" : "oldRecord: " + oldRecord.ToString() + "; ") + "newRecord: " + newRecord.ToString() + "}");
  3157. _dnsWebService.DnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  3158. Utf8JsonWriter jsonWriter = context.GetCurrentJsonWriter();
  3159. jsonWriter.WritePropertyName("zone");
  3160. WriteZoneInfoAsJson(zoneInfo, jsonWriter);
  3161. jsonWriter.WritePropertyName("updatedRecord");
  3162. WriteRecordAsJson(newRecord, jsonWriter, true, zoneInfo);
  3163. }
  3164. #endregion
  3165. #region properties
  3166. public uint DefaultRecordTtl
  3167. {
  3168. get { return _defaultRecordTtl; }
  3169. set { _defaultRecordTtl = value; }
  3170. }
  3171. #endregion
  3172. }
  3173. }