/** * @file llsechandler_basic.h * @brief Security API for services such as certificate handling * secure local storage, etc. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLSECHANDLER_BASIC #define LLSECHANDLER_BASIC #include "llsecapi.h" #include <vector> #include <openssl/x509.h> // helpers extern LLSD cert_name_from_X509_NAME(X509_NAME* name); extern std::string cert_string_name_from_X509_NAME(X509_NAME* name); extern std::string cert_string_from_asn1_integer(ASN1_INTEGER* value); extern LLDate cert_date_from_asn1_time(ASN1_TIME* asn1_time); extern std::string cert_get_digest(const std::string& digest_type, X509 *cert); // class LLCertificate // class LLBasicCertificate : public LLCertificate { public: LOG_CLASS(LLBasicCertificate); // The optional validation_params allow us to make the unit test time-invariant LLBasicCertificate(const std::string& pem_cert, const LLSD* validation_params = NULL); LLBasicCertificate(X509* openSSLX509, const LLSD* validation_params = NULL); virtual ~LLBasicCertificate(); virtual std::string getPem() const; virtual std::vector<U8> getBinary() const; virtual void getLLSD(LLSD &llsd); virtual X509* getOpenSSLX509() const; // set llsd elements for testing void setLLSD(const std::string name, const LLSD& value) { mLLSDInfo[name] = value; } protected: // certificates are stored as X509 objects, as validation and // other functionality is via openssl X509* mCert; LLSD& _initLLSD(); LLSD mLLSDInfo; }; // class LLBasicCertificateVector // Class representing a list of certificates // This implementation uses a stl vector of certificates. class LLBasicCertificateVector : virtual public LLCertificateVector { public: LLBasicCertificateVector() {} virtual ~LLBasicCertificateVector() {} // Implementation of the basic iterator implementation. // The implementation uses a vector iterator derived from // the vector in the LLBasicCertificateVector class class BasicIteratorImpl : public iterator_impl { public: BasicIteratorImpl(std::vector<LLPointer<LLCertificate> >::iterator _iter) { mIter = _iter;} virtual ~BasicIteratorImpl() {}; // seek forward or back. Used by the operator++/operator-- implementations virtual void seek(bool incr) { if(incr) { mIter++; } else { mIter--; } } // create a copy of the iterator implementation class, used by the iterator copy constructor virtual LLPointer<iterator_impl> clone() const { return new BasicIteratorImpl(mIter); } virtual bool equals(const LLPointer<iterator_impl>& _iter) const { const BasicIteratorImpl *rhs_iter = dynamic_cast<const BasicIteratorImpl *>(_iter.get()); llassert(rhs_iter); if (!rhs_iter) return 0; return (mIter == rhs_iter->mIter); } virtual LLPointer<LLCertificate> get() { return *mIter; } protected: friend class LLBasicCertificateVector; std::vector<LLPointer<LLCertificate> >::iterator mIter; }; // numeric index of the vector virtual LLPointer<LLCertificate> operator[](int _index) { return mCerts[_index];} // Iteration virtual iterator begin() { return iterator(new BasicIteratorImpl(mCerts.begin())); } virtual iterator end() { return iterator(new BasicIteratorImpl(mCerts.end())); } // find a cert given params virtual iterator find(const LLSD& params); // return the number of certs in the store virtual int size() const { return mCerts.size(); } // insert the cert to the store. if a copy of the cert already exists in the store, it is removed first virtual void add(LLPointer<LLCertificate> cert) { insert(end(), cert); } // insert the cert to the store. if a copy of the cert already exists in the store, it is removed first virtual void insert(iterator _iter, LLPointer<LLCertificate> cert); // remove a certificate from the store virtual LLPointer<LLCertificate> erase(iterator _iter); protected: std::vector<LLPointer<LLCertificate> >mCerts; }; // class LLCertificateStore // represents a store of certificates, typically a store of root CA // certificates. The store can be persisted, and can be used to validate // a cert chain // class LLBasicCertificateStore : virtual public LLBasicCertificateVector, public LLCertificateStore { public: LLBasicCertificateStore(const std::string& filename); void load_from_file(const std::string& filename); virtual ~LLBasicCertificateStore(); // persist the store virtual void save(); // return the store id virtual std::string storeId() const; // validate a certificate chain against a certificate store, using the // given validation policy. virtual void validate(int validation_policy, LLPointer<LLCertificateChain> ca_chain, const LLSD& validation_params); // Clears cache of certs validated agains store virtual void clearSertCache() { mTrustedCertCache.clear(); } protected: std::vector<LLPointer<LLCertificate> > mCerts; // cache of cert sha1 hashes to from/to date pairs, to improve // performance of cert trust. Note, these are not the CA certs, // but the certs that have been validated against this store. typedef std::map<std::string, std::pair<LLDate, LLDate> > t_cert_cache; t_cert_cache mTrustedCertCache; std::string mFilename; }; // class LLCertificateChain // Class representing a chain of certificates in order, with the // first element being the child cert. class LLBasicCertificateChain : virtual public LLBasicCertificateVector, public LLCertificateChain { public: LLBasicCertificateChain(X509_STORE_CTX * store); virtual ~LLBasicCertificateChain() {} }; // LLSecAPIBasicCredential class class LLSecAPIBasicCredential : public LLCredential { public: LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {} virtual ~LLSecAPIBasicCredential() {} // return a value representing the user id, used for server and voice // (could be guid, name in format "name_resident", whatever) virtual std::string userID() const; // printible string identifying the credential. virtual std::string asString() const; }; // LLSecAPIBasicHandler Class // Interface handler class for the various security storage handlers. class LLSecAPIBasicHandler : public LLSecAPIHandler { public: LLSecAPIBasicHandler(const std::string& protected_data_filename, const std::string& legacy_password_path); LLSecAPIBasicHandler(); void init(); virtual ~LLSecAPIBasicHandler(); // instantiate a certificate from a pem string virtual LLPointer<LLCertificate> getCertificate(const std::string& pem_cert); // instiate a certificate from an openssl X509 structure virtual LLPointer<LLCertificate> getCertificate(X509* openssl_cert); // instantiate a chain from an X509_STORE_CTX virtual LLPointer<LLCertificateChain> getCertificateChain(X509_STORE_CTX* chain); // instantiate a cert store given it's id. if a persisted version // exists, it'll be loaded. If not, one will be created (but not // persisted) virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id); // protectedData functions technically should be pretected or private, // they are not because of llsechandler_basic_test imlementation // persist data in a protected store virtual void setProtectedData(const std::string& data_type, const std::string& data_id, const LLSD& data); // retrieve protected data virtual LLSD getProtectedData(const std::string& data_type, const std::string& data_id); // delete a protected data item from the store virtual void deleteProtectedData(const std::string& data_type, const std::string& data_id); // persist data in a protected store's map virtual void addToProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem, const LLSD& data); // remove data from protected store's map virtual void removeFromProtectedMap(const std::string& data_type, const std::string& data_id, const std::string& map_elem); // ensure protected store's map is written to storage virtual void syncProtectedMap(); // credential management routines virtual LLPointer<LLCredential> createCredential(const std::string& grid, const LLSD& identifier, const LLSD& authenticator); // load single credencial from default storage virtual LLPointer<LLCredential> loadCredential(const std::string& grid); // save credencial to default storage virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator); virtual void deleteCredential(LLPointer<LLCredential> cred); // has map of credentials declared as specific storage virtual bool hasCredentialMap(const std::string& storage, const std::string& grid); // returns true if map is empty or does not exist virtual bool emptyCredentialMap(const std::string& storage, const std::string& grid); // load map of credentials from specific storage virtual void loadCredentialMap(const std::string& storage, const std::string& grid, credential_map_t& credential_map); // load single username from map of credentials from specific storage virtual LLPointer<LLCredential> loadFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userid); // add item to map of credentials from specific storage virtual void addToCredentialMap(const std::string& storage, LLPointer<LLCredential> cred, bool save_authenticator); // remove item from map of credentials from specific storage virtual void removeFromCredentialMap(const std::string& storage, LLPointer<LLCredential> cred); // remove item from map of credentials from specific storage virtual void removeFromCredentialMap(const std::string& storage, const std::string& grid, const std::string& userid); virtual void removeCredentialMap(const std::string& storage, const std::string& grid); protected: void _readProtectedData(unsigned char *unique_id, U32 id_len); void _readProtectedData(); void _writeProtectedData(); std::string _legacyLoadPassword(); std::string mProtectedDataFilename; LLSD mProtectedDataMap; LLPointer<LLBasicCertificateStore> mStore; std::string mLegacyPasswordPath; }; bool valueCompareLLSD(const LLSD& lhs, const LLSD& rhs); #endif // LLSECHANDLER_BASIC