From: bert hubert Date: Tue, 28 Apr 2015 17:11:53 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/master' into dnsname X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~88^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4d68b3b100a968e751eec72706431d3f3ae98645;p=thirdparty%2Fpdns.git Merge remote-tracking branch 'origin/master' into dnsname Conflicts: docs/markdown/authoritative/performance.md pdns/.gitignore pdns/dnsdist.cc pdns/dnsparser.cc pdns/qtype.cc pdns/test-dns_random_hh.cc --- 4d68b3b100a968e751eec72706431d3f3ae98645 diff --cc modules/gpgsqlbackend/spgsql.cc index 7610d12fd5,0bf4792729..bcb1c7bda7 --- a/modules/gpgsqlbackend/spgsql.cc +++ b/modules/gpgsqlbackend/spgsql.cc @@@ -1,8 -1,11 +1,11 @@@ /* Copyright 2003 - 2005 Netherlabs BV, bert.hubert@netherlabs.nl. See LICENSE for more information. */ + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif #include #include "spgsql.hh" - +#include #include #include "pdns/logger.hh" #include "pdns/dns.hh" diff --cc pdns/dnspacket.cc index 730c127c1d,c6a8e5f200..e202004edd --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@@ -475,6 -478,27 +478,27 @@@ bool DNSPacket::getTSIGDetails(TSIGReco return true; } + bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, string *keyname) const + { + MOADNSParser mdp(d_rawpacket); + bool gotit=false; + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if (gotit) { + L<first.d_type == QType::TKEY) { - *tr = *boost::dynamic_pointer_cast(i->first.d_content); ++ *tr = *std::dynamic_pointer_cast(i->first.d_content); + *keyname = i->first.d_label; + gotit=true; + } + } + + return gotit; + } + /** This function takes data from the network, possibly received with recvfrom, and parses it into our class. Results of calling this function multiple times on one packet are unknown. Returns -1 if the packet cannot be parsed. diff --cc pdns/dnsparser.cc index ecc5c4a4f2,b335ae763f..fc04d9bf65 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@@ -456,6 -456,50 +457,7 @@@ string PacketReader::getText(bool multi return ret; } + -void PacketReader::getLabelFromContent(const vector& content, uint16_t& frompos, string& ret, int recurs) -{ - if(recurs > 100) // the forward reference-check below should make this test 100% obsolete - throw MOADNSException("Loop"); - // it is tempting to call reserve on ret, but it turns out it creates a malloc/free storm in the loop - int pos = frompos; - for(;;) { - unsigned char labellen=content.at(frompos++); - - if(!labellen) { - if(ret.empty()) - ret.append(1,'.'); - break; - } - else if((labellen & 0xc0) == 0xc0) { - uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)content.at(frompos++) - sizeof(dnsheader); - // cout<<"This is an offset, need to go to: "<= pos) - throw MOADNSException("forward reference during label decompression"); - return getLabelFromContent(content, offset, ret, ++recurs); - } - else if(labellen > 63) - throw MOADNSException("Overly long label during label decompression ("+lexical_cast((unsigned int)labellen)+")"); - else { - // XXX FIXME THIS MIGHT BE VERY SLOW! - - for(string::size_type n = 0 ; n < labellen; ++n, frompos++) { - if(content.at(frompos)=='.' || content.at(frompos)=='\\') { - ret.append(1, '\\'); - ret.append(1, content[frompos]); - } - else if(content.at(frompos)==' ') { - ret+="\\032"; - } - else - ret.append(1, content[frompos]); - } - ret.append(1,'.'); - } - } -} - void PacketReader::xfrBlob(string& blob) try { diff --cc pdns/dynmessenger.cc index 092569bed3,001d7a4f2a..986b4bdf15 --- a/pdns/dynmessenger.cc +++ b/pdns/dynmessenger.cc @@@ -19,9 -19,11 +19,12 @@@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif #include "dynmessenger.hh" #include +#include "utility.hh" #include #include #include @@@ -93,9 -75,8 +76,8 @@@ DynMessenger::DynMessenger(const ComboA int timeout_sec, int timeout_usec) { - *d_local.sun_path=0; d_s=socket(AF_INET, SOCK_STREAM,0); - Utility::setCloseOnExec(d_s); + setCloseOnExec(d_s); if(d_s<0) { throw PDNSException(string("socket")+strerror(errno)); diff --cc pdns/misc.cc index 1dbb5ca1f9,3605e56dd1..8d3a8b4ba2 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@@ -20,9 -20,11 +20,12 @@@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif #include #include +#include #include #include #include diff --cc pdns/packethandler.cc index 651beb1384,96f463bdab..af58d62756 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@@ -1403,3 -1417,62 +1417,62 @@@ DNSPacket *PacketHandler::questionOrRec } + void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) { + TKEYRecordContent tkey_in; - boost::shared_ptr tkey_out(new TKEYRecordContent()); ++ std::shared_ptr tkey_out(new TKEYRecordContent()); + string label, lcLabel; + + if (!p->getTKEYRecord(&tkey_in, &label)) { + L<setRcode(RCode::FormErr); + return; + } + + // retain original label for response + lcLabel = toLowerCanonic(label); + + tkey_out->d_error = 0; + tkey_out->d_mode = tkey_in.d_mode; + tkey_out->d_algo = tkey_in.d_algo; + tkey_out->d_inception = time((time_t*)NULL); + tkey_out->d_expiration = tkey_out->d_inception+15; + + if (tkey_in.d_mode == 3) { + tkey_out->d_error = 19; // BADMODE + } else if (tkey_in.d_mode == 5) { + if (p->d_havetsig == false) { // unauthenticated + if (p->d.opcode == Opcode::Update) + r->setRcode(RCode::Refused); + else + r->setRcode(RCode::NotAuth); + return; + } + tkey_out->d_error = 20; // BADNAME (because we have no support for anything here) + } else { + if (p->d_havetsig == false && tkey_in.d_mode != 2) { // unauthenticated + if (p->d.opcode == Opcode::Update) + r->setRcode(RCode::Refused); + else + r->setRcode(RCode::NotAuth); + return; + } + tkey_out->d_error = 19; // BADMODE + } + + tkey_out->d_keysize = tkey_out->d_key.size(); + tkey_out->d_othersize = tkey_out->d_other.size(); + + DNSRecord rec; + rec.d_label = label; + rec.d_ttl = 0; + rec.d_type = QType::TKEY; + rec.d_class = QClass::ANY; + rec.d_content = tkey_out; + + DNSResourceRecord rr(rec); + rr.qclass = QClass::ANY; + rr.qtype = QType::TKEY; + rr.d_place = DNSResourceRecord::ANSWER; + r->addRecord(rr); + r->commitD(); + } diff --cc pdns/pkcs11signers.cc index 6dd3c669f8,5db3386fad..d827bd4d32 --- a/pdns/pkcs11signers.cc +++ b/pdns/pkcs11signers.cc @@@ -203,410 -199,482 +199,482 @@@ public }; }; - // representation of slot - class P11KitSlot { - private: - CK_SESSION_HANDLE d_session; - CK_SLOT_ID d_slot; - P11KitModule *d_module; - public: - P11KitSlot(); - P11KitSlot(CK_SLOT_ID slot, P11KitModule *module); - P11KitSlot(const P11KitSlot& rhs); - ~P11KitSlot(); + class Pkcs11Slot { + private: + bool d_logged_in; + CK_FUNCTION_LIST* d_functions; // module functions + CK_SESSION_HANDLE d_session; + CK_SLOT_ID d_slot; + CK_RV d_err; + pthread_mutex_t d_m; - void SetSlot(CK_SLOT_ID slot); - void SetModule(P11KitModule *module); + void logError(const std::string& operation) const { + if (d_err) { + std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X)") % operation % p11_kit_strerror(d_err) % d_err ); + L<d_m), NULL); + Lock l(&d_m); + + if ((d_err = d_functions->C_OpenSession(this->d_slot, CKF_SERIAL_SESSION|CKF_RW_SESSION, 0, 0, &(this->d_session)))) { + logError("C_OpenSession"); + throw PDNSException("Could not open session"); + } + // check if we need to login + if ((d_err = d_functions->C_GetTokenInfo(d_slot, &tokenInfo)) == 0) { + d_logged_in = ((tokenInfo.flags && CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED); + } else { + logError("C_GetTokenInfo"); + throw PDNSException("Cannot get token info for slot " + boost::lexical_cast(slot)); + } + } - CK_RV OpenSession(CK_FLAGS flags); - CK_RV CloseSession(); + bool Login(const std::string& pin) { + if (d_logged_in) return true; - CK_RV GetInfo(CK_SLOT_INFO_PTR info) const; - CK_RV GetTokenInfo(CK_TOKEN_INFO_PTR info) const; + unsigned char *uPin = new unsigned char[pin.size()]; + memcpy(uPin, pin.c_str(), pin.size()); + d_err = d_functions->C_Login(this->d_session, CKU_USER, uPin, pin.size()); + memset(uPin, 0, pin.size()); + delete [] uPin; + logError("C_Login"); - CK_RV Login(const std::string& pin, CK_USER_TYPE user); - CK_RV Logout(); + if (d_err == 0) { + d_logged_in = true; + } - CK_RV GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey); - CK_RV FindObjects(const std::vector& attributes, std::vector& objects, CK_ULONG maxobjects) const; - CK_RV SetAttributeValue(CK_OBJECT_HANDLE object, const std::vector& attributes); - CK_RV GetAttributeValue(CK_OBJECT_HANDLE object, std::vector& attributes) const; + return d_logged_in; + } - CK_RV Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const; - CK_RV Verify(const std::string& data, const std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const; + bool LoggedIn() const { return d_logged_in; } - CK_RV Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) const; + CK_SESSION_HANDLE& Session() { return d_session; } - CK_RV DigestInit(CK_MECHANISM_PTR mechanism) const; - CK_RV DigestUpdate(const std::string& data) const; - CK_RV DigestUpdate(CK_OBJECT_HANDLE key) const; - CK_RV DigestFinal(std::string& result) const; + CK_FUNCTION_LIST* f() { return d_functions; } + + pthread_mutex_t *m() { return &d_m; } }; - // representation of module (or Engine) - class P11KitModule - { + class Pkcs11Token { + private: - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + + CK_OBJECT_HANDLE d_public_key; + CK_OBJECT_HANDLE d_private_key; + CK_KEY_TYPE d_key_type; + + CK_ULONG d_bits; + std::string d_exponent; + std::string d_modulus; + std::string d_ec_point; + std::string d_ecdsa_params; + + std::string d_label; + + CK_RV d_err; + + void logError(const std::string& operation) const { + if (d_err) { + std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X)") % operation % p11_kit_strerror(d_err) % d_err ); + L<& slot, const std::string& label); ++ Pkcs11Token(const std::shared_ptr& slot, const std::string& label); + ~Pkcs11Token(); + + bool Login(const std::string& pin) { + if (pin.empty()) return CKR_PIN_INVALID; // no empty pin. + Lock l(d_slot->m()); - P11KitModule() {} + if (d_slot->Login(pin) == true) { + LoadAttributes(); + } - P11KitModule(const std::string& module) { - this->d_module = module; + return LoggedIn(); } - P11KitModule(const P11KitModule& rhs) { - functions = rhs.functions; - d_module = rhs.d_module; + bool LoggedIn() const { return d_slot->LoggedIn(); } + + void LoadAttributes() { + std::vector attr; + std::vector key; + attr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY)); + // attr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); + attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); + FindObjects2(attr, key, 1); + if (key.size() == 0) { + L<d_module = module; - }; + int GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) { + Lock l(d_slot->m()); - // basically get the function list - bool initialize() { - #ifdef HAVE_P11KIT1_V2 - functions = p11_kit_module_for_name(p11_modules, d_module.c_str()); - #else - functions = p11_kit_registered_name_to_module(d_module.c_str()); - #endif - if (functions == NULL) return false; - return true; - }; + size_t k; + CK_ATTRIBUTE_PTR pubAttr, privAttr; + pubAttr = new CK_ATTRIBUTE[pubAttributes.size()]; + privAttr = new CK_ATTRIBUTE[privAttributes.size()]; - // convenience method + checking that slot exists - bool GetSlot(CK_SLOT_ID slotId, P11KitSlot &slot) { - _CK_SLOT_INFO info; - if (this->functions->C_GetSlotInfo(slotId, &info)) { - return false; + k = 0; + BOOST_FOREACH(P11KitAttribute& attribute, pubAttributes) { + attribute.rattr(pubAttr+k); + k++; } - slot.SetSlot(slotId); - slot.SetModule(this); - return true; - }; - }; - P11KitSlot::P11KitSlot() { d_module = NULL; }; + k = 0; + BOOST_FOREACH(P11KitAttribute& attribute, privAttributes) { + attribute.rattr(privAttr+k); + k++; + } - P11KitSlot::P11KitSlot(CK_SLOT_ID slot, P11KitModule *module) - { - this->d_slot = slot; - this->d_module = module; - } + d_err = this->d_slot->f()->C_GenerateKeyPair(d_slot->Session(), mechanism, pubAttr, pubAttributes.size(), privAttr, privAttributes.size(), pubKey, privKey); + logError("C_GenerateKeyPair"); + delete [] pubAttr; + delete [] privAttr; - P11KitSlot::P11KitSlot(const P11KitSlot &rhs) - { - this->d_slot = rhs.d_slot; - this->d_module = rhs.d_module; - this->d_session = rhs.d_session; - } + if (d_err == 0) LoadAttributes(); - P11KitSlot::~P11KitSlot() - { - if (this->d_module && this->d_session) - this->d_module->functions->C_CloseSession(this->d_session); - } + return d_err; + } - // DO NOT CALL THIS ON YOUR OWN - void P11KitSlot::SetSlot(CK_SLOT_ID slot) { - this->d_slot = slot; - } + int Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); - // DO NOT CALL THIS ON YOUR OWN - void P11KitSlot::SetModule(P11KitModule *module) { - this->d_module = module; - } + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most signatures. - // Create new session, mostly uses CKF_SERIAL_SESSION (which is mandatory flag) - // Another flag you can pass is CFK_RW_SESSION - CK_RV P11KitSlot::OpenSession(CK_FLAGS flags) - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_OpenSession(this->d_slot, flags, 0, 0, &(this->d_session)); - } + // perform signature + if ((d_err = this->d_slot->f()->C_SignInit(d_slot->Session(), mechanism, d_private_key))) { logError("C_SignInit"); return d_err; } + d_err = this->d_slot->f()->C_Sign(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen); - CK_RV P11KitSlot::CloseSession() - { - if (!this->d_module) return 0xff; - CK_RV rv = this->d_module->functions->C_CloseSession(this->d_session); - this->d_session = 0; - return rv; - } + if (!d_err) { + result.assign((char*)buffer, buflen); + } - CK_RV P11KitSlot::GetInfo(CK_SLOT_INFO_PTR info) const - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_GetSlotInfo(this->d_slot, info); - } + memset(buffer,0,sizeof buffer); + logError("C_Sign"); + return d_err; + } - CK_RV P11KitSlot::GetTokenInfo(CK_TOKEN_INFO_PTR info) const - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_GetTokenInfo(this->d_slot, info); - } + int Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); - CK_RV P11KitSlot::Login(const std::string& pin, CK_USER_TYPE user) - { - if (!this->d_module) return 0xff; - CK_RV rv; - unsigned char *pPin; - pPin = new unsigned char[pin.size()]; - pin.copy(reinterpret_cast(pPin), pin.size()); - rv = this->d_module->functions->C_Login(this->d_session, user, pPin, pin.size()); - delete [] pPin; - return rv; - } + if ((d_err = this->d_slot->f()->C_VerifyInit(d_slot->Session(), mechanism, d_public_key))) { logError("C_VerifyInit"); return d_err; } + d_err = this->d_slot->f()->C_Verify(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size()); + logError("C_Verify"); + return d_err; + } - CK_RV P11KitSlot::Logout() - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_Logout(this->d_slot); - } + int Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); - CK_RV P11KitSlot::GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) { - if (!this->d_module) return 0xff; + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + if ((d_err = this->d_slot->f()->C_DigestInit(d_slot->Session(), mechanism))) { logError("C_DigestInit"); return d_err; } + d_err = this->d_slot->f()->C_Digest(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_Digest"); + return d_err; + } - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR pubAttr, privAttr; - pubAttr = new CK_ATTRIBUTE[pubAttributes.size()]; - privAttr = new CK_ATTRIBUTE[privAttributes.size()]; - - k = 0; - BOOST_FOREACH(P11KitAttribute& attribute, pubAttributes) { - attribute.rattr(pubAttr+k); - k++; - } + int DigestInit(CK_MECHANISM_PTR mechanism) { + d_err = d_slot->f()->C_DigestInit(d_slot->Session(), mechanism); + logError("C_DigestInit"); + return d_err; + } - k = 0; - BOOST_FOREACH(P11KitAttribute& attribute, privAttributes) { - attribute.rattr(privAttr+k); - k++; - } + int DigestUpdate(const std::string& data) { + d_err = d_slot->f()->C_DigestUpdate(d_slot->Session(), (unsigned char*)data.c_str(), data.size()); + logError("C_DigestUpdate"); + return d_err; + } - rv = this->d_module->functions->C_GenerateKeyPair(d_session, mechanism, pubAttr, pubAttributes.size(), privAttr, privAttributes.size(), pubKey, privKey); + int DigestKey(std::string& result) { + Lock l(d_slot->m()); + CK_MECHANISM mech; + mech.mechanism = CKM_SHA_1; - delete [] pubAttr; - delete [] privAttr; + DigestInit(&mech); - return rv; - } + if (d_key_type == CKK_RSA) { + DigestUpdate(d_modulus); + DigestUpdate(d_exponent); + } else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) { + DigestUpdate(d_ec_point); + } - // Finds object(s) that match exactly to attributes - CK_RV P11KitSlot::FindObjects(const std::vector& attributes, std::vector& objects, unsigned long maxobjects) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - unsigned long count; - CK_ATTRIBUTE_PTR attr; - CK_OBJECT_HANDLE_PTR handles = new CK_OBJECT_HANDLE[maxobjects]; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(const P11KitAttribute& attribute, attributes) { - attribute.rattr(attr+k); - k++; - } + DigestFinal(result); - // perform search - rv = this->d_module->functions->C_FindObjectsInit(d_session, attr, k); + return d_err; + } - if (rv) { - delete [] attr; - delete [] handles; - return rv; - } + int DigestFinal(std::string& result) { + CK_BYTE buffer[1024] = {0}; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + d_err = d_slot->f()->C_DigestFinal(d_slot->Session(), buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_DigestFinal"); + return d_err; + } + + int FindObjects(const std::vector& attributes, std::vector& objects, int maxobjects) { + Lock l(d_slot->m()); + return FindObjects2(attributes, objects, maxobjects); + } - count = maxobjects; - rv = this->d_module->functions->C_FindObjects(d_session, handles, maxobjects, &count); + int FindObjects2(const std::vector& attributes, std::vector& objects, int maxobjects) { + CK_RV rv; + size_t k; + unsigned long count; - if (!rv) { - objects.clear(); - for(k=0;kd_slot->f()->C_FindObjectsInit(d_slot->Session(), attr, k); + + if (d_err) { + delete [] attr; + delete [] handles; + logError("C_FindObjectsInit"); + return d_err; + } + + count = maxobjects; + rv = d_err = this->d_slot->f()->C_FindObjects(d_slot->Session(), handles, maxobjects, &count); + objects.clear(); + + if (!rv) { + for(k=0;kd_slot->f()->C_FindObjectsFinal(d_slot->Session()); + logError("C_FindObjectsFinal"); + + return rv; } - } - delete [] attr; - delete [] handles; + int GetAttributeValue(const CK_OBJECT_HANDLE& object, std::vector& attributes) + { + Lock l(d_slot->m()); + return GetAttributeValue2(object, attributes); + } - this->d_module->functions->C_FindObjectsFinal(d_session); + int GetAttributeValue2(const CK_OBJECT_HANDLE& object, std::vector& attributes) + { + size_t k; + CK_ATTRIBUTE_PTR attr; + attr = new CK_ATTRIBUTE[attributes.size()]; - return rv; - }; + k = 0; + BOOST_FOREACH(P11KitAttribute &attribute, attributes) { + attribute.wattr(attr+k); + k++; + } - // TODO: Untested codepath - CK_RV P11KitSlot::SetAttributeValue(CK_OBJECT_HANDLE object, const std::vector& attributes) - { - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR attr; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(const P11KitAttribute &attribute, attributes) { - attribute.rattr(attr+k); - k++; - } + // round 1 - get attribute sizes + d_err = d_slot->f()->C_GetAttributeValue(d_slot->Session(), object, attr, attributes.size()); + logError("C_GetAttributeValue"); + if (d_err) { + delete [] attr; + return d_err; + } - rv = this->d_module->functions->C_SetAttributeValue(d_session, object, attr, attributes.size()); + // then allocate memory + for(size_t k=0; k < attributes.size(); k++) { + if (attributes[k].valueType() == Attribute_String) { + attr[k].pValue = attributes[k].allocate(attr[k].ulValueLen); + } + } - delete [] attr; - return rv; - } + // round 2 - get actual values + d_err = d_slot->f()->C_GetAttributeValue(d_slot->Session(), object, attr, attributes.size()); + logError("C_GetAttributeValue"); - CK_RV P11KitSlot::GetAttributeValue(CK_OBJECT_HANDLE object, std::vector& attributes) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - size_t k; - CK_ATTRIBUTE_PTR attr; - attr = new CK_ATTRIBUTE[attributes.size()]; - - k = 0; - BOOST_FOREACH(P11KitAttribute &attribute, attributes) { - attribute.wattr(attr+k); - k++; - } + // copy values to map and release allocated memory + for(size_t k=0; k < attributes.size(); k++) { + if (attributes[k].valueType() == Attribute_String) { + attributes[k].commit(attr[k].ulValueLen); + } + } - // round 1 - get attribute sizes - rv = this->d_module->functions->C_GetAttributeValue(d_session, object, attr, attributes.size()); + delete [] attr; - if (rv) { - delete [] attr; - return rv; - } + return d_err; + }; - // then allocate memory - for(size_t k=0; k < attributes.size(); k++) { - if (attributes[k].valueType() == Attribute_String) { - attr[k].pValue = attributes[k].allocate(attr[k].ulValueLen); + const std::string& Modulus() { + return d_modulus; } - } - // round 2 - get actual values - rv = this->d_module->functions->C_GetAttributeValue(d_session, object, attr, attributes.size()); + const std::string& Exponent() { + return d_exponent; + } - // copy values to map and release allocated memory - for(size_t k=0; k < attributes.size(); k++) { - if (attributes[k].valueType() == Attribute_String) { - attributes[k].commit(attr[k].ulValueLen); + const std::string& ECPoint() { + return d_ec_point; + } + + const std::string& ECParameters() { + return d_ecdsa_params; + } + + CK_KEY_TYPE KeyType() { + return d_key_type; } - } - delete [] attr; + CK_ULONG Bits() { + return d_bits; + } - return rv; - static boost::shared_ptr GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label); ++ static std::shared_ptr GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label); }; - CK_RV P11KitSlot::Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most signatures. - - // perform signature - if ((rv = this->d_module->functions->C_SignInit(d_session, mechanism, key))) return rv; // well that failed. - rv = this->d_module->functions->C_Sign(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); -static std::map > pkcs11_slots; -static std::map > pkcs11_tokens; ++static std::map > pkcs11_slots; ++static std::map > pkcs11_tokens; + -boost::shared_ptr Pkcs11Token::GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label) { ++std::shared_ptr Pkcs11Token::GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label) { + // see if we can find module + std::string tidx = module; + tidx.append("|"); + tidx.append(boost::lexical_cast(slotId)); + std::string sidx = tidx; + tidx.append("|"); + tidx.append(label); - std::map >::iterator tokenIter; - std::map >::iterator slotIter; ++ std::map >::iterator tokenIter; ++ std::map >::iterator slotIter; + CK_RV err; + CK_FUNCTION_LIST* functions; + + if ((tokenIter = pkcs11_tokens.find(tidx)) != pkcs11_tokens.end()) return tokenIter->second; + + // see if we have slot + if ((slotIter = pkcs11_slots.find(sidx)) != pkcs11_slots.end()) { + pkcs11_tokens[tidx] = boost::make_shared(slotIter->second, label); + return pkcs11_tokens[tidx]; } - memset(buffer,0,sizeof buffer); - return rv; - }; + #ifdef HAVE_P11KIT1_V2 + functions = p11_kit_module_for_name(p11_modules, module.c_str()); + #else + functions = p11_kit_registered_name_to_module(module.c_str()); + #endif + if (functions == NULL) throw PDNSException("Cannot find PKCS#11 module " + module); + functions->C_Initialize(NULL); // initialize the module in case it hasn't been done yet. - CK_RV P11KitSlot::Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - if ((rv = this->d_module->functions->C_VerifyInit(d_session, mechanism, key))) return rv; - rv = this->d_module->functions->C_Verify(d_session, (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size()); - return rv; - }; + // try to locate a slot + _CK_SLOT_INFO info; + unsigned long slots; - CK_RV P11KitSlot::Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most digests - if ((rv = this->d_module->functions->C_DigestInit(d_session, mechanism))) return rv; - rv = this->d_module->functions->C_Digest(d_session, (unsigned char*)data.c_str(), data.size(), buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); + // this is required by certain tokens, otherwise C_GetSlotInfo will not return a token + err = functions->C_GetSlotList(CK_FALSE, NULL_PTR, &slots); + if (err) + L<(slotId) + std::string(" on module ") + module + std::string(": error code ") + boost::lexical_cast(err)); } - memset(buffer,0,sizeof buffer); - return rv; - }; + // store slot + pkcs11_slots[sidx] = boost::make_shared(functions, slotId); - CK_RV P11KitSlot::DigestInit(CK_MECHANISM_PTR mechanism) const - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestInit(d_session, mechanism); - } + // looks ok to me. + pkcs11_tokens[tidx] = boost::make_shared(pkcs11_slots[sidx], label); - CK_RV P11KitSlot::DigestUpdate(const std::string& data) const - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestUpdate(d_session, (unsigned char*)data.c_str(), data.size()); + return pkcs11_tokens[tidx]; } - CK_RV P11KitSlot::DigestUpdate(CK_OBJECT_HANDLE key) const - { - if (!this->d_module) return 0xff; - return this->d_module->functions->C_DigestKey(d_session, key); - } - - CK_RV P11KitSlot::DigestFinal(std::string& result) const - { - if (!this->d_module) return 0xff; - CK_RV rv; - CK_BYTE buffer[1024]; - CK_ULONG buflen = sizeof buffer; // should be enough for most digests - rv = this->d_module->functions->C_DigestFinal(d_session, buffer, &buflen); - if (!rv) { - result.assign((char*)buffer, buflen); - } - memset(buffer,0,sizeof buffer); - return rv; -Pkcs11Token::Pkcs11Token(const boost::shared_ptr& slot, const std::string& label) { ++Pkcs11Token::Pkcs11Token(const std::shared_ptr& slot, const std::string& label) { + // open a session + this->d_bits = 0; + this->d_slot = slot; + this->d_label = label; + this->d_err = 0; + Lock l(d_slot->m()); + if (this->d_slot->LoggedIn()) LoadAttributes(); } - // map between engine names and engines - static std::map pkcs11_engines; - // map between engine names and slots (not used now) - //static std::map pkcs11_slots; - - static bool pkcs11_GetSlot(const std::string& engine, CK_SLOT_ID slotId, const std::string& pin, CK_FLAGS flags, P11KitSlot& slot) - { - CK_RV rv; - if (engine.empty()) return false; - - // open module if necessary - if (pkcs11_engines.find(engine) == pkcs11_engines.end()) { - P11KitModule module(engine); - if (module.initialize() == false) { - throw PDNSException("Cannot initialize or unknown PKCS#11 engine " + engine); - } - pkcs11_engines[engine] = module; - } - pkcs11_engines[engine].GetSlot(slotId, slot); - rv = slot.OpenSession(flags); - if (rv) { - return false; - }; - rv = slot.Login(pin, CKU_USER); - if (rv) { - L< d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + std::string pubExp("\000\001\000\001", 4); // 65537 - + pubAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY)); pubAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA)); pubAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE)); @@@ -656,19 -726,14 +726,14 @@@ } }; - std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { + std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { std::string result; - std::vector key; - std::vector attr; - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - // find key that can be used for signing - attr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - d_slot.FindObjects(attr, key, 1); - // hopefully we have a key - if (key.size() == 0) return ""; - // choose mech - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + CK_MECHANISM mech; mech.mechanism = dnssec2smech[d_algorithm]; mech.pParameter = NULL; @@@ -683,10 -753,13 +753,13 @@@ std::string PKCS11DNSCryptoKeyEngine::h mech.mechanism = dnssec2hmech[d_algorithm]; mech.pParameter = NULL; mech.ulParameterLen = 0; - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); - if (d_slot.Digest(msg, result, &mech)) { + if (d_slot->Digest(msg, result, &mech)) { // FINE! I'll do this myself, then, shall I? switch(d_algorithm) { case 5: { @@@ -720,109 -793,71 +793,71 @@@ }; bool PKCS11DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const { - bool result; - std::vector key; - std::vector attr; - // find a key that can be used to verify signatures - attr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - // hopefully we have a key - if (key.size() == 0) return ""; - // choose mech - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + CK_MECHANISM mech; mech.mechanism = dnssec2smech[d_algorithm]; mech.pParameter = NULL; mech.ulParameterLen = 0; - result = d_slot.Verify(msg, signature, &mech, key[0]); - return result; + if (mech.mechanism == CKM_ECDSA) { + return (d_slot->Verify(this->hash(msg), signature, &mech)==0); + } else { + return (d_slot->Verify(msg, signature, &mech) == 0); + } }; - std::string PKCS11DNSCryptoKeyEngine::getPubKeyHash() const { - std::string result = ""; - std::vector key; - std::vector attr; + std::string PKCS11DNSCryptoKeyEngine::getPubKeyHash() const { // find us a public key - attr.push_back(P11KitAttribute(CKA_CLASS, CKO_PUBLIC_KEY)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS, "")); - attr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, "")); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - CK_MECHANISM mech; - mech.mechanism = CKM_SHA_1; - d_slot.DigestInit(&mech); - d_slot.DigestUpdate(attr[0].str()); - d_slot.DigestUpdate(attr[1].str()); - d_slot.DigestFinal(result); - } - } - return result; - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + std::string result; + if (d_slot->DigestKey(result) == 0) return result; + throw PDNSException("Could not digest key (maybe it's missing?)"); }; std::string PKCS11DNSCryptoKeyEngine::getPublicKeyString() const { std::string result(""); - std::vector key; - std::vector attr; - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS, "")); - attr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, "")); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - if(attr[1].str().length() < 255) - result.assign(1, (char) (unsigned int) attr[1].str().length()); - else { - result.assign(1, 0); - uint16_t len=htons(attr[1].str().length()); - result.append((char*)&len, 2); - } - result.append(attr[1].str()); - result.append(attr[0].str()); - } - // } else { - // std::cerr << "Could not find key" << std::endl; - } - return result; - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + if (d_slot->KeyType() == CKK_RSA) { + if (d_slot->Exponent().length() < 255) { + result.assign(1, (char) (unsigned int) d_slot->Exponent().length()); + } else { + result.assign(1, 0); + uint16_t len=htons(d_slot->Exponent().length()); + result.append((char*)&len, 2); + } + result.append(d_slot->Exponent()); + result.append(d_slot->Modulus()); + } else { + result.append(d_slot->ECPoint()); + } + return result; }; int PKCS11DNSCryptoKeyEngine::getBits() const { - int bits = -1; - std::vector key; - std::vector attr; - attr.push_back(P11KitAttribute(CKA_CLASS, CKO_PUBLIC_KEY)); - attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); - P11KitSlot d_slot; - pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION, d_slot); - - // std::cerr << "Looking for " << d_label << " from " << d_slot_id << std::endl; - - d_slot.FindObjects(attr, key, 1); - if (key.size() > 0) { - attr.clear(); - attr.push_back(P11KitAttribute(CKA_MODULUS_BITS, 0UL)); - if (d_slot.GetAttributeValue(key[0], attr) == 0) { - bits = static_cast(attr[0].ulong()); - } - // } else { - // std::cerr << "Could not find key" << std::endl; - } - return bits; - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + return d_slot->Bits(); }; - DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const { + DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const { storvector_t storvect; typedef std::vector > outputs_t; outputs_t outputs; @@@ -836,6 -871,21 +871,21 @@@ return storvect; }; + void PKCS11DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, stormap_t& stormap) { + drc.d_algorithm = atoi(stormap["algorithm"].c_str()); + d_module = stormap["engine"]; + d_slot_id = atoi(stormap["slot"].c_str()); + d_pin = stormap["pin"]; + d_label = stormap["label"]; + // validate parameters + - boost::shared_ptr d_slot; ++ std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label); + if (d_pin != "" && d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Could not log in to token (PIN wrong?)"); + }; + DNSCryptoKeyEngine* PKCS11DNSCryptoKeyEngine::maker(unsigned int algorithm) { return new PKCS11DNSCryptoKeyEngine(algorithm); diff --cc pdns/rec_channel.cc index 26cb32a7d4,77a5d68bac..a539643e48 --- a/pdns/rec_channel.cc +++ b/pdns/rec_channel.cc @@@ -1,5 -1,7 +1,8 @@@ + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif #include "rec_channel.hh" +#include "utility.hh" #include #include #include "misc.hh" diff --cc pdns/test-dns_random_hh.cc index c4e1fbb5cd,5e9eb4df31..f28a50b9be --- a/pdns/test-dns_random_hh.cc +++ b/pdns/test-dns_random_hh.cc @@@ -1,9 -1,8 +1,8 @@@ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_NO_MAIN -#ifdef HAVE_CONFIG_H + #include "config.h" - #ifndef HAVE_CXX11 - + #endif #include #include #include @@@ -47,8 -42,4 +46,8 @@@ BOOST_AUTO_TEST_CASE(test_dns_random_av // please add covariance tests, chi-square, Kolmogorov-Smirnov } + + BOOST_AUTO_TEST_SUITE_END() + - #endif ++#endif