X-Git-Url: http://tinc-vpn.org/git/browse?a=blobdiff_plain;f=lib%2Ffides.cc;h=dab667e5604d51403d3286c9f488b8d040d70978;hb=c0deb87e9de6041a023c80cf50a7870ce563a852;hp=b2ba1aa7c0a913636ef89c878123e651860fe0b5;hpb=4b17b54e2250ea75c9947b92a571554dae672bec;p=fides diff --git a/lib/fides.cc b/lib/fides.cc index b2ba1aa..dab667e 100644 --- a/lib/fides.cc +++ b/lib/fides.cc @@ -33,11 +33,16 @@ #include "fides.h" +#ifndef FIDES_DEBUG +#define FIDES_DEBUG false +#endif + +#define debug if(FIDES_DEBUG) + using namespace std; // Global state -Botan::LibraryInitializer libinit; Botan::AutoSeeded_RNG fides::rng; // Public key functions @@ -63,11 +68,11 @@ void fides::publickey::load(const std::string &filename) { load(in); } -void fides::publickey::save(ostream &out) { +void fides::publickey::save(ostream &out) const { out << to_string(); } -void fides::publickey::save(const std::string &filename) { +void fides::publickey::save(const std::string &filename) const { ofstream out(filename.c_str()); save(out); } @@ -81,18 +86,18 @@ void fides::publickey::from_string(const std::string &in) { } } -string fides::publickey::to_string() { +string fides::publickey::to_string() const { return Botan::X509::PEM_encode(*pub); } -string fides::publickey::fingerprint(unsigned int bits) { +string fides::publickey::fingerprint(unsigned int bits) const { // TODO: find out if there is a standard way to get a hash of an ECDSA public key Botan::SHA_256 sha256; Botan::SecureVector hash = sha256.process(Botan::X509::PEM_encode(*pub)); return string((const char *)hash.begin(), bits / 8); } -bool fides::publickey::verify(const std::string &statement, const std::string &signature) { +bool fides::publickey::verify(const std::string &statement, const std::string &signature) const { auto_ptr verifier(Botan::get_pk_verifier(*pub, "EMSA1(SHA-512)")); verifier->update((const Botan::byte *)statement.data(), statement.size()); Botan::SecureVector sig; @@ -143,16 +148,16 @@ void fides::privatekey::load_private(const std::string &filename) { load_private(in); } -void fides::privatekey::save_private(ostream &out) { +void fides::privatekey::save_private(ostream &out) const { out << Botan::PKCS8::PEM_encode(*priv); } -void fides::privatekey::save_private(const std::string &filename) { +void fides::privatekey::save_private(const std::string &filename) const { ofstream out(filename.c_str()); save_private(out); } -string fides::privatekey::sign(const std::string &statement) { +string fides::privatekey::sign(const std::string &statement) const { auto_ptr signer(Botan::get_pk_signer(*priv, "EMSA1(SHA-512)")); Botan::SecureVector sig = signer->sign_message((const Botan::byte *)statement.data(), statement.size(), rng); return string((const char *)sig.begin(), (size_t)sig.size()); @@ -186,23 +191,23 @@ string fides::b64decode(const string &in) { // Certificate functions -fides::certificate::certificate(publickey *key, struct timeval timestamp, const std::string &statement, const std::string &signature): signer(key), timestamp(timestamp), statement(statement), signature(signature) {} +fides::certificate::certificate(const publickey *key, struct timeval timestamp, const std::string &statement, const std::string &signature): signer(key), timestamp(timestamp), statement(statement), signature(signature) {} -bool fides::certificate::validate() { +bool fides::certificate::validate() const { string data = signer->fingerprint(256); data += string((const char *)×tamp, sizeof timestamp); data += statement; return signer->verify(data, signature); } -fides::certificate::certificate(privatekey *key, struct timeval timestamp, const std::string &statement): signer(key), timestamp(timestamp), statement(statement) { +fides::certificate::certificate(const privatekey *key, struct timeval timestamp, const std::string &statement): signer(key), timestamp(timestamp), statement(statement) { string data = signer->fingerprint(256); data += string((const char *)×tamp, sizeof timestamp); data += statement; signature = key->sign(data); } -string fides::certificate::fingerprint(unsigned int bits) { +string fides::certificate::fingerprint(unsigned int bits) const { return signature.substr(signature.size() - bits / 8); } @@ -250,7 +255,7 @@ static vector dirlist(const string &path) { return files; } -void fides::certificate_save(const certificate *cert, const string &filename) { +void fides::certificate_save(const certificate *cert, const string &filename) const { ofstream file(filename.c_str()); file << cert->to_string() << '\n'; } @@ -268,7 +273,7 @@ fides::certificate *fides::certificate_from_string(const string &data) { if(e == string::npos) throw exception("Invalid certificate"); string fingerprint = hexdecode(data.substr(0, e)); - publickey *signer = find_key(fingerprint); + const publickey *signer = find_key(fingerprint); if(!signer) throw exception("Unknown public key"); b = e + 1; @@ -296,7 +301,7 @@ fides::certificate *fides::certificate_from_string(const string &data) { // Fides main functions fides::fides(const string &dir): homedir(dir) { - cerr << "Fides initialising\n"; + debug cerr << "Fides initialising\n"; // Set homedir to provided directory, or $FIDES_HOME, or $HOME/.fides, or as a last resort $PWD/.fides if(homedir.empty()) @@ -331,7 +336,7 @@ fides::fides(const string &dir): homedir(dir) { } vector files = dirlist(keydir); for(size_t i = 0; i < files.size(); ++i) { - cerr << "Loading key " << files[i] << '\n'; + debug cerr << "Loading key " << files[i] << '\n'; publickey *key = new publickey(); key->load(keydir + files[i]); @@ -342,10 +347,10 @@ fides::fides(const string &dir): homedir(dir) { files = dirlist(certdir); for(size_t i = 0; i < files.size(); ++i) { - cerr << "Loading certificate " << files[i] << '\n'; + debug cerr << "Loading certificate " << files[i] << '\n'; certificate *cert = certificate_load(certdir + files[i]); if(false && !cert->validate()) { - cerr << "Bad certificate!\n"; + cerr << "Bad certificate in database: " << cert->to_string() << '\n'; continue; } certs[hexdecode(files[i])] = cert; @@ -359,18 +364,18 @@ fides::fides(const string &dir): homedir(dir) { } fides::~fides() { - cerr << "Fides exitting\n"; - for(map::iterator i = certs.begin(); i != certs.end(); ++i) + debug cerr << "Fides exitting\n"; + for(map::const_iterator i = certs.begin(); i != certs.end(); ++i) delete i->second; - for(map::iterator i = keys.begin(); i != keys.end(); ++i) + for(map::const_iterator i = keys.begin(); i != keys.end(); ++i) if(i->second != &mykey) delete i->second; } -bool fides::fsck() { +bool fides::fsck() const { int errors = 0; - for(map::iterator i = certs.begin(); i != certs.end(); ++i) { + for(map::const_iterator i = certs.begin(); i != certs.end(); ++i) { if(!i->second->validate()) { cerr << "Validation of certificate failed: " << i->second->to_string() << '\n'; errors++; @@ -381,16 +386,16 @@ bool fides::fsck() { return !errors; } -string fides::get_homedir() { +string fides::get_homedir() const { return homedir; } -bool fides::is_firstrun() { +bool fides::is_firstrun() const { return firstrun; } -fides::publickey *fides::find_key(const string &fingerprint) { - map::iterator i; +fides::publickey *fides::find_key(const string &fingerprint) const { + map::const_iterator i; i = keys.find(fingerprint); if(i != keys.end()) return i->second; @@ -398,9 +403,9 @@ fides::publickey *fides::find_key(const string &fingerprint) { return 0; } -vector fides::find_certificates(publickey *signer, const string ®ex) { - vector found; - map::iterator i; +vector fides::find_certificates(const publickey *signer, const string ®ex) const { + vector found; + map::const_iterator i; regexp regexp(regex); for(i = certs.begin(); i != certs.end(); ++i) { if(!i->second) { @@ -414,9 +419,9 @@ vector fides::find_certificates(publickey *signer, const s return found; } -vector fides::find_certificates(const string ®ex) { - vector found; - map::iterator i; +vector fides::find_certificates(const string ®ex) const { + vector found; + map::const_iterator i; regexp regexp(regex); for(i = certs.begin(); i != certs.end(); ++i) if(regexp.match(i->second->statement)) @@ -424,9 +429,9 @@ vector fides::find_certificates(const string ®ex) { return found; } -vector fides::find_certificates(publickey *signer) { - vector found; - map::iterator i; +vector fides::find_certificates(const publickey *signer) const { + vector found; + map::const_iterator i; for(i = certs.begin(); i != certs.end(); ++i) if(i->second->signer == signer) found.push_back(i->second); @@ -446,7 +451,7 @@ void fides::import_all(istream &in) { if(!line.compare(0, 9, "-----END ")) { fides::publickey *key = new publickey(); key->from_string(pem); - cerr << "Imported key " << hexencode(key->fingerprint()) << '\n'; + debug cerr << "Imported key " << hexencode(key->fingerprint()) << '\n'; merge(key); is_pem = false; } else { @@ -456,36 +461,36 @@ void fides::import_all(istream &in) { } fides::certificate *cert = certificate_from_string(line); - cerr << "Importing certificate " << hexencode(cert->fingerprint()) << '\n'; + debug cerr << "Importing certificate " << hexencode(cert->fingerprint()) << '\n'; merge(cert); } } -void fides::export_all(ostream &out) { - for(map::iterator i = keys.begin(); i != keys.end(); ++i) +void fides::export_all(ostream &out) const { + for(map::const_iterator i = keys.begin(); i != keys.end(); ++i) out << i->second->to_string(); - for(map::iterator i = certs.begin(); i != certs.end(); ++i) + for(map::const_iterator i = certs.begin(); i != certs.end(); ++i) out << i->second->to_string() << '\n'; } -void fides::trust(publickey *key) { +void fides::trust(const publickey *key) { string full = "t+ " + hexencode(key->fingerprint()); sign(full); } -void fides::distrust(publickey *key) { +void fides::distrust(const publickey *key) { string full = "t- " + hexencode(key->fingerprint()); sign(full); } -void fides::dctrust(publickey *key) { +void fides::dctrust(const publickey *key) { string full = "t0 " + hexencode(key->fingerprint()); sign(full); } void fides::update_trust() { // clear trust on all keys - for(map::iterator i = keys.begin(); i != keys.end(); ++i) + for(map::const_iterator i = keys.begin(); i != keys.end(); ++i) i->second->trust = 0; // Start by checking all trust certificates from ourself. @@ -512,7 +517,7 @@ void fides::update_trust() { // loop over all keys whose certificates need to be checked for(i = tocheck.begin(); i != tocheck.end(); ++i) { - cerr << "Trust for key " << hexencode((*i)->fingerprint()) << " set to " << (*i)->trust << '\n'; + debug cerr << "Trust for key " << hexencode((*i)->fingerprint()) << " set to " << (*i)->trust << '\n'; // except if this key is not trusted @@ -521,7 +526,7 @@ void fides::update_trust() { // find all non-zero trust certificates of this key - vector matches = find_certificates(*i, "^t[+-] "); + vector matches = find_certificates(*i, "^t[+-] "); // update trust value of those keys @@ -536,7 +541,7 @@ void fides::update_trust() { // except for keys we already checked if(checked.find(other) != checked.end()) { - cerr << "Skipping trust certificate for already checked key: " << matches[j]->to_string() << '\n'; + debug cerr << "Skipping trust certificate for already checked key: " << matches[j]->to_string() << '\n'; continue; } @@ -557,7 +562,7 @@ void fides::update_trust() { void fides::merge(publickey *key) { if(keys.find(key->fingerprint()) != keys.end()) { - cerr << "Key already known\n"; + debug cerr << "Key already known\n"; return; } @@ -571,21 +576,21 @@ void fides::merge(certificate *cert) { // If we already know this certificate, drop it. if(certs.find(cert->fingerprint()) != certs.end()) { - cerr << "Certificate already known\n"; + debug cerr << "Certificate already known\n"; return; } // If the certificate does not validate, drop it. if(!cert->validate()) { // TODO: this should not happen, be wary of DoS attacks - cerr << "Certificate invalid\n"; + cerr << "Trying to merge invalid certificate: " << cert->to_string() << '\n'; return; } // TODO: move these regexps to the class? regexp authexp("^a[+0-] "); regexp trustexp("^t[+0-] "); - vector others; + vector others; // Is this an authorisation cert? if(authexp.match(cert->statement)) { @@ -594,15 +599,15 @@ void fides::merge(certificate *cert) { others = find_certificates(cert->signer, string("^a[+0-] ") + cert->statement.substr(3) + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - cerr << "Certificate is overruled by a newer certificate\n"; + debug cerr << "Certificate is overruled by a newer certificate\n"; return; } if(timercmp(&others[0]->timestamp, &cert->timestamp, ==)) { // TODO: this should not happen, be wary of DoS attacks - cerr << "Certificate has same timestamp as another timestamp!\n"; + debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - cerr << "Certificate overrules an older certificate!\n"; + debug cerr << "Certificate overrules an older certificate!\n"; // save new cert first certificate_save(cert, certdir + hexencode(cert->fingerprint())); certs[cert->fingerprint()] = cert; @@ -623,15 +628,15 @@ void fides::merge(certificate *cert) { others = find_certificates(cert->signer, string("^t[+0-] ") + cert->statement.substr(3) + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - cerr << "Certificate is overruled by a newer certificate\n"; + debug cerr << "Certificate is overruled by a newer certificate\n"; return; } if(timercmp(&others[0]->timestamp, &cert->timestamp, ==)) { // TODO: this should not happen, be wary of DoS attacks - cerr << "Certificate has same timestamp as another timestamp!\n"; + debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - cerr << "Certificate overrules an older certificate!\n"; + debug cerr << "Certificate overrules an older certificate!\n"; // delete old one rename((certdir + hexencode(others[0]->fingerprint())).c_str(), (obsoletedir + hexencode(others[0]->fingerprint())).c_str()); certs.erase(others[0]->fingerprint()); @@ -647,15 +652,15 @@ void fides::merge(certificate *cert) { others = find_certificates(cert->signer, string("^") + cert->statement + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - cerr << "Certificate is overruled by a newer certificate\n"; + debug cerr << "Certificate is overruled by a newer certificate\n"; return; } if(timercmp(&others[0]->timestamp, &cert->timestamp, ==)) { // TODO: this should not happen, be wary of DoS attacks - cerr << "Certificate has same timestamp as another timestamp!\n"; + debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - cerr << "Certificate overrules an older certificate!\n"; + debug cerr << "Certificate overrules an older certificate!\n"; // delete old one rename((certdir + hexencode(others[0]->fingerprint())).c_str(), (obsoletedir + hexencode(others[0]->fingerprint())).c_str()); certs.erase(others[0]->fingerprint()); @@ -665,14 +670,14 @@ void fides::merge(certificate *cert) { return; } - cerr << "Certificate is new\n"; + debug cerr << "Certificate is new\n"; certs[cert->fingerprint()] = cert; certificate_save(cert, certdir + hexencode(cert->fingerprint())); } -void fides::auth_stats(const string &statement, int &self, int &trusted, int &all) { +void fides::auth_stats(const string &statement, int &self, int &trusted, int &all) const { self = trusted = all = 0; - vector matches = find_certificates(string("^a[+0-] ") + statement + '$'); + vector matches = find_certificates(string("^a[+0-] ") + statement + '$'); for(size_t i = 0; i < matches.size(); ++i) { char code = matches[i]->statement[1]; int diff = 0; @@ -688,15 +693,15 @@ void fides::auth_stats(const string &statement, int &self, int &trusted, int &al } } -bool fides::is_trusted(publickey *key) { +bool fides::is_trusted(const publickey *key) const { return key->trust > 0; } -bool fides::is_distrusted(publickey *key) { +bool fides::is_distrusted(const publickey *key) const { return key->trust < 0; } -bool fides::is_allowed(const string &statement, publickey *key) { +bool fides::is_allowed(const string &statement, const publickey *key) const { int self, trusted, all; if(key) @@ -712,7 +717,7 @@ bool fides::is_allowed(const string &statement, publickey *key) { return false; } -bool fides::is_denied(const string &statement, publickey *key) { +bool fides::is_denied(const string &statement, const publickey *key) const { int self, trusted, all; if(key) @@ -746,7 +751,7 @@ void fides::sign(const string &statement) { merge(new certificate(&mykey, latest, statement)); } -void fides::allow(const string &statement, publickey *key) { +void fides::allow(const string &statement, const publickey *key) { string full = "a+ "; if(key) full += hexencode(key->fingerprint()) + ' '; @@ -754,7 +759,7 @@ void fides::allow(const string &statement, publickey *key) { sign(full); } -void fides::dontcare(const string &statement, publickey *key) { +void fides::dontcare(const string &statement, const publickey *key) { string full = "a0 "; if(key) full += hexencode(key->fingerprint()) + ' '; @@ -762,7 +767,7 @@ void fides::dontcare(const string &statement, publickey *key) { sign(full); } -void fides::deny(const string &statement, publickey *key) { +void fides::deny(const string &statement, const publickey *key) { string full = "a- "; if(key) full += hexencode(key->fingerprint()) + ' ';