Skip to content

Instantly share code, notes, and snippets.

@Habbie
Created April 26, 2013 11:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Habbie/5466802 to your computer and use it in GitHub Desktop.
Save Habbie/5466802 to your computer and use it in GitHub Desktop.
Index: modules/remotebackend/unixconnector.cc
===================================================================
--- modules/remotebackend/unixconnector.cc (revision 2806)
+++ modules/remotebackend/unixconnector.cc (working copy)
@@ -50,18 +50,22 @@
};
ssize_t write(const std::string &data) {
- ssize_t nwrite, nbuf;
+ ssize_t nwrite, nbuf, pos;
char buf[1500];
Lock scoped_lock(&unix_mutex);
reconnect();
if (!connected) return -1;
- nbuf = data.copy(buf, sizeof buf); // copy data and write
- nwrite = ::write(fd, buf, nbuf);
- if (nwrite == -1) {
- connected = false;
- close(fd);
- return -1;
+ pos = 0;
+ while(pos < data.size()) {
+ nbuf = data.copy(buf, sizeof buf, pos); // copy data and write
+ nwrite = ::write(fd, buf, nbuf);
+ pos = pos + sizeof(buf);
+ if (nwrite == -1) {
+ connected = false;
+ close(fd);
+ return -1;
+ }
}
return nwrite;
};
Index: modules/remotebackend/remotebackend.cc
===================================================================
--- modules/remotebackend/remotebackend.cc (revision 2806)
+++ modules/remotebackend/remotebackend.cc (working copy)
@@ -352,6 +352,10 @@
return answer.asBool();
}
+bool RemoteBackend::doesDNSSEC() {
+ return d_dnssec;
+}
+
bool RemoteBackend::getTSIGKey(const std::string& name, std::string* algorithm, std::string* content) {
Json::Value query,answer;
query["method"] = "getTSIGKey";
@@ -369,6 +373,45 @@
return true;
}
+bool RemoteBackend::getDomainInfo(const string &domain, DomainInfo &di) {
+ Json::Value query,answer;
+ std::string kind;
+ query["method"] = "getDomainInfo";
+ query["parameters"] = Json::Value();
+ query["parameters"]["name"] = domain;
+
+ if (connector->send(query) == false || connector->recv(answer) == false)
+ return false;
+
+ // make sure we got zone & kind
+ if (!answer.isMember("zone")) {
+ L<<Logger::Error<<kBackendId<<"Missing zone in getDomainInfo return value"<<endl;
+ throw new AhuException();
+ }
+ // parse return value. we need at least zone,serial,kind
+ di.id = answer.get("id", Json::Value(-1)).asInt();
+ di.zone = answer["zone"].asString();
+ if (answer.isMember("masters") && answer["masters"].isArray()) {
+ Json::Value value = answer["masters"];
+ for(Json::Value::iterator i = value.begin(); i != value.end(); i++) {
+ di.masters.push_back((*i).asString());
+ }
+ }
+ di.notified_serial = -1;
+ di.serial = answer.get("serial", Json::Value(0)).asInt();
+ di.last_check = 0;
+ kind = answer.get("kind", Json::Value("native")).asString();
+ if (kind == "master") {
+ di.kind = DomainInfo::Master;
+ } else if (kind == "slave") {
+ di.kind = DomainInfo::Slave;
+ } else {
+ di.kind = DomainInfo::Native;
+ }
+ di.backend = this;
+ return true;
+}
+
DNSBackend *RemoteBackend::maker()
{
try {
Index: modules/remotebackend/test_backend.rb
===================================================================
--- modules/remotebackend/test_backend.rb (revision 2806)
+++ modules/remotebackend/test_backend.rb (working copy)
@@ -1,199 +0,0 @@
-#!/usr/bin/ruby
-
-require 'json'
-
-prefix = "2001:06e8:0500:0000"
-
-# domain keys
-
-$domain_keys = [
- {
- :id => 8,
- :flags => 257,
- :active => true,
- :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: nFfl3jgFE+KET9PFPVmRCVmGZ+o+Stnqq7AZPAmhSYf96BPqK3t22vKHJhmVla+td94if2XUSggRUDz8YSeIybVNDTCmhF4xNyhAYAeh+HxJQU7CL8jQLs0b86Hd/Ua/s2pmSFSX4vzoAg+1lucLT3AiGYWjrvciFFpWnMyYftqcfTy3Vu/TMA9Kr7tr75CsJ2mzu1rywHsvOErCY8xH6dGd2LCY9ozuOwsgAlou+rOF5W71UPIuomM9QcIdVD2nq8+aHSsKeWk8gabLEsKU0SFFutO/R41lYXiUaFv+zY7r7NmP+d0Wmr0rgnzq2vlV0USQhlDPAsPSVstAuMrjgw==
-PublicExponent: AQAB
-PrivateExponent: kSdnrMbKe7dqfcpDG9WMgYp6BS88A5/a2F2ysv+Ds+Q9cAENXTpPn2yNDd4+sd3pgcmYsjsS6deTr9/YFRXw9bKBKLI80JFdZhKng5hMvYqnBGQmt/Dz4/RE87PVLNIC4/mrFE4Bn2vStnRTu3WY/wURXf3YkgI+IdXsfQTsBNloLiRoVV1QmB4kkHtRXsr02dg4kMhaXA13kT7lsrquCvGoxP++keVJ88AaQA8si30/E+CSgrbCHThUXeL6ErYz6myI5O2RJqodlcEQeXYi2cNkzQJnO3yjXcaSJy2u3tVNE2wXCXf1pwHXyTA4YT1qMbMIABq9TiVW8Q2Kg4sN
-Prime1: wrNo1cyyL/LpO+Das2EQzMbX0ctdy0OPvg3kWZqt2ZEwJjcVe1Vav5ZzSWKQWuT0IytUst7qdTE7lKpWWKDAbxJ4IMcMiMN2iQqE9V/dhIJluIrshupQzdhnXR46MfbazkDuvMTM1Fk4ZOgm3lrJoRvl6EOxl7e9veTwCjKqrA8=
-Prime2: zZDvTPq/Ea7aKa+CNmP7oOYxpvE1fpPV8MRjQ+IMi8VIDHpE72NoSSVoVuSL7fgl7qAFlbJMEtQGIlqUFQkC0sbI6ddb1/Ane+xhH4aPaljtIJQs0GlM/ECz30qZCreyHqaVzXlk9ZrN7HlnIOQ//DV3lCsS8EE1djeQxFThrU0=
-Exponent1: S9uW1uX/7sqXsKq0yvrgjshSQf0YOB/Em2nSNE8duQzmU51Wk0z4JHk7xbXPRHq73A//2gkcFDjwW8XaCoHnN99cSnkDGy38uvwMPYXySrR7aWFHMnGMtgbAjvk990WUjpOh8I5Et99jJ32D11JMCKdT9iCZyuDd3mSaWX7QHGU=
-Exponent2: hiaslG8a3B5gz01zS62KHCG9i3XkdDtkJeDz6uwNRfW0JDhy3krgVsPryLETxHPpxUV2/49A6BSoACledC/SQN1rZnedv1lBWzUS2PEGjN+FuHoamNPvYruS5wiWwZDJ1AjgwBwVz9Z7xnQf4i4yt5Po+q/1hwb3LbPrbMT8Fg0=
-Coefficient: zZDvTPq/Ea7aKa+CNmP7oOYxpvE1fpPV8MRjQ+IMi8VIDHpE72NoSSVoVuSL7fgl7qAFlbJMEtQGIlqUFQkC0sbI6ddb1/Ane+xhH4aPaljtIJQs0GlM/ECz30qZCreyHqaVzXlk9ZrN7HlnIOQ//DV3lCsS8EE1djeQxFThrU0="
- },
- {
- :id => 9,
- :flags => 256,
- :active => true,
- :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: 0fcOKzIHcE5K3B3zwu0iAm4Z/cRBH9JX0mMhl9h58i0C8QEK3fK+425MEI/q4P7qGkwB9hJ9TefC5ny3b+F2iSIDTqcrMoRr6/lJO2YH7MyeuAv1T5HMsC7DoCkdaq0xuoOkOtKaVz5/FwSFmCIlCNeboFX3Fq4kCoWsa1m63AE=
-PublicExponent: AQAB
-PrivateExponent: BWc0q6LlcxvorEJvD/CXQ/W+YHvo6x84GFdpuWUeOj+zSC1tMKn7BJJFjdWOR0z4DEYxdLokFFmm99R0ygHE0ZWh7WS1OX5AzqoFczeC0BDLvoAYu6XMvwlYp78ffqlI2qv4ohfew5TYzWCugxIufFsC55i2FoworGBLSFUloaM=
-Prime1: +aIMyvDUAzL/JZDHsPLnawLhy7sfZB4BbtARAYxZ6HSE9MAnFKbQhXQ9yRdGLSZEhe8g5b9tXBvxT8TPIGhwcw==
-Prime2: 11H/gYNtYkloQuRcL2xd3ElxosgncgFvXKY0y4sGyJuEhHJfttaxXCmNfVN9fg5lX18kfxCv4s8rqI+M+rZouw==
-Exponent1: SmrNp34NpfqA52D2tsBizproVwSsgfsT8EXkm/KMJuj9bb0OqXBlPzN868Kdb/41dTvpMbRUVJ4b3OzN1lpsEw==
-Exponent2: zPRiTzd48SuKsNGJ5iIynbLTFe2LjntLM1eJvY2SYXWXCDOOZA2sOVvcMEU+mLS/Ta7UoJaTtUMZ/ZLW0Pa8bQ==
-Coefficient: 11H/gYNtYkloQuRcL2xd3ElxosgncgFvXKY0y4sGyJuEhHJfttaxXCmNfVN9fg5lX18kfxCv4s8rqI+M+rZouw=="
- },
- {
- :id => 10,
- :flags => 256,
- :active => false,
- :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: rzJLZNmV+xQLkYWT3PytSYDeE8SovXi9+WCp9MVkWcSj1BgrBbugregqsSQLvz+rGsgc2nK3kqygDhypRMExmd2TRHeIrtcLHZ3nq+mmL/GfE0K6KWS2FJx06ol7v9xG8esLe+TUSAENo2xFR0BFmkiJN+R5hq06Rb0Y7OMSBs8=
-PublicExponent: AQAB
-PrivateExponent: FwH6jMABG6bCQ4DQrlDbS6/felEf/TdXcOHqRU7houMEG4fLqUZpZO1Rzfmh4U0x4fktxjJn5pyXrcLDKAMHHv+DjtPSC4B+49HFOZEHl/522VYw6NyJ+Firk41hbFxIStSFYh47qxKyAwbI/LuyTJE0Au8D+4dl8oFwfh0x+aE=
-Prime1: 0sDZukxVtL4zI9JPvEdBUAXLu4I98GS7xhxiLNeb+iF2+Vvw06igV7+CccMldz/r3gqr9y+NdAloErFvkieLRQ==
-Prime2: 1M822AT25uYwdKiiYuBPQlUIKVuP1paa8y4rh+uDuoHpm9E29hwHr2uLXESOO5YxB0oc8yauNOdH+HGTg8GhAw==
-Exponent1: IOq2Fv7tM/mxCxtCEOogLVt6YqMJAY76NQsh2lciqYKojnHpv2VLBemHejU8mM+HC3snOMhYk5MUijbkcjNy8Q==
-Exponent2: V0LUkUWP3GQ9MEjJtVOXDHMDkrnZxDsjNF4VOXmoHT0SBnOGXupleFfX4DC4RdSzK/MG5elRe53ulAA2Zctq8w==
-Coefficient: 1M822AT25uYwdKiiYuBPQlUIKVuP1paa8y4rh+uDuoHpm9E29hwHr2uLXESOO5YxB0oc8yauNOdH+HGTg8GhAw=="
- }
-]
-
-def to32(number)
- number.to_s(32).tr "0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769"
-end
-
-def from32(str)
- str.tr("0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769").to_i(32)
-end
-
-def rr(qname, qtype, content, ttl, priority = 0, auth = 1)
- {:qname => qname, :qtype => qtype, :content => content, :ttl => ttl, :priority => priority, :auth => auth}
-end
-
-def send_result(result, log = nil)
- out = {:result => result}
- if log.class != Array
- log = [log]
- end
- out[:log] = log unless log.nil?
- print out.to_json
- print "\n"
-end
-
-def send_failure(msg)
- send_result false, [msg]
-end
-
-class Handler
- attr :prefix, :plen, :suffix, :domain
-
- def initialize(prefix)
- @prefix = prefix
- end
-
- def do_initialize(*args)
- # precalculate some things
- tmp = self.prefix.gsub(/[^0-9a-f]/,'')
- @plen = tmp.size
- @suffix = tmp.split(//).reverse.join('.')+".ip6.arpa"
- @domain = "dyn.example.com"
- send_result true, "Autorev v6 backend initialized"
- end
-
- def do_getbeforeandafternamesabsolute(args)
- qname = args["qname"]
- # assume prefix
- name = qname.gsub(/ /,'')
- nlen = 32-self.plen
-
- name_a = nil
- name_b = nil
- unhashed = nil
-
- if name == ''
- name_a = sprintf("%0#{nlen}x",0).split(//).join(' ')
- elsif name.size < nlen
- name_a = sprintf("%0#{nlen}x",0).split(//).join(' ')
- else
- unhashed = sprintf("%0#{nlen}x",name.to_i(16)).split(//).join(' ')
- if (name.to_i(16) > 0)
- name_b = sprintf("%0#{nlen}x",(name.to_i(16)-1)).split(//).join ' '
- end
- unless (name[/[^f]/].nil?)
- name_a = sprintf("%0#{nlen}x",(name.to_i(16)+1)).split(//).join ' '
- end
- end
- send_result ({:before => name_b, :after => name_a, :unhashed => unhashed})
- end
-
- def do_getbeforeandafternames(args)
- self.do_getbeforeandafternamesabsolute(args)
- end
-
- def do_getdomainkeys(args)
- if args["name"] == self.suffix
- send_result $domain_keys
- else
- send_result false
- end
- end
-
- def do_lookup(args)
- qtype = args["qtype"]
- qname = args["qname"]
-
- if qname[/.ip6.arpa$/]
- if qname == self.suffix
- ret = []
- if (qtype != "SOA")
- ret << rr(qname, "NS", "ns1.example.com",300)
- ret << rr(qname, "NS", "ns2.example.com",300)
- ret << rr(qname, "NS", "ns3.example.com",300)
- end
- ret << rr(qname,"SOA","ns1.example.com hostmaster.example.com #{Time.now.strftime("%Y%m%d%H")} 28800 7200 1209600 300",300)
- return send_result ret
- elsif qtype == "ANY" or qtype == "PTR"
- # assume suffix
- name = qname.gsub(self.suffix,"").split(".").reverse.join("")
- if name.empty? or name.size != 32-plen
- return send_result false
- end
- name = to32(name.to_i(16))
- return send_result [rr(qname, "PTR", "node-#{name}.#{self.domain}", 300)]
- end
- end
- send_result false
- end
-
- def do_getdomainmetadata(args)
- name = args["name"]
- kind = args["kind"]
- send_result false
- end
-end
-
-h = Handler.new(prefix)
-
-STDOUT.sync = true
-begin
- STDIN.each_line do |line|
- # expect json
- input = {}
- line = line.strip
- next if line.empty?
- begin
- input = JSON.parse(line)
- method = "do_#{input["method"].downcase}"
- args = input["parameters"]
-
- if h.respond_to?(method.to_sym) == false
- res = false
- send_result res, nil
- elsif args.size > 0
- h.send(method,args)
- else
- h.send(method)
- end
- rescue JSON::ParserError
- send_failure "Cannot parse input #{line}"
- next
- end
- end
-rescue SystemExit, Interrupt
-end
Index: modules/remotebackend/pipeconnector.cc
===================================================================
--- modules/remotebackend/pipeconnector.cc (revision 2806)
+++ modules/remotebackend/pipeconnector.cc (working copy)
@@ -1,6 +1,10 @@
#include "remotebackend.hh"
PipeConnector::PipeConnector(std::map<std::string,std::string> options) {
+ if (options.count("command") == 0) {
+ L<<Logger::Error<<"Cannot find 'command' option in connection string"<<endl;
+ throw new AhuException();
+ }
this->command = options.find("command")->second;
this->options = options;
this->coproc = NULL;
Index: modules/remotebackend/httpconnector.cc
===================================================================
--- modules/remotebackend/httpconnector.cc (revision 2806)
+++ modules/remotebackend/httpconnector.cc (working copy)
@@ -57,8 +57,12 @@
ss << "/" << method;
- // add the url components, if found, in following order
-
+ // add the url components, if found, in following order.
+ // id must be first due to the fact that the qname/name can be empty
+ if ((param = parameters.get("id", Json::Value())).isNull() == false) {
+ json2string(param, sparam);
+ ss << "/" << sparam;
+ }
if ((param = parameters.get("zonename", Json::Value())).isNull() == false) {
json2string(param, sparam);
ss << "/" << sparam;
@@ -83,11 +87,6 @@
ss << "/" << sparam;
}
- if ((param = parameters.get("id", Json::Value())).isNull() == false) {
- json2string(param, sparam);
- ss << "/" << sparam;
- }
-
// finally add suffix
ss << d_url_suffix;
curl_easy_setopt(d_c, CURLOPT_URL, ss.str().c_str());
@@ -102,7 +101,7 @@
// create post with keydata
std::stringstream ss2;
param = parameters["key"];
- ss2 << "flags" << param["flags"].asUInt() << "&active" << (param["active"].asBool() ? 1 : 0) << "&content=";
+ ss2 << "flags=" << param["flags"].asUInt() << "&active=" << (param["active"].asBool() ? 1 : 0) << "&content=";
tmpstr = curl_easy_escape(d_c, param["content"].asCString(), 0);
ss2 << tmpstr;
sparam = ss2.str();
Index: modules/remotebackend/regression-tests/pipe-backend.rb
===================================================================
--- modules/remotebackend/regression-tests/pipe-backend.rb (revision 2806)
+++ modules/remotebackend/regression-tests/pipe-backend.rb (working copy)
@@ -5,9 +5,12 @@
h = Handler.new("../modules/remotebackend/regression-tests/remote.sqlite3")
+f = File.open "/tmp/tmp.txt","a"
+
STDOUT.sync = true
begin
STDIN.each_line do |line|
+ f.puts line
# expect json
input = {}
line = line.strip
@@ -26,7 +29,7 @@
end
puts ({:result => res, :log => log}).to_json
rescue JSON::ParserError
- send_failure "Cannot parse input #{line}"
+ puts ({:result => false, :log => "Cannot parse input #{line}"}).to_json
next
end
end
Index: modules/remotebackend/regression-tests/http-backend.rb
===================================================================
--- modules/remotebackend/regression-tests/http-backend.rb (revision 2806)
+++ modules/remotebackend/regression-tests/http-backend.rb (working copy)
@@ -5,10 +5,17 @@
require "../modules/remotebackend/regression-tests/dnsbackend"
require "../modules/remotebackend/regression-tests/backend"
-server = WEBrick::HTTPServer.new :Port => 62434
+server = WEBrick::HTTPServer.new(
+ Port: 62434,
+ BindAddress: "localhost",
+# Logger: WEBrick::Log.new("remotebackend-server.log"),
+ AccessLog: [ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ]
+)
be = Handler.new("../modules/remotebackend/regression-tests/remote.sqlite3")
+server.mount "/dns", DNSBackendHandler, be
-server.mount "/dns", DNSBackendHandler, be
trap('INT') { server.stop }
+trap('TERM') { server.stop }
+
server.start
Index: modules/remotebackend/regression-tests/backend.rb
===================================================================
--- modules/remotebackend/regression-tests/backend.rb (revision 2806)
+++ modules/remotebackend/regression-tests/backend.rb (working copy)
@@ -8,34 +8,62 @@
end
class Handler
- attr :db
-
def initialize(dbpath)
- @db = SQLite3::Database.new dbpath
+ @dbpath = dbpath
end
+ def db
+ d = SQLite3::Database.new @dbpath
+ if block_given?
+ d.transaction
+ begin
+ yield d
+ rescue
+ d.rollback
+ return
+ end
+ d.commit
+ else
+ d
+ end
+ end
+
def do_initialize(*args)
return true, "Test bench initialized"
end
+ def getbeforename(qname, id)
+ before = db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ? ORDER BY ordername DESC", qname, id)
+ if (before.nil?)
+ before = db.get_first_value("SELECT ordername FROM records WHERE domain_id = ? ORDER by ordername DESC LIMIT 1", id)
+ end
+ before
+ end
+
+ def getaftername(qname, id)
+ after = db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ? ORDER BY ordername", qname, id)
+ if (after.nil?)
+ after = db.get_first_value("SELECT ordername FROM records WHERE domain_id = ? ORDER by ordername LIMIT 1", id)
+ end
+ after
+ end
+
+
def do_getbeforeandafternamesabsolute(args)
- before = @db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ?", args["qname"], args["id"])
- after = @db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ?", args["qname"], args["id"])
- return [{:before => before, :after => after, :unhashed => args["qname"]}, nil]
+ args["qname"] = "" if args["qname"].nil?
+ return [{:before => getbeforename(args["qname"],args["id"]), :after => getaftername(args["qname"],args["id"]), :unhashed => args["qname"]}, nil]
end
def do_getbeforeandafternames(args)
- before = @db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ?", args["qname"], args["id"])
- after = @db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ?", args["qname"], args["id"])
- return [{:before => before, :after => after, :unhashed => args["qname"]}, nil]
+ args["qname"] = "" if args["qname"].nil?
+ return [{:before => getbeforename(args["qname"],args["id"]), :after => getaftername(args["qname"],args["id"]), :unhashed => args["qname"]}, nil]
end
def do_getdomainkeys(args)
ret = []
- @db.execute("SELECT flags,active,content FROM domains JOIN cryptokeys ON domains.id = cryptokeys.domain_id WHERE domains.name = ?", args["name"]) do |row|
- ret << {:flags => row[0].to_i, :active => !(row[1].to_i.zero?), :content => row[2]}
+ db.execute("SELECT cryptokeys.id,flags,active,content FROM domains JOIN cryptokeys ON domains.id = cryptokeys.domain_id WHERE domains.name = ?", [args["name"]]) do |row|
+ ret << {:id => row[0].to_i, :flags => row[1].to_i, :active => !(row[2].to_i.zero?), :content => row[3]}
end
-
return false if ret.empty?
return [ret,nil]
end
@@ -45,13 +73,25 @@
loop do
begin
sargs = {}
- if (args["qtype"] == "ANY")
- sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname"
- sargs["qname"] = args["qname"]
+ if (args["zone-id"].to_i > 0)
+ sargs["domain_id"] = args["zone-id"].to_i
+ if (args["qtype"] == "ANY")
+ sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND domain_id = :domain_id"
+ sargs["qname"] = args["qname"]
+ else
+ sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype AND domain_id = :domain_id"
+ sargs["qname"] = args["qname"]
+ sargs["qtype"] = args["qtype"]
+ end
else
- sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype"
- sargs["qname"] = args["qname"]
- sargs["qtype"] = args["qtype"]
+ if (args["qtype"] == "ANY")
+ sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname"
+ sargs["qname"] = args["qname"]
+ else
+ sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype"
+ sargs["qname"] = args["qname"]
+ sargs["qtype"] = args["qtype"]
+ end
end
db.execute(sql, sargs) do |row|
ret << rr(row[1], row[2], row[3], row[4], row[5], row[6], row[0])
@@ -64,9 +104,21 @@
return false unless ret.size > 0
return [ret,nil]
end
-
+
+ def do_getdomaininfo(args)
+ ret = {}
+ sql = "SELECT name,content FROM records WHERE name = :name AND type = 'SOA'"
+ db.execute(sql, args) do |row|
+ ret[:zone] = row[0]
+ ret[:serial] = row[1].split(' ')[2].to_i
+ ret[:kind] = "native"
+ end
+ return [ret,nil] if ret.has_key?(:zone)
+ return false
+ end
+
def do_list(args)
- target = args["target"]
+ target = args["zonename"]
ret = []
loop do
begin
@@ -77,6 +129,7 @@
end
rescue Exception => e
e.backtrace
+ return false, [e.message]
end
break
end
@@ -84,11 +137,63 @@
return [ret,nil]
end
+ def do_adddomainkey(args)
+ d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+ return false if d_id.nil?
+ sql = "INSERT INTO cryptokeys (domain_id, flags, active, content) VALUES(?,?,?,?)"
+ active = args["key"]["active"]
+ if (active)
+ active = 1
+ else
+ active = 0
+ end
+ db do |tx|
+ tx.execute(sql, [d_id, args["key"]["flags"].to_i, active, args["key"]["content"]])
+ end
+ return db.get_first_value("SELECT last_insert_rowid()")
+ end
+
+ def do_deactivatedomainkey(args)
+ d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+ return false if d_id.nil?
+ db do |tx|
+ tx.execute("UPDATE cryptokeys SET active = 0 WHERE domain_id = ? AND id = ?", [d_id, args["id"]])
+ end
+ return true
+ end
+
+ def do_activatedomainkey(args)
+ d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+ return false if d_id.nil?
+ db do |tx|
+ db.execute("UPDATE cryptokeys SET active = 1 WHERE domain_id = ? AND id = ?", [d_id, args["id"]])
+ end
+ return true
+ end
+
def do_getdomainmetadata(args)
- return false
+ ret = []
+ sql = "SELECT content FROM domainmetadata JOIN domains WHERE name = :name AND kind = :kind"
+ sargs = {:name => args["name"], :kind => args["kind"]}
+ db.execute(sql,sargs) do |row|
+ ret << row[0]
+ end
+ return false unless ret.size > 0
+ return [ret,nil]
end
def do_setdomainmetadata(args)
- return false
+ d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+ return false if d_id.nil?
+ db do |tx|
+ sql = "DELETE FROM domainmetadata WHERE domain_id = ?"
+ tx.execute(sql, [d_id])
+ break if args["value"].nil?
+ sql = "INSERT INTO domainmetadata (domain_id,kind,content) VALUES(?,?,?)"
+ args["value"].each do |value|
+ tx.execute(sql,[d_id, args["kind"], value])
+ end
+ end
+ return true
end
end
Index: modules/remotebackend/regression-tests/test-schema.sql
===================================================================
--- modules/remotebackend/regression-tests/test-schema.sql (revision 2806)
+++ modules/remotebackend/regression-tests/test-schema.sql (working copy)
@@ -20,12 +20,15 @@
content VARCHAR(65535) DEFAULT NULL,
ttl INTEGER DEFAULT NULL,
prio INTEGER DEFAULT NULL,
- change_date INTEGER DEFAULT NULL
+ change_date INTEGER DEFAULT NULL,
+ ordername VARCHAR(255) DEFAULT NULL,
+ auth BOOL DEFAULT 0
);
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
+create index orderindex on records(ordername);
create table supermasters (
ip VARCHAR(25) NOT NULL,
@@ -33,10 +36,6 @@
account VARCHAR(40) DEFAULT NULL
);
-alter table records add ordername VARCHAR(255);
-alter table records add auth bool;
-create index orderindex on records(ordername);
-
create table domainmetadata (
id INTEGER PRIMARY KEY,
domain_id INT NOT NULL,
@@ -64,11 +63,27 @@
);
create unique index namealgoindex on tsigkeys(name, algorithm);
-insert into domains (name,type) VALUES('delegated.dnssec-parent.com','NATIVE');
-insert into domains (name,type) VALUES('dnssec-parent.com','NATIVE');
+
insert into domains (name,type) VALUES('example.com','NATIVE');
-insert into domains (name,type) VALUES('minimal.com','NATIVE');
-insert into domains (name,type) VALUES('test.com','NATIVE');
-insert into domains (name,type) VALUES('wtest.com','NATIVE');
+insert into domains (name,type) VALUES('up.example.com','NATIVE');
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "SOA", "120", "ns1.example.com hostmaster.example.com 2000010101 28800 7200 1209600 120", "", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "NS", "120", "ns1.example.com", "", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "NS", "120", "ns2.example.com", "", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "outpost.example.com", "A", "120", "192.168.2.1", "outpost", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "outpost.example.com", "AAAA", "120", "fe80::1", "outpost", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "www.example.com", "A", "120", "192.168.2.255", "www", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns1.example.com", "up", 0 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns2.example.com", "up", 0 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "ns1.example.com", "A", "120", "192.168.2.2", "ns1", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "ns2.example.com", "A", "120", "192.168.2.3", "ns2", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 1 50ea84825288d03bf9ddda0b0b5f8964c6fbafa8", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 2 bf31ef7aea46f2adca7a61fbb0629fb5c24116df0f22ec0115dbc7ebdddee04e", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 3 6ed18dceaba6d2547f2fc82ba3801fdc919db51b0e44baa261b887c824dd9a2d", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "SOA", "120", "ns1.example.com hostmaster.example.com 2000010101 28800 7200 1209600 120", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns1.example.com", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns2.example.com", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "jump.up.example.com", "A", "120", "192.168.3.1", "jump", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "jump.up.example.com", "TXT", "120", "a very very long indeed text string that should pass out clean and proper thru the entire chain of powerdns processing", "jump", 1 FROM domains WHERE name = "up.example.com";
+
commit;
Index: modules/remotebackend/regression-tests/dnsbackend.rb
===================================================================
--- modules/remotebackend/regression-tests/dnsbackend.rb (revision 2806)
+++ modules/remotebackend/regression-tests/dnsbackend.rb (working copy)
@@ -1,28 +1,60 @@
require 'json'
+require 'thread'
class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet
def initialize(server, dnsbackend)
@dnsbackend = dnsbackend
+ @semaphore = Mutex.new
+ @f = File.open("/tmp/tmp.txt","a")
end
+ def parse_url(url)
+ url = url.split('/')
+ method = url.shift.downcase
+
+ # do some determining based on method names
+ args = case method
+ when "lookup"
+ {
+ "qname" => url.shift,
+ "qtype" => url.shift,
+ }
+ when "list"
+ {
+ "zonename" => url.shift
+ }
+ when "getbeforeandafternamesabsolute", "getbeforeandafternames"
+ {
+ "id" => url.shift.to_i,
+ "qname" => url.shift
+ }
+ when "getdomainmetadata", "setdomainmetadata", "getdomainkeys"
+ {
+ "name" => url.shift,
+ "kind" => url.shift
+ }
+ when "removedomainkey", "activatedomainkey", "deactivatedomainkey"
+ {
+ "id" => url.shift,
+ "name" => url.shift
+ }
+ when "adddomainkey", "gettsigkey", "getdomaininfo"
+ {
+ "name" => url.shift
+ }
+ end
+
+ [method, args]
+ end
+
def do_GET(req,res)
tmp = req.path[/dns\/(.*)/,1]
return 400, "Bad request" if (tmp.nil?)
- tmp = tmp.split("/")
- method = "do_#{tmp.shift}".downcase
- args = {}
- if tmp.size > 0
- args["qname"] = tmp[0]
- args["name"] = tmp[0]
- args["target"] = tmp.shift
- end
- if tmp.size > 0
- args["kind"] = tmp[0]
- args["qtype"] = tmp[0]
- args["id"] = tmp.shift
- end
+ method, args = parse_url(tmp)
+ method = "do_#{method}"
+
# get more arguments
req.each do |k,v|
attr = k[/X-RemoteBackend-(.*)/,1]
@@ -31,25 +63,40 @@
end
end
- if @dnsbackend.respond_to?(method.to_sym)
- result, log = @dnsbackend.send(method.to_sym, args)
- body = {:result => result, :log => log}
- res.status = 200
- res["Content-Type"] = "application/javascript; charset=utf-8"
- res.body = body.to_json
- else
- res.status = 404
- res["Content-Type"] = "application/javascript; charset=utf-8"
- res.body = ({:result => false, :log => ["Method not found"]}).to_json
+ args = args.merge req.query
+
+ if method == "do_adddomainkey"
+ args["key"] = {
+ "flags" => args.delete("flags").to_i,
+ "active" => args.delete("active").to_i,
+ "content" => args.delete("content")
+ }
end
+
+ @f.puts method
+ @f.puts args
+
+ @semaphore.synchronize do
+ if @dnsbackend.respond_to?(method.to_sym)
+ result, log = @dnsbackend.send(method.to_sym, args)
+ body = {:result => result, :log => log}
+ res.status = 200
+ res["Content-Type"] = "application/javascript; charset=utf-8"
+ res.body = body.to_json
+ else
+ res.status = 404
+ res["Content-Type"] = "application/javascript; charset=utf-8"
+ res.body = ({:result => false, :log => ["Method not found"]}).to_json
+ end
+ end
end
def do_DELETE(req,res)
+ do_GET(req,res)
end
def do_POST(req,res)
req.continue
-
- # get method name and args
+ do_GET(req,res)
end
end
Index: modules/remotebackend/remotebackend.hh
===================================================================
--- modules/remotebackend/remotebackend.hh (revision 2806)
+++ modules/remotebackend/remotebackend.hh (working copy)
@@ -88,6 +88,8 @@
virtual int addDomainKey(const string& name, const KeyData& key);
virtual bool activateDomainKey(const string& name, unsigned int id);
virtual bool deactivateDomainKey(const string& name, unsigned int id);
+ virtual bool getDomainInfo(const string&, DomainInfo&);
+ virtual bool doesDNSSEC();
static DNSBackend *maker();
Index: regression-tests/start-test-stop
===================================================================
--- regression-tests/start-test-stop (revision 2806)
+++ regression-tests/start-test-stop (working copy)
@@ -44,6 +44,8 @@
tinydns
remotebackend-pipe remotebackend-unix remotebackend-http
remotebackend-pipe-dnssec remotebackend-unix-dnssec remotebackend-http-dnssec
+remotebackend-pipe-nsec3 remotebackend-unix-nsec3 remotebackend-http-nsec3
+remotebackend-pipe-nsec3-narrow remotebackend-unix-nsec3-narrow remotebackend-http-nsec3-narrow
add -presigned to any gmysql test (except narrow) to test
presigned operation
@@ -354,20 +356,26 @@
remotebackend-*)
remotetype=$(echo $context | cut -d- -f 2)
remotesec=$(echo $context | cut -d- -f 3)
+ narrow=$(echo $context | cut -d- -f 4)
+ testsdir=../modules/remotebackend/regression-tests/
case $remotetype in
http)
connstr="http:url=http://localhost:62434/dns"
- ../modules/remotebackend/regression-tests/http-backend.rb &
+ rm -f remotebackend-server.log
+ rm -f remotebackend-access.log
+ $testsdir/http-backend.rb &
echo $! > pdns-remotebackend.pid
+ # make sure it runs before continuing
+ sleep 2
;;
unix)
connstr="unix:path=/tmp/remote.socket"
- socat unix-listen:/tmp/remote.socket exec:../modules/remotebackend/regression-tests/pipe-backend.rb &
+ socat unix-listen:/tmp/remote.socket,fork exec:$testsdir/unix-backend.rb &
echo $! > pdns-remotebackend.pid
;;
pipe)
- connstr="pipe:command=../modules/remotebackend/regression-tests/pipe-backend.rb"
+ connstr="pipe:command=$testsdir/pipe-backend.rb"
;;
*)
echo "Invalid usage"
@@ -375,25 +383,67 @@
;;
esac
- if [ "$remotesec" = "dnssec" ]; then
- remote_add_param="--remote-dnssec=yes"
+ skipreasons="nodnssec"
+
+ if [ "$remotesec" = "nsec3" ]; then
+ remotedosec="yes"
+ if [ "$narrow" = "narrow" ]; then
+ extracontexts="dnssec nsec3 narrow"
+ skipreasons="narrow nsec3"
+ else
+ extracontexts="dnssec nsec3"
+ skipreasons="nsec3"
+ fi
+ remote_add_param="--remote-dnssec=yes"
+ else
+ if [ "$remotesec" = "dnssec" ]; then
+ remotedosec="yes"
+ remote_add_param="--remote-dnssec=yes"
+ extracontexts="dnssec"
+ skipreasons="nonsec3 nonarrow"
+ fi
fi
+ # generate pdns.conf for pdnssec
+ cat > pdns.conf <<EOF
+launch=remote
+remote-connection-string=$connstr
+EOF
+
$RUNWRAPPER ../pdns/pdns_server --daemon=no --local-port=$port --socket-dir=./ \
--no-shuffle --launch=remote \
--query-logging --loglevel=9 --cache-ttl=0 --no-config \
--send-root-referral \
--remote-connection-string="$connstr" $remote_add_param &
- if [ "$remotesec" = "dnssec" ]
- then
- extracontexts="dnssec"
- else
- skipreasons="nodnssec"
+ echo "Setting up test database..."
+ # setup test database
+ rm -f $testsdir/remote.sqlite3
+ sqlite3 $testsdir/remote.sqlite3 < $testsdir/test-schema.sql
+ chmod 0666 $testsdir/remote.sqlite3
+ if [ "$remotedosec" = "yes" ]; then
+ echo "remote-dnssec=yes" >> pdns.conf
+ ../pdns/pdnssec --config-dir=. import-zone-key example.com $testsdir/example.com.ksk ksk
+ ../pdns/pdnssec --config-dir=. import-zone-key example.com $testsdir/example.com.zsk.1 zsk
+ ../pdns/pdnssec --config-dir=. import-zone-key example.com $testsdir/example.com.zsk.2 zsk
+ ../pdns/pdnssec --config-dir=. activate-zone-key example.com 1
+ ../pdns/pdnssec --config-dir=. activate-zone-key example.com 2
+ ../pdns/pdnssec --config-dir=. deactivate-zone-key example.com 3
+
+ ../pdns/pdnssec --config-dir=. import-zone-key up.example.com $testsdir/up.example.com.ksk ksk
+ ../pdns/pdnssec --config-dir=. import-zone-key up.example.com $testsdir/up.example.com.zsk.1 zsk
+ ../pdns/pdnssec --config-dir=. import-zone-key up.example.com $testsdir/up.example.com.zsk.2 zsk
+ ../pdns/pdnssec --config-dir=. activate-zone-key example.com 4
+ ../pdns/pdnssec --config-dir=. activate-zone-key example.com 5
+ ../pdns/pdnssec --config-dir=. deactivate-zone-key example.com 6
+
+ if [ "$remotesec" = "nsec3" ]; then
+ ../pdns/pdnssec --config-dir=. set-nsec3 example.com
+ ../pdns/pdnssec --config-dir=. set-nsec3 up.example.com
+ fi
+
fi
- testsdir=../modules/remotebackend/regression-tests/
-
;;
*)
echo unknown context $context
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment