5 #include "dnsparser.hh"
8 #include "dnswriter.hh"
9 #include "dnsrecords.hh"
12 #include "dnssecinfra.hh"
14 #include "dns_random.hh"
15 #include "gss_context.hh"
19 int main(int argc
, char** argv
)
23 cerr
<<"Syntax: saxfr IP-address port zone [showdetails] [showflags] [unhash] [gss:remote-principal] [tsig:keyname:algo:secret]"<<endl
;
27 bool showdetails
=false;
32 TSIGHashEnum tsig_algo
;
36 string remote_principal
;
39 for(int i
=4; i
<argc
; i
++) {
40 if (strcmp(argv
[i
], "showdetails") == 0)
42 if (strcmp(argv
[i
], "showflags") == 0)
44 if (strcmp(argv
[i
], "unhash") == 0)
46 if (strncmp(argv
[i
], "gss:",4) == 0) {
50 remote_principal
= string(argv
[i
]+4);
51 if (remote_principal
.empty()) {
52 cerr
<<"Remote principal is required"<<endl
;
56 if (strncmp(argv
[i
], "tsig:",5) == 0) {
59 stringtok(parts
, argv
[i
], ":");
60 if (parts
.size()!=4) {
61 cerr
<<"Invalid syntax for tsig"<<endl
;
64 if (!getTSIGHashEnum(DNSName(parts
[2]), tsig_algo
)) {
65 cerr
<<"Cannot understand TSIG algorithm '"<<parts
[1]<<"'"<<endl
;
68 tsig_key
= DNSName(parts
[1]);
69 if (tsig_key
== DNSName()) {
70 cerr
<<"Key name must be set for tsig"<<endl
;
73 if (B64Decode(parts
[3], tsig_secret
)) {
74 cerr
<<"Secret must be base64 encoded"<<endl
;
77 if (tsig_secret
.size()==0) {
78 cerr
<<"Secret must be set for tsig"<<endl
;
87 vector
<uint8_t> packet
;
89 ComboAddress
dest(argv
[1] + (*argv
[1]=='@'), atoi(argv
[2]));
90 Socket
sock(dest
.sin4
.sin_family
, SOCK_STREAM
);
94 #ifndef ENABLE_GSS_TSIG
95 cerr
<<"No GSS support compiled in"<<endl
;
100 gssctx
.generateLabel(argv
[3]);
101 gssctx
.setPeerPrincipal(remote_principal
);
103 while(gssctx
.init(input
, output
) && gssctx
.valid() == false) {
105 DNSPacketWriter
pwtkey(packet
, gssctx
.getLabel(), QType::TKEY
, QClass::ANY
);
106 TKEYRecordContent tkrc
;
107 tkrc
.d_algo
= DNSName("gss-tsig.");
108 // coverity[store_truncates_time_t]
109 tkrc
.d_inception
= time((time_t*)NULL
);
110 tkrc
.d_expiration
= tkrc
.d_inception
+15;
113 tkrc
.d_keysize
= output
.size();
115 tkrc
.d_othersize
= 0;
116 pwtkey
.getHeader()->id
= dns_random_uint16();
117 pwtkey
.startRecord(gssctx
.getLabel(), QType::TKEY
, 3600, QClass::ANY
, DNSResourceRecord::ADDITIONAL
, false);
118 tkrc
.toPacket(pwtkey
);
120 for(const string
& msg
: gssctx
.getErrorStrings()) {
124 len
= htons(packet
.size());
125 if(sock
.write((char *) &len
, 2) != 2)
126 throw PDNSException("tcp write failed");
127 sock
.writen(string((char*)&packet
[0], packet
.size()));
128 if(sock
.read((char *) &len
, 2) != 2)
129 throw PDNSException("tcp read failed");
132 auto creply
= std::make_unique
<char[]>(len
);
136 numread
=sock
.read(creply
.get()+n
, len
-n
);
138 throw PDNSException("tcp read failed");
142 MOADNSParser
mdp(false, string(creply
.get(), len
));
143 if (mdp
.d_header
.rcode
!= 0) {
144 throw PDNSException(string("Remote server refused: ") + std::to_string(mdp
.d_header
.rcode
));
146 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
147 if(i
->first
.d_type
!= QType::TKEY
) continue;
148 // recover TKEY record
149 tkrc
= TKEYRecordContent(i
->first
.getContent()->getZoneRepresentation());
154 if (gssctx
.valid() == false) {
155 cerr
<<"Could not create GSS context"<<endl
;
159 tsig_key
= DNSName(gssctx
.getLabel());
163 DNSPacketWriter
pw(packet
, DNSName(argv
[3]), 252);
165 pw
.getHeader()->id
= dns_random_uint16();
168 TSIGRecordContent trc
;
169 trc
.d_algoName
= getTSIGAlgoName(tsig_algo
);
170 trc
.d_time
= time((time_t*)NULL
);
172 trc
.d_origID
=ntohs(pw
.getHeader()->id
);
174 addTSIG(pw
, trc
, tsig_key
, tsig_secret
, "", false);
177 len
= htons(packet
.size());
178 if(sock
.write((char *) &len
, 2) != 2)
179 throw PDNSException("tcp write failed");
181 sock
.writen(string(packet
.begin(), packet
.end()));
183 bool isNSEC3
= false;
185 vector
<pair
<DNSName
,string
> > records
;
187 map
<string
,DNSName
> hashes
;
188 NSEC3PARAMRecordContent ns3pr
;
191 TSIGRecordContent trc
;
193 if(sock
.read((char *) &len
, 2) != 2)
194 throw PDNSException("tcp read failed");
197 auto creply
= std::make_unique
<char[]>(len
);
201 numread
=sock
.read(creply
.get()+n
, len
-n
);
203 throw PDNSException("tcp read failed");
207 MOADNSParser
mdp(false, string(creply
.get(), len
));
208 if (mdp
.d_header
.rcode
!= 0) {
209 throw PDNSException(string("Remote server refused: ") + std::to_string(mdp
.d_header
.rcode
));
211 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
212 if (i
->first
.d_type
== QType::TSIG
) {
215 std::cerr
<<"Unexpected TSIG signature in data"<<endl
;
217 trc
= TSIGRecordContent(i
->first
.getContent()->getZoneRepresentation());
220 if(i
->first
.d_type
== QType::SOA
)
224 else if (i
->first
.d_type
== QType::NSEC3PARAM
) {
225 ns3pr
= NSEC3PARAMRecordContent(i
->first
.getContent()->getZoneRepresentation());
230 o
<<"\t"<<i
->first
.d_ttl
<<"\tIN\t"<<DNSRecordContent::NumberToType(i
->first
.d_type
);
233 o
<<"\t"<<i
->first
.getContent()->getZoneRepresentation();
235 else if(i
->first
.d_type
== QType::RRSIG
)
237 string zoneRep
= i
->first
.getContent()->getZoneRepresentation();
238 vector
<string
> parts
;
239 stringtok(parts
, zoneRep
);
240 o
<<"\t"<<parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" "<<parts
[3]<<" [expiry] [inception] [keytag] "<<parts
[7]<<" ...";
242 else if(i
->first
.d_type
== QType::NSEC3
)
244 string zoneRep
= i
->first
.getContent()->getZoneRepresentation();
245 vector
<string
> parts
;
246 stringtok(parts
, zoneRep
);
247 o
<<"\t"<<parts
[0]<<" ";
252 o
<<" "<<parts
[2]<<" "<<parts
[3]<<" "<<"[next owner]";
253 for(vector
<string
>::iterator iter
= parts
.begin()+5; iter
!= parts
.end(); ++iter
)
256 else if(i
->first
.d_type
== QType::DNSKEY
)
258 string zoneRep
= i
->first
.getContent()->getZoneRepresentation();
259 vector
<string
> parts
;
260 stringtok(parts
, zoneRep
);
261 o
<<"\t"<<parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" ...";
265 o
<<"\t"<<i
->first
.getContent()->getZoneRepresentation();
268 records
.emplace_back(i
->first
.d_name
, o
.str());
270 DNSName
shorter(i
->first
.d_name
);
272 labels
.insert(shorter
);
273 if (shorter
== DNSName(argv
[3]))
275 }while(shorter
.chopOff());
280 if (isNSEC3
&& unhash
)
283 for(const auto &label
: labels
) {
284 hashed
=toBase32Hex(hashQNameWithSalt(ns3pr
, label
));
285 hashes
.insert(pair
<string
,DNSName
>(hashed
, label
));
289 for(auto &record
: records
) {
290 DNSName label
/* FIXME400 rename */=record
.first
;
291 if (isNSEC3
&& unhash
)
293 auto i
= hashes
.find(label
.makeRelative(DNSName(argv
[3])).toStringNoDot());
294 if (i
!= hashes
.end())
297 cout
<<label
.toString()<<record
.second
<<endl
;
301 catch(PDNSException
&e2
) {
302 cerr
<<"Fatal: "<<e2
.reason
<<endl
;
304 catch(std::exception
&e
)
306 cerr
<<"Fatal: "<<e
.what()<<endl
;