]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge remote-tracking branch 'origin/master' into dnsname
authorbert hubert <bert.hubert@netherlabs.nl>
Tue, 28 Apr 2015 17:11:53 +0000 (19:11 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Tue, 28 Apr 2015 17:11:53 +0000 (19:11 +0200)
Conflicts:
docs/markdown/authoritative/performance.md
pdns/.gitignore
pdns/dnsdist.cc
pdns/dnsparser.cc
pdns/qtype.cc
pdns/test-dns_random_hh.cc

47 files changed:
1  2 
.travis.yml
configure.ac
modules/bindbackend/bindbackend2.hh
modules/gpgsqlbackend/gpgsqlbackend.cc
modules/gpgsqlbackend/spgsql.cc
modules/pipebackend/coprocess.cc
modules/remotebackend/Makefile.am
modules/remotebackend/pipeconnector.cc
pdns/Makefile-recursor
pdns/common_startup.cc
pdns/dbdnsseckeeper.cc
pdns/dist-recursor
pdns/dns.hh
pdns/dnsgram.cc
pdns/dnspacket.cc
pdns/dnsparser.cc
pdns/dnsproxy.cc
pdns/dnsreplay.cc
pdns/dnsscope.cc
pdns/dnswriter.cc
pdns/dynlistener.cc
pdns/dynloader.cc
pdns/dynmessenger.cc
pdns/iputils.cc
pdns/misc.cc
pdns/nameserver.cc
pdns/packethandler.cc
pdns/pdns_recursor.cc
pdns/pkcs11signers.cc
pdns/qtype.hh
pdns/rcpgenerator.cc
pdns/rec_channel.cc
pdns/rec_channel_rec.cc
pdns/recursor_cache.cc
pdns/resolver.cc
pdns/rfc2136handler.cc
pdns/signingpipe.cc
pdns/speedtest.cc
pdns/ssqlite3.cc
pdns/tcpreceiver.cc
pdns/test-dns_random_hh.cc
pdns/test-dnsrecords_cc.cc
pdns/test-misc_hh.cc
pdns/test-zoneparser_tng_cc.cc
pdns/tsig-tests.cc
pdns/unix_utility.cc
pdns/ws-api.cc

diff --cc .travis.yml
Simple merge
diff --cc configure.ac
Simple merge
Simple merge
index 7610d12fd59b88c1d2cbe813c2c5f5f42ace5936,0bf4792729cf1da6afaeb761c95b965d8ff1296b..bcb1c7bda72ddbbf2a070ce5b67cbbdb817492d8
@@@ -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 <string>
  #include "spgsql.hh"
 -
 +#include <sys/time.h>
  #include <iostream>
  #include "pdns/logger.hh"
  #include "pdns/dns.hh"
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc pdns/dns.hh
Simple merge
diff --cc pdns/dnsgram.cc
Simple merge
index 730c127c1dcf1e708a3f86f3c2cb10a721b539f1,c6a8e5f200b0c9b12b59f6ceccfc05100ab9bcba..e202004edd528d3c5a680636e3b529464eef6775
@@@ -475,6 -478,27 +478,27 @@@ bool DNSPacket::getTSIGDetails(TSIGReco
    return true;
  }
  
 -      *tr = *boost::dynamic_pointer_cast<TKEYRecordContent>(i->first.d_content);
+ 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<<Logger::Error<<"More than one TKEY record found in query"<<endl;
+       return false;
+     }
+     if(i->first.d_type == QType::TKEY) {
++      *tr = *std::dynamic_pointer_cast<TKEYRecordContent>(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.
index ecc5c4a4f2edcd25f78393879bb9eccaec60960e,b335ae763fc3177e40758618168a88f01311566b..fc04d9bf65db480d1168b43b6271c92bbcd321ef
@@@ -456,6 -456,50 +457,7 @@@ string PacketReader::getText(bool multi
    return ret;
  }
  
 -void PacketReader::getLabelFromContent(const vector<uint8_t>& 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: "<<offset<<endl;
 -
 -      if(offset >= 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<string>((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
  {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 092569bed3702ff1ee546ac9a318602fcfda6b77,001d7a4f2a1cdd2d92903e1dc61b29c5974cd0db..986b4bdf154234eb2001e63ad7120803c01f899e
      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 <cstdio>
 +#include "utility.hh"
  #include <cstdlib>
  #include <cstring>
  #include <cerrno>
@@@ -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/iputils.cc
Simple merge
diff --cc pdns/misc.cc
index 1dbb5ca1f9fe652c3088bcb79b7a545b53b1e438,3605e56dd170e2feb778f3e4d95d712b096e492e..8d3a8b4ba22b920fb68ae1f0a088c0a5cf3cf07d
      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
  #include <sys/param.h>
  #include <sys/socket.h>
 +#include <fcntl.h>
  #include <netdb.h>
  #include <sys/time.h>
  #include <time.h>
Simple merge
index 651beb1384d7c697060a97c88798ad6fecd6eb9f,96f463bdabe284780f932c501ca1551ea0b1f261..af58d62756342632a2498b660b12043175bb5aed
@@@ -1403,3 -1417,62 +1417,62 @@@ DNSPacket *PacketHandler::questionOrRec
  
  }
  
 -  boost::shared_ptr<TKEYRecordContent> tkey_out(new TKEYRecordContent());
+ void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) {
+   TKEYRecordContent tkey_in;
++  std::shared_ptr<TKEYRecordContent> tkey_out(new TKEYRecordContent());
+   string label, lcLabel;
+   if (!p->getTKEYRecord(&tkey_in, &label)) {
+     L<<Logger::Error<<"TKEY request but no TKEY RR found"<<endl;
+     r->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();
+ }
Simple merge
index 6dd3c669f80bc90be0be9bea2d73313a76a99ee7,5db3386fad0ae65318cb31c072e4fe187c6d82df..d827bd4d323da0e7fa049c6fce1825d1f41a7390
@@@ -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<<Logger::Error<< msg << endl;
+       }
+     }
+   public:
+     Pkcs11Slot(CK_FUNCTION_LIST* functions, const CK_SLOT_ID& slot) {
+       CK_TOKEN_INFO tokenInfo;
+       d_slot = slot;
+       d_functions = functions;
+       d_err = 0;
+       d_logged_in = false;
+       pthread_mutex_init(&(this->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<std::string>(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<P11KitAttribute>& pubAttributes, std::vector<P11KitAttribute>& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey);
-   CK_RV FindObjects(const std::vector<P11KitAttribute>& attributes, std::vector<CK_OBJECT_HANDLE>& objects, CK_ULONG maxobjects) const;
-   CK_RV SetAttributeValue(CK_OBJECT_HANDLE object, const std::vector<P11KitAttribute>& attributes);
-   CK_RV GetAttributeValue(CK_OBJECT_HANDLE object, std::vector<P11KitAttribute>& 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<Pkcs11Slot> d_slot;
++    std::shared_ptr<Pkcs11Slot> 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<<Logger::Error<< msg << endl;
+       }
+     }
    public:
-     std::string d_module;
-     CK_FUNCTION_LIST_PTR functions;
 -    Pkcs11Token(const boost::shared_ptr<Pkcs11Slot>& slot, const std::string& label); 
++    Pkcs11Token(const std::shared_ptr<Pkcs11Slot>& 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<P11KitAttribute> attr;
+       std::vector<CK_OBJECT_HANDLE> 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<<Logger::Warning<<"Cannot load PCKS#11 private key "<<d_label<<std::endl;;
+         return;
+       }
+       d_private_key = key[0];
+       attr.clear();
+       attr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY));
+ //      attr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE));
+       attr.push_back(P11KitAttribute(CKA_LABEL, d_label));
+       FindObjects2(attr, key, 1);
+       if (key.size() == 0) {
+         L<<Logger::Warning<<"Cannot load PCKS#11 public key "<<d_label<<std::endl;
+         return;
+       }
+       d_public_key = key[0];
+       attr.clear();
+       attr.push_back(P11KitAttribute(CKA_KEY_TYPE, 0UL));
+       if (GetAttributeValue2(d_public_key, attr)==0) {
+         d_key_type = attr[0].ulong();
+         if (d_key_type == CKK_RSA) {
+           attr.clear();
+           attr.push_back(P11KitAttribute(CKA_MODULUS, ""));
+           attr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, ""));
+           attr.push_back(P11KitAttribute(CKA_MODULUS_BITS, 0UL));
+           if (!GetAttributeValue2(d_public_key, attr)) {
+             d_modulus = attr[0].str();
+             d_exponent = attr[1].str();
+             d_bits = attr[2].ulong();
+           } else {
+             throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_label);
+           }
+         } else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) {
+           attr.clear();
+           attr.push_back(P11KitAttribute(CKA_ECDSA_PARAMS, ""));
+           attr.push_back(P11KitAttribute(CKA_EC_POINT, ""));
+           if (!GetAttributeValue2(d_public_key, attr)) {
+             d_ecdsa_params = attr[0].str();
+             if (d_ecdsa_params == "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07") d_bits = 256;
+             if (d_ecdsa_params == "\x06\x05\x2b\x81\x04\x00\x22") d_bits = 384;
+             d_ec_point = attr[1].str();
+           } else {
+             throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_label);
+           }
+         } else {
+           throw PDNSException("Cannot determine type for PCKS#11 public key " + d_label);
+         }
+       } else {
+         throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_label);
+       }
      }
  
-     void setModule(const std::string& module) {
-       this->d_module = module;
-     };
+     int GenerateKeyPair(CK_MECHANISM_PTR mechanism, std::vector<P11KitAttribute>& pubAttributes, std::vector<P11KitAttribute>& 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<char*>(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<P11KitAttribute>& pubAttributes, std::vector<P11KitAttribute>& 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<P11KitAttribute>& attributes, std::vector<CK_OBJECT_HANDLE>& 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<P11KitAttribute>& attributes, std::vector<CK_OBJECT_HANDLE>& 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<P11KitAttribute>& attributes, std::vector<CK_OBJECT_HANDLE>& objects, int maxobjects) {
+       CK_RV rv;
+       size_t k;
+       unsigned long count;
  
-   if (!rv) {
-     objects.clear();
-     for(k=0;k<count;k++) {
-       objects.push_back(handles[k]);
+       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++;
+       }
+       // perform search
+       d_err = this->d_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;k<count;k++) {
+           objects.push_back(handles[k]);
+         }
+       }
+       logError("C_FindObjects");
+       delete [] attr;
+       delete [] handles;
+       d_err = this->d_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<P11KitAttribute>& 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<P11KitAttribute>& 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<P11KitAttribute>& 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<P11KitAttribute>& 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<Pkcs11Token> GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label);
++    static std::shared_ptr<Pkcs11Token> 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<std::string, boost::shared_ptr<Pkcs11Slot> > pkcs11_slots;
 -static std::map<std::string, boost::shared_ptr<Pkcs11Token> > pkcs11_tokens;
++static std::map<std::string, std::shared_ptr<Pkcs11Slot> > pkcs11_slots;
++static std::map<std::string, std::shared_ptr<Pkcs11Token> > pkcs11_tokens;
 -boost::shared_ptr<Pkcs11Token> Pkcs11Token::GetToken(const std::string& module, const CK_SLOT_ID& slotId, const std::string& label) {
++std::shared_ptr<Pkcs11Token> 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<std::string>(slotId));
+   std::string sidx = tidx;
+   tidx.append("|");
+   tidx.append(label);
 -  std::map<std::string, boost::shared_ptr<Pkcs11Token> >::iterator tokenIter;
 -  std::map<std::string, boost::shared_ptr<Pkcs11Slot> >::iterator slotIter;
++  std::map<std::string, std::shared_ptr<Pkcs11Token> >::iterator tokenIter;
++  std::map<std::string, std::shared_ptr<Pkcs11Slot> >::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<Pkcs11Token>(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<<Logger::Warning<<"C_GetSlotList(CK_FALSE, NULL_PTR, &slots) = " << err << std::endl;
+   if ((err = functions->C_GetSlotInfo(slotId, &info))) {
+     throw PDNSException(std::string("Cannot find PKCS#11 slot ") + boost::lexical_cast<std::string>(slotId) + std::string(" on module ") + module + std::string(": error code ") + boost::lexical_cast<std::string>(err));
    }
-   memset(buffer,0,sizeof buffer);
  
-   return rv;
};
+   // store slot
  pkcs11_slots[sidx] = boost::make_shared<Pkcs11Slot>(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<Pkcs11Token>(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<Pkcs11Slot>& slot, const std::string& label) {
++Pkcs11Token::Pkcs11Token(const std::shared_ptr<Pkcs11Slot>& 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<std::string, P11KitModule> pkcs11_engines;
- // map between engine names and slots (not used now)
- //static std::map<std::string, CK_SLOT_ID> 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<<Logger::Error<<"Login failed for " << engine << " slot " << slotId << ": " << rv <<std::endl;
-   };
-   return rv == 0;
+ Pkcs11Token::~Pkcs11Token() {
  }
  
  PKCS11DNSCryptoKeyEngine::PKCS11DNSCryptoKeyEngine(unsigned int algorithm): DNSCryptoKeyEngine(algorithm) {}
@@@ -619,10 -687,14 +687,14 @@@ void PKCS11DNSCryptoKeyEngine::create(u
    CK_MECHANISM mech;
    CK_OBJECT_HANDLE pubKey, privKey;
    CK_RV rv;
-   P11KitSlot d_slot;
-   pkcs11_GetSlot(d_engine, d_slot_id, d_pin, CKF_SERIAL_SESSION|CKF_RW_SESSION, d_slot);
 -  boost::shared_ptr<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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));
    }
  };
  
- std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { 
+ std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const {
    std::string result;
-   std::vector<CK_OBJECT_HANDLE> key;
-   std::vector<P11KitAttribute> 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<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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: {
  };
  
  bool PKCS11DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const {
-   bool result;
-   std::vector<CK_OBJECT_HANDLE> key;
-   std::vector<P11KitAttribute> 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<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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<CK_OBJECT_HANDLE> key;
-   std::vector<P11KitAttribute> 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<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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<CK_OBJECT_HANDLE> key;
-   std::vector<P11KitAttribute> 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<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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<CK_OBJECT_HANDLE> key;
-   std::vector<P11KitAttribute> 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<int>(attr[0].ulong());
-      }
- //  } else {
- //     std::cerr << "Could not find key" << std::endl;
-   }
-   return bits;
 -  boost::shared_ptr<Pkcs11Token> d_slot;
++  std::shared_ptr<Pkcs11Token> 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<std::pair<std::string, std::string> > outputs_t;
    outputs_t outputs;
    return storvect;
  };
  
 -  boost::shared_ptr<Pkcs11Token> d_slot;
+ 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
++  std::shared_ptr<Pkcs11Token> 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/qtype.hh
Simple merge
Simple merge
index 26cb32a7d465c8e7b5f3e49a570b902ab6a8f545,77a5d68bacf90fd6833109d47f3be678377779ff..a539643e488901823d0a95e7886f5a26a6ce6204
@@@ -1,5 -1,7 +1,8 @@@
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
  #include "rec_channel.hh"
 +#include "utility.hh"
  #include <sys/socket.h>
  #include <cerrno>
  #include "misc.hh"
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index c4e1fbb5cd3a4e49763c6d406c9656d4cde8282f,5e9eb4df31de84ed4be9c5c844e2b6cadaff5fcd..f28a50b9bed45950565c2c2076cede7123e42503
@@@ -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 <boost/test/unit_test.hpp>
  #include <boost/assign/std/map.hpp>
  #include <boost/foreach.hpp>
@@@ -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
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc pdns/ws-api.cc
Simple merge