X-Git-Url: https://www.tinc-vpn.org/git/browse?p=fides;a=blobdiff_plain;f=lib%2Ffides.cc;h=7c3cabfe7f244976551d0ab10544c39aa3c69e92;hp=0e367aa7a9888f201c08f55dd003bbe7681c266f;hb=f36a11f15b1d75cf3d786cab06fefe0d50812c83;hpb=401e0b5e1d97ded0e2c7415c6dd0f94ee6bfb470 diff --git a/lib/fides.cc b/lib/fides.cc index 0e367aa..7c3cabf 100644 --- a/lib/fides.cc +++ b/lib/fides.cc @@ -34,12 +34,15 @@ using namespace std; -namespace fides { +namespace Fides { + static regexp authexp("^a[+0-] "); + static regexp trustexp("^t[+0-] "); + /// Saves a certificate to a file. // /// @param cert Certificate to save. /// @param filename File to save the certificate to. - void fides::certificate_save(const certificate *cert, const std::string &filename) const { + void Manager::certificate_save(const Certificate *cert, const std::string &filename) const { ofstream file(filename.c_str()); file << cert->to_string() << '\n'; } @@ -48,7 +51,7 @@ namespace fides { // /// @param filename File to save the certificate to. /// @return The certificate. - certificate *fides::certificate_load(const std::string &filename) { + Certificate *Manager::certificate_load(const std::string &filename) { ifstream file(filename.c_str()); string data; getline(file, data); @@ -59,42 +62,42 @@ namespace fides { // /// @param data String containing the certificate in textual form. /// @return The certificate. - certificate *fides::certificate_from_string(const std::string &data) { + Certificate *Manager::certificate_from_string(const std::string &data) { size_t b, e; e = data.find(' ', 0); if(e == string::npos) - throw exception("Invalid certificate"); + throw exception("Invalid Certificate"); string fingerprint = hexdecode(data.substr(0, e)); - const publickey *signer = find_key(fingerprint); + const PublicKey *signer = find_key(fingerprint); if(!signer) throw exception("Unknown public key"); b = e + 1; e = data.find('.', b); if(e == string::npos) - throw exception("Invalid certificate"); + throw exception("Invalid Certificate"); struct timeval timestamp; timestamp.tv_sec = atol(data.c_str() + b); b = e + 1; timestamp.tv_usec = atol(data.c_str() + b); e = data.find(' ', b); if(e == string::npos) - throw exception("Invalid certificate"); + throw exception("Invalid Certificate"); b = e + 1; e = data.find(' ', b); if(e == string::npos) - throw exception("Invalid certificate"); + throw exception("Invalid Certificate"); string signature = b64decode(data.substr(b, e - b)); b = e + 1; string statement = data.substr(b); - return new certificate(signer, timestamp, statement, signature); + return new Certificate(signer, timestamp, statement, signature); } - /// \class fides + /// \class Manager /// /// \brief Interaction with a Fides database. /// - /// A fides object manages a database of public keys and certificates. + /// A Manager object manages a database of public keys and certificates. /// New certificates can be created, certificates can be imported and exported, /// and queries can be done on the database. @@ -109,8 +112,8 @@ namespace fides { /// are used, in the given order: /// - \$FIDES_HOME /// - \$HOME/.fides - /// - \$WPD/.fides - fides::fides(const std::string &dir): homedir(dir) { + /// - \$PWD/.fides + Manager::Manager(const std::string &dir): homedir(dir) { debug cerr << "Fides initialising\n"; // Set homedir to provided directory, or $FIDES_HOME, or $HOME/.fides, or as a last resort $PWD/.fides @@ -137,7 +140,7 @@ namespace fides { try { mykey.load_private(homedir + "priv"); firstrun = false; - } catch(fides::exception &e) { + } catch(exception &e) { cerr << "Fides generating keypair\n"; mykey.generate(); mykey.save_private(homedir + "priv"); @@ -148,7 +151,7 @@ namespace fides { for(size_t i = 0; i < files.size(); ++i) { debug cerr << "Loading key " << files[i] << '\n'; - publickey *key = new publickey(); + PublicKey *key = new PublicKey(); key->load(keydir + files[i]); keys[hexdecode(files[i])] = key; } @@ -157,27 +160,27 @@ namespace fides { files = dirlist(certdir); for(size_t i = 0; i < files.size(); ++i) { - debug cerr << "Loading certificate " << files[i] << '\n'; - certificate *cert = certificate_load(certdir + files[i]); + debug cerr << "Loading Certificate " << files[i] << '\n'; + Certificate *cert = certificate_load(certdir + files[i]); if(false && !cert->validate()) { - cerr << "Bad certificate in database: " << cert->to_string() << '\n'; + cerr << "Bad Certificate in database: " << cert->to_string() << '\n'; continue; } certs[hexdecode(files[i])] = cert; } - // TODO: save and load this value + /// \TODO save and load this value latest.tv_sec = 0; latest.tv_usec = 0; update_trust(); } - fides::~fides() { + Manager::~Manager() { debug cerr << "Fides exitting\n"; - for(map::const_iterator i = certs.begin(); i != certs.end(); ++i) + for(map::const_iterator i = certs.begin(); i != certs.end(); ++i) delete i->second; - for(map::const_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; } @@ -185,31 +188,31 @@ namespace fides { /// Checks the validaty of all certificates. // /// @return True if all known certificates are valid, false otherwise. - bool fides::fsck() const { + bool Manager::fsck() const { int errors = 0; - for(map::const_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'; + cerr << "Validation of Certificate failed: " << i->second->to_string() << '\n'; errors++; } } - cerr << errors << " errors in " << certs.size() << " certificates\n"; + cerr << errors << " errors in " << certs.size() << " Certificates\n"; return !errors; } /// Returns the base directory used by Fides. // /// @return The home directory. - string fides::get_homedir() const { + string Manager::get_homedir() const { return homedir; } /// Tests whether this is the first time Fides has run and has generated new keys. // /// @return True if this is the first time, false otherwise. - bool fides::is_firstrun() const { + bool Manager::is_firstrun() const { return firstrun; } @@ -217,8 +220,8 @@ namespace fides { // /// @param fingerprint String containing a fingerprint. /// @return Pointer to the public key corresponding to the fingerprint, or NULL if it was not found. - publickey *fides::find_key(const std::string &fingerprint) const { - map::const_iterator i; + PublicKey *Manager::find_key(const std::string &fingerprint) const { + map::const_iterator i; i = keys.find(fingerprint); if(i != keys.end()) return i->second; @@ -231,13 +234,13 @@ namespace fides { /// @param signer Public key to match certificates to. /// @param regex Regular expression to match the statement of each certificate to. /// @return A vector of certificates that match the criteria. - vector fides::find_certificates(const publickey *signer, const std::string ®ex) const { - vector found; - map::const_iterator i; + vector Manager::find_certificates(const PublicKey *signer, const std::string ®ex) const { + vector found; + map::const_iterator i; regexp regexp(regex); for(i = certs.begin(); i != certs.end(); ++i) { if(!i->second) { - cerr << "No certificate for " << hexencode(i->first) << '\n'; + cerr << "No Certificate for " << hexencode(i->first) << '\n'; continue; } if(i->second->signer == signer) @@ -251,9 +254,9 @@ namespace fides { // /// @param regex Regular expression to match the statement of each certificate to. /// @return A vector of certificates that match the criteria. - vector fides::find_certificates(const std::string ®ex) const { - vector found; - map::const_iterator i; + vector Manager::find_certificates(const std::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)) @@ -265,9 +268,9 @@ namespace fides { // /// @param signer Public key to match certificates to. /// @return A vector of certificates that match the criteria. - vector fides::find_certificates(const publickey *signer) const { - vector found; - map::const_iterator i; + vector Manager::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); @@ -277,7 +280,7 @@ namespace fides { /// Import public keys and certificates from a stream. // /// @param in Stream to read from. - void fides::import_all(std::istream &in) { + void Manager::import_all(std::istream &in) { string line, pem; bool is_pem = false; @@ -288,7 +291,7 @@ namespace fides { if(is_pem || !line.compare(0, 11, "-----BEGIN ")) { pem += line + '\n'; if(!line.compare(0, 9, "-----END ")) { - publickey *key = new publickey(); + PublicKey *key = new PublicKey(); key->from_string(pem); debug cerr << "Imported key " << hexencode(key->fingerprint()) << '\n'; merge(key); @@ -299,8 +302,8 @@ namespace fides { continue; } - certificate *cert = certificate_from_string(line); - debug cerr << "Importing certificate " << hexencode(cert->fingerprint()) << '\n'; + Certificate *cert = certificate_from_string(line); + debug cerr << "Importing Certificate " << hexencode(cert->fingerprint()) << '\n'; merge(cert); } } @@ -308,10 +311,10 @@ namespace fides { /// Export all public keys and certificates to a stream. // /// @param out Stream to write to. - void fides::export_all(std::ostream &out) const { - for(map::const_iterator i = keys.begin(); i != keys.end(); ++i) + void Manager::export_all(std::ostream &out) const { + for(map::const_iterator i = keys.begin(); i != keys.end(); ++i) out << i->second->to_string(); - for(map::const_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'; } @@ -319,10 +322,10 @@ namespace fides { // /// This creates a certificate that says that we trust the given public key. /// If a key is trusted, then authorisation certificates from that key are taken into account - /// when calling functions such as fides::is_allowed(). + /// when calling functions such as Manager::is_allowed(). /// /// @param key Public key to trust. - void fides::trust(const publickey *key) { + void Manager::trust(const PublicKey *key) { string full = "t+ " + hexencode(key->fingerprint()); sign(full); } @@ -331,10 +334,10 @@ namespace fides { // /// This creates a certificate that says that we distrust the given public key. /// If a key is distrusted, then authorisation certificates from that key are not taken into account - /// when calling functions such as fides::is_allowed(). + /// when calling functions such as Manager::is_allowed(). /// /// @param key Public key to trust. - void fides::distrust(const publickey *key) { + void Manager::distrust(const PublicKey *key) { string full = "t- " + hexencode(key->fingerprint()); sign(full); } @@ -345,15 +348,15 @@ namespace fides { /// This key and certificates created by it are then treated as if we have never trusted nor distrusted this key. /// /// @param key Public key to trust. - void fides::dctrust(const publickey *key) { + void Manager::dctrust(const PublicKey *key) { string full = "t0 " + hexencode(key->fingerprint()); sign(full); } /// Recalculate the trust value of all known public keys. - void fides::update_trust() { + void Manager::update_trust() { // clear trust on all keys - for(map::const_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. @@ -364,10 +367,10 @@ namespace fides { // Already checked keys are never updated anymore (TODO: is that smart?) // Certificates of keys with a zero or negative trust score are not processed. - set checked; - set tocheck; - set newkeys; - set::iterator i; + set checked; + set tocheck; + set newkeys; + set::iterator i; mykey.trust = 3; tocheck.insert(&mykey); @@ -389,22 +392,22 @@ namespace fides { // 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 for(size_t j = 0; j < matches.size(); j++) { - publickey *other = find_key(hexdecode(matches[j]->statement.substr(3))); + PublicKey *other = find_key(hexdecode(matches[j]->statement.substr(3))); if(!other) { - cerr << "Trust certificate for unknown key: " << matches[j]->to_string() << '\n'; + cerr << "Trust Certificate for unknown key: " << matches[j]->to_string() << '\n'; continue; } // except for keys we already checked if(checked.find(other) != checked.end()) { - debug 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; } @@ -426,7 +429,7 @@ namespace fides { /// Merges a public key into the database. // /// @param key The public key to merge. - void fides::merge(publickey *key) { + void Manager::merge(PublicKey *key) { if(keys.find(key->fingerprint()) != keys.end()) { debug cerr << "Key already known\n"; return; @@ -445,7 +448,7 @@ namespace fides { /// the older certificate will be removed. /// /// @param cert The certificate to merge. - void fides::merge(certificate *cert) { + void Manager::merge(Certificate *cert) { // TODO: check if cert is already in database // TODO: check if cert obsoletes other certs @@ -458,14 +461,11 @@ namespace fides { // If the certificate does not validate, drop it. if(!cert->validate()) { // TODO: this should not happen, be wary of DoS attacks - cerr << "Trying to merge invalid certificate: " << cert->to_string() << '\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)) { @@ -474,7 +474,7 @@ namespace fides { others = find_certificates(cert->signer, string("^a[+0-] ") + cert->statement.substr(3) + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - debug 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, ==)) { @@ -482,7 +482,7 @@ namespace fides { debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - debug 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; @@ -503,7 +503,7 @@ namespace fides { others = find_certificates(cert->signer, string("^t[+0-] ") + cert->statement.substr(3) + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - debug 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, ==)) { @@ -511,7 +511,7 @@ namespace fides { debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - debug 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()); @@ -527,7 +527,7 @@ namespace fides { others = find_certificates(cert->signer, string("^") + cert->statement + '$'); if(others.size()) { if(timercmp(&others[0]->timestamp, &cert->timestamp, >)) { - debug 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, ==)) { @@ -535,7 +535,7 @@ namespace fides { debug cerr << "Certificate has same timestamp as another timestamp!\n"; return; } - debug 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()); @@ -560,9 +560,9 @@ namespace fides { /// gave a positive authorisation, 0 if there is a tie, /// or negative if the majority gave a negative authorisation. /// @param all Same as trusted but for all public keys. - void fides::auth_stats(const std::string &statement, int &self, int &trusted, int &all) const { + void Manager::auth_stats(const std::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; @@ -582,7 +582,7 @@ namespace fides { // /// @param key The public key to test. /// @return True if the key is explicitly trusted, false otherwise. - bool fides::is_trusted(const publickey *key) const { + bool Manager::is_trusted(const PublicKey *key) const { return key->trust > 0; } @@ -590,7 +590,7 @@ namespace fides { // /// @param key The public key to test. /// @return True if the key is explicitly distrusted, false otherwise. - bool fides::is_distrusted(const publickey *key) const { + bool Manager::is_distrusted(const PublicKey *key) const { return key->trust < 0; } @@ -599,7 +599,7 @@ namespace fides { /// @param statement The statement to test. /// @param key The public key to test. /// @return True if the statement is allowed for the given key, false otherwise. - bool fides::is_allowed(const std::string &statement, const publickey *key) const { + bool Manager::is_allowed(const std::string &statement, const PublicKey *key) const { int self, trusted, all; if(key) @@ -620,7 +620,7 @@ namespace fides { /// @param statement The statement to test. /// @param key The public key to test. /// @return True if the statement is denied for the given key, false otherwise. - bool fides::is_denied(const std::string &statement, const publickey *key) const { + bool Manager::is_denied(const std::string &statement, const PublicKey *key) const { int self, trusted, all; if(key) @@ -639,7 +639,7 @@ namespace fides { /// Creates a certificate for the given statement. // /// @param statement The statement to create a certificate for. - void fides::sign(const std::string &statement) { + void Manager::sign(const std::string &statement) { // Try to set "latest" to now, but ensure monoticity struct timeval now; gettimeofday(&now, 0); @@ -654,10 +654,10 @@ namespace fides { } // Create a new certificate and merge it with our database - merge(new certificate(&mykey, latest, statement)); + merge(new Certificate(&mykey, latest, statement)); } - void fides::allow(const std::string &statement, const publickey *key) { + void Manager::allow(const std::string &statement, const PublicKey *key) { string full = "a+ "; if(key) full += hexencode(key->fingerprint()) + ' '; @@ -665,7 +665,7 @@ namespace fides { sign(full); } - void fides::dontcare(const std::string &statement, const publickey *key) { + void Manager::dontcare(const std::string &statement, const PublicKey *key) { string full = "a0 "; if(key) full += hexencode(key->fingerprint()) + ' '; @@ -673,7 +673,7 @@ namespace fides { sign(full); } - void fides::deny(const std::string &statement, const publickey *key) { + void Manager::deny(const std::string &statement, const PublicKey *key) { string full = "a- "; if(key) full += hexencode(key->fingerprint()) + ' ';