WebService.cs 183 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470
  1. /*
  2. Technitium DNS Server
  3. Copyright (C) 2020 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.Dhcp;
  16. using DnsServerCore.Dhcp.Options;
  17. using DnsServerCore.Dns;
  18. using DnsServerCore.Dns.ResourceRecords;
  19. using DnsServerCore.Dns.Zones;
  20. using Newtonsoft.Json;
  21. using Newtonsoft.Json.Converters;
  22. using System;
  23. using System.Collections.Concurrent;
  24. using System.Collections.Generic;
  25. using System.IO;
  26. using System.Net;
  27. using System.Net.Http;
  28. using System.Reflection;
  29. using System.Security.Cryptography;
  30. using System.Security.Cryptography.X509Certificates;
  31. using System.Text;
  32. using System.Threading;
  33. using System.Threading.Tasks;
  34. using TechnitiumLibrary.IO;
  35. using TechnitiumLibrary.Net;
  36. using TechnitiumLibrary.Net.Dns;
  37. using TechnitiumLibrary.Net.Dns.ResourceRecords;
  38. using TechnitiumLibrary.Net.Proxy;
  39. namespace DnsServerCore
  40. {
  41. public class WebService : IDisposable
  42. {
  43. #region enum
  44. enum ServiceState
  45. {
  46. Stopped = 0,
  47. Starting = 1,
  48. Running = 2,
  49. Stopping = 3
  50. }
  51. #endregion
  52. #region variables
  53. readonly Version _currentVersion;
  54. readonly string _appFolder;
  55. readonly string _configFolder;
  56. readonly Uri _updateCheckUri;
  57. readonly LogManager _log;
  58. DnsServer _dnsServer;
  59. DhcpServer _dhcpServer;
  60. int _webServicePort;
  61. HttpListener _webService;
  62. Thread _webServiceThread;
  63. readonly IndependentTaskScheduler _webServiceTaskScheduler = new IndependentTaskScheduler(ThreadPriority.AboveNormal);
  64. string _webServiceHostname;
  65. string _tlsCertificatePath;
  66. string _tlsCertificatePassword;
  67. Timer _tlsCertificateUpdateTimer;
  68. DateTime _tlsCertificateLastModifiedOn;
  69. const int TLS_CERTIFICATE_UPDATE_TIMER_INITIAL_INTERVAL = 60000;
  70. const int TLS_CERTIFICATE_UPDATE_TIMER_INTERVAL = 60000;
  71. const int MAX_LOGIN_ATTEMPTS = 5;
  72. const int BLOCK_ADDRESS_INTERVAL = 5 * 60 * 1000;
  73. readonly ConcurrentDictionary<IPAddress, int> _failedLoginAttempts = new ConcurrentDictionary<IPAddress, int>();
  74. readonly ConcurrentDictionary<IPAddress, DateTime> _blockedAddresses = new ConcurrentDictionary<IPAddress, DateTime>();
  75. readonly ConcurrentDictionary<string, string> _credentials = new ConcurrentDictionary<string, string>();
  76. readonly ConcurrentDictionary<string, UserSession> _sessions = new ConcurrentDictionary<string, UserSession>();
  77. volatile ServiceState _state = ServiceState.Stopped;
  78. Timer _blockListUpdateTimer;
  79. DateTime _blockListLastUpdatedOn;
  80. const int BLOCK_LIST_UPDATE_AFTER_HOURS = 24;
  81. const int BLOCK_LIST_UPDATE_TIMER_INITIAL_INTERVAL = 5000;
  82. const int BLOCK_LIST_UPDATE_TIMER_INTERVAL = 900000;
  83. List<string> _configDisabledZones;
  84. #endregion
  85. #region constructor
  86. public WebService(string configFolder = null, Uri updateCheckUri = null)
  87. {
  88. Assembly assembly = Assembly.GetExecutingAssembly();
  89. AssemblyName assemblyName = assembly.GetName();
  90. _currentVersion = assemblyName.Version;
  91. _appFolder = Path.GetDirectoryName(assembly.Location);
  92. if (configFolder == null)
  93. _configFolder = Path.Combine(_appFolder, "config");
  94. else
  95. _configFolder = configFolder;
  96. if (!Directory.Exists(_configFolder))
  97. Directory.CreateDirectory(_configFolder);
  98. _updateCheckUri = updateCheckUri;
  99. string logFolder = Path.Combine(_configFolder, "logs");
  100. if (!Directory.Exists(logFolder))
  101. Directory.CreateDirectory(logFolder);
  102. _log = new LogManager(logFolder);
  103. string blockListsFolder = Path.Combine(_configFolder, "blocklists");
  104. if (!Directory.Exists(blockListsFolder))
  105. Directory.CreateDirectory(blockListsFolder);
  106. }
  107. #endregion
  108. #region IDisposable
  109. private bool _disposed = false;
  110. protected virtual void Dispose(bool disposing)
  111. {
  112. if (_disposed)
  113. return;
  114. if (disposing)
  115. {
  116. Stop();
  117. if (_webService != null)
  118. _webService.Close();
  119. if (_dnsServer != null)
  120. _dnsServer.Dispose();
  121. if (_dhcpServer != null)
  122. _dhcpServer.Dispose();
  123. if (_log != null)
  124. _log.Dispose();
  125. }
  126. _disposed = true;
  127. }
  128. public void Dispose()
  129. {
  130. Dispose(true);
  131. }
  132. #endregion
  133. #region private
  134. private void AcceptWebRequestAsync(object state)
  135. {
  136. try
  137. {
  138. while (true)
  139. {
  140. HttpListenerContext context = _webService.GetContext();
  141. _ = Task.Factory.StartNew(delegate ()
  142. {
  143. return ProcessRequestAsync(context.Request, context.Response);
  144. }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, _webServiceTaskScheduler);
  145. }
  146. }
  147. catch (Exception ex)
  148. {
  149. if ((_state == ServiceState.Stopping) || (_state == ServiceState.Stopped))
  150. return; //web service stopping
  151. _log.Write(ex);
  152. throw;
  153. }
  154. }
  155. private async Task ProcessRequestAsync(HttpListenerRequest request, HttpListenerResponse response)
  156. {
  157. response.AddHeader("Server", "");
  158. response.AddHeader("X-Robots-Tag", "noindex, nofollow");
  159. try
  160. {
  161. Uri url = request.Url;
  162. string path = url.AbsolutePath;
  163. if (!path.StartsWith("/") || path.Contains("/../") || path.Contains("/.../"))
  164. {
  165. await SendErrorAsync(response, 404);
  166. return;
  167. }
  168. if (path.StartsWith("/api/"))
  169. {
  170. using (MemoryStream mS = new MemoryStream())
  171. {
  172. try
  173. {
  174. JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
  175. jsonWriter.WriteStartObject();
  176. switch (path)
  177. {
  178. case "/api/login":
  179. await LoginAsync(request, jsonWriter);
  180. break;
  181. case "/api/logout":
  182. Logout(request);
  183. break;
  184. default:
  185. if (!IsSessionValid(request))
  186. throw new InvalidTokenWebServiceException("Invalid token or session expired.");
  187. jsonWriter.WritePropertyName("response");
  188. jsonWriter.WriteStartObject();
  189. try
  190. {
  191. switch (path)
  192. {
  193. case "/api/changePassword":
  194. ChangePassword(request);
  195. break;
  196. case "/api/checkForUpdate":
  197. await CheckForUpdateAsync(request, jsonWriter);
  198. break;
  199. case "/api/getDnsSettings":
  200. GetDnsSettings(jsonWriter);
  201. break;
  202. case "/api/setDnsSettings":
  203. SetDnsSettings(request, jsonWriter);
  204. break;
  205. case "/api/getStats":
  206. await GetStats(request, jsonWriter);
  207. break;
  208. case "/api/flushDnsCache":
  209. FlushCache(request);
  210. break;
  211. case "/api/listCachedZones":
  212. ListCachedZones(request, jsonWriter);
  213. break;
  214. case "/api/deleteCachedZone":
  215. DeleteCachedZone(request);
  216. break;
  217. case "/api/listAllowedZones":
  218. ListAllowedZones(request, jsonWriter);
  219. break;
  220. case "/api/importAllowedZones":
  221. ImportAllowedZones(request);
  222. break;
  223. case "/api/exportAllowedZones":
  224. ExportAllowedZones(response);
  225. return;
  226. case "/api/deleteAllowedZone":
  227. DeleteAllowedZone(request);
  228. break;
  229. case "/api/allowZone":
  230. AllowZone(request);
  231. break;
  232. case "/api/listBlockedZones":
  233. ListBlockedZones(request, jsonWriter);
  234. break;
  235. case "/api/importBlockedZones":
  236. ImportBlockedZones(request);
  237. break;
  238. case "/api/exportBlockedZones":
  239. ExportBlockedZones(response);
  240. return;
  241. case "/api/deleteBlockedZone":
  242. DeleteBlockedZone(request);
  243. break;
  244. case "/api/blockZone":
  245. BlockZone(request);
  246. break;
  247. case "/api/listZones":
  248. ListZones(jsonWriter);
  249. break;
  250. case "/api/createZone":
  251. await CreateZoneAsync(request, jsonWriter);
  252. break;
  253. case "/api/deleteZone":
  254. DeleteZone(request);
  255. break;
  256. case "/api/enableZone":
  257. EnableZone(request);
  258. break;
  259. case "/api/disableZone":
  260. DisableZone(request);
  261. break;
  262. case "/api/addRecord":
  263. AddRecord(request);
  264. break;
  265. case "/api/getRecords":
  266. GetRecords(request, jsonWriter);
  267. break;
  268. case "/api/deleteRecord":
  269. DeleteRecord(request);
  270. break;
  271. case "/api/updateRecord":
  272. UpdateRecord(request);
  273. break;
  274. case "/api/resolveQuery":
  275. await ResolveQuery(request, jsonWriter);
  276. break;
  277. case "/api/listLogs":
  278. ListLogs(jsonWriter);
  279. break;
  280. case "/api/deleteLog":
  281. DeleteLog(request);
  282. break;
  283. case "/api/listDhcpScopes":
  284. ListDhcpScopes(jsonWriter);
  285. break;
  286. case "/api/listDhcpLeases":
  287. ListDhcpLeases(jsonWriter);
  288. break;
  289. case "/api/getDhcpScope":
  290. GetDhcpScope(request, jsonWriter);
  291. break;
  292. case "/api/setDhcpScope":
  293. await SetDhcpScopeAsync(request);
  294. break;
  295. case "/api/enableDhcpScope":
  296. await EnableDhcpScopeAsync(request);
  297. break;
  298. case "/api/disableDhcpScope":
  299. DisableDhcpScope(request);
  300. break;
  301. case "/api/deleteDhcpScope":
  302. DeleteDhcpScope(request);
  303. break;
  304. default:
  305. await SendErrorAsync(response, 404);
  306. return;
  307. }
  308. }
  309. finally
  310. {
  311. jsonWriter.WriteEndObject();
  312. }
  313. break;
  314. }
  315. jsonWriter.WritePropertyName("status");
  316. jsonWriter.WriteValue("ok");
  317. jsonWriter.WriteEndObject();
  318. jsonWriter.Flush();
  319. }
  320. catch (InvalidTokenWebServiceException ex)
  321. {
  322. mS.SetLength(0);
  323. JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
  324. jsonWriter.WriteStartObject();
  325. jsonWriter.WritePropertyName("status");
  326. jsonWriter.WriteValue("invalid-token");
  327. jsonWriter.WritePropertyName("errorMessage");
  328. jsonWriter.WriteValue(ex.Message);
  329. jsonWriter.WriteEndObject();
  330. jsonWriter.Flush();
  331. }
  332. catch (Exception ex)
  333. {
  334. _log.Write(GetRequestRemoteEndPoint(request), ex);
  335. mS.SetLength(0);
  336. JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
  337. jsonWriter.WriteStartObject();
  338. jsonWriter.WritePropertyName("status");
  339. jsonWriter.WriteValue("error");
  340. jsonWriter.WritePropertyName("errorMessage");
  341. jsonWriter.WriteValue(ex.Message);
  342. jsonWriter.WritePropertyName("stackTrace");
  343. jsonWriter.WriteValue(ex.StackTrace);
  344. if (ex.InnerException != null)
  345. {
  346. jsonWriter.WritePropertyName("innerErrorMessage");
  347. jsonWriter.WriteValue(ex.InnerException.Message);
  348. }
  349. jsonWriter.WriteEndObject();
  350. jsonWriter.Flush();
  351. }
  352. response.ContentType = "application/json; charset=utf-8";
  353. response.ContentEncoding = Encoding.UTF8;
  354. response.ContentLength64 = mS.Length;
  355. using (Stream stream = response.OutputStream)
  356. {
  357. mS.WriteTo(response.OutputStream);
  358. }
  359. }
  360. }
  361. else if (path.StartsWith("/log/"))
  362. {
  363. if (!IsSessionValid(request))
  364. {
  365. await SendErrorAsync(response, 403, "Invalid token or session expired.");
  366. return;
  367. }
  368. string[] pathParts = path.Split('/');
  369. string logFileName = pathParts[2];
  370. string logFile = Path.Combine(_log.LogFolder, logFileName + ".log");
  371. int limit = 0;
  372. string strLimit = request.QueryString["limit"];
  373. if (!string.IsNullOrEmpty(strLimit))
  374. limit = int.Parse(strLimit);
  375. LogManager.DownloadLog(response, logFile, limit * 1024 * 1024);
  376. }
  377. else
  378. {
  379. if (path == "/")
  380. {
  381. path = "/index.html";
  382. }
  383. else if ((path == "/blocklist.txt") && !IPAddress.IsLoopback(GetRequestRemoteEndPoint(request).Address))
  384. {
  385. await SendErrorAsync(response, 403);
  386. return;
  387. }
  388. string wwwroot = Path.Combine(_appFolder, "www");
  389. path = Path.GetFullPath(wwwroot + path.Replace('/', Path.DirectorySeparatorChar));
  390. if (!path.StartsWith(wwwroot) || !File.Exists(path))
  391. {
  392. await SendErrorAsync(response, 404);
  393. return;
  394. }
  395. await SendFileAsync(response, path);
  396. }
  397. }
  398. catch (Exception ex)
  399. {
  400. if ((_state == ServiceState.Stopping) || (_state == ServiceState.Stopped))
  401. return; //web service stopping
  402. _log.Write(GetRequestRemoteEndPoint(request), ex);
  403. await SendError(response, ex);
  404. }
  405. }
  406. private static IPEndPoint GetRequestRemoteEndPoint(HttpListenerRequest request)
  407. {
  408. try
  409. {
  410. if (request.RemoteEndPoint == null)
  411. return new IPEndPoint(IPAddress.Any, 0);
  412. if (NetUtilities.IsPrivateIP(request.RemoteEndPoint.Address))
  413. {
  414. string xRealIp = request.Headers["X-Real-IP"];
  415. if (IPAddress.TryParse(xRealIp, out IPAddress address))
  416. {
  417. //get the real IP address of the requesting client from X-Real-IP header set in nginx proxy_pass block
  418. return new IPEndPoint(address, 0);
  419. }
  420. }
  421. return request.RemoteEndPoint;
  422. }
  423. catch
  424. {
  425. return new IPEndPoint(IPAddress.Any, 0);
  426. }
  427. }
  428. private static Task SendError(HttpListenerResponse response, Exception ex)
  429. {
  430. return SendErrorAsync(response, 500, ex.ToString());
  431. }
  432. private static async Task SendErrorAsync(HttpListenerResponse response, int statusCode, string message = null)
  433. {
  434. try
  435. {
  436. string statusString = statusCode + " " + DnsServer.GetHttpStatusString((HttpStatusCode)statusCode);
  437. byte[] buffer = Encoding.UTF8.GetBytes("<html><head><title>" + statusString + "</title></head><body><h1>" + statusString + "</h1>" + (message == null ? "" : "<p>" + message + "</p>") + "</body></html>");
  438. response.StatusCode = statusCode;
  439. response.ContentType = "text/html";
  440. response.ContentLength64 = buffer.Length;
  441. using (Stream stream = response.OutputStream)
  442. {
  443. await stream.WriteAsync(buffer, 0, buffer.Length);
  444. }
  445. }
  446. catch
  447. { }
  448. }
  449. private static async Task SendFileAsync(HttpListenerResponse response, string filePath)
  450. {
  451. using (FileStream fS = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
  452. {
  453. response.ContentType = WebUtilities.GetContentType(filePath).MediaType;
  454. response.ContentLength64 = fS.Length;
  455. response.AddHeader("Cache-Control", "private, max-age=300");
  456. using (Stream stream = response.OutputStream)
  457. {
  458. try
  459. {
  460. await fS.CopyToAsync(stream);
  461. }
  462. catch (HttpListenerException)
  463. {
  464. //ignore this error
  465. }
  466. }
  467. }
  468. }
  469. private string CreateSession(string username)
  470. {
  471. string token = BinaryNumber.GenerateRandomNumber256().ToString();
  472. if (!_sessions.TryAdd(token, new UserSession(username)))
  473. throw new WebServiceException("Error while creating session. Please try again.");
  474. return token;
  475. }
  476. private UserSession GetSession(string token)
  477. {
  478. if (_sessions.TryGetValue(token, out UserSession session))
  479. return session;
  480. return null;
  481. }
  482. private UserSession GetSession(HttpListenerRequest request)
  483. {
  484. string strToken = request.QueryString["token"];
  485. if (string.IsNullOrEmpty(strToken))
  486. throw new WebServiceException("Parameter 'token' missing.");
  487. return GetSession(strToken);
  488. }
  489. private UserSession DeleteSession(string token)
  490. {
  491. if (_sessions.TryRemove(token, out UserSession session))
  492. return session;
  493. return null;
  494. }
  495. private UserSession DeleteSession(HttpListenerRequest request)
  496. {
  497. string strToken = request.QueryString["token"];
  498. if (string.IsNullOrEmpty(strToken))
  499. throw new WebServiceException("Parameter 'token' missing.");
  500. return DeleteSession(strToken);
  501. }
  502. private void FailedLoginAttempt(IPAddress address)
  503. {
  504. _failedLoginAttempts.AddOrUpdate(address, 1, delegate (IPAddress key, int attempts)
  505. {
  506. return attempts + 1;
  507. });
  508. }
  509. private bool LoginAttemptsExceedLimit(IPAddress address, int limit)
  510. {
  511. if (!_failedLoginAttempts.TryGetValue(address, out int attempts))
  512. return false;
  513. return attempts >= limit;
  514. }
  515. private void ResetFailedLoginAttempt(IPAddress address)
  516. {
  517. _failedLoginAttempts.TryRemove(address, out _);
  518. }
  519. private void BlockAddress(IPAddress address, int interval)
  520. {
  521. _blockedAddresses.TryAdd(address, DateTime.UtcNow.AddMilliseconds(interval));
  522. }
  523. private bool IsAddressBlocked(IPAddress address)
  524. {
  525. if (!_blockedAddresses.TryGetValue(address, out DateTime expiry))
  526. return false;
  527. if (expiry > DateTime.UtcNow)
  528. {
  529. return true;
  530. }
  531. else
  532. {
  533. UnblockAddress(address);
  534. ResetFailedLoginAttempt(address);
  535. return false;
  536. }
  537. }
  538. private void UnblockAddress(IPAddress address)
  539. {
  540. _blockedAddresses.TryRemove(address, out _);
  541. }
  542. private async Task LoginAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
  543. {
  544. string strUsername = request.QueryString["user"];
  545. if (string.IsNullOrEmpty(strUsername))
  546. throw new WebServiceException("Parameter 'user' missing.");
  547. string strPassword = request.QueryString["pass"];
  548. if (string.IsNullOrEmpty(strPassword))
  549. throw new WebServiceException("Parameter 'pass' missing.");
  550. IPEndPoint remoteEP = GetRequestRemoteEndPoint(request);
  551. if (IsAddressBlocked(remoteEP.Address))
  552. throw new WebServiceException("Max limit of " + MAX_LOGIN_ATTEMPTS + " attempts exceeded. Access blocked for " + (BLOCK_ADDRESS_INTERVAL / 1000) + " seconds.");
  553. strUsername = strUsername.ToLower();
  554. string strPasswordHash = GetPasswordHash(strUsername, strPassword);
  555. if (!_credentials.TryGetValue(strUsername, out string passwordHash) || (passwordHash != strPasswordHash))
  556. {
  557. if (strPassword != "admin") //exception for default password
  558. {
  559. FailedLoginAttempt(remoteEP.Address);
  560. if (LoginAttemptsExceedLimit(remoteEP.Address, MAX_LOGIN_ATTEMPTS))
  561. BlockAddress(remoteEP.Address, BLOCK_ADDRESS_INTERVAL);
  562. await Task.Delay(1000);
  563. }
  564. throw new WebServiceException("Invalid username or password: " + strUsername);
  565. }
  566. ResetFailedLoginAttempt(remoteEP.Address);
  567. _log.Write(remoteEP, "[" + strUsername + "] User logged in.");
  568. string token = CreateSession(strUsername);
  569. jsonWriter.WritePropertyName("token");
  570. jsonWriter.WriteValue(token);
  571. }
  572. private bool IsSessionValid(HttpListenerRequest request)
  573. {
  574. UserSession session = GetSession(request);
  575. if (session == null)
  576. return false;
  577. if (session.HasExpired())
  578. {
  579. DeleteSession(request);
  580. return false;
  581. }
  582. session.UpdateLastSeen();
  583. return true;
  584. }
  585. private void ChangePassword(HttpListenerRequest request)
  586. {
  587. string strToken = request.QueryString["token"];
  588. if (string.IsNullOrEmpty(strToken))
  589. throw new WebServiceException("Parameter 'token' missing.");
  590. string strPassword = request.QueryString["pass"];
  591. if (string.IsNullOrEmpty(strPassword))
  592. throw new WebServiceException("Parameter 'pass' missing.");
  593. UserSession session = GetSession(strToken);
  594. if (session == null)
  595. throw new WebServiceException("User session does not exists.");
  596. SetCredentials(session.Username, strPassword);
  597. SaveConfigFile();
  598. _log.Write(GetRequestRemoteEndPoint(request), "[" + session.Username + "] Password was changed for user.");
  599. }
  600. private void Logout(HttpListenerRequest request)
  601. {
  602. string strToken = request.QueryString["token"];
  603. if (string.IsNullOrEmpty(strToken))
  604. throw new WebServiceException("Parameter 'token' missing.");
  605. UserSession session = DeleteSession(strToken);
  606. if (session != null)
  607. _log.Write(GetRequestRemoteEndPoint(request), "[" + session.Username + "] User logged out.");
  608. }
  609. public static void CreateUpdateInfo(Stream s, string version, string displayText, string downloadLink)
  610. {
  611. BinaryWriter bW = new BinaryWriter(s);
  612. bW.Write(Encoding.ASCII.GetBytes("DU")); //format
  613. bW.Write((byte)2); //version
  614. bW.WriteShortString(version);
  615. bW.WriteShortString(displayText);
  616. bW.WriteShortString(downloadLink);
  617. }
  618. private async Task CheckForUpdateAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
  619. {
  620. Version updateVersion = null;
  621. string displayText = null;
  622. string downloadLink = null;
  623. bool updateAvailable = false;
  624. if (_updateCheckUri != null)
  625. {
  626. try
  627. {
  628. HttpClientHandler handler = new HttpClientHandler();
  629. handler.Proxy = _dnsServer.Proxy;
  630. using (HttpClient http = new HttpClient(handler))
  631. {
  632. byte[] response = await http.GetByteArrayAsync(_updateCheckUri);
  633. using (MemoryStream mS = new MemoryStream(response, false))
  634. {
  635. BinaryReader bR = new BinaryReader(mS);
  636. if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "DU") //format
  637. throw new InvalidDataException("DNS Server update info format is invalid.");
  638. switch (bR.ReadByte()) //version
  639. {
  640. case 2:
  641. updateVersion = new Version(bR.ReadShortString());
  642. displayText = bR.ReadShortString();
  643. downloadLink = bR.ReadShortString();
  644. break;
  645. default:
  646. throw new InvalidDataException("DNS Server update info version not supported.");
  647. }
  648. updateAvailable = updateVersion > _currentVersion;
  649. }
  650. }
  651. _log.Write(GetRequestRemoteEndPoint(request), "Check for update was done {updateAvailable: " + updateAvailable + "; updateVersion: " + updateVersion + "; displayText: " + displayText + "; downloadLink: " + downloadLink + ";}");
  652. }
  653. catch (Exception ex)
  654. {
  655. _log.Write(GetRequestRemoteEndPoint(request), "Check for update was done {updateAvailable: False;}\r\n" + ex.ToString());
  656. }
  657. }
  658. jsonWriter.WritePropertyName("updateAvailable");
  659. jsonWriter.WriteValue(updateAvailable);
  660. if (updateAvailable)
  661. {
  662. if (!string.IsNullOrEmpty(displayText))
  663. {
  664. jsonWriter.WritePropertyName("displayText");
  665. jsonWriter.WriteValue(displayText);
  666. }
  667. jsonWriter.WritePropertyName("downloadLink");
  668. jsonWriter.WriteValue(downloadLink);
  669. }
  670. }
  671. private static string GetCleanVersion(Version version)
  672. {
  673. string strVersion = version.Major + "." + version.Minor;
  674. if (version.Build > 0)
  675. strVersion += "." + version.Build;
  676. if (version.Revision > 0)
  677. strVersion += "." + version.Revision;
  678. return strVersion;
  679. }
  680. private void GetDnsSettings(JsonTextWriter jsonWriter)
  681. {
  682. jsonWriter.WritePropertyName("version");
  683. jsonWriter.WriteValue(GetCleanVersion(_currentVersion));
  684. jsonWriter.WritePropertyName("serverDomain");
  685. jsonWriter.WriteValue(_dnsServer.ServerDomain);
  686. jsonWriter.WritePropertyName("webServicePort");
  687. jsonWriter.WriteValue(_webServicePort);
  688. jsonWriter.WritePropertyName("dnsServerLocalEndPoints");
  689. jsonWriter.WriteStartArray();
  690. foreach (IPEndPoint localEP in _dnsServer.LocalEndPoints)
  691. jsonWriter.WriteValue(localEP.ToString());
  692. jsonWriter.WriteEndArray();
  693. jsonWriter.WritePropertyName("enableDnsOverHttp");
  694. jsonWriter.WriteValue(_dnsServer.EnableDnsOverHttp);
  695. jsonWriter.WritePropertyName("enableDnsOverTls");
  696. jsonWriter.WriteValue(_dnsServer.EnableDnsOverTls);
  697. jsonWriter.WritePropertyName("enableDnsOverHttps");
  698. jsonWriter.WriteValue(_dnsServer.EnableDnsOverHttps);
  699. jsonWriter.WritePropertyName("tlsCertificatePath");
  700. jsonWriter.WriteValue(_tlsCertificatePath);
  701. jsonWriter.WritePropertyName("tlsCertificatePassword");
  702. jsonWriter.WriteValue("************");
  703. jsonWriter.WritePropertyName("preferIPv6");
  704. jsonWriter.WriteValue(_dnsServer.PreferIPv6);
  705. jsonWriter.WritePropertyName("logQueries");
  706. jsonWriter.WriteValue(_dnsServer.QueryLogManager != null);
  707. jsonWriter.WritePropertyName("allowRecursion");
  708. jsonWriter.WriteValue(_dnsServer.AllowRecursion);
  709. jsonWriter.WritePropertyName("allowRecursionOnlyForPrivateNetworks");
  710. jsonWriter.WriteValue(_dnsServer.AllowRecursionOnlyForPrivateNetworks);
  711. jsonWriter.WritePropertyName("cachePrefetchEligibility");
  712. jsonWriter.WriteValue(_dnsServer.CachePrefetchEligibility);
  713. jsonWriter.WritePropertyName("cachePrefetchTrigger");
  714. jsonWriter.WriteValue(_dnsServer.CachePrefetchTrigger);
  715. jsonWriter.WritePropertyName("cachePrefetchSampleIntervalInMinutes");
  716. jsonWriter.WriteValue(_dnsServer.CachePrefetchSampleIntervalInMinutes);
  717. jsonWriter.WritePropertyName("cachePrefetchSampleEligibilityHitsPerHour");
  718. jsonWriter.WriteValue(_dnsServer.CachePrefetchSampleEligibilityHitsPerHour);
  719. jsonWriter.WritePropertyName("proxy");
  720. if (_dnsServer.Proxy == null)
  721. {
  722. jsonWriter.WriteNull();
  723. }
  724. else
  725. {
  726. jsonWriter.WriteStartObject();
  727. NetProxy proxy = _dnsServer.Proxy;
  728. jsonWriter.WritePropertyName("type");
  729. jsonWriter.WriteValue(proxy.Type.ToString());
  730. jsonWriter.WritePropertyName("address");
  731. jsonWriter.WriteValue(proxy.Address);
  732. jsonWriter.WritePropertyName("port");
  733. jsonWriter.WriteValue(proxy.Port);
  734. NetworkCredential credential = proxy.Credential;
  735. if (credential != null)
  736. {
  737. jsonWriter.WritePropertyName("username");
  738. jsonWriter.WriteValue(credential.UserName);
  739. jsonWriter.WritePropertyName("password");
  740. jsonWriter.WriteValue(credential.Password);
  741. }
  742. jsonWriter.WritePropertyName("bypass");
  743. jsonWriter.WriteStartArray();
  744. foreach (NetProxyBypassItem item in proxy.BypassList)
  745. jsonWriter.WriteValue(item.Value);
  746. jsonWriter.WriteEndArray();
  747. jsonWriter.WriteEndObject();
  748. }
  749. jsonWriter.WritePropertyName("forwarders");
  750. DnsTransportProtocol forwarderProtocol = DnsTransportProtocol.Udp;
  751. if (_dnsServer.Forwarders == null)
  752. {
  753. jsonWriter.WriteNull();
  754. }
  755. else
  756. {
  757. forwarderProtocol = _dnsServer.Forwarders[0].Protocol;
  758. jsonWriter.WriteStartArray();
  759. foreach (NameServerAddress forwarder in _dnsServer.Forwarders)
  760. jsonWriter.WriteValue(forwarder.OriginalAddress);
  761. jsonWriter.WriteEndArray();
  762. }
  763. jsonWriter.WritePropertyName("forwarderProtocol");
  764. jsonWriter.WriteValue(forwarderProtocol.ToString());
  765. jsonWriter.WritePropertyName("blockListUrls");
  766. if (_dnsServer.BlockListZoneManager.BlockListUrls.Count == 0)
  767. {
  768. jsonWriter.WriteNull();
  769. }
  770. else
  771. {
  772. jsonWriter.WriteStartArray();
  773. foreach (Uri blockListUrl in _dnsServer.BlockListZoneManager.BlockListUrls)
  774. jsonWriter.WriteValue(blockListUrl.AbsoluteUri);
  775. jsonWriter.WriteEndArray();
  776. }
  777. }
  778. private void SetDnsSettings(HttpListenerRequest request, JsonTextWriter jsonWriter)
  779. {
  780. string strServerDomain = request.QueryString["serverDomain"];
  781. if (!string.IsNullOrEmpty(strServerDomain))
  782. _dnsServer.ServerDomain = strServerDomain;
  783. string strDnsServerLocalEndPoints = request.QueryString["dnsServerLocalEndPoints"];
  784. if (strDnsServerLocalEndPoints != null)
  785. {
  786. if (string.IsNullOrEmpty(strDnsServerLocalEndPoints))
  787. strDnsServerLocalEndPoints = "0.0.0.0:53,[::]:53";
  788. string[] strLocalEndPoints = strDnsServerLocalEndPoints.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  789. List<IPEndPoint> localEndPoints = new List<IPEndPoint>(strLocalEndPoints.Length);
  790. for (int i = 0; i < strLocalEndPoints.Length; i++)
  791. {
  792. NameServerAddress nameServer = new NameServerAddress(strLocalEndPoints[i]);
  793. if (nameServer.IPEndPoint != null)
  794. localEndPoints.Add(nameServer.IPEndPoint);
  795. }
  796. _dnsServer.LocalEndPoints = localEndPoints;
  797. }
  798. int oldWebServicePort = _webServicePort;
  799. string strWebServicePort = request.QueryString["webServicePort"];
  800. if (!string.IsNullOrEmpty(strWebServicePort))
  801. _webServicePort = int.Parse(strWebServicePort);
  802. string enableDnsOverHttp = request.QueryString["enableDnsOverHttp"];
  803. if (!string.IsNullOrEmpty(enableDnsOverHttp))
  804. _dnsServer.EnableDnsOverHttp = bool.Parse(enableDnsOverHttp);
  805. string strEnableDnsOverTls = request.QueryString["enableDnsOverTls"];
  806. if (!string.IsNullOrEmpty(strEnableDnsOverTls))
  807. _dnsServer.EnableDnsOverTls = bool.Parse(strEnableDnsOverTls);
  808. string strEnableDnsOverHttps = request.QueryString["enableDnsOverHttps"];
  809. if (!string.IsNullOrEmpty(strEnableDnsOverHttps))
  810. _dnsServer.EnableDnsOverHttps = bool.Parse(strEnableDnsOverHttps);
  811. string strTlsCertificatePath = request.QueryString["tlsCertificatePath"];
  812. string strTlsCertificatePassword = request.QueryString["tlsCertificatePassword"];
  813. if (string.IsNullOrEmpty(strTlsCertificatePath))
  814. {
  815. StopTlsCertificateUpdateTimer();
  816. _tlsCertificatePath = null;
  817. _tlsCertificatePassword = "";
  818. }
  819. else
  820. {
  821. if (strTlsCertificatePassword == "************")
  822. strTlsCertificatePassword = _tlsCertificatePassword;
  823. if ((strTlsCertificatePath != _tlsCertificatePath) || (strTlsCertificatePassword != _tlsCertificatePassword))
  824. {
  825. LoadTlsCertificate(strTlsCertificatePath, strTlsCertificatePassword);
  826. _tlsCertificatePath = strTlsCertificatePath;
  827. _tlsCertificatePassword = strTlsCertificatePassword;
  828. StartTlsCertificateUpdateTimer();
  829. }
  830. }
  831. string strPreferIPv6 = request.QueryString["preferIPv6"];
  832. if (!string.IsNullOrEmpty(strPreferIPv6))
  833. _dnsServer.PreferIPv6 = bool.Parse(strPreferIPv6);
  834. string strLogQueries = request.QueryString["logQueries"];
  835. if (!string.IsNullOrEmpty(strLogQueries))
  836. {
  837. if (bool.Parse(strLogQueries))
  838. _dnsServer.QueryLogManager = _log;
  839. else
  840. _dnsServer.QueryLogManager = null;
  841. }
  842. string strAllowRecursion = request.QueryString["allowRecursion"];
  843. if (!string.IsNullOrEmpty(strAllowRecursion))
  844. _dnsServer.AllowRecursion = bool.Parse(strAllowRecursion);
  845. string strAllowRecursionOnlyForPrivateNetworks = request.QueryString["allowRecursionOnlyForPrivateNetworks"];
  846. if (!string.IsNullOrEmpty(strAllowRecursionOnlyForPrivateNetworks))
  847. _dnsServer.AllowRecursionOnlyForPrivateNetworks = bool.Parse(strAllowRecursionOnlyForPrivateNetworks);
  848. string strCachePrefetchEligibility = request.QueryString["cachePrefetchEligibility"];
  849. if (!string.IsNullOrEmpty(strCachePrefetchEligibility))
  850. _dnsServer.CachePrefetchEligibility = int.Parse(strCachePrefetchEligibility);
  851. string strCachePrefetchTrigger = request.QueryString["cachePrefetchTrigger"];
  852. if (!string.IsNullOrEmpty(strCachePrefetchTrigger))
  853. _dnsServer.CachePrefetchTrigger = int.Parse(strCachePrefetchTrigger);
  854. string strCachePrefetchSampleIntervalInMinutes = request.QueryString["cachePrefetchSampleIntervalInMinutes"];
  855. if (!string.IsNullOrEmpty(strCachePrefetchSampleIntervalInMinutes))
  856. _dnsServer.CachePrefetchSampleIntervalInMinutes = int.Parse(strCachePrefetchSampleIntervalInMinutes);
  857. string strCachePrefetchSampleEligibilityHitsPerHour = request.QueryString["cachePrefetchSampleEligibilityHitsPerHour"];
  858. if (!string.IsNullOrEmpty(strCachePrefetchSampleEligibilityHitsPerHour))
  859. _dnsServer.CachePrefetchSampleEligibilityHitsPerHour = int.Parse(strCachePrefetchSampleEligibilityHitsPerHour);
  860. string strProxyType = request.QueryString["proxyType"];
  861. if (!string.IsNullOrEmpty(strProxyType))
  862. {
  863. NetProxyType proxyType = (NetProxyType)Enum.Parse(typeof(NetProxyType), strProxyType, true);
  864. if (proxyType == NetProxyType.None)
  865. {
  866. _dnsServer.Proxy = null;
  867. }
  868. else
  869. {
  870. NetworkCredential credential = null;
  871. string strUsername = request.QueryString["proxyUsername"];
  872. if (!string.IsNullOrEmpty(strUsername))
  873. credential = new NetworkCredential(strUsername, request.QueryString["proxyPassword"]);
  874. _dnsServer.Proxy = NetProxy.CreateProxy(proxyType, request.QueryString["proxyAddress"], int.Parse(request.QueryString["proxyPort"]), credential);
  875. string strProxyBypass = request.QueryString["proxyBypass"];
  876. if (!string.IsNullOrEmpty(strProxyBypass))
  877. {
  878. string[] strBypassList = strProxyBypass.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  879. _dnsServer.Proxy.BypassList.Clear();
  880. for (int i = 0; i < strBypassList.Length; i++)
  881. _dnsServer.Proxy.BypassList.Add(new NetProxyBypassItem(strBypassList[i]));
  882. }
  883. }
  884. }
  885. DnsTransportProtocol forwarderProtocol = DnsTransportProtocol.Udp;
  886. string strForwarderProtocol = request.QueryString["forwarderProtocol"];
  887. if (!string.IsNullOrEmpty(strForwarderProtocol))
  888. forwarderProtocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), strForwarderProtocol, true);
  889. string strForwarders = request.QueryString["forwarders"];
  890. if (!string.IsNullOrEmpty(strForwarders))
  891. {
  892. if (strForwarders == "false")
  893. {
  894. _dnsServer.Forwarders = null;
  895. }
  896. else
  897. {
  898. string[] strForwardersList = strForwarders.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  899. NameServerAddress[] forwarders = new NameServerAddress[strForwardersList.Length];
  900. for (int i = 0; i < strForwardersList.Length; i++)
  901. {
  902. if ((forwarderProtocol == DnsTransportProtocol.Tls) && IPAddress.TryParse(strForwardersList[i], out _))
  903. strForwardersList[i] += ":853";
  904. forwarders[i] = new NameServerAddress(strForwardersList[i], forwarderProtocol);
  905. }
  906. _dnsServer.Forwarders = forwarders;
  907. }
  908. }
  909. string strBlockListUrls = request.QueryString["blockListUrls"];
  910. if (!string.IsNullOrEmpty(strBlockListUrls))
  911. {
  912. if (strBlockListUrls == "false")
  913. {
  914. StopBlockListUpdateTimer();
  915. _dnsServer.BlockListZoneManager.BlockListUrls.Clear();
  916. _dnsServer.BlockListZoneManager.Flush();
  917. }
  918. else
  919. {
  920. bool updated = false;
  921. string[] strBlockListUrlList = strBlockListUrls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  922. if (oldWebServicePort != _webServicePort)
  923. {
  924. for (int i = 0; i < strBlockListUrlList.Length; i++)
  925. {
  926. if (strBlockListUrlList[i].Contains("http://localhost:" + oldWebServicePort + "/blocklist.txt"))
  927. {
  928. strBlockListUrlList[i] = "http://localhost:" + _webServicePort + "/blocklist.txt";
  929. updated = true;
  930. break;
  931. }
  932. }
  933. }
  934. if (!updated)
  935. {
  936. if (strBlockListUrlList.Length != _dnsServer.BlockListZoneManager.BlockListUrls.Count)
  937. {
  938. updated = true;
  939. }
  940. else
  941. {
  942. foreach (string strBlockListUrl in strBlockListUrlList)
  943. {
  944. if (!_dnsServer.BlockListZoneManager.BlockListUrls.Contains(new Uri(strBlockListUrl)))
  945. {
  946. updated = true;
  947. break;
  948. }
  949. }
  950. }
  951. }
  952. if (updated)
  953. {
  954. _dnsServer.BlockListZoneManager.BlockListUrls.Clear();
  955. foreach (string strBlockListUrl in strBlockListUrlList)
  956. {
  957. Uri blockListUrl = new Uri(strBlockListUrl);
  958. if (!_dnsServer.BlockListZoneManager.BlockListUrls.Contains(blockListUrl))
  959. _dnsServer.BlockListZoneManager.BlockListUrls.Add(blockListUrl);
  960. }
  961. _blockListLastUpdatedOn = new DateTime();
  962. StopBlockListUpdateTimer();
  963. StartBlockListUpdateTimer();
  964. }
  965. }
  966. }
  967. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS Settings were updated {serverDomain: " + _dnsServer.ServerDomain + "; dnsServerLocalEndPoints: " + strDnsServerLocalEndPoints + "; webServicePort: " + _webServicePort + "; enableDnsOverHttp: " + _dnsServer.EnableDnsOverHttp + "; enableDnsOverTls: " + _dnsServer.EnableDnsOverTls + "; enableDnsOverHttps: " + _dnsServer.EnableDnsOverHttps + "; tlsCertificatePath: " + _tlsCertificatePath + "; preferIPv6: " + _dnsServer.PreferIPv6 + "; logQueries: " + (_dnsServer.QueryLogManager != null) + "; allowRecursion: " + _dnsServer.AllowRecursion + "; allowRecursionOnlyForPrivateNetworks: " + _dnsServer.AllowRecursionOnlyForPrivateNetworks + "; proxyType: " + strProxyType + "; forwarders: " + strForwarders + "; forwarderProtocol: " + strForwarderProtocol + "; blockListUrl: " + strBlockListUrls + ";}");
  968. SaveConfigFile();
  969. GetDnsSettings(jsonWriter);
  970. }
  971. private async Task GetStats(HttpListenerRequest request, JsonTextWriter jsonWriter)
  972. {
  973. string strType = request.QueryString["type"];
  974. if (string.IsNullOrEmpty(strType))
  975. strType = "lastHour";
  976. Dictionary<string, List<KeyValuePair<string, int>>> data;
  977. switch (strType)
  978. {
  979. case "lastHour":
  980. data = _dnsServer.StatsManager.GetLastHourStats();
  981. break;
  982. case "lastDay":
  983. data = _dnsServer.StatsManager.GetLastDayStats();
  984. break;
  985. case "lastWeek":
  986. data = _dnsServer.StatsManager.GetLastWeekStats();
  987. break;
  988. case "lastMonth":
  989. data = _dnsServer.StatsManager.GetLastMonthStats();
  990. break;
  991. case "lastYear":
  992. data = _dnsServer.StatsManager.GetLastYearStats();
  993. break;
  994. default:
  995. throw new WebServiceException("Unknown stats type requested: " + strType);
  996. }
  997. //stats
  998. {
  999. List<KeyValuePair<string, int>> stats = data["stats"];
  1000. jsonWriter.WritePropertyName("stats");
  1001. jsonWriter.WriteStartObject();
  1002. foreach (KeyValuePair<string, int> item in stats)
  1003. {
  1004. jsonWriter.WritePropertyName(item.Key);
  1005. jsonWriter.WriteValue(item.Value);
  1006. }
  1007. jsonWriter.WritePropertyName("allowedZones");
  1008. jsonWriter.WriteValue(_dnsServer.AllowedZoneManager.TotalZonesAllowed);
  1009. jsonWriter.WritePropertyName("blockedZones");
  1010. jsonWriter.WriteValue(_dnsServer.BlockedZoneManager.TotalZonesBlocked + _dnsServer.BlockListZoneManager.TotalZonesBlocked);
  1011. jsonWriter.WriteEndObject();
  1012. }
  1013. //main chart
  1014. {
  1015. jsonWriter.WritePropertyName("mainChartData");
  1016. jsonWriter.WriteStartObject();
  1017. //label
  1018. {
  1019. List<KeyValuePair<string, int>> statsPerInterval = data["totalQueriesPerInterval"];
  1020. jsonWriter.WritePropertyName("labels");
  1021. jsonWriter.WriteStartArray();
  1022. foreach (KeyValuePair<string, int> item in statsPerInterval)
  1023. jsonWriter.WriteValue(item.Key);
  1024. jsonWriter.WriteEndArray();
  1025. }
  1026. //datasets
  1027. {
  1028. jsonWriter.WritePropertyName("datasets");
  1029. jsonWriter.WriteStartArray();
  1030. WriteChartDataSet(jsonWriter, "Total", "rgba(102, 153, 255, 0.1)", "rgb(102, 153, 255)", data["totalQueriesPerInterval"]);
  1031. WriteChartDataSet(jsonWriter, "No Error", "rgba(92, 184, 92, 0.1)", "rgb(92, 184, 92)", data["totalNoErrorPerInterval"]);
  1032. WriteChartDataSet(jsonWriter, "Server Failure", "rgba(217, 83, 79, 0.1)", "rgb(217, 83, 79)", data["totalServerFailurePerInterval"]);
  1033. WriteChartDataSet(jsonWriter, "Name Error", "rgba(7, 7, 7, 0.1)", "rgb(7, 7, 7)", data["totalNameErrorPerInterval"]);
  1034. WriteChartDataSet(jsonWriter, "Refused", "rgba(91, 192, 222, 0.1)", "rgb(91, 192, 222)", data["totalRefusedPerInterval"]);
  1035. WriteChartDataSet(jsonWriter, "Authoritative", "rgba(150, 150, 0, 0.1)", "rgb(150, 150, 0)", data["totalAuthHitPerInterval"]);
  1036. WriteChartDataSet(jsonWriter, "Recursive", "rgba(23, 162, 184, 0.1)", "rgb(23, 162, 184)", data["totalRecursionsPerInterval"]);
  1037. WriteChartDataSet(jsonWriter, "Cached", "rgba(111, 84, 153, 0.1)", "rgb(111, 84, 153)", data["totalCacheHitPerInterval"]);
  1038. WriteChartDataSet(jsonWriter, "Blocked", "rgba(255, 165, 0, 0.1)", "rgb(255, 165, 0)", data["totalBlockedPerInterval"]);
  1039. WriteChartDataSet(jsonWriter, "Clients", "rgba(51, 122, 183, 0.1)", "rgb(51, 122, 183)", data["totalClientsPerInterval"]);
  1040. jsonWriter.WriteEndArray();
  1041. }
  1042. jsonWriter.WriteEndObject();
  1043. }
  1044. //query response chart
  1045. {
  1046. jsonWriter.WritePropertyName("queryResponseChartData");
  1047. jsonWriter.WriteStartObject();
  1048. List<KeyValuePair<string, int>> stats = data["stats"];
  1049. //labels
  1050. {
  1051. jsonWriter.WritePropertyName("labels");
  1052. jsonWriter.WriteStartArray();
  1053. foreach (KeyValuePair<string, int> item in stats)
  1054. {
  1055. switch (item.Key)
  1056. {
  1057. case "totalAuthoritative":
  1058. jsonWriter.WriteValue("Authoritative");
  1059. break;
  1060. case "totalRecursive":
  1061. jsonWriter.WriteValue("Recursive");
  1062. break;
  1063. case "totalCached":
  1064. jsonWriter.WriteValue("Cached");
  1065. break;
  1066. case "totalBlocked":
  1067. jsonWriter.WriteValue("Blocked");
  1068. break;
  1069. }
  1070. }
  1071. jsonWriter.WriteEndArray();
  1072. }
  1073. //datasets
  1074. {
  1075. jsonWriter.WritePropertyName("datasets");
  1076. jsonWriter.WriteStartArray();
  1077. jsonWriter.WriteStartObject();
  1078. jsonWriter.WritePropertyName("data");
  1079. jsonWriter.WriteStartArray();
  1080. foreach (KeyValuePair<string, int> item in stats)
  1081. {
  1082. switch (item.Key)
  1083. {
  1084. case "totalAuthoritative":
  1085. case "totalRecursive":
  1086. case "totalCached":
  1087. case "totalBlocked":
  1088. jsonWriter.WriteValue(item.Value);
  1089. break;
  1090. }
  1091. }
  1092. jsonWriter.WriteEndArray();
  1093. jsonWriter.WritePropertyName("backgroundColor");
  1094. jsonWriter.WriteStartArray();
  1095. jsonWriter.WriteValue("rgba(150, 150, 0, 0.5)");
  1096. jsonWriter.WriteValue("rgba(23, 162, 184, 0.5)");
  1097. jsonWriter.WriteValue("rgba(111, 84, 153, 0.5)");
  1098. jsonWriter.WriteValue("rgba(255, 165, 0, 0.5)");
  1099. jsonWriter.WriteEndArray();
  1100. jsonWriter.WriteEndObject();
  1101. jsonWriter.WriteEndArray();
  1102. }
  1103. jsonWriter.WriteEndObject();
  1104. }
  1105. //query type chart
  1106. {
  1107. jsonWriter.WritePropertyName("queryTypeChartData");
  1108. jsonWriter.WriteStartObject();
  1109. List<KeyValuePair<string, int>> queryTypes = data["queryTypes"];
  1110. //labels
  1111. {
  1112. jsonWriter.WritePropertyName("labels");
  1113. jsonWriter.WriteStartArray();
  1114. foreach (KeyValuePair<string, int> item in queryTypes)
  1115. jsonWriter.WriteValue(item.Key);
  1116. jsonWriter.WriteEndArray();
  1117. }
  1118. //datasets
  1119. {
  1120. jsonWriter.WritePropertyName("datasets");
  1121. jsonWriter.WriteStartArray();
  1122. jsonWriter.WriteStartObject();
  1123. jsonWriter.WritePropertyName("data");
  1124. jsonWriter.WriteStartArray();
  1125. foreach (KeyValuePair<string, int> item in queryTypes)
  1126. jsonWriter.WriteValue(item.Value);
  1127. jsonWriter.WriteEndArray();
  1128. jsonWriter.WritePropertyName("backgroundColor");
  1129. jsonWriter.WriteStartArray();
  1130. jsonWriter.WriteValue("rgba(102, 153, 255, 0.5)");
  1131. jsonWriter.WriteValue("rgba(92, 184, 92, 0.5)");
  1132. jsonWriter.WriteValue("rgba(91, 192, 222, 0.5)");
  1133. jsonWriter.WriteValue("rgba(255, 165, 0, 0.5)");
  1134. jsonWriter.WriteValue("rgba(51, 122, 183, 0.5)");
  1135. jsonWriter.WriteEndArray();
  1136. jsonWriter.WriteEndObject();
  1137. jsonWriter.WriteEndArray();
  1138. }
  1139. jsonWriter.WriteEndObject();
  1140. }
  1141. //top clients
  1142. {
  1143. List<KeyValuePair<string, int>> topClients = data["topClients"];
  1144. IDictionary<string, string> clientIpMap = _dhcpServer.GetAddressClientMap();
  1145. jsonWriter.WritePropertyName("topClients");
  1146. jsonWriter.WriteStartArray();
  1147. foreach (KeyValuePair<string, int> item in topClients)
  1148. {
  1149. jsonWriter.WriteStartObject();
  1150. jsonWriter.WritePropertyName("name");
  1151. jsonWriter.WriteValue(item.Key);
  1152. if (clientIpMap.TryGetValue(item.Key, out string clientDomain))
  1153. {
  1154. jsonWriter.WritePropertyName("domain");
  1155. jsonWriter.WriteValue(clientDomain);
  1156. }
  1157. else
  1158. {
  1159. IPAddress address = IPAddress.Parse(item.Key);
  1160. if (IPAddress.IsLoopback(address))
  1161. {
  1162. jsonWriter.WritePropertyName("domain");
  1163. jsonWriter.WriteValue("localhost");
  1164. }
  1165. else
  1166. {
  1167. try
  1168. {
  1169. DnsDatagram ptrResponse = await _dnsServer.DirectQueryAsync(new DnsQuestionRecord(address, DnsClass.IN), 200);
  1170. if ((ptrResponse != null) && (ptrResponse.Answer.Count > 0))
  1171. {
  1172. IReadOnlyList<string> ptrDomains = DnsClient.ParseResponsePTR(ptrResponse);
  1173. if (ptrDomains != null)
  1174. {
  1175. jsonWriter.WritePropertyName("domain");
  1176. jsonWriter.WriteValue(ptrDomains[0]);
  1177. }
  1178. }
  1179. }
  1180. catch
  1181. { }
  1182. }
  1183. }
  1184. jsonWriter.WritePropertyName("hits");
  1185. jsonWriter.WriteValue(item.Value);
  1186. jsonWriter.WriteEndObject();
  1187. }
  1188. jsonWriter.WriteEndArray();
  1189. }
  1190. //top domains
  1191. {
  1192. List<KeyValuePair<string, int>> topDomains = data["topDomains"];
  1193. jsonWriter.WritePropertyName("topDomains");
  1194. jsonWriter.WriteStartArray();
  1195. foreach (KeyValuePair<string, int> item in topDomains)
  1196. {
  1197. jsonWriter.WriteStartObject();
  1198. jsonWriter.WritePropertyName("name");
  1199. jsonWriter.WriteValue(item.Key);
  1200. jsonWriter.WritePropertyName("hits");
  1201. jsonWriter.WriteValue(item.Value);
  1202. jsonWriter.WriteEndObject();
  1203. }
  1204. jsonWriter.WriteEndArray();
  1205. }
  1206. //top blocked domains
  1207. {
  1208. List<KeyValuePair<string, int>> topBlockedDomains = data["topBlockedDomains"];
  1209. jsonWriter.WritePropertyName("topBlockedDomains");
  1210. jsonWriter.WriteStartArray();
  1211. foreach (KeyValuePair<string, int> item in topBlockedDomains)
  1212. {
  1213. jsonWriter.WriteStartObject();
  1214. jsonWriter.WritePropertyName("name");
  1215. jsonWriter.WriteValue(item.Key);
  1216. jsonWriter.WritePropertyName("hits");
  1217. jsonWriter.WriteValue(item.Value);
  1218. jsonWriter.WriteEndObject();
  1219. }
  1220. jsonWriter.WriteEndArray();
  1221. }
  1222. }
  1223. private static void WriteChartDataSet(JsonTextWriter jsonWriter, string label, string backgroundColor, string borderColor, List<KeyValuePair<string, int>> statsPerInterval)
  1224. {
  1225. jsonWriter.WriteStartObject();
  1226. jsonWriter.WritePropertyName("label");
  1227. jsonWriter.WriteValue(label);
  1228. jsonWriter.WritePropertyName("backgroundColor");
  1229. jsonWriter.WriteValue(backgroundColor);
  1230. jsonWriter.WritePropertyName("borderColor");
  1231. jsonWriter.WriteValue(borderColor);
  1232. jsonWriter.WritePropertyName("borderWidth");
  1233. jsonWriter.WriteValue(2);
  1234. jsonWriter.WritePropertyName("fill");
  1235. jsonWriter.WriteValue(true);
  1236. jsonWriter.WritePropertyName("data");
  1237. jsonWriter.WriteStartArray();
  1238. foreach (KeyValuePair<string, int> item in statsPerInterval)
  1239. jsonWriter.WriteValue(item.Value);
  1240. jsonWriter.WriteEndArray();
  1241. jsonWriter.WriteEndObject();
  1242. }
  1243. private void FlushCache(HttpListenerRequest request)
  1244. {
  1245. _dnsServer.CacheZoneManager.Flush();
  1246. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Cache was flushed.");
  1247. }
  1248. private void ListCachedZones(HttpListenerRequest request, JsonTextWriter jsonWriter)
  1249. {
  1250. string domain = request.QueryString["domain"];
  1251. if (domain == null)
  1252. domain = "";
  1253. string direction = request.QueryString["direction"];
  1254. List<string> subZones;
  1255. List<DnsResourceRecord> records;
  1256. while (true)
  1257. {
  1258. subZones = _dnsServer.CacheZoneManager.ListSubDomains(domain);
  1259. records = _dnsServer.CacheZoneManager.ListAllRecords(domain);
  1260. if (records.Count > 0)
  1261. break;
  1262. if (subZones.Count != 1)
  1263. break;
  1264. if (direction == "up")
  1265. {
  1266. if (domain.Length == 0)
  1267. break;
  1268. int i = domain.IndexOf('.');
  1269. if (i < 0)
  1270. domain = "";
  1271. else
  1272. domain = domain.Substring(i + 1);
  1273. }
  1274. else if (domain.Length == 0)
  1275. {
  1276. domain = subZones[0];
  1277. }
  1278. else
  1279. {
  1280. domain = subZones[0] + "." + domain;
  1281. }
  1282. }
  1283. subZones.Sort();
  1284. jsonWriter.WritePropertyName("domain");
  1285. jsonWriter.WriteValue(domain);
  1286. jsonWriter.WritePropertyName("zones");
  1287. jsonWriter.WriteStartArray();
  1288. if (domain.Length != 0)
  1289. domain = "." + domain;
  1290. foreach (string subZone in subZones)
  1291. jsonWriter.WriteValue(subZone + domain);
  1292. jsonWriter.WriteEndArray();
  1293. WriteRecordsAsJson(records, jsonWriter, false);
  1294. }
  1295. private void DeleteCachedZone(HttpListenerRequest request)
  1296. {
  1297. string domain = request.QueryString["domain"];
  1298. if (string.IsNullOrEmpty(domain))
  1299. throw new WebServiceException("Parameter 'domain' missing.");
  1300. if (_dnsServer.CacheZoneManager.DeleteZone(domain))
  1301. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Cached zone was deleted: " + domain);
  1302. }
  1303. private void ListAllowedZones(HttpListenerRequest request, JsonTextWriter jsonWriter)
  1304. {
  1305. string domain = request.QueryString["domain"];
  1306. if (domain == null)
  1307. domain = "";
  1308. string direction = request.QueryString["direction"];
  1309. List<string> subZones;
  1310. IReadOnlyList<DnsResourceRecord> records;
  1311. while (true)
  1312. {
  1313. subZones = _dnsServer.AllowedZoneManager.ListSubDomains(domain);
  1314. records = _dnsServer.AllowedZoneManager.QueryRecords(domain, DnsResourceRecordType.ANY);
  1315. if (records.Count > 0)
  1316. break;
  1317. if (subZones.Count != 1)
  1318. break;
  1319. if (direction == "up")
  1320. {
  1321. if (domain.Length == 0)
  1322. break;
  1323. int i = domain.IndexOf('.');
  1324. if (i < 0)
  1325. domain = "";
  1326. else
  1327. domain = domain.Substring(i + 1);
  1328. }
  1329. else if (domain.Length == 0)
  1330. {
  1331. domain = subZones[0];
  1332. }
  1333. else
  1334. {
  1335. domain = subZones[0] + "." + domain;
  1336. }
  1337. }
  1338. subZones.Sort();
  1339. jsonWriter.WritePropertyName("domain");
  1340. jsonWriter.WriteValue(domain);
  1341. jsonWriter.WritePropertyName("zones");
  1342. jsonWriter.WriteStartArray();
  1343. if (domain.Length != 0)
  1344. domain = "." + domain;
  1345. foreach (string subZone in subZones)
  1346. jsonWriter.WriteValue(subZone + domain);
  1347. jsonWriter.WriteEndArray();
  1348. WriteRecordsAsJson(new List<DnsResourceRecord>(records), jsonWriter, false);
  1349. }
  1350. private void ImportAllowedZones(HttpListenerRequest request)
  1351. {
  1352. if (!request.ContentType.StartsWith("application/x-www-form-urlencoded"))
  1353. throw new WebServiceException("Invalid content type. Expected application/x-www-form-urlencoded.");
  1354. string formRequest;
  1355. using (StreamReader sR = new StreamReader(request.InputStream, request.ContentEncoding))
  1356. {
  1357. formRequest = sR.ReadToEnd();
  1358. }
  1359. string[] formParts = formRequest.Split('&');
  1360. foreach (string formPart in formParts)
  1361. {
  1362. if (formPart.StartsWith("allowedZones="))
  1363. {
  1364. string[] allowedZones = formPart.Substring(13).Split(',');
  1365. bool added = false;
  1366. foreach (string allowedZone in allowedZones)
  1367. {
  1368. if (_dnsServer.AllowedZoneManager.AllowZone(allowedZone))
  1369. added = true;
  1370. }
  1371. if (added)
  1372. {
  1373. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Total " + allowedZones.Length + " zones were imported into allowed zone successfully.");
  1374. _dnsServer.AllowedZoneManager.SaveZoneFile();
  1375. }
  1376. return;
  1377. }
  1378. }
  1379. throw new WebServiceException("Parameter 'allowedZones' missing.");
  1380. }
  1381. private void ExportAllowedZones(HttpListenerResponse response)
  1382. {
  1383. IReadOnlyList<AuthZoneInfo> zoneInfoList = _dnsServer.AllowedZoneManager.ListZones();
  1384. response.ContentType = "text/plain";
  1385. response.AddHeader("Content-Disposition", "attachment;filename=AllowedZones.txt");
  1386. using (StreamWriter sW = new StreamWriter(new BufferedStream(response.OutputStream)))
  1387. {
  1388. foreach (AuthZoneInfo zoneInfo in zoneInfoList)
  1389. sW.WriteLine(zoneInfo.Name);
  1390. }
  1391. }
  1392. private void DeleteAllowedZone(HttpListenerRequest request)
  1393. {
  1394. string domain = request.QueryString["domain"];
  1395. if (string.IsNullOrEmpty(domain))
  1396. throw new WebServiceException("Parameter 'domain' missing.");
  1397. if (_dnsServer.AllowedZoneManager.DeleteZone(domain))
  1398. {
  1399. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Allowed zone was deleted: " + domain);
  1400. _dnsServer.AllowedZoneManager.SaveZoneFile();
  1401. }
  1402. }
  1403. private void AllowZone(HttpListenerRequest request)
  1404. {
  1405. string domain = request.QueryString["domain"];
  1406. if (string.IsNullOrEmpty(domain))
  1407. throw new WebServiceException("Parameter 'domain' missing.");
  1408. if (IPAddress.TryParse(domain, out IPAddress ipAddress))
  1409. domain = (new DnsQuestionRecord(ipAddress, DnsClass.IN)).Name;
  1410. if (_dnsServer.AllowedZoneManager.AllowZone(domain))
  1411. {
  1412. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Zone was allowed: " + domain);
  1413. _dnsServer.AllowedZoneManager.SaveZoneFile();
  1414. }
  1415. }
  1416. private void ListBlockedZones(HttpListenerRequest request, JsonTextWriter jsonWriter)
  1417. {
  1418. string domain = request.QueryString["domain"];
  1419. if (domain == null)
  1420. domain = "";
  1421. string direction = request.QueryString["direction"];
  1422. List<string> subZones;
  1423. IReadOnlyList<DnsResourceRecord> records;
  1424. while (true)
  1425. {
  1426. subZones = _dnsServer.BlockedZoneManager.ListSubDomains(domain);
  1427. records = _dnsServer.BlockedZoneManager.QueryRecords(domain, DnsResourceRecordType.ANY);
  1428. if (records.Count > 0)
  1429. break;
  1430. if (subZones.Count != 1)
  1431. break;
  1432. if (direction == "up")
  1433. {
  1434. if (domain.Length == 0)
  1435. break;
  1436. int i = domain.IndexOf('.');
  1437. if (i < 0)
  1438. domain = "";
  1439. else
  1440. domain = domain.Substring(i + 1);
  1441. }
  1442. else if (domain.Length == 0)
  1443. {
  1444. domain = subZones[0];
  1445. }
  1446. else
  1447. {
  1448. domain = subZones[0] + "." + domain;
  1449. }
  1450. }
  1451. subZones.Sort();
  1452. jsonWriter.WritePropertyName("domain");
  1453. jsonWriter.WriteValue(domain);
  1454. jsonWriter.WritePropertyName("zones");
  1455. jsonWriter.WriteStartArray();
  1456. if (domain.Length != 0)
  1457. domain = "." + domain;
  1458. foreach (string subZone in subZones)
  1459. jsonWriter.WriteValue(subZone + domain);
  1460. jsonWriter.WriteEndArray();
  1461. WriteRecordsAsJson(new List<DnsResourceRecord>(records), jsonWriter, false);
  1462. }
  1463. private void ImportBlockedZones(HttpListenerRequest request)
  1464. {
  1465. if (!request.ContentType.StartsWith("application/x-www-form-urlencoded"))
  1466. throw new WebServiceException("Invalid content type. Expected application/x-www-form-urlencoded.");
  1467. string formRequest;
  1468. using (StreamReader sR = new StreamReader(request.InputStream, request.ContentEncoding))
  1469. {
  1470. formRequest = sR.ReadToEnd();
  1471. }
  1472. string[] formParts = formRequest.Split('&');
  1473. foreach (string formPart in formParts)
  1474. {
  1475. if (formPart.StartsWith("blockedZones="))
  1476. {
  1477. string[] blockedZones = formPart.Substring(13).Split(',');
  1478. bool added = false;
  1479. foreach (string blockedZone in blockedZones)
  1480. {
  1481. if (_dnsServer.BlockedZoneManager.BlockZone(blockedZone))
  1482. added = true;
  1483. }
  1484. if (added)
  1485. {
  1486. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Total " + blockedZones.Length + " zones were imported into blocked zone successfully.");
  1487. _dnsServer.BlockedZoneManager.SaveZoneFile();
  1488. }
  1489. return;
  1490. }
  1491. }
  1492. throw new WebServiceException("Parameter 'blockedZones' missing.");
  1493. }
  1494. private void ExportBlockedZones(HttpListenerResponse response)
  1495. {
  1496. IReadOnlyList<AuthZoneInfo> zoneInfoList = _dnsServer.BlockedZoneManager.ListZones();
  1497. response.ContentType = "text/plain";
  1498. response.AddHeader("Content-Disposition", "attachment;filename=BlockedZones.txt");
  1499. using (StreamWriter sW = new StreamWriter(new BufferedStream(response.OutputStream)))
  1500. {
  1501. foreach (AuthZoneInfo zoneInfo in zoneInfoList)
  1502. sW.WriteLine(zoneInfo.Name);
  1503. }
  1504. }
  1505. private void DeleteBlockedZone(HttpListenerRequest request)
  1506. {
  1507. string domain = request.QueryString["domain"];
  1508. if (string.IsNullOrEmpty(domain))
  1509. throw new WebServiceException("Parameter 'domain' missing.");
  1510. if (_dnsServer.BlockedZoneManager.DeleteZone(domain))
  1511. {
  1512. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Blocked zone was deleted: " + domain);
  1513. _dnsServer.BlockedZoneManager.SaveZoneFile();
  1514. }
  1515. }
  1516. private void BlockZone(HttpListenerRequest request)
  1517. {
  1518. string domain = request.QueryString["domain"];
  1519. if (string.IsNullOrEmpty(domain))
  1520. throw new WebServiceException("Parameter 'domain' missing.");
  1521. if (IPAddress.TryParse(domain, out IPAddress ipAddress))
  1522. domain = (new DnsQuestionRecord(ipAddress, DnsClass.IN)).Name;
  1523. if (_dnsServer.BlockedZoneManager.BlockZone(domain))
  1524. {
  1525. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Domain was added to blocked zone: " + domain);
  1526. _dnsServer.BlockedZoneManager.SaveZoneFile();
  1527. }
  1528. }
  1529. private void ListZones(JsonTextWriter jsonWriter)
  1530. {
  1531. List<AuthZoneInfo> zones = _dnsServer.AuthZoneManager.ListZones();
  1532. zones.Sort();
  1533. jsonWriter.WritePropertyName("zones");
  1534. jsonWriter.WriteStartArray();
  1535. foreach (AuthZoneInfo zone in zones)
  1536. {
  1537. jsonWriter.WriteStartObject();
  1538. jsonWriter.WritePropertyName("name");
  1539. jsonWriter.WriteValue(zone.Name);
  1540. jsonWriter.WritePropertyName("type");
  1541. jsonWriter.WriteValue(zone.Type.ToString());
  1542. switch (zone.Type)
  1543. {
  1544. case AuthZoneType.Primary:
  1545. jsonWriter.WritePropertyName("internal");
  1546. jsonWriter.WriteValue(zone.Internal);
  1547. break;
  1548. case AuthZoneType.Secondary:
  1549. case AuthZoneType.Stub:
  1550. jsonWriter.WritePropertyName("expiry");
  1551. jsonWriter.WriteValue(zone.Expiry.ToLocalTime().ToString("dd MMM yyyy HH:mm:ss"));
  1552. jsonWriter.WritePropertyName("isExpired");
  1553. jsonWriter.WriteValue(zone.IsExpired);
  1554. break;
  1555. }
  1556. jsonWriter.WritePropertyName("disabled");
  1557. jsonWriter.WriteValue(zone.Disabled);
  1558. jsonWriter.WriteEndObject();
  1559. }
  1560. jsonWriter.WriteEndArray();
  1561. }
  1562. private async Task CreateZoneAsync(HttpListenerRequest request, JsonTextWriter jsonWriter)
  1563. {
  1564. string domain = request.QueryString["domain"];
  1565. if (string.IsNullOrEmpty(domain))
  1566. throw new WebServiceException("Parameter 'domain' missing.");
  1567. if (domain.Contains("*"))
  1568. throw new WebServiceException("Domain name for a zone cannot contain wildcard character.");
  1569. if (IPAddress.TryParse(domain, out IPAddress ipAddress))
  1570. {
  1571. domain = new DnsQuestionRecord(ipAddress, DnsClass.IN).Name.ToLower();
  1572. }
  1573. else if (domain.Contains("/"))
  1574. {
  1575. string[] parts = domain.Split('/');
  1576. if ((parts.Length == 2) && IPAddress.TryParse(parts[0], out ipAddress) && int.TryParse(parts[1], out int subnetMaskWidth))
  1577. domain = Zone.GetReverseZone(ipAddress, subnetMaskWidth);
  1578. }
  1579. else if (domain.EndsWith("."))
  1580. {
  1581. domain = domain.Substring(0, domain.Length - 1);
  1582. }
  1583. AuthZoneType type = AuthZoneType.Primary;
  1584. string strType = request.QueryString["type"];
  1585. if (!string.IsNullOrEmpty(strType))
  1586. type = (AuthZoneType)Enum.Parse(typeof(AuthZoneType), strType, true);
  1587. switch (type)
  1588. {
  1589. case AuthZoneType.Primary:
  1590. if (_dnsServer.AuthZoneManager.CreatePrimaryZone(domain, _dnsServer.ServerDomain, false) == null)
  1591. throw new WebServiceException("Zone already exists: " + domain);
  1592. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Authoritative primary zone was created: " + domain);
  1593. _dnsServer.AuthZoneManager.SaveZoneFile(domain);
  1594. break;
  1595. case AuthZoneType.Secondary:
  1596. {
  1597. string strPrimaryNameServerAddresses = request.QueryString["primaryNameServerAddresses"];
  1598. if (string.IsNullOrEmpty(strPrimaryNameServerAddresses))
  1599. strPrimaryNameServerAddresses = null;
  1600. if (await _dnsServer.AuthZoneManager.CreateSecondaryZoneAsync(domain, strPrimaryNameServerAddresses) == null)
  1601. throw new WebServiceException("Zone already exists: " + domain);
  1602. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Authoritative secondary zone was created: " + domain);
  1603. _dnsServer.AuthZoneManager.SaveZoneFile(domain);
  1604. }
  1605. break;
  1606. case AuthZoneType.Stub:
  1607. {
  1608. string strPrimaryNameServerAddresses = request.QueryString["primaryNameServerAddresses"];
  1609. if (string.IsNullOrEmpty(strPrimaryNameServerAddresses))
  1610. strPrimaryNameServerAddresses = null;
  1611. if (await _dnsServer.AuthZoneManager.CreateStubZoneAsync(domain, strPrimaryNameServerAddresses) == null)
  1612. throw new WebServiceException("Zone already exists: " + domain);
  1613. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Stub zone was created: " + domain);
  1614. _dnsServer.AuthZoneManager.SaveZoneFile(domain);
  1615. }
  1616. break;
  1617. case AuthZoneType.Forwarder:
  1618. {
  1619. DnsTransportProtocol forwarderProtocol = DnsTransportProtocol.Udp;
  1620. string strForwarderProtocol = request.QueryString["protocol"];
  1621. if (!string.IsNullOrEmpty(strForwarderProtocol))
  1622. forwarderProtocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), strForwarderProtocol, true);
  1623. string strForwarder = request.QueryString["forwarder"];
  1624. if (string.IsNullOrEmpty(strForwarder))
  1625. throw new WebServiceException("Parameter 'forwarder' missing.");
  1626. if (_dnsServer.AuthZoneManager.CreateForwarderZone(domain, forwarderProtocol, strForwarder) == null)
  1627. throw new WebServiceException("Zone already exists: " + domain);
  1628. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Forwarder zone was created: " + domain);
  1629. _dnsServer.AuthZoneManager.SaveZoneFile(domain);
  1630. }
  1631. break;
  1632. default:
  1633. throw new NotSupportedException("Zone type not supported.");
  1634. }
  1635. jsonWriter.WritePropertyName("domain");
  1636. jsonWriter.WriteValue(string.IsNullOrEmpty(domain) ? "." : domain);
  1637. }
  1638. private void DeleteZone(HttpListenerRequest request)
  1639. {
  1640. string domain = request.QueryString["domain"];
  1641. if (string.IsNullOrEmpty(domain))
  1642. throw new WebServiceException("Parameter 'domain' missing.");
  1643. if (domain.EndsWith("."))
  1644. domain = domain.Substring(0, domain.Length - 1);
  1645. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  1646. if (zoneInfo == null)
  1647. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1648. if (zoneInfo.Internal)
  1649. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  1650. if (!_dnsServer.AuthZoneManager.DeleteZone(domain))
  1651. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1652. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was deleted: " + domain);
  1653. _dnsServer.AuthZoneManager.DeleteZoneFile(domain);
  1654. }
  1655. private void EnableZone(HttpListenerRequest request)
  1656. {
  1657. string domain = request.QueryString["domain"];
  1658. if (string.IsNullOrEmpty(domain))
  1659. throw new WebServiceException("Parameter 'domain' missing.");
  1660. if (domain.EndsWith("."))
  1661. domain = domain.Substring(0, domain.Length - 1);
  1662. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  1663. if (zoneInfo == null)
  1664. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1665. if (zoneInfo.Internal)
  1666. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  1667. zoneInfo.Disabled = false;
  1668. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was enabled: " + domain);
  1669. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1670. }
  1671. private void DisableZone(HttpListenerRequest request)
  1672. {
  1673. string domain = request.QueryString["domain"];
  1674. if (string.IsNullOrEmpty(domain))
  1675. throw new WebServiceException("Parameter 'domain' missing.");
  1676. if (domain.EndsWith("."))
  1677. domain = domain.Substring(0, domain.Length - 1);
  1678. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  1679. if (zoneInfo == null)
  1680. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1681. if (zoneInfo.Internal)
  1682. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  1683. zoneInfo.Disabled = true;
  1684. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] " + zoneInfo.Type.ToString() + " zone was disabled: " + domain);
  1685. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1686. }
  1687. private void AddRecord(HttpListenerRequest request)
  1688. {
  1689. string domain = request.QueryString["domain"];
  1690. if (string.IsNullOrEmpty(domain))
  1691. throw new WebServiceException("Parameter 'domain' missing.");
  1692. if (domain.EndsWith("."))
  1693. domain = domain.Substring(0, domain.Length - 1);
  1694. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  1695. if (zoneInfo == null)
  1696. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1697. if (zoneInfo.Internal)
  1698. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  1699. string strType = request.QueryString["type"];
  1700. if (string.IsNullOrEmpty(strType))
  1701. throw new WebServiceException("Parameter 'type' missing.");
  1702. DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), strType);
  1703. string value = request.QueryString["value"];
  1704. if (string.IsNullOrEmpty(value))
  1705. throw new WebServiceException("Parameter 'value' missing.");
  1706. uint ttl;
  1707. string strTtl = request.QueryString["ttl"];
  1708. if (string.IsNullOrEmpty(strTtl))
  1709. ttl = 3600;
  1710. else
  1711. ttl = uint.Parse(strTtl);
  1712. switch (type)
  1713. {
  1714. case DnsResourceRecordType.A:
  1715. case DnsResourceRecordType.AAAA:
  1716. IPAddress ipAddress = IPAddress.Parse(value);
  1717. bool ptr = false;
  1718. string strPtr = request.QueryString["ptr"];
  1719. if (!string.IsNullOrEmpty(strPtr))
  1720. ptr = bool.Parse(strPtr);
  1721. if (ptr)
  1722. {
  1723. string ptrDomain = Zone.GetReverseZone(ipAddress, 32);
  1724. AuthZoneInfo reverseZoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(ptrDomain);
  1725. if (reverseZoneInfo == null)
  1726. throw new DnsServerException("No reverse zone available to add PTR record.");
  1727. if (reverseZoneInfo.Internal)
  1728. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is an internal zone.");
  1729. if (reverseZoneInfo.Type != AuthZoneType.Primary)
  1730. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is not a primary zone.");
  1731. _dnsServer.AuthZoneManager.SetRecords(ptrDomain, DnsResourceRecordType.PTR, ttl, new DnsPTRRecord[] { new DnsPTRRecord(domain) });
  1732. _dnsServer.AuthZoneManager.SaveZoneFile(reverseZoneInfo.Name);
  1733. }
  1734. if (type == DnsResourceRecordType.A)
  1735. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsARecord(ipAddress));
  1736. else
  1737. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsAAAARecord(ipAddress));
  1738. break;
  1739. case DnsResourceRecordType.MX:
  1740. {
  1741. string preference = request.QueryString["preference"];
  1742. if (string.IsNullOrEmpty(preference))
  1743. throw new WebServiceException("Parameter 'preference' missing.");
  1744. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsMXRecord(ushort.Parse(preference), value));
  1745. }
  1746. break;
  1747. case DnsResourceRecordType.TXT:
  1748. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsTXTRecord(value));
  1749. break;
  1750. case DnsResourceRecordType.NS:
  1751. {
  1752. string glueAddresses = request.QueryString["glue"];
  1753. if (string.IsNullOrEmpty(glueAddresses))
  1754. glueAddresses = null;
  1755. DnsResourceRecord nsRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsNSRecord(value));
  1756. if (glueAddresses != null)
  1757. nsRecord.SetGlueRecords(glueAddresses);
  1758. _dnsServer.AuthZoneManager.AddRecord(nsRecord);
  1759. }
  1760. break;
  1761. case DnsResourceRecordType.PTR:
  1762. _dnsServer.AuthZoneManager.SetRecords(domain, type, ttl, new DnsResourceRecordData[] { new DnsPTRRecord(value) });
  1763. break;
  1764. case DnsResourceRecordType.CNAME:
  1765. _dnsServer.AuthZoneManager.SetRecords(domain, type, ttl, new DnsResourceRecordData[] { new DnsCNAMERecord(value) });
  1766. break;
  1767. case DnsResourceRecordType.SRV:
  1768. {
  1769. string priority = request.QueryString["priority"];
  1770. if (string.IsNullOrEmpty(priority))
  1771. throw new WebServiceException("Parameter 'priority' missing.");
  1772. string weight = request.QueryString["weight"];
  1773. if (string.IsNullOrEmpty(weight))
  1774. throw new WebServiceException("Parameter 'weight' missing.");
  1775. string port = request.QueryString["port"];
  1776. if (string.IsNullOrEmpty(port))
  1777. throw new WebServiceException("Parameter 'port' missing.");
  1778. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsSRVRecord(ushort.Parse(priority), ushort.Parse(weight), ushort.Parse(port), value));
  1779. }
  1780. break;
  1781. case DnsResourceRecordType.CAA:
  1782. {
  1783. string flags = request.QueryString["flags"];
  1784. if (string.IsNullOrEmpty(flags))
  1785. throw new WebServiceException("Parameter 'flags' missing.");
  1786. string tag = request.QueryString["tag"];
  1787. if (string.IsNullOrEmpty(tag))
  1788. throw new WebServiceException("Parameter 'tag' missing.");
  1789. _dnsServer.AuthZoneManager.AddRecord(domain, type, ttl, new DnsCAARecord(byte.Parse(flags), tag, value));
  1790. }
  1791. break;
  1792. case DnsResourceRecordType.ANAME:
  1793. _dnsServer.AuthZoneManager.SetRecords(domain, type, ttl, new DnsResourceRecordData[] { new DnsANAMERecord(value) });
  1794. break;
  1795. case DnsResourceRecordType.FWD:
  1796. {
  1797. string protocol = request.QueryString["protocol"];
  1798. if (string.IsNullOrEmpty(protocol))
  1799. protocol = "Udp";
  1800. _dnsServer.AuthZoneManager.AddRecord(domain, type, 0, new DnsForwarderRecord((DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), protocol, true), value));
  1801. }
  1802. break;
  1803. default:
  1804. throw new WebServiceException("Type not supported for AddRecords().");
  1805. }
  1806. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] New record was added to authoritative zone {domain: " + domain + "; type: " + type + "; value: " + value + "; ttl: " + ttl + ";}");
  1807. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  1808. }
  1809. private void GetRecords(HttpListenerRequest request, JsonTextWriter jsonWriter)
  1810. {
  1811. string domain = request.QueryString["domain"];
  1812. if (string.IsNullOrEmpty(domain))
  1813. throw new WebServiceException("Parameter 'domain' missing.");
  1814. if (domain.EndsWith("."))
  1815. domain = domain.Substring(0, domain.Length - 1);
  1816. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  1817. if (zoneInfo == null)
  1818. throw new WebServiceException("Zone '" + domain + "' was not found.");
  1819. jsonWriter.WritePropertyName("zone");
  1820. jsonWriter.WriteStartObject();
  1821. jsonWriter.WritePropertyName("name");
  1822. jsonWriter.WriteValue(zoneInfo.Name);
  1823. jsonWriter.WritePropertyName("type");
  1824. jsonWriter.WriteValue(zoneInfo.Type.ToString());
  1825. switch (zoneInfo.Type)
  1826. {
  1827. case AuthZoneType.Primary:
  1828. jsonWriter.WritePropertyName("internal");
  1829. jsonWriter.WriteValue(zoneInfo.Internal);
  1830. break;
  1831. case AuthZoneType.Secondary:
  1832. case AuthZoneType.Stub:
  1833. jsonWriter.WritePropertyName("expiry");
  1834. jsonWriter.WriteValue(zoneInfo.Expiry.ToLocalTime().ToString("dd MMM yyyy HH:mm:ss"));
  1835. jsonWriter.WritePropertyName("isExpired");
  1836. jsonWriter.WriteValue(zoneInfo.IsExpired);
  1837. break;
  1838. }
  1839. jsonWriter.WritePropertyName("disabled");
  1840. jsonWriter.WriteValue(zoneInfo.Disabled);
  1841. jsonWriter.WriteEndObject();
  1842. List<DnsResourceRecord> records = _dnsServer.AuthZoneManager.ListAllRecords(domain);
  1843. WriteRecordsAsJson(records, jsonWriter, true);
  1844. }
  1845. private static void WriteRecordsAsJson(List<DnsResourceRecord> records, JsonTextWriter jsonWriter, bool authoritativeZoneRecords)
  1846. {
  1847. if (records == null)
  1848. {
  1849. jsonWriter.WritePropertyName("records");
  1850. jsonWriter.WriteStartArray();
  1851. jsonWriter.WriteEndArray();
  1852. return;
  1853. }
  1854. records.Sort();
  1855. Dictionary<string, Dictionary<DnsResourceRecordType, List<DnsResourceRecord>>> groupedByDomainRecords = DnsResourceRecord.GroupRecords(records);
  1856. jsonWriter.WritePropertyName("records");
  1857. jsonWriter.WriteStartArray();
  1858. foreach (KeyValuePair<string, Dictionary<DnsResourceRecordType, List<DnsResourceRecord>>> groupedByTypeRecords in groupedByDomainRecords)
  1859. {
  1860. foreach (KeyValuePair<DnsResourceRecordType, List<DnsResourceRecord>> groupedRecords in groupedByTypeRecords.Value)
  1861. {
  1862. foreach (DnsResourceRecord record in groupedRecords.Value)
  1863. {
  1864. jsonWriter.WriteStartObject();
  1865. if (authoritativeZoneRecords)
  1866. {
  1867. jsonWriter.WritePropertyName("disabled");
  1868. jsonWriter.WriteValue(record.IsDisabled());
  1869. }
  1870. jsonWriter.WritePropertyName("name");
  1871. jsonWriter.WriteValue(record.Name);
  1872. jsonWriter.WritePropertyName("type");
  1873. jsonWriter.WriteValue(record.Type.ToString());
  1874. jsonWriter.WritePropertyName("ttl");
  1875. if (authoritativeZoneRecords)
  1876. jsonWriter.WriteValue(record.TtlValue);
  1877. else
  1878. jsonWriter.WriteValue(record.TTL);
  1879. jsonWriter.WritePropertyName("rData");
  1880. jsonWriter.WriteStartObject();
  1881. switch (record.Type)
  1882. {
  1883. case DnsResourceRecordType.A:
  1884. {
  1885. DnsARecord rdata = (record.RDATA as DnsARecord);
  1886. if (rdata != null)
  1887. {
  1888. jsonWriter.WritePropertyName("value");
  1889. jsonWriter.WriteValue(rdata.IPAddress);
  1890. }
  1891. }
  1892. break;
  1893. case DnsResourceRecordType.AAAA:
  1894. {
  1895. DnsAAAARecord rdata = (record.RDATA as DnsAAAARecord);
  1896. if (rdata != null)
  1897. {
  1898. jsonWriter.WritePropertyName("value");
  1899. jsonWriter.WriteValue(rdata.IPAddress);
  1900. }
  1901. }
  1902. break;
  1903. case DnsResourceRecordType.SOA:
  1904. {
  1905. DnsSOARecord rdata = record.RDATA as DnsSOARecord;
  1906. if (rdata != null)
  1907. {
  1908. jsonWriter.WritePropertyName("primaryNameServer");
  1909. jsonWriter.WriteValue(rdata.PrimaryNameServer);
  1910. jsonWriter.WritePropertyName("responsiblePerson");
  1911. jsonWriter.WriteValue(rdata.ResponsiblePerson);
  1912. jsonWriter.WritePropertyName("serial");
  1913. jsonWriter.WriteValue(rdata.Serial);
  1914. jsonWriter.WritePropertyName("refresh");
  1915. jsonWriter.WriteValue(rdata.Refresh);
  1916. jsonWriter.WritePropertyName("retry");
  1917. jsonWriter.WriteValue(rdata.Retry);
  1918. jsonWriter.WritePropertyName("expire");
  1919. jsonWriter.WriteValue(rdata.Expire);
  1920. jsonWriter.WritePropertyName("minimum");
  1921. jsonWriter.WriteValue(rdata.Minimum);
  1922. }
  1923. IReadOnlyList<DnsResourceRecord> glueRecords = record.GetGlueRecords();
  1924. if (glueRecords.Count > 0)
  1925. {
  1926. string primaryAddresses = null;
  1927. foreach (DnsResourceRecord glueRecord in glueRecords)
  1928. {
  1929. if (primaryAddresses == null)
  1930. primaryAddresses = glueRecord.RDATA.ToString();
  1931. else
  1932. primaryAddresses = primaryAddresses + ", " + glueRecord.RDATA.ToString();
  1933. }
  1934. jsonWriter.WritePropertyName("primaryAddresses");
  1935. jsonWriter.WriteValue(primaryAddresses);
  1936. }
  1937. }
  1938. break;
  1939. case DnsResourceRecordType.PTR:
  1940. {
  1941. DnsPTRRecord rdata = record.RDATA as DnsPTRRecord;
  1942. if (rdata != null)
  1943. {
  1944. jsonWriter.WritePropertyName("value");
  1945. jsonWriter.WriteValue(rdata.Domain);
  1946. }
  1947. }
  1948. break;
  1949. case DnsResourceRecordType.MX:
  1950. {
  1951. DnsMXRecord rdata = record.RDATA as DnsMXRecord;
  1952. if (rdata != null)
  1953. {
  1954. jsonWriter.WritePropertyName("preference");
  1955. jsonWriter.WriteValue(rdata.Preference);
  1956. jsonWriter.WritePropertyName("value");
  1957. jsonWriter.WriteValue(rdata.Exchange);
  1958. }
  1959. }
  1960. break;
  1961. case DnsResourceRecordType.TXT:
  1962. {
  1963. DnsTXTRecord rdata = record.RDATA as DnsTXTRecord;
  1964. if (rdata != null)
  1965. {
  1966. jsonWriter.WritePropertyName("value");
  1967. jsonWriter.WriteValue(rdata.Text);
  1968. }
  1969. }
  1970. break;
  1971. case DnsResourceRecordType.NS:
  1972. {
  1973. DnsNSRecord rdata = record.RDATA as DnsNSRecord;
  1974. if (rdata != null)
  1975. {
  1976. jsonWriter.WritePropertyName("value");
  1977. jsonWriter.WriteValue(rdata.NameServer);
  1978. }
  1979. IReadOnlyList<DnsResourceRecord> glueRecords = record.GetGlueRecords();
  1980. if (glueRecords.Count > 0)
  1981. {
  1982. string glue = null;
  1983. foreach (DnsResourceRecord glueRecord in glueRecords)
  1984. {
  1985. if (glue == null)
  1986. glue = glueRecord.RDATA.ToString();
  1987. else
  1988. glue = glue + ", " + glueRecord.RDATA.ToString();
  1989. }
  1990. jsonWriter.WritePropertyName("glue");
  1991. jsonWriter.WriteValue(glue);
  1992. }
  1993. }
  1994. break;
  1995. case DnsResourceRecordType.CNAME:
  1996. {
  1997. DnsCNAMERecord rdata = record.RDATA as DnsCNAMERecord;
  1998. if (rdata != null)
  1999. {
  2000. jsonWriter.WritePropertyName("value");
  2001. jsonWriter.WriteValue(rdata.Domain);
  2002. }
  2003. }
  2004. break;
  2005. case DnsResourceRecordType.SRV:
  2006. {
  2007. DnsSRVRecord rdata = record.RDATA as DnsSRVRecord;
  2008. if (rdata != null)
  2009. {
  2010. jsonWriter.WritePropertyName("priority");
  2011. jsonWriter.WriteValue(rdata.Priority);
  2012. jsonWriter.WritePropertyName("weight");
  2013. jsonWriter.WriteValue(rdata.Weight);
  2014. jsonWriter.WritePropertyName("port");
  2015. jsonWriter.WriteValue(rdata.Port);
  2016. jsonWriter.WritePropertyName("value");
  2017. jsonWriter.WriteValue(rdata.Target);
  2018. }
  2019. }
  2020. break;
  2021. case DnsResourceRecordType.CAA:
  2022. {
  2023. DnsCAARecord rdata = record.RDATA as DnsCAARecord;
  2024. if (rdata != null)
  2025. {
  2026. jsonWriter.WritePropertyName("flags");
  2027. jsonWriter.WriteValue(rdata.Flags);
  2028. jsonWriter.WritePropertyName("tag");
  2029. jsonWriter.WriteValue(rdata.Tag);
  2030. jsonWriter.WritePropertyName("value");
  2031. jsonWriter.WriteValue(rdata.Value);
  2032. }
  2033. }
  2034. break;
  2035. case DnsResourceRecordType.ANAME:
  2036. {
  2037. DnsANAMERecord rdata = record.RDATA as DnsANAMERecord;
  2038. if (rdata != null)
  2039. {
  2040. jsonWriter.WritePropertyName("value");
  2041. jsonWriter.WriteValue(rdata.Domain);
  2042. }
  2043. }
  2044. break;
  2045. case DnsResourceRecordType.FWD:
  2046. {
  2047. DnsForwarderRecord rdata = record.RDATA as DnsForwarderRecord;
  2048. if (rdata != null)
  2049. {
  2050. jsonWriter.WritePropertyName("protocol");
  2051. jsonWriter.WriteValue(rdata.Protocol.ToString());
  2052. jsonWriter.WritePropertyName("value");
  2053. jsonWriter.WriteValue(rdata.Forwarder);
  2054. }
  2055. }
  2056. break;
  2057. default:
  2058. {
  2059. jsonWriter.WritePropertyName("value");
  2060. using (MemoryStream mS = new MemoryStream())
  2061. {
  2062. record.RDATA.WriteTo(mS, new List<DnsDomainOffset>());
  2063. jsonWriter.WriteValue(Convert.ToBase64String(mS.ToArray()));
  2064. }
  2065. }
  2066. break;
  2067. }
  2068. jsonWriter.WriteEndObject();
  2069. jsonWriter.WriteEndObject();
  2070. }
  2071. }
  2072. }
  2073. jsonWriter.WriteEndArray();
  2074. }
  2075. private void DeleteRecord(HttpListenerRequest request)
  2076. {
  2077. string domain = request.QueryString["domain"];
  2078. if (string.IsNullOrEmpty(domain))
  2079. throw new WebServiceException("Parameter 'domain' missing.");
  2080. if (domain.EndsWith("."))
  2081. domain = domain.Substring(0, domain.Length - 1);
  2082. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  2083. if (zoneInfo == null)
  2084. throw new WebServiceException("Zone '" + domain + "' was not found.");
  2085. if (zoneInfo.Internal)
  2086. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  2087. string strType = request.QueryString["type"];
  2088. if (string.IsNullOrEmpty(strType))
  2089. throw new WebServiceException("Parameter 'type' missing.");
  2090. DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), strType);
  2091. string value = request.QueryString["value"];
  2092. if (string.IsNullOrEmpty(value))
  2093. throw new WebServiceException("Parameter 'value' missing.");
  2094. switch (type)
  2095. {
  2096. case DnsResourceRecordType.A:
  2097. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsARecord(IPAddress.Parse(value)));
  2098. break;
  2099. case DnsResourceRecordType.AAAA:
  2100. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsAAAARecord(IPAddress.Parse(value)));
  2101. break;
  2102. case DnsResourceRecordType.MX:
  2103. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsMXRecord(0, value));
  2104. break;
  2105. case DnsResourceRecordType.TXT:
  2106. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsTXTRecord(value));
  2107. break;
  2108. case DnsResourceRecordType.NS:
  2109. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsNSRecord(value));
  2110. break;
  2111. case DnsResourceRecordType.CNAME:
  2112. case DnsResourceRecordType.PTR:
  2113. case DnsResourceRecordType.ANAME:
  2114. _dnsServer.AuthZoneManager.DeleteRecords(domain, type);
  2115. break;
  2116. case DnsResourceRecordType.SRV:
  2117. {
  2118. string port = request.QueryString["port"];
  2119. if (string.IsNullOrEmpty(port))
  2120. throw new WebServiceException("Parameter 'port' missing.");
  2121. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsSRVRecord(0, 0, ushort.Parse(port), value));
  2122. }
  2123. break;
  2124. case DnsResourceRecordType.CAA:
  2125. {
  2126. string flags = request.QueryString["flags"];
  2127. if (string.IsNullOrEmpty(flags))
  2128. throw new WebServiceException("Parameter 'flags' missing.");
  2129. string tag = request.QueryString["tag"];
  2130. if (string.IsNullOrEmpty(tag))
  2131. throw new WebServiceException("Parameter 'tag' missing.");
  2132. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsCAARecord(byte.Parse(flags), tag, value));
  2133. }
  2134. break;
  2135. case DnsResourceRecordType.FWD:
  2136. {
  2137. string strProtocol = request.QueryString["protocol"];
  2138. if (string.IsNullOrEmpty(strProtocol))
  2139. strProtocol = "Udp";
  2140. _dnsServer.AuthZoneManager.DeleteRecord(domain, type, new DnsForwarderRecord((DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), strProtocol, true), value));
  2141. }
  2142. break;
  2143. default:
  2144. throw new WebServiceException("Type not supported for DeleteRecord().");
  2145. }
  2146. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Record was deleted from authoritative zone {domain: " + domain + "; type: " + type + "; value: " + value + ";}");
  2147. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  2148. }
  2149. private void UpdateRecord(HttpListenerRequest request)
  2150. {
  2151. string strType = request.QueryString["type"];
  2152. if (string.IsNullOrEmpty(strType))
  2153. throw new WebServiceException("Parameter 'type' missing.");
  2154. DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), strType);
  2155. string domain = request.QueryString["domain"];
  2156. if (string.IsNullOrEmpty(domain))
  2157. throw new WebServiceException("Parameter 'domain' missing.");
  2158. if (domain.EndsWith("."))
  2159. domain = domain.Substring(0, domain.Length - 1);
  2160. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  2161. if (zoneInfo == null)
  2162. throw new WebServiceException("Zone '" + domain + "' was not found.");
  2163. if (zoneInfo.Internal)
  2164. throw new WebServiceException("Access was denied to manage internal DNS Server zone.");
  2165. string newDomain = request.QueryString["newDomain"];
  2166. if (string.IsNullOrEmpty(newDomain))
  2167. newDomain = domain;
  2168. if (newDomain.EndsWith("."))
  2169. newDomain = newDomain.Substring(0, newDomain.Length - 1);
  2170. uint ttl;
  2171. string strTtl = request.QueryString["ttl"];
  2172. if (string.IsNullOrEmpty(strTtl))
  2173. ttl = 3600;
  2174. else
  2175. ttl = uint.Parse(strTtl);
  2176. string value = request.QueryString["value"];
  2177. string newValue = request.QueryString["newValue"];
  2178. if (string.IsNullOrEmpty(newValue))
  2179. newValue = value;
  2180. bool disable = false;
  2181. string strDisable = request.QueryString["disable"];
  2182. if (!string.IsNullOrEmpty(strDisable))
  2183. disable = bool.Parse(strDisable);
  2184. switch (type)
  2185. {
  2186. case DnsResourceRecordType.A:
  2187. case DnsResourceRecordType.AAAA:
  2188. {
  2189. IPAddress oldIpAddress = IPAddress.Parse(value);
  2190. IPAddress newIpAddress = IPAddress.Parse(newValue);
  2191. bool ptr = false;
  2192. string strPtr = request.QueryString["ptr"];
  2193. if (!string.IsNullOrEmpty(strPtr))
  2194. ptr = bool.Parse(strPtr);
  2195. if (ptr)
  2196. {
  2197. //delete old PTR record if any
  2198. _dnsServer.AuthZoneManager.DeleteRecords(Zone.GetReverseZone(oldIpAddress, 32), DnsResourceRecordType.PTR);
  2199. //add new PTR record
  2200. string ptrDomain = Zone.GetReverseZone(newIpAddress, 32);
  2201. AuthZoneInfo reverseZoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(ptrDomain);
  2202. if (reverseZoneInfo == null)
  2203. throw new DnsServerException("No reverse zone available to add PTR record.");
  2204. if (reverseZoneInfo.Internal)
  2205. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is an internal zone.");
  2206. if (reverseZoneInfo.Type != AuthZoneType.Primary)
  2207. throw new DnsServerException("Reverse zone '" + reverseZoneInfo.Name + "' is not a primary zone.");
  2208. _dnsServer.AuthZoneManager.SetRecords(ptrDomain, DnsResourceRecordType.PTR, ttl, new DnsPTRRecord[] { new DnsPTRRecord(domain) });
  2209. _dnsServer.AuthZoneManager.SaveZoneFile(reverseZoneInfo.Name);
  2210. }
  2211. DnsResourceRecord oldRecord;
  2212. DnsResourceRecord newRecord;
  2213. if (type == DnsResourceRecordType.A)
  2214. {
  2215. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsARecord(oldIpAddress));
  2216. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsARecord(newIpAddress));
  2217. }
  2218. else
  2219. {
  2220. oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsAAAARecord(oldIpAddress));
  2221. newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsAAAARecord(newIpAddress));
  2222. }
  2223. if (disable)
  2224. newRecord.Disable();
  2225. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2226. }
  2227. break;
  2228. case DnsResourceRecordType.MX:
  2229. {
  2230. string preference = request.QueryString["preference"];
  2231. if (string.IsNullOrEmpty(preference))
  2232. preference = "1";
  2233. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsMXRecord(0, value));
  2234. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsMXRecord(ushort.Parse(preference), newValue));
  2235. if (disable)
  2236. newRecord.Disable();
  2237. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2238. }
  2239. break;
  2240. case DnsResourceRecordType.TXT:
  2241. {
  2242. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsTXTRecord(value));
  2243. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsTXTRecord(newValue));
  2244. if (disable)
  2245. newRecord.Disable();
  2246. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2247. }
  2248. break;
  2249. case DnsResourceRecordType.NS:
  2250. {
  2251. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsNSRecord(value));
  2252. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsNSRecord(newValue));
  2253. if (disable)
  2254. newRecord.Disable();
  2255. string glueAddresses = request.QueryString["glue"];
  2256. if (!string.IsNullOrEmpty(glueAddresses))
  2257. newRecord.SetGlueRecords(glueAddresses);
  2258. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2259. }
  2260. break;
  2261. case DnsResourceRecordType.SOA:
  2262. {
  2263. string primaryNameServer = request.QueryString["primaryNameServer"];
  2264. if (string.IsNullOrEmpty(primaryNameServer))
  2265. throw new WebServiceException("Parameter 'primaryNameServer' missing.");
  2266. string responsiblePerson = request.QueryString["responsiblePerson"];
  2267. if (string.IsNullOrEmpty(responsiblePerson))
  2268. throw new WebServiceException("Parameter 'responsiblePerson' missing.");
  2269. string serial = request.QueryString["serial"];
  2270. if (string.IsNullOrEmpty(serial))
  2271. throw new WebServiceException("Parameter 'serial' missing.");
  2272. string refresh = request.QueryString["refresh"];
  2273. if (string.IsNullOrEmpty(refresh))
  2274. throw new WebServiceException("Parameter 'refresh' missing.");
  2275. string retry = request.QueryString["retry"];
  2276. if (string.IsNullOrEmpty(retry))
  2277. throw new WebServiceException("Parameter 'retry' missing.");
  2278. string expire = request.QueryString["expire"];
  2279. if (string.IsNullOrEmpty(expire))
  2280. throw new WebServiceException("Parameter 'expire' missing.");
  2281. string minimum = request.QueryString["minimum"];
  2282. if (string.IsNullOrEmpty(minimum))
  2283. throw new WebServiceException("Parameter 'minimum' missing.");
  2284. DnsResourceRecord soaRecord = new DnsResourceRecord(domain, type, DnsClass.IN, ttl, new DnsSOARecord(primaryNameServer, responsiblePerson, uint.Parse(serial), uint.Parse(refresh), uint.Parse(retry), uint.Parse(expire), uint.Parse(minimum)));
  2285. string primaryAddresses = request.QueryString["primaryAddresses"];
  2286. if (!string.IsNullOrEmpty(primaryAddresses))
  2287. soaRecord.SetGlueRecords(primaryAddresses);
  2288. _dnsServer.AuthZoneManager.SetRecord(soaRecord);
  2289. }
  2290. break;
  2291. case DnsResourceRecordType.PTR:
  2292. {
  2293. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsPTRRecord(value));
  2294. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsPTRRecord(newValue));
  2295. if (disable)
  2296. newRecord.Disable();
  2297. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2298. }
  2299. break;
  2300. case DnsResourceRecordType.CNAME:
  2301. {
  2302. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsCNAMERecord(value));
  2303. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsCNAMERecord(newValue));
  2304. if (disable)
  2305. newRecord.Disable();
  2306. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2307. }
  2308. break;
  2309. case DnsResourceRecordType.SRV:
  2310. {
  2311. string port = request.QueryString["port"];
  2312. if (string.IsNullOrEmpty(port))
  2313. throw new WebServiceException("Parameter 'port' missing.");
  2314. string priority = request.QueryString["priority"];
  2315. if (string.IsNullOrEmpty(priority))
  2316. throw new WebServiceException("Parameter 'priority' missing.");
  2317. string weight = request.QueryString["weight"];
  2318. if (string.IsNullOrEmpty(weight))
  2319. throw new WebServiceException("Parameter 'weight' missing.");
  2320. string newPort = request.QueryString["newPort"];
  2321. if (string.IsNullOrEmpty(newPort))
  2322. newPort = port;
  2323. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsSRVRecord(0, 0, ushort.Parse(port), value));
  2324. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsSRVRecord(ushort.Parse(priority), ushort.Parse(weight), ushort.Parse(newPort), newValue));
  2325. if (disable)
  2326. newRecord.Disable();
  2327. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2328. }
  2329. break;
  2330. case DnsResourceRecordType.CAA:
  2331. {
  2332. string flags = request.QueryString["flags"];
  2333. if (string.IsNullOrEmpty(flags))
  2334. throw new WebServiceException("Parameter 'flags' missing.");
  2335. string tag = request.QueryString["tag"];
  2336. if (string.IsNullOrEmpty(tag))
  2337. throw new WebServiceException("Parameter 'tag' missing.");
  2338. string newFlags = request.QueryString["newFlags"];
  2339. if (string.IsNullOrEmpty(newFlags))
  2340. newFlags = flags;
  2341. string newTag = request.QueryString["newTag"];
  2342. if (string.IsNullOrEmpty(newTag))
  2343. newTag = tag;
  2344. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsCAARecord(byte.Parse(flags), tag, value));
  2345. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsCAARecord(byte.Parse(newFlags), newTag, newValue));
  2346. if (disable)
  2347. newRecord.Disable();
  2348. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2349. }
  2350. break;
  2351. case DnsResourceRecordType.ANAME:
  2352. {
  2353. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsANAMERecord(value));
  2354. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsANAMERecord(newValue));
  2355. if (disable)
  2356. newRecord.Disable();
  2357. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2358. }
  2359. break;
  2360. case DnsResourceRecordType.FWD:
  2361. {
  2362. string strProtocol = request.QueryString["protocol"];
  2363. if (string.IsNullOrEmpty(strProtocol))
  2364. strProtocol = "Udp";
  2365. DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), strProtocol, true);
  2366. DnsResourceRecord oldRecord = new DnsResourceRecord(domain, type, DnsClass.IN, 0, new DnsForwarderRecord(protocol, value));
  2367. DnsResourceRecord newRecord = new DnsResourceRecord(newDomain, type, DnsClass.IN, ttl, new DnsForwarderRecord(protocol, newValue));
  2368. if (disable)
  2369. newRecord.Disable();
  2370. _dnsServer.AuthZoneManager.UpdateRecord(oldRecord, newRecord);
  2371. }
  2372. break;
  2373. default:
  2374. throw new WebServiceException("Type not supported for UpdateRecords().");
  2375. }
  2376. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Record was updated for authoritative zone {oldDomain: " + domain + "; domain: " + newDomain + "; type: " + type + "; oldValue: " + value + "; value: " + newValue + "; ttl: " + ttl + "; disabled: " + disable + ";}");
  2377. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  2378. }
  2379. private async Task ResolveQuery(HttpListenerRequest request, JsonTextWriter jsonWriter)
  2380. {
  2381. string server = request.QueryString["server"];
  2382. if (string.IsNullOrEmpty(server))
  2383. throw new WebServiceException("Parameter 'server' missing.");
  2384. string domain = request.QueryString["domain"];
  2385. if (string.IsNullOrEmpty(domain))
  2386. throw new WebServiceException("Parameter 'domain' missing.");
  2387. domain = domain.Trim();
  2388. if (domain.EndsWith("."))
  2389. domain = domain.Substring(0, domain.Length - 1);
  2390. string strType = request.QueryString["type"];
  2391. if (string.IsNullOrEmpty(strType))
  2392. throw new WebServiceException("Parameter 'type' missing.");
  2393. DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), strType);
  2394. string strProtocol = request.QueryString["protocol"];
  2395. if (string.IsNullOrEmpty(strProtocol))
  2396. strProtocol = "Udp";
  2397. bool importRecords = false;
  2398. string strImport = request.QueryString["import"];
  2399. if (!string.IsNullOrEmpty(strImport))
  2400. importRecords = bool.Parse(strImport);
  2401. NetProxy proxy = _dnsServer.Proxy;
  2402. bool preferIPv6 = _dnsServer.PreferIPv6;
  2403. DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), strProtocol, true);
  2404. const int RETRIES = 1;
  2405. const int TIMEOUT = 10000;
  2406. DnsDatagram dnsResponse;
  2407. if (server.Equals("recursive-resolver", StringComparison.OrdinalIgnoreCase))
  2408. {
  2409. if (type == DnsResourceRecordType.AXFR)
  2410. throw new DnsServerException("Cannot do zone transfer (AXFR) for 'recursive-resolver'.");
  2411. DnsQuestionRecord question;
  2412. if ((type == DnsResourceRecordType.PTR) && IPAddress.TryParse(domain, out IPAddress address))
  2413. question = new DnsQuestionRecord(address, DnsClass.IN);
  2414. else
  2415. question = new DnsQuestionRecord(domain, type, DnsClass.IN);
  2416. dnsResponse = await DnsClient.RecursiveResolveAsync(question, null, null, proxy, preferIPv6, RETRIES, TIMEOUT);
  2417. }
  2418. else
  2419. {
  2420. if (type == DnsResourceRecordType.AXFR)
  2421. protocol = DnsTransportProtocol.Tcp;
  2422. NameServerAddress nameServer;
  2423. if (server.Equals("this-server", StringComparison.OrdinalIgnoreCase))
  2424. {
  2425. switch (protocol)
  2426. {
  2427. case DnsTransportProtocol.Udp:
  2428. nameServer = _dnsServer.ThisServer;
  2429. break;
  2430. case DnsTransportProtocol.Tcp:
  2431. nameServer = new NameServerAddress(_dnsServer.ThisServer, DnsTransportProtocol.Tcp);
  2432. break;
  2433. case DnsTransportProtocol.Tls:
  2434. throw new DnsServerException("Cannot use DNS-over-TLS protocol for 'this-server'. Please use the TLS certificate domain name as the server.");
  2435. case DnsTransportProtocol.Https:
  2436. throw new DnsServerException("Cannot use DNS-over-HTTPS protocol for 'this-server'. Please use the TLS certificate domain name with a url as the server.");
  2437. case DnsTransportProtocol.HttpsJson:
  2438. throw new DnsServerException("Cannot use DNS-over-HTTPS (JSON) protocol for 'this-server'. Please use the TLS certificate domain name with a url as the server.");
  2439. default:
  2440. throw new InvalidOperationException();
  2441. }
  2442. proxy = null; //no proxy required for this server
  2443. }
  2444. else
  2445. {
  2446. if ((protocol == DnsTransportProtocol.Tls) && !server.Contains(":853"))
  2447. server += ":853";
  2448. nameServer = new NameServerAddress(server, protocol);
  2449. if (nameServer.IPEndPoint == null)
  2450. {
  2451. if (proxy == null)
  2452. {
  2453. if (_dnsServer.AllowRecursion)
  2454. await nameServer.ResolveIPAddressAsync(new NameServerAddress[] { _dnsServer.ThisServer }, proxy, preferIPv6, RETRIES, TIMEOUT);
  2455. else
  2456. await nameServer.RecursiveResolveIPAddressAsync(_dnsServer.DnsCache, proxy, preferIPv6, RETRIES, TIMEOUT);
  2457. }
  2458. }
  2459. else if (protocol != DnsTransportProtocol.Tls)
  2460. {
  2461. try
  2462. {
  2463. if (_dnsServer.AllowRecursion)
  2464. await nameServer.ResolveDomainNameAsync(new NameServerAddress[] { _dnsServer.ThisServer }, proxy, preferIPv6, RETRIES, TIMEOUT);
  2465. else
  2466. await nameServer.RecursiveResolveDomainNameAsync(_dnsServer.DnsCache, proxy, preferIPv6, RETRIES, TIMEOUT);
  2467. }
  2468. catch
  2469. { }
  2470. }
  2471. }
  2472. dnsResponse = await new DnsClient(nameServer) { Proxy = proxy, PreferIPv6 = preferIPv6, Retries = RETRIES, Timeout = TIMEOUT }.ResolveAsync(domain, type);
  2473. }
  2474. if (importRecords)
  2475. {
  2476. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  2477. if (zoneInfo == null)
  2478. {
  2479. zoneInfo = _dnsServer.AuthZoneManager.CreatePrimaryZone(domain, _dnsServer.ServerDomain, false);
  2480. if (zoneInfo == null)
  2481. throw new DnsServerException("Cannot import records: failed to create primary zone.");
  2482. }
  2483. else
  2484. {
  2485. switch (zoneInfo.Type)
  2486. {
  2487. case AuthZoneType.Primary:
  2488. case AuthZoneType.Forwarder:
  2489. break;
  2490. default:
  2491. throw new DnsServerException("Cannot import records: import zone must be of primary or forwarder type.");
  2492. }
  2493. }
  2494. if (type == DnsResourceRecordType.AXFR)
  2495. {
  2496. bool dontRemoveRecords = zoneInfo.Type == AuthZoneType.Forwarder;
  2497. _dnsServer.AuthZoneManager.SyncRecords(domain, dnsResponse.Answer, null, dontRemoveRecords);
  2498. }
  2499. else
  2500. {
  2501. List<DnsResourceRecord> syncRecords = new List<DnsResourceRecord>();
  2502. foreach (DnsResourceRecord record in dnsResponse.Answer)
  2503. {
  2504. if (record.Name.Equals(domain, StringComparison.OrdinalIgnoreCase))
  2505. {
  2506. record.RemoveExpiry();
  2507. syncRecords.Add(record);
  2508. }
  2509. }
  2510. _dnsServer.AuthZoneManager.SyncRecords(domain, syncRecords, null, true);
  2511. }
  2512. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DNS Client imported record(s) for authoritative zone {server: " + server + "; domain: " + domain + "; type: " + type + ";}");
  2513. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  2514. }
  2515. jsonWriter.WritePropertyName("result");
  2516. jsonWriter.WriteRawValue(JsonConvert.SerializeObject(dnsResponse, new StringEnumConverter()));
  2517. }
  2518. private void ListLogs(JsonTextWriter jsonWriter)
  2519. {
  2520. string[] logFiles = Directory.GetFiles(_log.LogFolder, "*.log");
  2521. Array.Sort(logFiles);
  2522. Array.Reverse(logFiles);
  2523. jsonWriter.WritePropertyName("logFiles");
  2524. jsonWriter.WriteStartArray();
  2525. foreach (string logFile in logFiles)
  2526. {
  2527. jsonWriter.WriteStartObject();
  2528. jsonWriter.WritePropertyName("fileName");
  2529. jsonWriter.WriteValue(Path.GetFileNameWithoutExtension(logFile));
  2530. jsonWriter.WritePropertyName("size");
  2531. jsonWriter.WriteValue(WebUtilities.GetFormattedSize(new FileInfo(logFile).Length));
  2532. jsonWriter.WriteEndObject();
  2533. }
  2534. jsonWriter.WriteEndArray();
  2535. }
  2536. private void DeleteLog(HttpListenerRequest request)
  2537. {
  2538. string log = request.QueryString["log"];
  2539. if (string.IsNullOrEmpty(log))
  2540. throw new WebServiceException("Parameter 'log' missing.");
  2541. string logFile = Path.Combine(_log.LogFolder, log + ".log");
  2542. if (_log.CurrentLogFile.Equals(logFile, StringComparison.OrdinalIgnoreCase))
  2543. _log.DeleteCurrentLogFile();
  2544. else
  2545. File.Delete(logFile);
  2546. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] Log file was deleted: " + log);
  2547. }
  2548. private void ListDhcpLeases(JsonTextWriter jsonWriter)
  2549. {
  2550. ICollection<Scope> scopes = _dhcpServer.Scopes;
  2551. //sort by name
  2552. Scope[] scopesArray = new Scope[scopes.Count];
  2553. scopes.CopyTo(scopesArray, 0);
  2554. Array.Sort(scopesArray);
  2555. jsonWriter.WritePropertyName("leases");
  2556. jsonWriter.WriteStartArray();
  2557. foreach (Scope scope in scopesArray)
  2558. {
  2559. ICollection<Lease> leases = scope.Leases;
  2560. //sort by address
  2561. Lease[] leasesArray = new Lease[leases.Count];
  2562. leases.CopyTo(leasesArray, 0);
  2563. Array.Sort(leasesArray);
  2564. foreach (Lease lease in leasesArray)
  2565. {
  2566. jsonWriter.WriteStartObject();
  2567. jsonWriter.WritePropertyName("scope");
  2568. jsonWriter.WriteValue(scope.Name);
  2569. jsonWriter.WritePropertyName("type");
  2570. jsonWriter.WriteValue(lease.Type.ToString());
  2571. jsonWriter.WritePropertyName("hardwareAddress");
  2572. jsonWriter.WriteValue(BitConverter.ToString(lease.HardwareAddress));
  2573. jsonWriter.WritePropertyName("address");
  2574. jsonWriter.WriteValue(lease.Address.ToString());
  2575. jsonWriter.WritePropertyName("hostName");
  2576. jsonWriter.WriteValue(lease.HostName);
  2577. jsonWriter.WritePropertyName("leaseObtained");
  2578. jsonWriter.WriteValue(lease.LeaseObtained.ToLocalTime().ToString());
  2579. jsonWriter.WritePropertyName("leaseExpires");
  2580. jsonWriter.WriteValue(lease.LeaseExpires.ToLocalTime().ToString());
  2581. jsonWriter.WriteEndObject();
  2582. }
  2583. }
  2584. jsonWriter.WriteEndArray();
  2585. }
  2586. private void ListDhcpScopes(JsonTextWriter jsonWriter)
  2587. {
  2588. ICollection<Scope> scopes = _dhcpServer.Scopes;
  2589. //sort by name
  2590. Scope[] scopesArray = new Scope[scopes.Count];
  2591. scopes.CopyTo(scopesArray, 0);
  2592. Array.Sort(scopesArray);
  2593. jsonWriter.WritePropertyName("scopes");
  2594. jsonWriter.WriteStartArray();
  2595. foreach (Scope scope in scopesArray)
  2596. {
  2597. jsonWriter.WriteStartObject();
  2598. jsonWriter.WritePropertyName("name");
  2599. jsonWriter.WriteValue(scope.Name);
  2600. jsonWriter.WritePropertyName("enabled");
  2601. jsonWriter.WriteValue(scope.Enabled);
  2602. jsonWriter.WritePropertyName("startingAddress");
  2603. jsonWriter.WriteValue(scope.StartingAddress.ToString());
  2604. jsonWriter.WritePropertyName("endingAddress");
  2605. jsonWriter.WriteValue(scope.EndingAddress.ToString());
  2606. jsonWriter.WritePropertyName("subnetMask");
  2607. jsonWriter.WriteValue(scope.SubnetMask.ToString());
  2608. jsonWriter.WritePropertyName("networkAddress");
  2609. jsonWriter.WriteValue(scope.NetworkAddress.ToString());
  2610. jsonWriter.WritePropertyName("broadcastAddress");
  2611. jsonWriter.WriteValue(scope.BroadcastAddress.ToString());
  2612. if (scope.InterfaceAddress != null)
  2613. {
  2614. jsonWriter.WritePropertyName("interfaceAddress");
  2615. jsonWriter.WriteValue(scope.InterfaceAddress.ToString());
  2616. }
  2617. jsonWriter.WriteEndObject();
  2618. }
  2619. jsonWriter.WriteEndArray();
  2620. }
  2621. private void GetDhcpScope(HttpListenerRequest request, JsonTextWriter jsonWriter)
  2622. {
  2623. string scopeName = request.QueryString["name"];
  2624. if (string.IsNullOrEmpty(scopeName))
  2625. throw new WebServiceException("Parameter 'name' missing.");
  2626. Scope scope = _dhcpServer.GetScope(scopeName);
  2627. if (scope == null)
  2628. throw new WebServiceException("DHCP scope was not found: " + scopeName);
  2629. jsonWriter.WritePropertyName("name");
  2630. jsonWriter.WriteValue(scope.Name);
  2631. jsonWriter.WritePropertyName("startingAddress");
  2632. jsonWriter.WriteValue(scope.StartingAddress.ToString());
  2633. jsonWriter.WritePropertyName("endingAddress");
  2634. jsonWriter.WriteValue(scope.EndingAddress.ToString());
  2635. jsonWriter.WritePropertyName("subnetMask");
  2636. jsonWriter.WriteValue(scope.SubnetMask.ToString());
  2637. jsonWriter.WritePropertyName("leaseTimeDays");
  2638. jsonWriter.WriteValue(scope.LeaseTimeDays);
  2639. jsonWriter.WritePropertyName("leaseTimeHours");
  2640. jsonWriter.WriteValue(scope.LeaseTimeHours);
  2641. jsonWriter.WritePropertyName("leaseTimeMinutes");
  2642. jsonWriter.WriteValue(scope.LeaseTimeMinutes);
  2643. jsonWriter.WritePropertyName("offerDelayTime");
  2644. jsonWriter.WriteValue(scope.OfferDelayTime);
  2645. if (!string.IsNullOrEmpty(scope.DomainName))
  2646. {
  2647. jsonWriter.WritePropertyName("domainName");
  2648. jsonWriter.WriteValue(scope.DomainName);
  2649. }
  2650. jsonWriter.WritePropertyName("dnsTtl");
  2651. jsonWriter.WriteValue(scope.DnsTtl);
  2652. if (scope.RouterAddress != null)
  2653. {
  2654. jsonWriter.WritePropertyName("routerAddress");
  2655. jsonWriter.WriteValue(scope.RouterAddress.ToString());
  2656. }
  2657. jsonWriter.WritePropertyName("useThisDnsServer");
  2658. jsonWriter.WriteValue(scope.UseThisDnsServer);
  2659. if (scope.DnsServers != null)
  2660. {
  2661. jsonWriter.WritePropertyName("dnsServers");
  2662. jsonWriter.WriteStartArray();
  2663. foreach (IPAddress dnsServer in scope.DnsServers)
  2664. jsonWriter.WriteValue(dnsServer.ToString());
  2665. jsonWriter.WriteEndArray();
  2666. }
  2667. if (scope.WinsServers != null)
  2668. {
  2669. jsonWriter.WritePropertyName("winsServers");
  2670. jsonWriter.WriteStartArray();
  2671. foreach (IPAddress winsServer in scope.WinsServers)
  2672. jsonWriter.WriteValue(winsServer.ToString());
  2673. jsonWriter.WriteEndArray();
  2674. }
  2675. if (scope.NtpServers != null)
  2676. {
  2677. jsonWriter.WritePropertyName("ntpServers");
  2678. jsonWriter.WriteStartArray();
  2679. foreach (IPAddress ntpServer in scope.NtpServers)
  2680. jsonWriter.WriteValue(ntpServer.ToString());
  2681. jsonWriter.WriteEndArray();
  2682. }
  2683. if (scope.StaticRoutes != null)
  2684. {
  2685. jsonWriter.WritePropertyName("staticRoutes");
  2686. jsonWriter.WriteStartArray();
  2687. foreach (ClasslessStaticRouteOption.Route route in scope.StaticRoutes)
  2688. {
  2689. jsonWriter.WriteStartObject();
  2690. jsonWriter.WritePropertyName("destination");
  2691. jsonWriter.WriteValue(route.Destination.ToString());
  2692. jsonWriter.WritePropertyName("subnetMask");
  2693. jsonWriter.WriteValue(route.SubnetMask.ToString());
  2694. jsonWriter.WritePropertyName("router");
  2695. jsonWriter.WriteValue(route.Router.ToString());
  2696. jsonWriter.WriteEndObject();
  2697. }
  2698. jsonWriter.WriteEndArray();
  2699. }
  2700. if (scope.Exclusions != null)
  2701. {
  2702. jsonWriter.WritePropertyName("exclusions");
  2703. jsonWriter.WriteStartArray();
  2704. foreach (Exclusion exclusion in scope.Exclusions)
  2705. {
  2706. jsonWriter.WriteStartObject();
  2707. jsonWriter.WritePropertyName("startingAddress");
  2708. jsonWriter.WriteValue(exclusion.StartingAddress.ToString());
  2709. jsonWriter.WritePropertyName("endingAddress");
  2710. jsonWriter.WriteValue(exclusion.EndingAddress.ToString());
  2711. jsonWriter.WriteEndObject();
  2712. }
  2713. jsonWriter.WriteEndArray();
  2714. }
  2715. jsonWriter.WritePropertyName("reservedLeases");
  2716. jsonWriter.WriteStartArray();
  2717. foreach (Lease reservedLease in scope.ReservedLeases)
  2718. {
  2719. jsonWriter.WriteStartObject();
  2720. jsonWriter.WritePropertyName("hostName");
  2721. jsonWriter.WriteValue(reservedLease.HostName);
  2722. jsonWriter.WritePropertyName("hardwareAddress");
  2723. jsonWriter.WriteValue(BitConverter.ToString(reservedLease.HardwareAddress));
  2724. jsonWriter.WritePropertyName("address");
  2725. jsonWriter.WriteValue(reservedLease.Address.ToString());
  2726. jsonWriter.WritePropertyName("comments");
  2727. jsonWriter.WriteValue(reservedLease.Comments);
  2728. jsonWriter.WriteEndObject();
  2729. }
  2730. jsonWriter.WriteEndArray();
  2731. jsonWriter.WritePropertyName("allowOnlyReservedLeases");
  2732. jsonWriter.WriteValue(scope.AllowOnlyReservedLeases);
  2733. }
  2734. private async Task SetDhcpScopeAsync(HttpListenerRequest request)
  2735. {
  2736. string scopeName = request.QueryString["name"];
  2737. if (string.IsNullOrEmpty(scopeName))
  2738. throw new WebServiceException("Parameter 'name' missing.");
  2739. string newName = request.QueryString["newName"];
  2740. if (!string.IsNullOrEmpty(newName) && !newName.Equals(scopeName))
  2741. {
  2742. _dhcpServer.RenameScope(scopeName, newName);
  2743. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was renamed successfully: '" + scopeName + "' to '" + newName + "'");
  2744. scopeName = newName;
  2745. }
  2746. string strStartingAddress = request.QueryString["startingAddress"];
  2747. if (string.IsNullOrEmpty(strStartingAddress))
  2748. throw new WebServiceException("Parameter 'startingAddress' missing.");
  2749. string strEndingAddress = request.QueryString["endingAddress"];
  2750. if (string.IsNullOrEmpty(strStartingAddress))
  2751. throw new WebServiceException("Parameter 'endingAddress' missing.");
  2752. string strSubnetMask = request.QueryString["subnetMask"];
  2753. if (string.IsNullOrEmpty(strStartingAddress))
  2754. throw new WebServiceException("Parameter 'subnetMask' missing.");
  2755. bool scopeExists;
  2756. Scope scope = _dhcpServer.GetScope(scopeName);
  2757. if (scope == null)
  2758. {
  2759. //scope does not exists; create new scope
  2760. scopeExists = false;
  2761. scope = new Scope(scopeName, true, IPAddress.Parse(strStartingAddress), IPAddress.Parse(strEndingAddress), IPAddress.Parse(strSubnetMask));
  2762. }
  2763. else
  2764. {
  2765. scopeExists = true;
  2766. IPAddress startingAddress = IPAddress.Parse(strStartingAddress);
  2767. IPAddress endingAddress = IPAddress.Parse(strEndingAddress);
  2768. //validate scope address
  2769. foreach (Scope existingScope in _dhcpServer.Scopes)
  2770. {
  2771. if (existingScope.Equals(scope))
  2772. continue;
  2773. if (existingScope.IsAddressInRange(startingAddress) || existingScope.IsAddressInRange(endingAddress))
  2774. throw new DhcpServerException("Scope with overlapping range already exists: " + existingScope.StartingAddress.ToString() + "-" + existingScope.EndingAddress.ToString());
  2775. }
  2776. scope.ChangeNetwork(startingAddress, endingAddress, IPAddress.Parse(strSubnetMask));
  2777. }
  2778. string strLeaseTimeDays = request.QueryString["leaseTimeDays"];
  2779. if (!string.IsNullOrEmpty(strLeaseTimeDays))
  2780. scope.LeaseTimeDays = ushort.Parse(strLeaseTimeDays);
  2781. string strLeaseTimeHours = request.QueryString["leaseTimeHours"];
  2782. if (!string.IsNullOrEmpty(strLeaseTimeHours))
  2783. scope.LeaseTimeHours = byte.Parse(strLeaseTimeHours);
  2784. string strLeaseTimeMinutes = request.QueryString["leaseTimeMinutes"];
  2785. if (!string.IsNullOrEmpty(strLeaseTimeMinutes))
  2786. scope.LeaseTimeMinutes = byte.Parse(strLeaseTimeMinutes);
  2787. string strOfferDelayTime = request.QueryString["offerDelayTime"];
  2788. if (!string.IsNullOrEmpty(strOfferDelayTime))
  2789. scope.OfferDelayTime = ushort.Parse(strOfferDelayTime);
  2790. string strDomainName = request.QueryString["domainName"];
  2791. if (strDomainName != null)
  2792. scope.DomainName = strDomainName.Length == 0 ? null : strDomainName;
  2793. string strDnsTtl = request.QueryString["dnsTtl"];
  2794. if (!string.IsNullOrEmpty(strDnsTtl))
  2795. scope.DnsTtl = uint.Parse(strDnsTtl);
  2796. string strRouterAddress = request.QueryString["routerAddress"];
  2797. if (strRouterAddress != null)
  2798. scope.RouterAddress = strRouterAddress.Length == 0 ? null : IPAddress.Parse(strRouterAddress);
  2799. string strUseThisDnsServer = request.QueryString["useThisDnsServer"];
  2800. if (!string.IsNullOrEmpty(strUseThisDnsServer))
  2801. scope.UseThisDnsServer = bool.Parse(strUseThisDnsServer);
  2802. if (!scope.UseThisDnsServer)
  2803. {
  2804. string strDnsServers = request.QueryString["dnsServers"];
  2805. if (strDnsServers != null)
  2806. {
  2807. if (strDnsServers.Length == 0)
  2808. {
  2809. scope.DnsServers = null;
  2810. }
  2811. else
  2812. {
  2813. string[] strDnsServerParts = strDnsServers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2814. IPAddress[] dnsServers = new IPAddress[strDnsServerParts.Length];
  2815. for (int i = 0; i < strDnsServerParts.Length; i++)
  2816. dnsServers[i] = IPAddress.Parse(strDnsServerParts[i]);
  2817. scope.DnsServers = dnsServers;
  2818. }
  2819. }
  2820. }
  2821. string strWinsServers = request.QueryString["winsServers"];
  2822. if (strWinsServers != null)
  2823. {
  2824. if (strWinsServers.Length == 0)
  2825. {
  2826. scope.WinsServers = null;
  2827. }
  2828. else
  2829. {
  2830. string[] strWinsServerParts = strWinsServers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2831. IPAddress[] winsServers = new IPAddress[strWinsServerParts.Length];
  2832. for (int i = 0; i < strWinsServerParts.Length; i++)
  2833. winsServers[i] = IPAddress.Parse(strWinsServerParts[i]);
  2834. scope.WinsServers = winsServers;
  2835. }
  2836. }
  2837. string strNtpServers = request.QueryString["ntpServers"];
  2838. if (strNtpServers != null)
  2839. {
  2840. if (strNtpServers.Length == 0)
  2841. {
  2842. scope.NtpServers = null;
  2843. }
  2844. else
  2845. {
  2846. string[] strNtpServerParts = strNtpServers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2847. IPAddress[] ntpServers = new IPAddress[strNtpServerParts.Length];
  2848. for (int i = 0; i < strNtpServerParts.Length; i++)
  2849. ntpServers[i] = IPAddress.Parse(strNtpServerParts[i]);
  2850. scope.NtpServers = ntpServers;
  2851. }
  2852. }
  2853. string strStaticRoutes = request.QueryString["staticRoutes"];
  2854. if (strStaticRoutes != null)
  2855. {
  2856. if (strStaticRoutes.Length == 0)
  2857. {
  2858. scope.StaticRoutes = null;
  2859. }
  2860. else
  2861. {
  2862. string[] strStaticRoutesParts = strStaticRoutes.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2863. ClasslessStaticRouteOption.Route[] staticRoutes = new ClasslessStaticRouteOption.Route[strStaticRoutesParts.Length];
  2864. for (int i = 0; i < strStaticRoutesParts.Length; i++)
  2865. {
  2866. string[] routeParts = strStaticRoutesParts[i].Split(';');
  2867. staticRoutes[i] = new ClasslessStaticRouteOption.Route(IPAddress.Parse(routeParts[0]), IPAddress.Parse(routeParts[1]), IPAddress.Parse(routeParts[2]));
  2868. }
  2869. scope.StaticRoutes = staticRoutes;
  2870. }
  2871. }
  2872. string strExclusions = request.QueryString["exclusions"];
  2873. if (strExclusions != null)
  2874. {
  2875. if (strExclusions.Length == 0)
  2876. {
  2877. scope.Exclusions = null;
  2878. }
  2879. else
  2880. {
  2881. string[] strExclusionsParts = strExclusions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2882. Exclusion[] exclusions = new Exclusion[strExclusionsParts.Length];
  2883. for (int i = 0; i < strExclusionsParts.Length; i++)
  2884. {
  2885. string[] rangeParts = strExclusionsParts[i].Split(';');
  2886. exclusions[i] = new Exclusion(IPAddress.Parse(rangeParts[0]), IPAddress.Parse(rangeParts[1]));
  2887. }
  2888. scope.Exclusions = exclusions;
  2889. }
  2890. }
  2891. string strReservedLeases = request.QueryString["reservedLeases"];
  2892. if (strReservedLeases != null)
  2893. {
  2894. if (strReservedLeases.Length == 0)
  2895. {
  2896. scope.ReservedLeases = null;
  2897. }
  2898. else
  2899. {
  2900. string[] strReservedLeaseParts = strReservedLeases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  2901. Lease[] reservedLeases = new Lease[strReservedLeaseParts.Length];
  2902. for (int i = 0; i < strReservedLeaseParts.Length; i++)
  2903. {
  2904. string[] leaseParts = strReservedLeaseParts[i].Split(';');
  2905. Lease reservedLease = new Lease(LeaseType.Reserved, null, leaseParts[0], IPAddress.Parse(leaseParts[1]), leaseParts[2]);
  2906. Lease existingReservedLease = scope.GetReservedLease(reservedLease.ClientIdentifier);
  2907. if (existingReservedLease != null)
  2908. reservedLease.SetHostName(existingReservedLease.HostName);
  2909. reservedLeases[i] = reservedLease;
  2910. }
  2911. scope.ReservedLeases = reservedLeases;
  2912. }
  2913. }
  2914. string strAllowOnlyReservedLeases = request.QueryString["allowOnlyReservedLeases"];
  2915. if (!string.IsNullOrEmpty(strAllowOnlyReservedLeases))
  2916. scope.AllowOnlyReservedLeases = bool.Parse(strAllowOnlyReservedLeases);
  2917. if (scopeExists)
  2918. {
  2919. _dhcpServer.SaveScope(scopeName);
  2920. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was updated successfully: " + scopeName);
  2921. }
  2922. else
  2923. {
  2924. await _dhcpServer.AddScopeAsync(scope);
  2925. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was added successfully: " + scopeName);
  2926. }
  2927. }
  2928. private async Task EnableDhcpScopeAsync(HttpListenerRequest request)
  2929. {
  2930. string scopeName = request.QueryString["name"];
  2931. if (string.IsNullOrEmpty(scopeName))
  2932. throw new WebServiceException("Parameter 'name' missing.");
  2933. if (!await _dhcpServer.EnableScopeAsync(scopeName))
  2934. throw new WebServiceException("Failed to enable DHCP scope, please check logs for details: " + scopeName);
  2935. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was enabled successfully: " + scopeName);
  2936. }
  2937. private void DisableDhcpScope(HttpListenerRequest request)
  2938. {
  2939. string scopeName = request.QueryString["name"];
  2940. if (string.IsNullOrEmpty(scopeName))
  2941. throw new WebServiceException("Parameter 'name' missing.");
  2942. if (!_dhcpServer.DisableScope(scopeName))
  2943. throw new WebServiceException("Failed to disable DHCP scope, please check logs for details: " + scopeName);
  2944. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was disabled successfully: " + scopeName);
  2945. }
  2946. private void DeleteDhcpScope(HttpListenerRequest request)
  2947. {
  2948. string scopeName = request.QueryString["name"];
  2949. if (string.IsNullOrEmpty(scopeName))
  2950. throw new WebServiceException("Parameter 'name' missing.");
  2951. _dhcpServer.DeleteScope(scopeName);
  2952. _log.Write(GetRequestRemoteEndPoint(request), "[" + GetSession(request).Username + "] DHCP scope was deleted successfully: " + scopeName);
  2953. }
  2954. private void SetCredentials(string username, string password)
  2955. {
  2956. username = username.ToLower();
  2957. string passwordHash = GetPasswordHash(username, password);
  2958. _credentials[username] = passwordHash;
  2959. }
  2960. private void LoadCredentials(string username, string passwordHash)
  2961. {
  2962. username = username.ToLower();
  2963. _credentials[username] = passwordHash;
  2964. }
  2965. private static string GetPasswordHash(string username, string password)
  2966. {
  2967. using (HMAC hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
  2968. {
  2969. return BitConverter.ToString(hmac.ComputeHash(Encoding.UTF8.GetBytes(username))).Replace("-", "").ToLower();
  2970. }
  2971. }
  2972. private void StartBlockListUpdateTimer()
  2973. {
  2974. if (_blockListUpdateTimer == null)
  2975. {
  2976. _blockListUpdateTimer = new Timer(async delegate (object state)
  2977. {
  2978. try
  2979. {
  2980. if (DateTime.UtcNow > _blockListLastUpdatedOn.AddHours(BLOCK_LIST_UPDATE_AFTER_HOURS))
  2981. {
  2982. if (await _dnsServer.BlockListZoneManager.UpdateBlockListsAsync())
  2983. {
  2984. //block lists were updated
  2985. //save last updated on time
  2986. _blockListLastUpdatedOn = DateTime.UtcNow;
  2987. SaveConfigFile();
  2988. }
  2989. }
  2990. }
  2991. catch (Exception ex)
  2992. {
  2993. _log.Write("DNS Server encountered an error while updating block lists.\r\n" + ex.ToString());
  2994. }
  2995. }, null, BLOCK_LIST_UPDATE_TIMER_INITIAL_INTERVAL, BLOCK_LIST_UPDATE_TIMER_INTERVAL);
  2996. }
  2997. }
  2998. private void StopBlockListUpdateTimer()
  2999. {
  3000. if (_blockListUpdateTimer != null)
  3001. {
  3002. _blockListUpdateTimer.Dispose();
  3003. _blockListUpdateTimer = null;
  3004. }
  3005. }
  3006. private void StartTlsCertificateUpdateTimer()
  3007. {
  3008. if (_tlsCertificateUpdateTimer == null)
  3009. {
  3010. _tlsCertificateUpdateTimer = new Timer(delegate (object state)
  3011. {
  3012. try
  3013. {
  3014. FileInfo fileInfo = new FileInfo(_tlsCertificatePath);
  3015. if (fileInfo.Exists && (fileInfo.LastWriteTimeUtc != _tlsCertificateLastModifiedOn))
  3016. LoadTlsCertificate(_tlsCertificatePath, _tlsCertificatePassword);
  3017. }
  3018. catch (Exception ex)
  3019. {
  3020. _log.Write("DNS Server encountered an error while updating TLS Certificate: " + _tlsCertificatePath + "\r\n" + ex.ToString());
  3021. }
  3022. }, null, TLS_CERTIFICATE_UPDATE_TIMER_INITIAL_INTERVAL, TLS_CERTIFICATE_UPDATE_TIMER_INTERVAL);
  3023. }
  3024. }
  3025. private void StopTlsCertificateUpdateTimer()
  3026. {
  3027. if (_tlsCertificateUpdateTimer != null)
  3028. {
  3029. _tlsCertificateUpdateTimer.Dispose();
  3030. _tlsCertificateUpdateTimer = null;
  3031. }
  3032. }
  3033. private void LoadTlsCertificate(string tlsCertificatePath, string tlsCertificatePassword)
  3034. {
  3035. FileInfo fileInfo = new FileInfo(tlsCertificatePath);
  3036. if (!fileInfo.Exists)
  3037. throw new ArgumentException("Tls certificate file does not exists: " + tlsCertificatePath);
  3038. if (Path.GetExtension(tlsCertificatePath) != ".pfx")
  3039. throw new ArgumentException("Tls certificate file must be PKCS #12 formatted with .pfx extension: " + tlsCertificatePath);
  3040. X509Certificate2 certificate = new X509Certificate2(tlsCertificatePath, tlsCertificatePassword);
  3041. if (!certificate.Verify())
  3042. throw new ArgumentException("Tls certificate is invalid.");
  3043. _dnsServer.Certificate = certificate;
  3044. _tlsCertificateLastModifiedOn = fileInfo.LastWriteTimeUtc;
  3045. _log.Write("DNS Server TLS certificate was loaded: " + tlsCertificatePath);
  3046. }
  3047. private void LoadConfigFile()
  3048. {
  3049. string configFile = Path.Combine(_configFolder, "dns.config");
  3050. try
  3051. {
  3052. bool passwordResetOption = false;
  3053. if (!File.Exists(configFile))
  3054. {
  3055. string passwordResetConfigFile = Path.Combine(_configFolder, "reset.config");
  3056. if (File.Exists(passwordResetConfigFile))
  3057. {
  3058. passwordResetOption = true;
  3059. configFile = passwordResetConfigFile;
  3060. }
  3061. }
  3062. byte version;
  3063. using (FileStream fS = new FileStream(configFile, FileMode.Open, FileAccess.Read))
  3064. {
  3065. BinaryReader bR = new BinaryReader(fS);
  3066. if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "DS") //format
  3067. throw new InvalidDataException("DnsServer config file format is invalid.");
  3068. version = bR.ReadByte();
  3069. switch (version)
  3070. {
  3071. case 2:
  3072. case 3:
  3073. case 4:
  3074. case 5:
  3075. case 6:
  3076. case 7:
  3077. case 8:
  3078. case 9:
  3079. case 10:
  3080. case 11:
  3081. _dnsServer.ServerDomain = bR.ReadShortString();
  3082. _webServicePort = bR.ReadInt32();
  3083. _dnsServer.PreferIPv6 = bR.ReadBoolean();
  3084. if (bR.ReadBoolean()) //logQueries
  3085. _dnsServer.QueryLogManager = _log;
  3086. _dnsServer.AllowRecursion = bR.ReadBoolean();
  3087. if (version >= 4)
  3088. _dnsServer.AllowRecursionOnlyForPrivateNetworks = bR.ReadBoolean();
  3089. else
  3090. _dnsServer.AllowRecursionOnlyForPrivateNetworks = true; //default true for security reasons
  3091. if (version >= 9)
  3092. {
  3093. _dnsServer.CachePrefetchEligibility = bR.ReadInt32();
  3094. _dnsServer.CachePrefetchTrigger = bR.ReadInt32();
  3095. _dnsServer.CachePrefetchSampleIntervalInMinutes = bR.ReadInt32();
  3096. _dnsServer.CachePrefetchSampleEligibilityHitsPerHour = bR.ReadInt32();
  3097. }
  3098. NetProxyType proxyType = (NetProxyType)bR.ReadByte();
  3099. if (proxyType != NetProxyType.None)
  3100. {
  3101. string address = bR.ReadShortString();
  3102. int port = bR.ReadInt32();
  3103. NetworkCredential credential = null;
  3104. if (bR.ReadBoolean()) //credential set
  3105. credential = new NetworkCredential(bR.ReadShortString(), bR.ReadShortString());
  3106. _dnsServer.Proxy = NetProxy.CreateProxy(proxyType, address, port, credential);
  3107. if (version >= 10)
  3108. {
  3109. int count = bR.ReadByte();
  3110. _dnsServer.Proxy.BypassList.Clear();
  3111. for (int i = 0; i < count; i++)
  3112. _dnsServer.Proxy.BypassList.Add(new NetProxyBypassItem(bR.ReadShortString()));
  3113. }
  3114. }
  3115. else
  3116. {
  3117. _dnsServer.Proxy = null;
  3118. }
  3119. {
  3120. int count = bR.ReadByte();
  3121. if (count > 0)
  3122. {
  3123. NameServerAddress[] forwarders = new NameServerAddress[count];
  3124. for (int i = 0; i < count; i++)
  3125. forwarders[i] = new NameServerAddress(bR);
  3126. _dnsServer.Forwarders = forwarders;
  3127. }
  3128. }
  3129. if (version <= 10)
  3130. {
  3131. DnsTransportProtocol forwarderProtocol = (DnsTransportProtocol)bR.ReadByte();
  3132. if (_dnsServer.Forwarders != null)
  3133. {
  3134. List<NameServerAddress> forwarders = new List<NameServerAddress>();
  3135. foreach (NameServerAddress forwarder in _dnsServer.Forwarders)
  3136. {
  3137. if (forwarder.Protocol == forwarderProtocol)
  3138. forwarders.Add(forwarder);
  3139. else
  3140. forwarders.Add(new NameServerAddress(forwarder, forwarderProtocol));
  3141. }
  3142. _dnsServer.Forwarders = forwarders;
  3143. }
  3144. }
  3145. {
  3146. int count = bR.ReadByte();
  3147. if (count > 0)
  3148. {
  3149. if (version > 2)
  3150. {
  3151. for (int i = 0; i < count; i++)
  3152. LoadCredentials(bR.ReadShortString(), bR.ReadShortString());
  3153. }
  3154. else
  3155. {
  3156. for (int i = 0; i < count; i++)
  3157. SetCredentials(bR.ReadShortString(), bR.ReadShortString());
  3158. }
  3159. }
  3160. }
  3161. if (version <= 6)
  3162. {
  3163. int count = bR.ReadInt32();
  3164. _configDisabledZones = new List<string>(count);
  3165. for (int i = 0; i < count; i++)
  3166. {
  3167. string domain = bR.ReadShortString();
  3168. _configDisabledZones.Add(domain);
  3169. }
  3170. }
  3171. if (version > 4)
  3172. {
  3173. //read block list urls
  3174. int count = bR.ReadByte();
  3175. for (int i = 0; i < count; i++)
  3176. _dnsServer.BlockListZoneManager.BlockListUrls.Add(new Uri(bR.ReadShortString()));
  3177. _blockListLastUpdatedOn = bR.ReadDate();
  3178. }
  3179. if (version >= 11)
  3180. {
  3181. int count = bR.ReadByte();
  3182. if (count > 0)
  3183. {
  3184. IPEndPoint[] localEndPoints = new IPEndPoint[count];
  3185. for (int i = 0; i < count; i++)
  3186. localEndPoints[i] = (IPEndPoint)EndPointExtension.Parse(bR);
  3187. _dnsServer.LocalEndPoints = localEndPoints;
  3188. }
  3189. }
  3190. else if (version >= 6)
  3191. {
  3192. int count = bR.ReadByte();
  3193. if (count > 0)
  3194. {
  3195. IPEndPoint[] localEndPoints = new IPEndPoint[count];
  3196. for (int i = 0; i < count; i++)
  3197. localEndPoints[i] = new IPEndPoint(IPAddressExtension.Parse(bR), 53);
  3198. _dnsServer.LocalEndPoints = localEndPoints;
  3199. }
  3200. }
  3201. if (version >= 8)
  3202. {
  3203. _dnsServer.EnableDnsOverHttp = bR.ReadBoolean();
  3204. _dnsServer.EnableDnsOverTls = bR.ReadBoolean();
  3205. _dnsServer.EnableDnsOverHttps = bR.ReadBoolean();
  3206. _tlsCertificatePath = bR.ReadShortString();
  3207. _tlsCertificatePassword = bR.ReadShortString();
  3208. if (_tlsCertificatePath.Length == 0)
  3209. _tlsCertificatePath = null;
  3210. if (_tlsCertificatePath != null)
  3211. {
  3212. try
  3213. {
  3214. LoadTlsCertificate(_tlsCertificatePath, _tlsCertificatePassword);
  3215. }
  3216. catch (Exception ex)
  3217. {
  3218. _log.Write("DNS Server encountered an error while loading TLS certificate: " + _tlsCertificatePath + "\r\n" + ex.ToString());
  3219. }
  3220. StartTlsCertificateUpdateTimer();
  3221. }
  3222. }
  3223. break;
  3224. default:
  3225. throw new InvalidDataException("DnsServer config version not supported.");
  3226. }
  3227. }
  3228. _log.Write("DNS Server config file was loaded: " + configFile);
  3229. if (passwordResetOption)
  3230. {
  3231. SetCredentials("admin", "admin");
  3232. _log.Write("DNS Server reset password for user: admin");
  3233. SaveConfigFile();
  3234. try
  3235. {
  3236. File.Delete(configFile);
  3237. }
  3238. catch
  3239. { }
  3240. }
  3241. if (version <= 6)
  3242. SaveConfigFile(); //save as new config version to avoid loading old version next time
  3243. }
  3244. catch (FileNotFoundException)
  3245. {
  3246. _log.Write("DNS Server config file was not found: " + configFile);
  3247. _log.Write("DNS Server is restoring default config file.");
  3248. _webServicePort = 5380;
  3249. SetCredentials("admin", "admin");
  3250. _dnsServer.AllowRecursion = true;
  3251. _dnsServer.AllowRecursionOnlyForPrivateNetworks = true; //default true for security reasons
  3252. SaveConfigFile();
  3253. }
  3254. catch (Exception ex)
  3255. {
  3256. _log.Write("DNS Server encountered an error while loading config file: " + configFile + "\r\n" + ex.ToString());
  3257. _log.Write("Note: You may try deleting the config file to fix this issue. However, you will lose DNS settings but, zone data wont be affected.");
  3258. throw;
  3259. }
  3260. }
  3261. private void SaveConfigFile()
  3262. {
  3263. string configFile = Path.Combine(_configFolder, "dns.config");
  3264. using (MemoryStream mS = new MemoryStream())
  3265. {
  3266. //serialize config
  3267. BinaryWriter bW = new BinaryWriter(mS);
  3268. bW.Write(Encoding.ASCII.GetBytes("DS")); //format
  3269. bW.Write((byte)11); //version
  3270. bW.WriteShortString(_dnsServer.ServerDomain);
  3271. bW.Write(_webServicePort);
  3272. bW.Write(_dnsServer.PreferIPv6);
  3273. bW.Write(_dnsServer.QueryLogManager != null); //logQueries
  3274. bW.Write(_dnsServer.AllowRecursion);
  3275. bW.Write(_dnsServer.AllowRecursionOnlyForPrivateNetworks);
  3276. bW.Write(_dnsServer.CachePrefetchEligibility);
  3277. bW.Write(_dnsServer.CachePrefetchTrigger);
  3278. bW.Write(_dnsServer.CachePrefetchSampleIntervalInMinutes);
  3279. bW.Write(_dnsServer.CachePrefetchSampleEligibilityHitsPerHour);
  3280. if (_dnsServer.Proxy == null)
  3281. {
  3282. bW.Write((byte)NetProxyType.None);
  3283. }
  3284. else
  3285. {
  3286. bW.Write((byte)_dnsServer.Proxy.Type);
  3287. bW.WriteShortString(_dnsServer.Proxy.Address);
  3288. bW.Write(_dnsServer.Proxy.Port);
  3289. NetworkCredential credential = _dnsServer.Proxy.Credential;
  3290. if (credential == null)
  3291. {
  3292. bW.Write(false);
  3293. }
  3294. else
  3295. {
  3296. bW.Write(true);
  3297. bW.WriteShortString(credential.UserName);
  3298. bW.WriteShortString(credential.Password);
  3299. }
  3300. //bypass list
  3301. {
  3302. bW.Write(Convert.ToByte(_dnsServer.Proxy.BypassList.Count));
  3303. foreach (NetProxyBypassItem item in _dnsServer.Proxy.BypassList)
  3304. bW.WriteShortString(item.Value);
  3305. }
  3306. }
  3307. if (_dnsServer.Forwarders == null)
  3308. {
  3309. bW.Write((byte)0);
  3310. }
  3311. else
  3312. {
  3313. bW.Write(Convert.ToByte(_dnsServer.Forwarders.Count));
  3314. foreach (NameServerAddress forwarder in _dnsServer.Forwarders)
  3315. forwarder.WriteTo(bW);
  3316. }
  3317. {
  3318. bW.Write(Convert.ToByte(_credentials.Count));
  3319. foreach (KeyValuePair<string, string> credential in _credentials)
  3320. {
  3321. bW.WriteShortString(credential.Key);
  3322. bW.WriteShortString(credential.Value);
  3323. }
  3324. }
  3325. //block list
  3326. {
  3327. bW.Write(Convert.ToByte(_dnsServer.BlockListZoneManager.BlockListUrls.Count));
  3328. foreach (Uri blockListUrl in _dnsServer.BlockListZoneManager.BlockListUrls)
  3329. bW.WriteShortString(blockListUrl.AbsoluteUri);
  3330. bW.Write(_blockListLastUpdatedOn);
  3331. }
  3332. {
  3333. bW.Write(Convert.ToByte(_dnsServer.LocalEndPoints.Count));
  3334. foreach (IPEndPoint localEP in _dnsServer.LocalEndPoints)
  3335. localEP.WriteTo(bW);
  3336. }
  3337. bW.Write(_dnsServer.EnableDnsOverHttp);
  3338. bW.Write(_dnsServer.EnableDnsOverTls);
  3339. bW.Write(_dnsServer.EnableDnsOverHttps);
  3340. if (_tlsCertificatePath == null)
  3341. bW.WriteShortString(string.Empty);
  3342. else
  3343. bW.WriteShortString(_tlsCertificatePath);
  3344. if (_tlsCertificatePassword == null)
  3345. bW.WriteShortString(string.Empty);
  3346. else
  3347. bW.WriteShortString(_tlsCertificatePassword);
  3348. //write config
  3349. mS.Position = 0;
  3350. using (FileStream fS = new FileStream(configFile, FileMode.Create, FileAccess.Write))
  3351. {
  3352. mS.CopyTo(fS);
  3353. }
  3354. }
  3355. _log.Write("DNS Server config file was saved: " + configFile);
  3356. }
  3357. #endregion
  3358. #region public
  3359. public void Start()
  3360. {
  3361. if (_disposed)
  3362. throw new ObjectDisposedException("WebService");
  3363. if (_state != ServiceState.Stopped)
  3364. throw new InvalidOperationException("Web Service is already running.");
  3365. _state = ServiceState.Starting;
  3366. try
  3367. {
  3368. //init dns server
  3369. _dnsServer = new DnsServer(_configFolder, Path.Combine(_appFolder, "dohwww"), _log);
  3370. //init dhcp server
  3371. _dhcpServer = new DhcpServer(Path.Combine(_configFolder, "scopes"), _log);
  3372. _dhcpServer.AuthZoneManager = _dnsServer.AuthZoneManager;
  3373. //load config
  3374. LoadConfigFile();
  3375. //load all zones files
  3376. _dnsServer.AuthZoneManager.LoadAllZoneFiles();
  3377. //disable zones from old config format
  3378. if (_configDisabledZones != null)
  3379. {
  3380. foreach (string domain in _configDisabledZones)
  3381. {
  3382. AuthZoneInfo zoneInfo = _dnsServer.AuthZoneManager.GetAuthZoneInfo(domain);
  3383. if (zoneInfo != null)
  3384. {
  3385. zoneInfo.Disabled = true;
  3386. _dnsServer.AuthZoneManager.SaveZoneFile(zoneInfo.Name);
  3387. }
  3388. }
  3389. }
  3390. //load allowed zone and blocked zone
  3391. _dnsServer.AllowedZoneManager.LoadAllowedZoneFile();
  3392. _dnsServer.BlockedZoneManager.LoadBlockedZoneFile();
  3393. //load block list zone async
  3394. if (_dnsServer.BlockListZoneManager.BlockListUrls.Count > 0)
  3395. {
  3396. ThreadPool.QueueUserWorkItem(delegate (object state)
  3397. {
  3398. try
  3399. {
  3400. _dnsServer.BlockListZoneManager.LoadBlockLists();
  3401. StartBlockListUpdateTimer();
  3402. }
  3403. catch (Exception ex)
  3404. {
  3405. _log.Write(ex);
  3406. }
  3407. });
  3408. }
  3409. //start dns and dhcp
  3410. _dnsServer.Start();
  3411. _dhcpServer.Start();
  3412. //start web service
  3413. try
  3414. {
  3415. _webService = new HttpListener();
  3416. _webService.Prefixes.Add("http://+:" + _webServicePort + "/");
  3417. _webService.Start();
  3418. _webServiceHostname = Environment.MachineName.ToLower();
  3419. }
  3420. catch (Exception ex)
  3421. {
  3422. _log.Write("Web Service failed to bind using default hostname. Attempting to bind again using 'localhost' hostname.\r\n" + ex.ToString());
  3423. _webService = new HttpListener();
  3424. _webService.Prefixes.Add("http://localhost:" + _webServicePort + "/");
  3425. _webService.Start();
  3426. _webServiceHostname = "localhost";
  3427. }
  3428. _webService.IgnoreWriteExceptions = true;
  3429. _webServiceThread = new Thread(AcceptWebRequestAsync);
  3430. _webServiceThread.Name = "WebService";
  3431. _webServiceThread.IsBackground = true;
  3432. _webServiceThread.Start();
  3433. _state = ServiceState.Running;
  3434. _log.Write(new IPEndPoint(IPAddress.Any, _webServicePort), "Web Service (v" + _currentVersion.ToString() + ") was started successfully.");
  3435. }
  3436. catch (Exception ex)
  3437. {
  3438. _log.Write("Failed to start Web Service (v" + _currentVersion.ToString() + ")\r\n" + ex.ToString());
  3439. throw;
  3440. }
  3441. }
  3442. public void Stop()
  3443. {
  3444. if (_state != ServiceState.Running)
  3445. return;
  3446. _state = ServiceState.Stopping;
  3447. try
  3448. {
  3449. _webService.Stop();
  3450. _dnsServer.Stop();
  3451. _dhcpServer.Stop();
  3452. StopBlockListUpdateTimer();
  3453. StopTlsCertificateUpdateTimer();
  3454. _state = ServiceState.Stopped;
  3455. _log.Write(new IPEndPoint(IPAddress.Loopback, _webServicePort), "Web Service (v" + _currentVersion.ToString() + ") was stopped successfully.");
  3456. }
  3457. catch (Exception ex)
  3458. {
  3459. _log.Write("Failed to stop Web Service (v" + _currentVersion.ToString() + ")\r\n" + ex.ToString());
  3460. throw;
  3461. }
  3462. }
  3463. #endregion
  3464. #region properties
  3465. public string ConfigFolder
  3466. { get { return _configFolder; } }
  3467. public int WebServicePort
  3468. { get { return _webServicePort; } }
  3469. public string WebServiceHostname
  3470. { get { return _webServiceHostname; } }
  3471. #endregion
  3472. }
  3473. }