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 tkrc
.d_inception
= time((time_t*)NULL
);
109 tkrc
.d_expiration
= tkrc
.d_inception
+15;
112 tkrc
.d_keysize
= output
.size();
114 tkrc
.d_othersize
= 0;
115 pwtkey
.getHeader()->id
= dns_random(0xffff);
116 pwtkey
.startRecord(gssctx
.getLabel(), QType::TKEY
, 3600, QClass::ANY
, DNSResourceRecord::ADDITIONAL
, false);
117 tkrc
.toPacket(pwtkey
);
119 for(const string
& msg
: gssctx
.getErrorStrings()) {
123 len
= htons(packet
.size());
124 if(sock
.write((char *) &len
, 2) != 2)
125 throw PDNSException("tcp write failed");
126 sock
.writen(string((char*)&packet
[0], packet
.size()));
127 if(sock
.read((char *) &len
, 2) != 2)
128 throw PDNSException("tcp read failed");
131 char *creply
= new char[len
];
135 numread
=sock
.read(creply
+n
, len
-n
);
137 throw PDNSException("tcp read failed");
141 MOADNSParser
mdp(false, string(creply
, len
));
142 if (mdp
.d_header
.rcode
!= 0) {
143 throw PDNSException(string("Remote server refused: ") + std::to_string(mdp
.d_header
.rcode
));
145 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
146 if(i
->first
.d_type
!= QType::TKEY
) continue;
147 // recover TKEY record
148 tkrc
= TKEYRecordContent(i
->first
.d_content
->getZoneRepresentation());
153 if (gssctx
.valid() == false) {
154 cerr
<<"Could not create GSS context"<<endl
;
158 tsig_key
= DNSName(gssctx
.getLabel());
162 DNSPacketWriter
pw(packet
, DNSName(argv
[3]), 252);
164 pw
.getHeader()->id
= dns_random(0xffff);
167 TSIGRecordContent trc
;
168 trc
.d_algoName
= getTSIGAlgoName(tsig_algo
);
169 trc
.d_time
= time((time_t*)NULL
);
171 trc
.d_origID
=ntohs(pw
.getHeader()->id
);
173 addTSIG(pw
, trc
, tsig_key
, tsig_secret
, "", false);
176 len
= htons(packet
.size());
177 if(sock
.write((char *) &len
, 2) != 2)
178 throw PDNSException("tcp write failed");
180 sock
.writen(string(packet
.begin(), packet
.end()));
182 bool isNSEC3
= false;
184 vector
<pair
<DNSName
,string
> > records
;
186 map
<string
,DNSName
> hashes
;
187 NSEC3PARAMRecordContent ns3pr
;
190 TSIGRecordContent trc
;
192 if(sock
.read((char *) &len
, 2) != 2)
193 throw PDNSException("tcp read failed");
196 char *creply
= new char[len
];
200 numread
=sock
.read(creply
+n
, len
-n
);
202 throw PDNSException("tcp read failed");
206 MOADNSParser
mdp(false, string(creply
, len
));
207 if (mdp
.d_header
.rcode
!= 0) {
208 throw PDNSException(string("Remote server refused: ") + std::to_string(mdp
.d_header
.rcode
));
210 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
211 if (i
->first
.d_type
== QType::TSIG
) {
214 std::cerr
<<"Unexpected TSIG signature in data"<<endl
;
216 trc
= TSIGRecordContent(i
->first
.d_content
->getZoneRepresentation());
219 if(i
->first
.d_type
== QType::SOA
)
223 else if (i
->first
.d_type
== QType::NSEC3PARAM
) {
224 ns3pr
= NSEC3PARAMRecordContent(i
->first
.d_content
->getZoneRepresentation());
229 o
<<"\t"<<i
->first
.d_ttl
<<"\tIN\t"<<DNSRecordContent::NumberToType(i
->first
.d_type
);
232 o
<<"\t"<<i
->first
.d_content
->getZoneRepresentation();
234 else if(i
->first
.d_type
== QType::RRSIG
)
236 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
237 vector
<string
> parts
;
238 stringtok(parts
, zoneRep
);
239 o
<<"\t"<<parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" "<<parts
[3]<<" [expiry] [inception] [keytag] "<<parts
[7]<<" ...";
241 else if(i
->first
.d_type
== QType::NSEC3
)
243 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
244 vector
<string
> parts
;
245 stringtok(parts
, zoneRep
);
246 o
<<"\t"<<parts
[0]<<" ";
251 o
<<" "<<parts
[2]<<" "<<parts
[3]<<" "<<"[next owner]";
252 for(vector
<string
>::iterator iter
= parts
.begin()+5; iter
!= parts
.end(); ++iter
)
255 else if(i
->first
.d_type
== QType::DNSKEY
)
257 string zoneRep
= i
->first
.d_content
->getZoneRepresentation();
258 vector
<string
> parts
;
259 stringtok(parts
, zoneRep
);
260 o
<<"\t"<<parts
[0]<<" "<<parts
[1]<<" "<<parts
[2]<<" ...";
264 o
<<"\t"<<i
->first
.d_content
->getZoneRepresentation();
267 records
.push_back(make_pair(i
->first
.d_name
,o
.str()));
269 DNSName
shorter(i
->first
.d_name
);
271 labels
.insert(shorter
);
272 if (shorter
== DNSName(argv
[3]))
274 }while(shorter
.chopOff());
281 if (isNSEC3
&& unhash
)
284 for(const auto &label
: labels
) {
285 hashed
=toBase32Hex(hashQNameWithSalt(ns3pr
, label
));
286 hashes
.insert(pair
<string
,DNSName
>(hashed
, label
));
290 for(auto &record
: records
) {
291 DNSName label
/* FIXME400 rename */=record
.first
;
292 if (isNSEC3
&& unhash
)
294 auto i
= hashes
.find(label
.makeRelative(DNSName(argv
[3])).toStringNoDot());
295 if (i
!= hashes
.end())
298 cout
<<label
.toString()<<record
.second
<<endl
;
302 catch(PDNSException
&e2
) {
303 cerr
<<"Fatal: "<<e2
.reason
<<endl
;
305 catch(std::exception
&e
)
307 cerr
<<"Fatal: "<<e
.what()<<endl
;