Make libfides quiet unless FIDES_DEBUG is defined to true.
[fides] / lib / fides.cc
index b2ba1aa..dab667e 100644 (file)
 
 #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<Botan::byte> 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<Botan::PK_Verifier> verifier(Botan::get_pk_verifier(*pub, "EMSA1(SHA-512)"));
        verifier->update((const Botan::byte *)statement.data(), statement.size());
        Botan::SecureVector<Botan::byte> 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<Botan::PK_Signer> signer(Botan::get_pk_signer(*priv, "EMSA1(SHA-512)"));
        Botan::SecureVector<Botan::byte> 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 *)&timestamp, 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 *)&timestamp, 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<string> 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<string> 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<string, certificate *>::iterator i = certs.begin(); i != certs.end(); ++i)
+       debug cerr << "Fides exitting\n";
+       for(map<string, certificate *>::const_iterator i = certs.begin(); i != certs.end(); ++i)
                delete i->second;
-       for(map<string, publickey *>::iterator i = keys.begin(); i != keys.end(); ++i)
+       for(map<string, publickey *>::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<string, certificate *>::iterator i = certs.begin(); i != certs.end(); ++i) {
+       for(map<string, certificate *>::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<string, publickey *>::iterator i;
+fides::publickey *fides::find_key(const string &fingerprint) const {
+       map<string, publickey *>::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::certificate *> fides::find_certificates(publickey *signer, const string &regex) {
-       vector<certificate *> found;
-       map<string, certificate *>::iterator i;
+vector<const fides::certificate *> fides::find_certificates(const publickey *signer, const string &regex) const {
+       vector<const certificate *> found;
+       map<string, certificate *>::const_iterator i;
        regexp regexp(regex);
        for(i = certs.begin(); i != certs.end(); ++i) {
                if(!i->second) {
@@ -414,9 +419,9 @@ vector<fides::certificate *> fides::find_certificates(publickey *signer, const s
        return found;
 }
 
-vector<fides::certificate *> fides::find_certificates(const string &regex) {
-       vector<certificate *> found;
-       map<string, certificate *>::iterator i;
+vector<const fides::certificate *> fides::find_certificates(const string &regex) const {
+       vector<const certificate *> found;
+       map<string, certificate *>::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::certificate *> fides::find_certificates(const string &regex) {
        return found;
 }
 
-vector<fides::certificate *> fides::find_certificates(publickey *signer) {
-       vector<certificate *> found;
-       map<string, certificate *>::iterator i;
+vector<const fides::certificate *> fides::find_certificates(const publickey *signer) const {
+       vector<const certificate *> found;
+       map<string, certificate *>::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<string, publickey *>::iterator i = keys.begin(); i != keys.end(); ++i)
+void fides::export_all(ostream &out) const {
+       for(map<string, publickey *>::const_iterator i = keys.begin(); i != keys.end(); ++i)
                out << i->second->to_string();
-       for(map<string, certificate *>::iterator i = certs.begin(); i != certs.end(); ++i)
+       for(map<string, certificate *>::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<string, publickey *>::iterator i = keys.begin(); i != keys.end(); ++i)
+       for(map<string, publickey *>::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<certificate *> matches = find_certificates(*i, "^t[+-] ");
+                       vector<const certificate *> 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<certificate *> others;
+       vector<const certificate *> 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<certificate *> matches = find_certificates(string("^a[+0-] ") + statement + '$');
+       vector<const certificate *> 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()) + ' ';