Created
April 26, 2013 11:44
-
-
Save Habbie/5466802 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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