1
2 /***************************************************************************
3 * nmap_dns.cc -- Handles parallel reverse DNS resolution for target IPs *
4 * *
5 ***********************IMPORTANT NMAP LICENSE TERMS************************
6 * *
7 * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap *
8 * Project"). Nmap is also a registered trademark of the Nmap Project. *
9 * *
10 * This program is distributed under the terms of the Nmap Public Source *
11 * License (NPSL). The exact license text applying to a particular Nmap *
12 * release or source code control revision is contained in the LICENSE *
13 * file distributed with that version of Nmap or source code control *
14 * revision. More Nmap copyright/legal information is available from *
15 * https://nmap.org/book/man-legal.html, and further information on the *
16 * NPSL license itself can be found at https://nmap.org/npsl. This header *
17 * summarizes some key points from the Nmap license, but is no substitute *
18 * for the actual license text. *
19 * *
20 * Nmap is generally free for end users to download and use themselves, *
21 * including commercial use. It is available from https://nmap.org. *
22 * *
23 * The Nmap license generally prohibits companies from using and *
24 * redistributing Nmap in commercial products, but we sell a special Nmap *
25 * OEM Edition with a more permissive license and special features for *
26 * this purpose. See https://nmap.org/oem *
27 * *
28 * If you have received a written Nmap license agreement or contract *
29 * stating terms other than these (such as an Nmap OEM license), you may *
30 * choose to use and redistribute Nmap under those terms instead. *
31 * *
32 * The official Nmap Windows builds include the Npcap software *
33 * (https://npcap.org) for packet capture and transmission. It is under *
34 * separate license terms which forbid redistribution without special *
35 * permission. So the official Nmap Windows builds may not be *
36 * redistributed without special permission (such as an Nmap OEM *
37 * license). *
38 * *
39 * Source is provided to this software because we believe users have a *
40 * right to know exactly what a program is going to do before they run it. *
41 * This also allows you to audit the software for security holes. *
42 * *
43 * Source code also allows you to port Nmap to new platforms, fix bugs, *
44 * and add new features. You are highly encouraged to submit your *
45 * changes as a Github PR or by email to the dev@nmap.org mailing list *
46 * for possible incorporation into the main distribution. Unless you *
47 * specify otherwise, it is understood that you are offering us very *
48 * broad rights to use your submissions as described in the Nmap Public *
49 * Source License Contributor Agreement. This is important because we *
50 * fund the project by selling licenses with various terms, and also *
51 * because the inability to relicense code has caused devastating *
52 * problems for other Free Software projects (such as KDE and NASM). *
53 * *
54 * The free version of Nmap is distributed in the hope that it will be *
55 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
56 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties, *
57 * indemnification and commercial support are all available through the *
58 * Npcap OEM program--see https://nmap.org/oem. *
59 * *
60 ***************************************************************************/
61
62 // mass_rdns - Parallel Asynchronous Reverse DNS Resolution
63 //
64 // One of Nmap's features is to perform reverse DNS queries
65 // on large number of IP addresses. Nmap supports 2 different
66 // methods of accomplishing this:
67 //
68 // System Resolver (specified using --system-dns):
69 // Performs sequential getnameinfo() calls on all the IPs.
70 // As reliable as your system resolver, almost guaranteed
71 // to be portable, but intolerably slow for scans of hundreds
72 // or more because the result from each query needs to be
73 // received before the next one can be sent.
74 //
75 // Mass/Async DNS (default):
76 // Attempts to resolve host names in parallel using a set
77 // of DNS servers. DNS servers are found here:
78 //
79 // --dns-servers <serv1[,serv2],...> (all platforms - overrides everything else)
80 //
81 // /etc/resolv.conf (only on unix)
82 //
83 // These registry keys: (only on windows)
84 //
85 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
86 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
87 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\*\NameServer
88 // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\*\DhcpNameServer
89 //
90 //
91 // Also, most systems maintain a file "/etc/hosts" that contains
92 // IP to hostname mappings. We also try to consult these files. Here
93 // is where we look for the files:
94 //
95 // Unix: /etc/hosts
96 //
97 // Windows:
98 // for 95/98/Me: WINDOWS_DIR\hosts
99 // for NT/2000/XP Pro: WINDOWS_DIR\system32\drivers\etc\hosts
100 // for XP Home: WINDOWS_DIR\system32\drivers\etc\hosts
101 // --see http://accs-net.com/hosts/how_to_use_hosts.html
102 //
103 //
104 // Created by Doug Hoyte <doug at hcsw.org> http://www.hcsw.org
105 // DNS Caching and aging added by Eddie Bell ejlbell@gmail.com 2007
106 // IPv6 and improved DNS cache by Gioacchino Mazzurco <gmazzurco89@gmail.com> 2015
107
108
109 // TODO:
110 //
111 // * Tune performance parameters
112 //
113 // * Figure out best way to estimate completion time
114 // and display it in a ScanProgressMeter
115
116 #ifdef WIN32
117 #include "nmap_winconfig.h"
118 /* Need DnetName2PcapName */
119 #include "libnetutil/netutil.h"
120 #endif
121
122 #include "nmap.h"
123 #include "NmapOps.h"
124 #include "nmap_dns.h"
125 #include "nsock.h"
126 #include "nmap_error.h"
127 #include "nmap_tty.h"
128 #include "tcpip.h"
129 #include "timing.h"
130 #include "Target.h"
131
132 #include <stdlib.h>
133 #include <limits.h>
134 #include <list>
135 #include <vector>
136
137 extern NmapOps o;
138
139
140
141 //------------------- Performance Parameters ---------------------
142
143 // Algorithm:
144 //
145 // A batch of num_targets hosts is passed to nmap_mass_rdns():
146 // void nmap_mass_rdns(Target **targets, int num_targets)
147 //
148 // mass_dns sends out CAPACITY_MIN of these hosts to the DNS
149 // servers detected, alternating in sequence.
150
151 // When a request is fulfilled (either a resolved domain, NXDomain,
152 // or confirmed ServFail) CAPACITY_UP_STEP is added to the current
153 // capacity of the server the request was found by.
154
155 // When a request times out and retries on the same server,
156 // the server's capacity is scaled by CAPACITY_MINOR_DOWN_STEP.
157
158 // When a request times out and moves to the next server in
159 // sequence, the server's capacity is scaled by CAPACITY_MAJOR_DOWN_STEP.
160
161 // mass_dns tries to maintain the current number of "outstanding
162 // queries" on each server to that of its current capacity. The
163 // packet is dropped if it cycles through all specified DNS
164 // servers.
165
166
167 // Since multiple DNS servers can be specified, different sequences
168 // of timers are maintained. These are the various retransmission
169 // intervals for each server before we move on to the next DNS server:
170
171 // In milliseconds
172 // Each row MUST be terminated with -1
173 static int read_timeouts[][4] = {
174 { 4000, 4000, 5000, -1 }, // 1 server
175 { 2500, 4000, -1, -1 }, // 2 servers
176 { 2500, 3000, -1, -1 }, // 3+ servers
177 };
178
179 #define CAPACITY_MIN 10
180 #define CAPACITY_MAX 200
181 #define CAPACITY_UP_STEP 2
182 #define CAPACITY_MINOR_DOWN_SCALE 0.9
183 #define CAPACITY_MAJOR_DOWN_SCALE 0.7
184
185 // Each request will try to resolve on at most this many servers:
186 #define SERVERS_TO_TRY 3
187
188
189 //------------------- Other Parameters ---------------------
190
191 // How often to display a short debugging summary if debugging is
192 // specified. Lower numbers means it's displayed more often.
193 #define SUMMARY_DELAY 50
194
195 // Minimum debugging level to display packet trace
196 #define TRACE_DEBUG_LEVEL 4
197
198 // The amount of time we wait for nsock_write() to complete before
199 // retransmission. This should almost never happen. (in milliseconds)
200 #define WRITE_TIMEOUT 100
201
202
203 //------------------- Internal Structures ---------------------
204
205 struct dns_server;
206 struct request;
207 typedef struct sockaddr_storage sockaddr_storage;
208
209 struct dns_server {
210 std::string hostname;
211 sockaddr_storage addr;
212 size_t addr_len;
213 nsock_iod nsd;
214 int connected;
215 int reqs_on_wire;
216 int capacity;
217 int write_busy;
218 std::list<request *> to_process;
219 std::list<request *> in_process;
220 };
221
222 struct request {
223 Target *targ;
224 struct timeval timeout;
225 int tries;
226 int servers_tried;
227 dns_server *first_server;
228 dns_server *curr_server;
229 u16 id;
230 };
231
232 /*keeps record of a request going through a particular DNS server
233 helps in attaining faster lookup based on ID */
234 struct info{
235 dns_server *server;
236 request *tpreq;
237 };
238
239 class HostElem
240 {
241 public:
HostElem(const std::string & name_,const sockaddr_storage & ip)242 HostElem(const std::string & name_, const sockaddr_storage & ip) :
243 name(name_), addr(ip), cache_hits(0) {}
~HostElem()244 ~HostElem() {}
245
246 /* Ages entries and return true with a cache hit of 0 (the least used) */
isTimeToClean(HostElem he)247 static bool isTimeToClean(HostElem he)
248 {
249 if(he.cache_hits)
250 {
251 he.cache_hits >>= 1;
252 return false;
253 }
254
255 return true;
256 }
257
258 const std::string name;
259 const sockaddr_storage addr;
260 u8 cache_hits;
261 };
262
263 class HostCacheLine : public std::list<HostElem>{};
264
265 class HostCache
266 {
267 public:
268 // TODO: avoid hardcode this constant
HostCache()269 HostCache() : lines_count(256), hash_mask(lines_count-1),
270 hosts_storage(new HostCacheLine[lines_count]), elements_count(0)
271 {}
~HostCache()272 ~HostCache()
273 {
274 delete[] hosts_storage;
275 }
276
hash(sockaddr_storage ip)277 u32 hash(sockaddr_storage ip)
278 {
279 u32 ret = 0;
280
281 switch (ip.ss_family)
282 {
283 case AF_INET:
284 {
285 u8 * ipv4 = (u8 *) &((const struct sockaddr_in *) &ip)->sin_addr;
286 // Shuffle bytes a little so we avoid awful performances in commons
287 // usages patterns like 10.0.1-255.1 and lines_count 256
288 ret = ipv4[0] + (ipv4[1]<<3) + (ipv4[2]<<5) + (ipv4[3]<<7);
289 break;
290 }
291 case AF_INET6:
292 {
293 const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *) &ip;
294 u32 * ipv6 = (u32 *) sa6->sin6_addr.s6_addr;
295 ret = ipv6[0] + ipv6[1] + ipv6[2] + ipv6[3];
296 break;
297 }
298 }
299
300 return ret & hash_mask;
301 }
302
303 /* Add to the dns cache. If there are too many entries
304 * we age and remove the least frequently used ones to
305 * make more space. */
add(const sockaddr_storage & ip,const std::string & hname)306 bool add( const sockaddr_storage & ip, const std::string & hname)
307 {
308 std::string discard;
309 if(lookup(ip, discard)) return false;
310
311 if(elements_count >= lines_count) prune();
312
313 HostElem he(hname, ip);
314 hosts_storage[hash(ip)].push_back(he);
315 ++elements_count;
316 return true;
317 }
318
prune()319 u32 prune()
320 {
321 u32 original_count = elements_count;
322 for(u32 i = 0; i < lines_count; ++i)
323 {
324 std::list<HostElem>::iterator it = find_if(hosts_storage[i].begin(),
325 hosts_storage[i].end(),
326 HostElem::isTimeToClean);
327 while ( it != hosts_storage[i].end() )
328 {
329 it = hosts_storage[i].erase(it);
330 assert(elements_count > 0);
331 --elements_count;
332 }
333 }
334
335 return original_count - elements_count;
336 }
337
338 /* Search for a hostname in the cache and increment
339 * its cache hit counter if found */
lookup(const sockaddr_storage & ip,std::string & name)340 bool lookup(const sockaddr_storage & ip, std::string & name)
341 {
342 std::list<HostElem>::iterator hostI;
343 u32 ip_hash = hash(ip);
344 for( hostI = hosts_storage[ip_hash].begin();
345 hostI != hosts_storage[ip_hash].end();
346 ++hostI)
347 {
348 if (sockaddr_storage_equal(&hostI->addr, &ip))
349 {
350 if(hostI->cache_hits < UCHAR_MAX)
351 hostI->cache_hits++;
352 name = hostI->name;
353 return true;
354 }
355 }
356 return false;
357 }
358
359 protected:
360 const u32 lines_count;
361 const u32 hash_mask;
362 HostCacheLine * const hosts_storage;
363 u32 elements_count;
364 };
365
366 //------------------- Globals ---------------------
367
368 u16 DNS::Factory::progressiveId = get_random_u16();
369 static std::list<dns_server> servs;
370 static std::list<request *> new_reqs;
371 static std::list<request *> deferred_reqs;
372 static std::map<u16, info> records;
373 static int total_reqs;
374 static nsock_pool dnspool=NULL;
375
376 /* The DNS cache, not just for entries from /etc/hosts. */
377 static HostCache host_cache;
378
379 static int stat_actual, stat_ok, stat_nx, stat_sf, stat_trans, stat_dropped, stat_cname;
380 static struct timeval starttv;
381 static int read_timeout_index;
382
383 static int firstrun=1;
384 static ScanProgressMeter *SPM;
385
386
387 //------------------- Prototypes and macros ---------------------
388 static void read_evt_handler(nsock_pool, nsock_event, void *);
389 static void put_dns_packet_on_wire(request *req);
390
391 #define ACTION_FINISHED 0
392 #define ACTION_SYSTEM_RESOLVE 1
393 #define ACTION_TIMEOUT 2
394
395 //------------------- Misc code ---------------------
396
output_summary()397 static void output_summary() {
398 int tp = stat_ok + stat_nx + stat_dropped;
399 struct timeval now;
400
401 memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
402
403 if (o.debugging && (tp%SUMMARY_DELAY == 0))
404 log_write(LOG_STDOUT, "mass_rdns: %.2fs %d/%d [#: %lu, OK: %d, NX: %d, DR: %d, SF: %d, TR: %d]\n",
405 TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
406 tp, stat_actual,
407 (unsigned long) servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans);
408 }
409
check_capacities(dns_server * tpserv)410 static void check_capacities(dns_server *tpserv) {
411 if (tpserv->capacity < CAPACITY_MIN) tpserv->capacity = CAPACITY_MIN;
412 if (tpserv->capacity > CAPACITY_MAX) tpserv->capacity = CAPACITY_MAX;
413 if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "CAPACITY <%s> = %d\n", tpserv->hostname.c_str(), tpserv->capacity);
414 }
415
416 // Closes all nsis created in connect_dns_servers()
close_dns_servers()417 static void close_dns_servers() {
418 std::list<dns_server>::iterator serverI;
419
420 for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
421 if (serverI->connected) {
422 nsock_iod_delete(serverI->nsd, NSOCK_PENDING_SILENT);
423 serverI->connected = 0;
424 serverI->to_process.clear();
425 serverI->in_process.clear();
426 }
427 }
428 }
429
430
431 // Puts as many packets on the line as capacity will allow
do_possible_writes()432 static void do_possible_writes() {
433 std::list<dns_server>::iterator servI;
434 request *tpreq;
435
436 for(servI = servs.begin(); servI != servs.end(); servI++) {
437 if (servI->write_busy == 0 && servI->reqs_on_wire < servI->capacity) {
438 tpreq = NULL;
439 if (!servI->to_process.empty()) {
440 tpreq = servI->to_process.front();
441 servI->to_process.pop_front();
442 } else if (!new_reqs.empty()) {
443 tpreq = new_reqs.front();
444 assert(tpreq != NULL);
445 tpreq->first_server = tpreq->curr_server = &*servI;
446 new_reqs.pop_front();
447 }
448
449 if (tpreq) {
450 if (o.debugging >= TRACE_DEBUG_LEVEL)
451 log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , servI->hostname.c_str());
452 stat_trans++;
453 put_dns_packet_on_wire(tpreq);
454 }
455 }
456 }
457 }
458
459 // nsock write handler
write_evt_handler(nsock_pool nsp,nsock_event evt,void * req_v)460 static void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v) {
461 info record;
462 request *req = (request *) req_v;
463
464 req->curr_server->write_busy = 0;
465
466 req->curr_server->in_process.push_front(req);
467 record.tpreq = req;
468 record.server = req->curr_server;
469 records[req->id] = record;
470
471 do_possible_writes();
472 }
473
474 // Takes a DNS request structure and actually puts it on the wire
475 // (calls nsock_write()). Does various other tasks like recording
476 // the time for the timeout.
put_dns_packet_on_wire(request * req)477 static void put_dns_packet_on_wire(request *req) {
478 const size_t maxlen = 512;
479 u8 packet[maxlen];
480 size_t plen=0;
481
482 struct timeval now, timeout;
483
484 req->id = DNS::Factory::progressiveId;
485 req->curr_server->write_busy = 1;
486 req->curr_server->reqs_on_wire++;
487
488 plen = DNS::Factory::buildReverseRequest(*req->targ->TargetSockAddr(), packet, maxlen);
489
490 memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
491 TIMEVAL_MSEC_ADD(timeout, now, read_timeouts[read_timeout_index][req->tries]);
492 memcpy(&req->timeout, &timeout, sizeof(struct timeval));
493
494 req->tries++;
495
496 nsock_write(dnspool, req->curr_server->nsd, write_evt_handler, WRITE_TIMEOUT, req, reinterpret_cast<const char *>(packet), plen);
497 }
498
499 // Processes DNS packets that have timed out
500 // Returns time until next read timeout
deal_with_timedout_reads()501 static int deal_with_timedout_reads() {
502 std::list<dns_server>::iterator servI;
503 std::list<dns_server>::iterator servItemp;
504 std::list<request *>::iterator reqI;
505 std::list<request *>::iterator nextI;
506 std::map<u16, info>::iterator infoI;
507 request *tpreq;
508 struct timeval now;
509 int tp, min_timeout = INT_MAX;
510
511 memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
512
513 if (keyWasPressed())
514 SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now);
515
516 for(servI = servs.begin(); servI != servs.end(); servI++) {
517 nextI = servI->in_process.begin();
518 if (nextI == servI->in_process.end()) continue;
519
520 do {
521 reqI = nextI++;
522 tpreq = *reqI;
523
524 tp = TIMEVAL_MSEC_SUBTRACT(tpreq->timeout, now);
525 if (tp > 0 && tp < min_timeout) min_timeout = tp;
526
527 if (tp <= 0) {
528 servI->capacity = (int) (servI->capacity * CAPACITY_MINOR_DOWN_SCALE);
529 check_capacities(&*servI);
530 servI->in_process.erase(reqI);
531 std::map<u16, info>::iterator it = records.find(tpreq->id);
532 if ( it != records.end() )
533 records.erase(it);
534 servI->reqs_on_wire--;
535
536 // If we've tried this server enough times, move to the next one
537 if (read_timeouts[read_timeout_index][tpreq->tries] == -1) {
538 servI->capacity = (int) (servI->capacity * CAPACITY_MAJOR_DOWN_SCALE);
539 check_capacities(&*servI);
540
541 servItemp = servI;
542 servItemp++;
543
544 if (servItemp == servs.end()) servItemp = servs.begin();
545
546 tpreq->curr_server = &*servItemp;
547 tpreq->tries = 0;
548 tpreq->servers_tried++;
549
550 if (tpreq->curr_server == tpreq->first_server || tpreq->servers_tried == SERVERS_TO_TRY) {
551 // Either give up on the IP
552 // or, for maximum reliability, put the server back into processing
553 // Note it's possible that this will never terminate.
554 // FIXME: Find a good compromise
555
556 // **** We've already tried all servers... give up
557 if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: *DR*OPPING <%s>\n", tpreq->targ->targetipstr());
558
559 output_summary();
560 stat_dropped++;
561 total_reqs--;
562 infoI = records.find(tpreq->id);
563 if ( infoI != records.end() )
564 records.erase(infoI);
565 delete tpreq;
566
567 // **** OR We start at the back of this server's queue
568 //servItemp->to_process.push_back(tpreq);
569 } else {
570 servItemp->to_process.push_back(tpreq);
571 }
572 } else {
573 servI->to_process.push_back(tpreq);
574 }
575
576 }
577
578 } while (nextI != servI->in_process.end());
579
580 }
581
582 if (min_timeout > 500) return 500;
583 else return min_timeout;
584
585 }
586
587 // After processing a DNS response, we search through the IPs we're
588 // looking for and update their results as necessary.
589 // Returns non-zero if this matches a query we're looking for
process_result(const sockaddr_storage & ip,const std::string & result,int action,u16 id)590 static int process_result(const sockaddr_storage &ip, const std::string &result, int action, u16 id)
591 {
592 request *tpreq;
593 std::map<u16, info>::iterator infoI;
594 dns_server *server;
595
596 infoI = records.find(id);
597
598 if( infoI != records.end() ){
599
600 tpreq = infoI->second.tpreq;
601 server = infoI->second.server;
602
603 if( !result.empty() && !sockaddr_storage_equal(&ip, tpreq->targ->TargetSockAddr()) )
604 return 0;
605
606 if (action == ACTION_SYSTEM_RESOLVE || action == ACTION_FINISHED)
607 {
608 server->capacity += CAPACITY_UP_STEP;
609 check_capacities(&*server);
610
611 if(!result.empty())
612 {
613 tpreq->targ->setHostName(result.c_str());
614 host_cache.add(* tpreq->targ->TargetSockAddr(), result);
615 }
616
617 records.erase(infoI);
618 server->in_process.remove(tpreq);
619 server->reqs_on_wire--;
620
621 total_reqs--;
622
623 if (action == ACTION_SYSTEM_RESOLVE) deferred_reqs.push_back(tpreq);
624 if (action == ACTION_FINISHED) delete tpreq;
625 }
626 else
627 {
628 memcpy(&tpreq->timeout, nsock_gettimeofday(), sizeof(struct timeval));
629 deal_with_timedout_reads();
630 }
631
632 do_possible_writes();
633
634 // Close DNS servers if we're all done so that we kill
635 // all events and return from nsock_loop immediateley
636 if (total_reqs == 0)
637 close_dns_servers();
638 return 1;
639 }
640 return 0;
641 }
642
643 // Nsock read handler. One nsock read for each DNS server exists at each
644 // time. This function uses various helper functions as defined above.
read_evt_handler(nsock_pool nsp,nsock_event evt,void *)645 static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *) {
646 u8 *buf;
647 int buflen;
648
649 if (total_reqs >= 1)
650 nsock_read(nsp, nse_iod(evt), read_evt_handler, -1, NULL);
651
652 if (nse_type(evt) != NSE_TYPE_READ || nse_status(evt) != NSE_STATUS_SUCCESS) {
653 if (o.debugging)
654 log_write(LOG_STDOUT, "mass_dns: warning: got a %s:%s in %s()\n",
655 nse_type2str(nse_type(evt)),
656 nse_status2str(nse_status(evt)), __func__);
657 return;
658 }
659
660 buf = (unsigned char *) nse_readbuf(evt, &buflen);
661
662 DNS::Packet p;
663 size_t readed_bytes = p.parseFromBuffer(buf, buflen);
664 if(readed_bytes < DNS::DATA) return;
665
666 // We should have 1+ queries:
667 u16 &f = p.flags;
668 if(p.queries.empty() || !DNS_HAS_FLAG(f, DNS::RESPONSE) ||
669 !DNS_HAS_FLAG(f, DNS::OP_STANDARD_QUERY) ||
670 (f & DNS::ZERO) || DNS_HAS_ERR(f, DNS::ERR_FORMAT) ||
671 DNS_HAS_ERR(f, DNS::ERR_NOT_IMPLEMENTED) || DNS_HAS_ERR(f, DNS::ERR_REFUSED))
672 return;
673
674 if (DNS_HAS_ERR(f, DNS::ERR_NAME))
675 {
676 sockaddr_storage discard;
677 if(process_result(discard, "", ACTION_FINISHED, p.id))
678 {
679 if (o.debugging >= TRACE_DEBUG_LEVEL)
680 log_write(LOG_STDOUT, "mass_rdns: NXDOMAIN <id = %d>\n", p.id);
681 output_summary();
682 stat_nx++;
683 }
684
685 return;
686 }
687
688 if (DNS_HAS_ERR(f, DNS::ERR_SERVFAIL))
689 {
690 sockaddr_storage discard;
691 if (process_result(discard, "", ACTION_TIMEOUT, p.id))
692 {
693 if (o.debugging >= TRACE_DEBUG_LEVEL)
694 log_write(LOG_STDOUT, "mass_rdns: SERVFAIL <id = %d>\n", p.id);
695 stat_sf++;
696 }
697
698 return;
699 }
700
701 bool processing_successful = false;
702
703 sockaddr_storage ip;
704 ip.ss_family = AF_UNSPEC;
705 std::string alias;
706
707 for(std::list<DNS::Answer>::const_iterator it = p.answers.begin();
708 it != p.answers.end() && !processing_successful; ++it )
709 {
710 const DNS::Answer &a = *it;
711 if(a.record_class == DNS::CLASS_IN)
712 {
713 switch(a.record_type)
714 {
715 case DNS::PTR:
716 {
717 DNS::PTR_Record * ptr = static_cast<DNS::PTR_Record *>(a.record);
718
719 if(
720 // If CNAME answer filled in ip with a matching alias
721 (ip.ss_family != AF_UNSPEC && a.name == alias )
722 // Or if we can get an IP from reversing the .arpa PTR address
723 || DNS::Factory::ptrToIp(a.name, ip))
724 {
725 if ((processing_successful = process_result(ip, ptr->value, ACTION_FINISHED, p.id)))
726 {
727 if (o.debugging >= TRACE_DEBUG_LEVEL)
728 {
729 char ipstr[INET6_ADDRSTRLEN];
730 sockaddr_storage_iptop(&ip, ipstr);
731 log_write(LOG_STDOUT, "mass_rdns: OK MATCHED <%s> to <%s>\n",
732 ipstr,
733 ptr->value.c_str());
734 }
735 output_summary();
736 stat_ok++;
737 }
738 }
739 break;
740 }
741 case DNS::CNAME:
742 {
743 if(DNS::Factory::ptrToIp(a.name, ip))
744 {
745 DNS::CNAME_Record * cname = static_cast<DNS::CNAME_Record *>(a.record);
746 alias = cname->value;
747 if (o.debugging >= TRACE_DEBUG_LEVEL)
748 {
749 char ipstr[INET6_ADDRSTRLEN];
750 sockaddr_storage_iptop(&ip, ipstr);
751 log_write(LOG_STDOUT, "mass_rdns: CNAME found for <%s> to <%s>\n", ipstr, alias.c_str());
752 }
753 }
754 break;
755 }
756 default:
757 break;
758 }
759 }
760 }
761
762 if (!processing_successful) {
763 if (DNS_HAS_FLAG(f, DNS::TRUNCATED)) {
764 // TODO: TCP fallback, or only use system resolver if user didn't specify --dns-servers
765 process_result(ip, "", ACTION_SYSTEM_RESOLVE, p.id);
766 }
767 else if (!alias.empty()) {
768 if (o.debugging >= TRACE_DEBUG_LEVEL)
769 {
770 char ipstr[INET6_ADDRSTRLEN];
771 sockaddr_storage_iptop(&ip, ipstr);
772 log_write(LOG_STDOUT, "mass_rdns: CNAME for <%s> not processed.\n", ipstr);
773 }
774 // TODO: Send a PTR request for alias instead. Meanwhile, we'll just fall
775 // back to using system resolver. Alternative: report the canonical name
776 // (alias), but that's not very useful.
777 process_result(ip, "", ACTION_SYSTEM_RESOLVE, p.id);
778 }
779 else {
780 if (o.debugging >= TRACE_DEBUG_LEVEL) {
781 log_write(LOG_STDOUT, "mass_rdns: Unable to process the response\n");
782 }
783 }
784 }
785 }
786
787
788 // nsock connect handler - Empty because it doesn't really need to do anything...
connect_evt_handler(nsock_pool,nsock_event,void *)789 static void connect_evt_handler(nsock_pool, nsock_event, void *) {}
790
791
792 // Adds DNS servers to the dns_server list. They can be separated by
793 // commas or spaces - NOTE this doesn't actually do any connecting!
add_dns_server(char * ipaddrs)794 static void add_dns_server(char *ipaddrs) {
795 std::list<dns_server>::iterator servI;
796 char *hostname;
797 struct sockaddr_storage addr;
798 size_t addr_len = sizeof(addr);
799
800 for (hostname = strtok(ipaddrs, " ,"); hostname != NULL; hostname = strtok(NULL, " ,")) {
801
802 if (resolve(hostname, 0, (struct sockaddr_storage *) &addr, &addr_len,
803 o.spoofsource ? o.af() : PF_UNSPEC) != 0)
804 continue;
805
806 for(servI = servs.begin(); servI != servs.end(); servI++) {
807 // Already added!
808 if (memcmp(&addr, &servI->addr, sizeof(addr)) == 0) break;
809 }
810
811 // If it hasn't already been added, add it!
812 if (servI == servs.end()) {
813 dns_server tpserv;
814
815 tpserv.hostname = hostname;
816 memcpy(&tpserv.addr, &addr, sizeof(addr));
817 tpserv.addr_len = addr_len;
818
819 servs.push_front(tpserv);
820
821 if (o.debugging) log_write(LOG_STDOUT, "mass_rdns: Using DNS server %s\n", hostname);
822 }
823
824 }
825
826 }
827
828 // Creates a new nsi for each DNS server
connect_dns_servers()829 static void connect_dns_servers() {
830 std::list<dns_server>::iterator serverI;
831 for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
832 serverI->nsd = nsock_iod_new(dnspool, NULL);
833 if (o.spoofsource) {
834 struct sockaddr_storage ss;
835 size_t sslen;
836 o.SourceSockAddr(&ss, &sslen);
837 nsock_iod_set_localaddr(serverI->nsd, &ss, sslen);
838 }
839 if (o.ipoptionslen)
840 nsock_iod_set_ipoptions(serverI->nsd, o.ipoptions, o.ipoptionslen);
841 serverI->reqs_on_wire = 0;
842 serverI->capacity = CAPACITY_MIN;
843 serverI->write_busy = 0;
844
845 nsock_connect_udp(dnspool, serverI->nsd, connect_evt_handler, NULL, (struct sockaddr *) &serverI->addr, serverI->addr_len, 53);
846 nsock_read(dnspool, serverI->nsd, read_evt_handler, -1, NULL);
847 serverI->connected = 1;
848 }
849
850 }
851
852
853 #ifdef WIN32
interface_is_known_by_guid(const char * guid)854 static bool interface_is_known_by_guid(const char *guid) {
855 struct interface_info *iflist;
856 int i, n;
857
858 iflist = getinterfaces(&n, NULL, 0);
859 if (iflist == NULL)
860 return false;
861
862 for (i = 0; i < n; i++) {
863 char pcap_name[1024];
864 char *pcap_guid;
865
866 if (!DnetName2PcapName(iflist[i].devname, pcap_name, sizeof(pcap_name)))
867 continue;
868 pcap_guid = strchr(pcap_name, '{');
869 if (pcap_guid == NULL)
870 continue;
871 if (strcasecmp(guid, pcap_guid) == 0)
872 return true;
873 }
874
875 return false;
876 }
877
878 // Reads the Windows registry and adds all the nameservers found via the
879 // add_dns_server() function.
win32_read_registry()880 void win32_read_registry() {
881 HKEY hKey;
882 HKEY hKey2;
883 char keybasebuf[2048];
884 char buf[2048], keyname[2048], *p;
885 DWORD sz, i;
886
887 Snprintf(keybasebuf, sizeof(keybasebuf), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters");
888 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keybasebuf,
889 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
890 if (firstrun) error("mass_dns: warning: Error opening registry to read DNS servers. Try using --system-dns or specify valid servers with --dns-servers");
891 return;
892 }
893
894 sz = sizeof(buf);
895 if (RegQueryValueEx(hKey, "NameServer", NULL, NULL, (LPBYTE) buf, (LPDWORD) &sz) == ERROR_SUCCESS)
896 add_dns_server(buf);
897
898 sz = sizeof(buf);
899 if (RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE) buf, (LPDWORD) &sz) == ERROR_SUCCESS)
900 add_dns_server(buf);
901
902 RegCloseKey(hKey);
903
904 Snprintf(keybasebuf, sizeof(keybasebuf), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces");
905 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keybasebuf,
906 0, KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS) {
907
908 for (i=0; sz = sizeof(buf), RegEnumKeyEx(hKey, i, buf, &sz, NULL, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS; i++) {
909
910 // If we don't have pcap, interface_is_known_by_guid will crash. Just use any servers we can find.
911 if (o.have_pcap && !interface_is_known_by_guid(buf)) {
912 if (o.debugging > 1)
913 log_write(LOG_PLAIN, "Interface %s is not known; ignoring its nameservers.\n", buf);
914 continue;
915 }
916
917 Snprintf(keyname, sizeof(keyname), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s", buf);
918
919 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname,
920 0, KEY_READ, &hKey2) == ERROR_SUCCESS) {
921
922 sz = sizeof(buf);
923 if (RegQueryValueEx(hKey2, "DhcpNameServer", NULL, NULL, (LPBYTE) buf, (LPDWORD) &sz) == ERROR_SUCCESS)
924 add_dns_server(buf);
925
926 sz = sizeof(buf);
927 if (RegQueryValueEx(hKey2, "NameServer", NULL, NULL, (LPBYTE) buf, (LPDWORD) &sz) == ERROR_SUCCESS)
928 add_dns_server(buf);
929
930 RegCloseKey(hKey2);
931 }
932 }
933
934 RegCloseKey(hKey);
935
936 }
937
938 }
939 #endif // WIN32
940
941
942
943 // Parses /etc/resolv.conf (unix) and adds all the nameservers found via the
944 // add_dns_server() function.
parse_resolvdotconf()945 static void parse_resolvdotconf() {
946 FILE *fp;
947 char buf[2048], *tp;
948 char fmt[32];
949 char ipaddr[INET6_ADDRSTRLEN+1];
950
951 fp = fopen("/etc/resolv.conf", "r");
952 if (fp == NULL) {
953 if (firstrun) error("mass_dns: warning: Unable to open /etc/resolv.conf. Try using --system-dns or specify valid servers with --dns-servers");
954 return;
955 }
956
957 Snprintf(fmt, sizeof(fmt), "nameserver %%%us", INET6_ADDRSTRLEN);
958
959 while (fgets(buf, sizeof(buf), fp)) {
960 tp = buf;
961
962 // Clip off comments #, \r, \n
963 while (*tp != '\r' && *tp != '\n' && *tp != '#' && *tp) tp++;
964 *tp = '\0';
965
966 tp = buf;
967 // Skip any leading whitespace
968 while (*tp == ' ' || *tp == '\t') tp++;
969
970 if (sscanf(tp, fmt, ipaddr) == 1) add_dns_server(ipaddr);
971 }
972
973 fclose(fp);
974 }
975
976
parse_etchosts(const char * fname)977 static void parse_etchosts(const char *fname) {
978 FILE *fp;
979 char buf[2048], hname[256], ipaddrstr[INET6_ADDRSTRLEN+1], *tp;
980 sockaddr_storage ia;
981
982 fp = fopen(fname, "r");
983 if (fp == NULL) return; // silently is OK
984
985 while (fgets(buf, sizeof(buf), fp)) {
986 tp = buf;
987
988 // Clip off comments #, \r, \n
989 while (*tp != '\r' && *tp != '\n' && *tp != '#' && *tp) tp++;
990 *tp = '\0';
991
992 tp = buf;
993 // Skip any leading whitespace
994 while (*tp == ' ' || *tp == '\t') tp++;
995
996 std::stringstream pattern;
997 pattern << "%" << INET6_ADDRSTRLEN << "s %255s";
998 if (sscanf(tp, pattern.str().c_str(), ipaddrstr, hname) == 2)
999 if (sockaddr_storage_inet_pton(ipaddrstr, &ia))
1000 {
1001 const std::string hname_ = hname;
1002 host_cache.add(ia, hname_);
1003 }
1004 }
1005
1006 fclose(fp);
1007 }
1008
etchosts_init(void)1009 static void etchosts_init(void) {
1010 static int initialized = 0;
1011 if (initialized) return;
1012 initialized = 1;
1013
1014 #ifdef WIN32
1015 char windows_dir[1024];
1016 char tpbuf[2048];
1017 int has_backslash;
1018
1019 if (!GetWindowsDirectory(windows_dir, sizeof(windows_dir)))
1020 fatal("Failed to determine your windows directory");
1021
1022 // If it has a backslash it's C:\, otherwise something like C:\WINNT
1023 has_backslash = (windows_dir[strlen(windows_dir)-1] == '\\');
1024
1025 // Windows 95/98/Me:
1026 Snprintf(tpbuf, sizeof(tpbuf), "%s%shosts", windows_dir, has_backslash ? "" : "\\");
1027 parse_etchosts(tpbuf);
1028
1029 // Windows NT/2000/XP/2K3:
1030 Snprintf(tpbuf, sizeof(tpbuf), "%s%ssystem32\\drivers\\etc\\hosts", windows_dir, has_backslash ? "" : "\\");
1031 parse_etchosts(tpbuf);
1032
1033 #else
1034 parse_etchosts("/etc/hosts");
1035 #endif // WIN32
1036 }
1037
1038 /* Initialize the global servs list of DNS servers. If the --dns-servers option
1039 * was given, use the listed servers; otherwise get the list from resolv.conf or
1040 * the Windows registry. If o.mass_dns is false, the list of servers is empty.
1041 * This function caches the results from the first time it is run. */
init_servs(void)1042 static void init_servs(void) {
1043 static bool initialized = false;
1044
1045 if (initialized)
1046 return;
1047
1048 initialized = true;
1049
1050 if (!o.mass_dns)
1051 return;
1052
1053 if (o.dns_servers) {
1054 add_dns_server(o.dns_servers);
1055 } else {
1056 #ifndef WIN32
1057 parse_resolvdotconf();
1058 #else
1059 win32_read_registry();
1060 #endif
1061 }
1062 }
1063
1064 //------------------- Main loops ---------------------
1065
1066
1067 // Actual main loop
nmap_mass_rdns_core(Target ** targets,int num_targets)1068 static void nmap_mass_rdns_core(Target **targets, int num_targets) {
1069
1070 Target **hostI;
1071 std::list<request *>::iterator reqI;
1072 request *tpreq;
1073 int timeout;
1074 const char *tpname;
1075 int i;
1076 char spmobuf[1024];
1077
1078 // If necessary, set up the dns server list
1079 init_servs();
1080
1081 if (servs.size() == 0 && firstrun) error("mass_dns: warning: Unable to "
1082 "determine any DNS servers. Reverse"
1083 " DNS is disabled. Try using "
1084 "--system-dns or specify valid "
1085 "servers with --dns-servers");
1086
1087
1088 // If necessary, read /etc/hosts and put entries into the hashtable
1089 etchosts_init();
1090
1091
1092 total_reqs = 0;
1093
1094 // Set up the request structure
1095 for(hostI = targets; hostI < targets+num_targets; hostI++)
1096 {
1097 if (!((*hostI)->flags & HOST_UP) && !o.always_resolve) continue;
1098
1099 // See if it's cached
1100 std::string res;
1101 if (host_cache.lookup(*(*hostI)->TargetSockAddr(), res)) {
1102 tpname = res.c_str();
1103 (*hostI)->setHostName(tpname);
1104 continue;
1105 }
1106
1107 tpreq = new request;
1108 tpreq->targ = *hostI;
1109 tpreq->tries = 0;
1110 tpreq->servers_tried = 0;
1111
1112 new_reqs.push_back(tpreq);
1113
1114 stat_actual++;
1115 total_reqs++;
1116 }
1117
1118 if (total_reqs == 0 || servs.size() == 0) return;
1119
1120 // And finally, do it!
1121
1122 if ((dnspool = nsock_pool_new(NULL)) == NULL)
1123 fatal("Unable to create nsock pool in %s()", __func__);
1124
1125 nmap_set_nsock_logger();
1126 nmap_adjust_loglevel(o.packetTrace());
1127
1128 nsock_pool_set_device(dnspool, o.device);
1129
1130 if (o.proxy_chain)
1131 nsock_pool_set_proxychain(dnspool, o.proxy_chain);
1132
1133 connect_dns_servers();
1134
1135 deferred_reqs.clear();
1136
1137 read_timeout_index = MIN(sizeof(read_timeouts)/sizeof(read_timeouts[0]), servs.size()) - 1;
1138
1139 Snprintf(spmobuf, sizeof(spmobuf), "Parallel DNS resolution of %d host%s.", stat_actual, stat_actual-1 ? "s" : "");
1140 SPM = new ScanProgressMeter(spmobuf);
1141
1142 while (total_reqs > 0) {
1143 timeout = deal_with_timedout_reads();
1144
1145 do_possible_writes();
1146
1147 if (total_reqs <= 0) break;
1148
1149 /* Because this can change with runtime interaction */
1150 nmap_adjust_loglevel(o.packetTrace());
1151
1152 nsock_loop(dnspool, timeout);
1153 }
1154
1155 SPM->endTask(NULL, NULL);
1156 delete SPM;
1157
1158 close_dns_servers();
1159
1160 nsock_pool_delete(dnspool);
1161
1162 if (deferred_reqs.size() && o.debugging)
1163 log_write(LOG_STDOUT, "Performing system-dns for %d domain names that were deferred\n", (int) deferred_reqs.size());
1164
1165 if (deferred_reqs.size()) {
1166 Snprintf(spmobuf, sizeof(spmobuf), "System DNS resolution of %u host%s.", (unsigned) deferred_reqs.size(), deferred_reqs.size()-1 ? "s" : "");
1167 SPM = new ScanProgressMeter(spmobuf);
1168
1169 for(i=0, reqI = deferred_reqs.begin(); reqI != deferred_reqs.end(); reqI++, i++) {
1170 struct sockaddr_storage ss;
1171 size_t sslen;
1172 char hostname[FQDN_LEN + 1] = "";
1173
1174 if (keyWasPressed())
1175 SPM->printStats((double) i / deferred_reqs.size(), NULL);
1176
1177 tpreq = *reqI;
1178
1179 if (tpreq->targ->TargetSockAddr(&ss, &sslen) != 0)
1180 fatal("Failed to get target socket address.");
1181
1182 if (getnameinfo((struct sockaddr *)&ss, sslen, hostname,
1183 sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
1184 stat_ok++;
1185 stat_cname++;
1186 tpreq->targ->setHostName(hostname);
1187 }
1188
1189 delete tpreq;
1190
1191 }
1192
1193 SPM->endTask(NULL, NULL);
1194 delete SPM;
1195 }
1196
1197 deferred_reqs.clear();
1198
1199 }
1200
nmap_system_rdns_core(Target ** targets,int num_targets)1201 static void nmap_system_rdns_core(Target **targets, int num_targets) {
1202 Target **hostI;
1203 Target *currenths;
1204 struct sockaddr_storage ss;
1205 size_t sslen;
1206 char hostname[FQDN_LEN + 1] = "";
1207 char spmobuf[1024];
1208 int i;
1209
1210 for(hostI = targets; hostI < targets+num_targets; hostI++) {
1211 currenths = *hostI;
1212
1213 if (((currenths->flags & HOST_UP) || o.always_resolve) && !o.noresolve) stat_actual++;
1214 }
1215
1216 Snprintf(spmobuf, sizeof(spmobuf), "System DNS resolution of %d host%s.", stat_actual, stat_actual-1 ? "s" : "");
1217 SPM = new ScanProgressMeter(spmobuf);
1218
1219 for(i=0, hostI = targets; hostI < targets+num_targets; hostI++, i++) {
1220 currenths = *hostI;
1221
1222 if (keyWasPressed())
1223 SPM->printStats((double) i / stat_actual, NULL);
1224
1225 if (((currenths->flags & HOST_UP) || o.always_resolve) && !o.noresolve) {
1226 if (currenths->TargetSockAddr(&ss, &sslen) != 0)
1227 fatal("Failed to get target socket address.");
1228 if (getnameinfo((struct sockaddr *)&ss, sslen, hostname,
1229 sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
1230 stat_ok++;
1231 currenths->setHostName(hostname);
1232 }
1233 }
1234 }
1235
1236 SPM->endTask(NULL, NULL);
1237 delete SPM;
1238 }
1239
1240
1241 // Publicly available function. Basically just a wrapper so we
1242 // can record time information, restart statistics, etc.
nmap_mass_rdns(Target ** targets,int num_targets)1243 void nmap_mass_rdns(Target **targets, int num_targets) {
1244
1245 struct timeval now;
1246
1247 gettimeofday(&starttv, NULL);
1248
1249 stat_actual = stat_ok = stat_nx = stat_sf = stat_trans = stat_dropped = stat_cname = 0;
1250
1251 if (o.mass_dns)
1252 nmap_mass_rdns_core(targets, num_targets);
1253 else
1254 nmap_system_rdns_core(targets, num_targets);
1255
1256 gettimeofday(&now, NULL);
1257
1258 if (stat_actual > 0) {
1259 if (o.debugging || o.verbose >= 3) {
1260 if (o.mass_dns) {
1261 // #: Number of DNS servers used
1262 // OK: Number of fully reverse resolved queries
1263 // NX: Number of confirmations of 'No such reverse domain eXists'
1264 // DR: Dropped IPs (no valid responses were received)
1265 // SF: Number of IPs that got 'Server Failure's
1266 // TR: Total number of transmissions necessary. The number of domains is ideal, higher is worse
1267 log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: Async [#: %lu, OK: %d, NX: %d, DR: %d, SF: %d, TR: %d, CN: %d]\n",
1268 stat_actual, TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
1269 (unsigned long) servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans, stat_cname);
1270 } else {
1271 log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: System [OK: %d, ??: %d]\n",
1272 stat_actual, TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
1273 stat_ok, stat_actual - stat_ok);
1274 }
1275 }
1276 }
1277
1278 firstrun=0;
1279 }
1280
1281
1282 // Returns a list of known DNS servers
get_dns_servers()1283 std::list<std::string> get_dns_servers() {
1284 init_servs();
1285
1286 // If the user said --system-dns (!o.mass_dns), we should never return a list
1287 // of servers.
1288 assert(o.mass_dns || servs.empty());
1289
1290 std::list<dns_server>::iterator servI;
1291 std::list<std::string> serverList;
1292 for(servI = servs.begin(); servI != servs.end(); servI++) {
1293 serverList.push_back(inet_socktop((struct sockaddr_storage *) &servI->addr));
1294 }
1295 return serverList;
1296 }
1297
ipToPtr(const sockaddr_storage & ip,std::string & ptr)1298 bool DNS::Factory::ipToPtr(const sockaddr_storage &ip, std::string &ptr)
1299 {
1300 switch (ip.ss_family) {
1301 case AF_INET:
1302 {
1303 ptr.clear();
1304 char ipv4_c[INET_ADDRSTRLEN];
1305 if(!sockaddr_storage_iptop(&ip, ipv4_c)) return false;
1306
1307 std::string ipv4 = ipv4_c;
1308 std::string octet;
1309 std::string::const_reverse_iterator crend = ipv4.rend();
1310 for (std::string::const_reverse_iterator c=ipv4.rbegin(); c != crend; ++c)
1311 if((*c)=='.')
1312 {
1313 ptr += octet + ".";
1314 octet.clear();
1315 }
1316 else
1317 octet = (*c) + octet;
1318
1319 ptr += octet + IPV4_PTR_DOMAIN;
1320
1321 break;
1322 }
1323 case AF_INET6:
1324 {
1325 ptr.clear();
1326 const struct sockaddr_in6 &s6 = (const struct sockaddr_in6 &) ip;
1327 const u8 * ipv6 = s6.sin6_addr.s6_addr;
1328 for (short i=15; i>=0; --i)
1329 {
1330 char tmp[3];
1331 sprintf(tmp, "%02x", ipv6[i]);
1332 ptr += '.';
1333 ptr += tmp[1];
1334 ptr += '.';
1335 ptr += tmp[0];
1336 }
1337 ptr.erase(ptr.begin());
1338 ptr += IPV6_PTR_DOMAIN;
1339 break;
1340 }
1341 default:
1342 return false;
1343 }
1344 return true;
1345 }
1346
ptrToIp(const std::string & ptr,sockaddr_storage & ip)1347 bool DNS::Factory::ptrToIp(const std::string &ptr, sockaddr_storage &ip)
1348 {
1349 const char *cptr = ptr.c_str();
1350 const char *p = NULL;
1351
1352 memset(&ip, 0, sizeof(sockaddr_storage));
1353
1354 // Check whether the name ends with the IPv4 PTR domain
1355 if (NULL != (p = strcasestr(cptr + ptr.length() + 1 - sizeof(C_IPV4_PTR_DOMAIN), C_IPV4_PTR_DOMAIN)))
1356 {
1357 struct sockaddr_in *ip4 = (struct sockaddr_in *)&ip;
1358 u8 place_value[] = {1, 10, 100};
1359 u8 *v = (u8 *) &(ip4->sin_addr.s_addr);
1360 size_t place = 0;
1361 size_t i = 0;
1362
1363 p--;
1364 while (i < sizeof(ip4->sin_addr.s_addr))
1365 {
1366 if (*p == '.')
1367 {
1368 place = 0;
1369 p--;
1370 i++;
1371 }
1372 if (p < cptr)
1373 {
1374 break;
1375 }
1376 u8 n = *p;
1377 if (n >= '0' && n <= '9') { // 0-9
1378 n -= 0x30;
1379 }
1380 else { // invalid
1381 return false;
1382 }
1383 v[i] += n * place_value[place];
1384 place++;
1385 p--;
1386 }
1387 ip.ss_family = AF_INET;
1388 }
1389 // If not, check IPv6
1390 else if (NULL != (p = strcasestr(cptr + ptr.length() + 1 - sizeof(C_IPV6_PTR_DOMAIN), C_IPV6_PTR_DOMAIN)))
1391 {
1392 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&ip;
1393 u8 alt = 0;
1394 size_t i=0;
1395
1396 p--;
1397 while (i < sizeof(ip6->sin6_addr.s6_addr))
1398 {
1399 if (*p == '.')
1400 {
1401 p--;
1402 }
1403 if (p < cptr)
1404 {
1405 break;
1406 }
1407 u8 n = *p;
1408 // First subtract base regardless of underflow:
1409 if (n < 0x3A) { // 0-9
1410 n -= 0x30;
1411 }
1412 else if (n < 0x47) { // A-F
1413 n -= 0x37;
1414 }
1415 else if (n < 0x67) { // a-f
1416 n -= 0x57;
1417 }
1418 else { // invalid
1419 return false;
1420 }
1421 // Now catch any of the underflow conditions above:
1422 if (n > 0xf) { // invalid
1423 return false;
1424 }
1425 if (alt == 0) { // high nibble
1426 ip6->sin6_addr.s6_addr[i] += n << 4;
1427 alt = 1;
1428 }
1429 else { // low nibble
1430 ip6->sin6_addr.s6_addr[i] += n;
1431 alt = 0;
1432 i++;
1433 }
1434 p--;
1435 }
1436 ip.ss_family = AF_INET6;
1437 }
1438 return true;
1439 }
1440
buildSimpleRequest(const std::string & name,RECORD_TYPE rt,u8 * buf,size_t maxlen)1441 size_t DNS::Factory::buildSimpleRequest(const std::string &name, RECORD_TYPE rt, u8 *buf, size_t maxlen)
1442 {
1443 size_t ret=0 , tmp=0;
1444 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(progressiveId++, buf, ID, maxlen)); // Postincrement inmportant here
1445 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(OP_STANDARD_QUERY | RECURSION_DESIRED, buf, FLAGS_OFFSET, maxlen));
1446 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(1, buf, QDCOUNT, maxlen));
1447 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(0, buf, ANCOUNT, maxlen));
1448 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(0, buf, NSCOUNT, maxlen));
1449 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(0, buf, ARCOUNT, maxlen));
1450 DNS_CHECK_ACCUMLATE(ret, tmp, putDomainName(name, buf, DATA, maxlen));
1451 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(rt, buf, ret, maxlen));
1452 DNS_CHECK_ACCUMLATE(ret, tmp, putUnsignedShort(CLASS_IN, buf, ret, maxlen));
1453
1454 return ret;
1455 }
1456
buildReverseRequest(const sockaddr_storage & ip,u8 * buf,size_t maxlen)1457 size_t DNS::Factory::buildReverseRequest(const sockaddr_storage &ip, u8 *buf, size_t maxlen)
1458 {
1459 std::string name;
1460 if(ipToPtr(ip,name))
1461 return buildSimpleRequest(name, PTR, buf, maxlen);
1462 return 0;
1463 }
1464
putUnsignedShort(u16 num,u8 * buf,size_t offset,size_t maxlen)1465 size_t DNS::Factory::putUnsignedShort(u16 num, u8 *buf, size_t offset, size_t maxlen)
1466 {
1467 size_t max_access = offset+1;
1468 if(buf && (maxlen > max_access))
1469 {
1470 buf[offset] = (num >> 8) & 0xFF;
1471 buf[max_access] = num & 0xFF;
1472 return 2;
1473 }
1474
1475 return 0;
1476 }
1477
putDomainName(const std::string & name,u8 * buf,size_t offset,size_t maxlen)1478 size_t DNS::Factory::putDomainName(const std::string &name, u8 *buf, size_t offset, size_t maxlen)
1479 {
1480 size_t ret=0;
1481 if( !( buf && (maxlen > (offset + name.length() + 1))) ) return ret;
1482
1483 std::string namew = name + ".";
1484 std::string accumulator;
1485 for (std::string::const_iterator c=namew.begin(); c != namew.end(); ++c)
1486 {
1487 if((*c)=='.')
1488 {
1489 u8 length = accumulator.length();
1490 *(buf+offset+ret) = length;
1491 ret += 1;
1492
1493 memcpy(buf+offset+ret, accumulator.c_str(), length);
1494 ret += length;
1495 accumulator.clear();
1496 }
1497 else
1498 accumulator += (*c);
1499 }
1500
1501 *(buf+offset+ret) = 0;
1502 ret += 1;
1503
1504 return ret;
1505 }
1506
parseUnsignedShort(u16 & num,const u8 * buf,size_t offset,size_t maxlen)1507 size_t DNS::Factory::parseUnsignedShort(u16 &num, const u8 *buf, size_t offset, size_t maxlen)
1508 {
1509 size_t max_access = offset+1;
1510 if(buf && (maxlen > max_access))
1511 {
1512 const u8 * n = buf + offset;
1513 num = n[1] + (n[0]<<8);
1514 return 2;
1515 }
1516
1517 return 0;
1518 }
1519
parseUnsignedInt(u32 & num,const u8 * buf,size_t offset,size_t maxlen)1520 size_t DNS::Factory::parseUnsignedInt(u32 &num, const u8 *buf, size_t offset, size_t maxlen)
1521 {
1522 size_t max_access = offset+3;
1523 if(buf && (maxlen > max_access))
1524 {
1525 const u8 * n = buf + offset;
1526 num = n[3] + (n[2]<<8) + (n[1]<<16) + (n[0]<<24);
1527 return 4;
1528 }
1529
1530 return 0;
1531 }
1532
parseDomainName(std::string & name,const u8 * buf,size_t offset,size_t maxlen)1533 size_t DNS::Factory::parseDomainName(std::string &name, const u8 *buf, size_t offset, size_t maxlen)
1534 {
1535 size_t tmp, ret = 0;
1536
1537 name.clear();
1538 while(u8 label_length = buf[offset+ret++]) // Postincrement important here
1539 {
1540 if((label_length & COMPRESSED_NAME) == COMPRESSED_NAME)
1541 {
1542 --ret; // The byte it's part of the pointer, wasn't really consumed yet
1543 u16 real_offset;
1544 DNS_CHECK_ACCUMLATE(ret, tmp, parseUnsignedShort(real_offset, buf, offset+ret, maxlen));
1545 real_offset -= COMPRESSED_NAME<<8;
1546 if( real_offset < offset)
1547 {
1548 std::string val;
1549 DNS_CHECK_ACCUMLATE(tmp, tmp, parseDomainName(val, buf, real_offset, maxlen));
1550 name+=val;
1551 return ret;
1552 }
1553 else return 0;
1554 }
1555
1556 for(u8 i=0; i<label_length; ++i)
1557 {
1558 size_t index = offset+ret++; // Postincrement important here
1559 DNS_CHECK_UPPER_BOUND(index, maxlen);
1560 name += buf[index];
1561 }
1562 name += '.';
1563 }
1564
1565 std::string::iterator it = name.end()-1;
1566 if( *it == '.') name.erase(it);
1567
1568 return ret;
1569 }
1570
parseFromBuffer(const u8 * buf,size_t offset,size_t maxlen)1571 size_t DNS::A_Record::parseFromBuffer(const u8 *buf, size_t offset, size_t maxlen)
1572 {
1573 size_t tmp, ret = 0;
1574 u32 num;
1575 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedInt(num, buf, offset, maxlen));
1576
1577 memset(&value, 0, sizeof(value));
1578 struct sockaddr_in * ip4addr = (sockaddr_in *) &value;
1579 ip4addr->sin_family = AF_INET;
1580 ip4addr->sin_addr.s_addr = htonl(num);
1581
1582 return ret;
1583 }
1584
parseFromBuffer(const u8 * buf,size_t offset,size_t maxlen)1585 size_t DNS::Query::parseFromBuffer(const u8 *buf, size_t offset, size_t maxlen)
1586 {
1587 size_t ret=0;
1588
1589 if (buf && ((maxlen - offset) > 5))
1590 {
1591 size_t tmp=0;
1592 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseDomainName(name, buf, offset+ret, maxlen));
1593 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(record_type, buf, offset+ret, maxlen));
1594 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(record_class, buf, offset+ret, maxlen));
1595 }
1596
1597 return ret;
1598 }
1599
parseFromBuffer(const u8 * buf,size_t offset,size_t maxlen)1600 size_t DNS::Answer::parseFromBuffer(const u8 *buf, size_t offset, size_t maxlen)
1601 {
1602 size_t ret=0;
1603
1604 if (buf && ((maxlen - offset) > 7))
1605 {
1606 size_t tmp;
1607 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseDomainName(name, buf, offset+ret, maxlen));
1608 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(record_type, buf, offset+ret, maxlen));
1609 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(record_class, buf, offset+ret, maxlen));
1610 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedInt(ttl, buf, offset+ret, maxlen));
1611 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(length, buf, offset+ret, maxlen));
1612
1613 DNS_CHECK_UPPER_BOUND(offset+ret+length, maxlen);
1614
1615 switch(record_type)
1616 {
1617 case A:
1618 {
1619 record = new A_Record();
1620 break;
1621 }
1622 case CNAME:
1623 {
1624 record = new CNAME_Record();
1625 break;
1626 }
1627 case PTR:
1628 {
1629 record = new PTR_Record();
1630 break;
1631 }
1632 default:
1633 return 0;
1634 }
1635
1636 DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
1637 }
1638
1639 return ret;
1640 }
1641
operator =(const Answer & r)1642 DNS::Answer& DNS::Answer::operator=(const Answer &r)
1643 {
1644 name = r.name;
1645 record_type = r.record_type;
1646 record_class = r.record_class;
1647 ttl = r.ttl;
1648 length = r.length;
1649 record = r.record->clone();
1650 return *this;
1651 }
1652
parseFromBuffer(const u8 * buf,size_t maxlen)1653 size_t DNS::Packet::parseFromBuffer(const u8 *buf, size_t maxlen)
1654 {
1655 if( !buf || maxlen < DATA) return 0;
1656
1657 size_t tmp, ret = 0;
1658 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(id, buf, ID, maxlen));
1659 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(flags, buf, FLAGS_OFFSET, maxlen));
1660
1661 u16 queries_counter, answers_counter, authorities_counter, additionals_counter;
1662 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(queries_counter, buf, QDCOUNT, maxlen));
1663 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(answers_counter, buf, ANCOUNT, maxlen));
1664 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(authorities_counter, buf, NSCOUNT, maxlen));
1665 DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedShort(additionals_counter, buf, ARCOUNT, maxlen));
1666
1667 queries.clear();
1668 for(u16 i=0; i<queries_counter; ++i)
1669 {
1670 Query q;
1671 DNS_CHECK_ACCUMLATE(ret, tmp, q.parseFromBuffer(buf, ret, maxlen));
1672 queries.push_back(q);
1673 }
1674
1675 answers.clear();
1676 for(u16 i=0; i<answers_counter; ++i)
1677 {
1678 Answer a;
1679 DNS_CHECK_ACCUMLATE(ret, tmp, a.parseFromBuffer(buf, ret, maxlen));
1680 answers.push_back(a);
1681 };
1682
1683 return ret;
1684 }
1685