~ubuntu-branches/ubuntu/oneiric/squid3/oneiric-security

« back to all changes in this revision

Viewing changes to src/dns_internal.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mahyuddin Susanto
  • Date: 2011-02-15 18:46:13 UTC
  • mfrom: (21.2.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110215184613-1u3dh5sz4i055flk
Tags: 3.1.10-1ubuntu1
* Merge from debian unstable. (LP: #719283)  Remaining changes:
  - debian/patches/18-fix-ftbfs-binutils-gold.dpatch: Add library linker into
    LIBS instead to LDFLAGS to fixing FTBFS binutils-gold.
* Drop Ubuntu configuration for ufw which landed in Debian and sync it: 
  - debian/squid3.ufw.profile.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
#include "fde.h"
44
44
#include "ip/tools.h"
45
45
#include "MemBuf.h"
46
 
 
 
46
#include "util.h"
47
47
#include "wordlist.h"
48
48
 
49
49
#if HAVE_ARPA_NAMESER_H
201
201
 
202
202
    if (A.IsAnyAddr()) {
203
203
        debugs(78, 0, "WARNING: Squid does not accept " << A << " in DNS server specifications.");
204
 
        A = "127.0.0.1";
 
204
        A.SetLocalhost();
205
205
        debugs(78, 0, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine");
206
206
    }
207
207
 
 
208
    if (!Ip::EnableIpv6 && !A.SetIPv4()) {
 
209
        debugs(78, DBG_IMPORTANT, "WARNING: IPv6 is disabled. Discarding " << A << " in DNS server specifications.");
 
210
        return;
 
211
    }
 
212
 
208
213
    if (nns == nns_alloc) {
209
214
        int oldalloc = nns_alloc;
210
215
        ns *oldptr = nameservers;
253
258
 
254
259
    assert(npc < npc_alloc);
255
260
    strcpy(searchpath[npc].domain, buf);
 
261
    Tolower(searchpath[npc].domain);
256
262
    debugs(78, 3, "idnsAddPathComponent: Added domain #" << npc << ": " << searchpath[npc].domain);
257
263
    npc++;
258
264
}
700
706
}
701
707
 
702
708
static void
703
 
idnsInitVCConnected(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data)
 
709
idnsInitVCConnected(int fd, const DnsLookupDetails &details, comm_err_t status, int xerrno, void *data)
704
710
{
705
711
    nsvc * vc = (nsvc *)data;
706
712
 
707
713
    if (status != COMM_OK) {
708
 
        char buf[MAX_IPSTRLEN];
709
 
        debugs(78, 1, "idnsInitVCConnected: Failed to connect to nameserver " << nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN) << " using TCP!");
 
714
        char buf[MAX_IPSTRLEN] = "";
 
715
        if (vc->ns < nns)
 
716
            nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN);
 
717
        debugs(78, 1, HERE << "Failed to connect to nameserver " << buf << " using TCP: " << details);
710
718
        comm_close(fd);
711
719
        return;
712
720
    }
722
730
    nsvc * vc = (nsvc *)data;
723
731
    delete vc->queue;
724
732
    delete vc->msg;
725
 
    nameservers[vc->ns].vc = NULL;
 
733
    if (vc->ns < nns) // XXX: idnsShutdown may have freed nameservers[]
 
734
        nameservers[vc->ns].vc = NULL;
726
735
    cbdataFree(vc);
727
736
}
728
737
 
732
741
    char buf[MAX_IPSTRLEN];
733
742
 
734
743
    nsvc *vc = cbdataAlloc(nsvc);
 
744
    assert(ns < nns);
735
745
    nameservers[ns].vc = vc;
736
746
    vc->ns = ns;
737
747
 
742
752
    else
743
753
        addr = Config.Addrs.udp_incoming;
744
754
 
 
755
    if (nameservers[ns].S.IsIPv4() && !addr.SetIPv4()) {
 
756
        debugs(31, DBG_CRITICAL, "ERROR: Cannot contact DNS nameserver " << nameservers[ns].S << " from " << addr);
 
757
        addr.SetAnyAddr();
 
758
        addr.SetIPv4();
 
759
    }
 
760
 
745
761
    vc->queue = new MemBuf;
746
762
 
747
763
    vc->msg = new MemBuf;
765
781
static void
766
782
idnsSendQueryVC(idns_query * q, int ns)
767
783
{
 
784
    assert(ns < nns);
768
785
    if (nameservers[ns].vc == NULL)
769
786
        idnsInitVC(ns);
770
787
 
817
834
        } else {
818
835
            if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6())
819
836
                y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz);
820
 
            else
 
837
            else if (DnsSocketA)
821
838
                x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz);
822
839
        }
823
840
 
832
849
 
833
850
    } while ( (x<0 && y<0) && q->nsends % nns != 0);
834
851
 
835
 
    if (y >= 0) {
 
852
    if (y > 0) {
836
853
        fd_bytes(DnsSocketB, y, FD_WRITE);
837
 
        commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
838
854
    }
839
 
 
840
 
    if (x >= 0) {
 
855
    if (x > 0) {
841
856
        fd_bytes(DnsSocketA, x, FD_WRITE);
842
 
        commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
843
857
    }
844
858
 
845
859
    nameservers[ns].nqueries++;
1097
1111
        safe_free(message->answer);
1098
1112
 
1099
1113
        message->answer = result;
 
1114
        message->ancount += q->initial_AAAA.count;
1100
1115
        n += q->initial_AAAA.count;
1101
1116
        q->initial_AAAA.count=0;
1102
1117
    } else if (q->initial_AAAA.count > 0 && n <= 0) {
1126
1141
 
1127
1142
    debugs(78, 3, "idnsRead: starting with FD " << fd);
1128
1143
 
 
1144
    // Always keep reading. This stops (or at least makes harder) several
 
1145
    // attacks on the DNS client.
 
1146
    commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
 
1147
 
1129
1148
    /* BUG (UNRESOLVED)
1130
1149
     *  two code lines after returning from comm_udprecvfrom()
1131
1150
     *  something overwrites the memory behind the from parameter.
1172
1191
 
1173
1192
        if (ns >= 0) {
1174
1193
            nameservers[ns].nreplies++;
1175
 
        } else if (Config.onoff.ignore_unknown_nameservers) {
 
1194
        }
 
1195
 
 
1196
        // Before unknown_nameservers check to avoid flooding cache.log on attacks,
 
1197
        // but after the ++ above to keep statistics right.
 
1198
        if (!lru_list.head)
 
1199
            continue; // Don't process replies if there is no pending query.
 
1200
 
 
1201
        if (ns < 0 && Config.onoff.ignore_unknown_nameservers) {
1176
1202
            static time_t last_warning = 0;
1177
1203
 
1178
1204
            if (squid_curtime - last_warning > 60) {
1186
1212
 
1187
1213
        idnsGrokReply(rbuf, len);
1188
1214
    }
1189
 
 
1190
 
    if (lru_list.head) {
1191
 
        commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
1192
 
    }
1193
1215
}
1194
1216
 
1195
1217
static void
1257
1279
        return;
1258
1280
    }
1259
1281
 
1260
 
    vc->msg->size += len;       // XXX should not access -> size directly
 
1282
    vc->msg->size += len;       // XXX should not access -> size directly
1261
1283
 
1262
1284
    if (vc->msg->contentSize() < vc->msglen) {
1263
1285
        comm_read(fd, buf + len, vc->msglen - vc->msg->contentSize(), idnsReadVC, vc);
1264
1286
        return;
1265
1287
    }
1266
1288
 
 
1289
    assert(vc->ns < nns);
1267
1290
    debugs(78, 3, "idnsReadVC: FD " << fd << ": received " <<
1268
1291
           (int) vc->msg->contentSize() << " bytes via tcp from " <<
1269
1292
           nameservers[vc->ns].S << ".");
1376
1399
        if (DnsSocketB >= 0) {
1377
1400
            port = comm_local_port(DnsSocketB);
1378
1401
            debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB);
 
1402
            commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
1379
1403
        }
1380
1404
        if (DnsSocketA >= 0) {
1381
1405
            port = comm_local_port(DnsSocketA);
1382
1406
            debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA);
 
1407
            commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
1383
1408
        }
1384
1409
    }
1385
1410
 
1445
1470
        }
1446
1471
    }
1447
1472
 
 
1473
    // XXX: vcs are not closed/freed yet and may try to access nameservers[]
1448
1474
    idnsFreeNameservers();
1449
1475
    idnsFreeSearchpath();
1450
1476
}