PageRenderTime 569ms CodeModel.GetById 201ms app.highlight 149ms RepoModel.GetById 213ms app.codeStats 0ms

/indra/newview/llsecapi.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 493 lines | 290 code | 112 blank | 91 comment | 5 complexity | eca85bff6e4d697597b979ab68e2165a MD5 | raw file
  1/** 
  2 * @file llsecapi.h
  3 * @brief Security API for services such as certificate handling
  4 * secure local storage, etc.
  5 *
  6 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2010, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#ifndef LLSECAPI_H
 29#define LLSECAPI_H
 30#include <vector>
 31#include <openssl/x509.h>
 32#include <ostream>
 33
 34#ifdef LL_WINDOWS
 35#pragma warning(disable:4250)
 36#endif // LL_WINDOWS
 37
 38// All error handling is via exceptions.
 39
 40
 41#define CERT_SUBJECT_NAME "subject_name"
 42#define CERT_ISSUER_NAME "issuer_name"
 43#define CERT_NAME_CN "commonName"
 44		
 45#define CERT_SUBJECT_NAME_STRING "subject_name_string"
 46#define CERT_ISSUER_NAME_STRING "issuer_name_string"
 47		
 48#define CERT_SERIAL_NUMBER "serial_number"
 49		
 50#define CERT_VALID_FROM "valid_from"
 51#define CERT_VALID_TO "valid_to"
 52#define CERT_SHA1_DIGEST "sha1_digest"
 53#define CERT_MD5_DIGEST "md5_digest"
 54#define CERT_HOSTNAME "hostname"
 55#define CERT_BASIC_CONSTRAINTS "basicConstraints"
 56#define CERT_BASIC_CONSTRAINTS_CA "CA"
 57#define CERT_BASIC_CONSTRAINTS_PATHLEN "pathLen"
 58
 59#define CERT_KEY_USAGE "keyUsage"
 60#define CERT_KU_DIGITAL_SIGNATURE    "digitalSignature"
 61#define CERT_KU_NON_REPUDIATION      "nonRepudiation"
 62#define CERT_KU_KEY_ENCIPHERMENT     "keyEncipherment"
 63#define CERT_KU_DATA_ENCIPHERMENT    "dataEncipherment"
 64#define CERT_KU_KEY_AGREEMENT        "keyAgreement"
 65#define CERT_KU_CERT_SIGN        "certSigning"
 66#define CERT_KU_CRL_SIGN             "crlSigning"
 67#define CERT_KU_ENCIPHER_ONLY        "encipherOnly"
 68#define CERT_KU_DECIPHER_ONLY        "decipherOnly"
 69
 70#define BASIC_SECHANDLER "BASIC_SECHANDLER"
 71#define CERT_VALIDATION_DATE "validation_date"
 72
 73#define CERT_EXTENDED_KEY_USAGE "extendedKeyUsage"
 74#define CERT_EKU_SERVER_AUTH SN_server_auth
 75
 76#define CERT_SUBJECT_KEY_IDENTFIER "subjectKeyIdentifier"
 77#define CERT_AUTHORITY_KEY_IDENTIFIER "authorityKeyIdentifier"
 78#define CERT_AUTHORITY_KEY_IDENTIFIER_ID "authorityKeyIdentifierId"
 79#define CERT_AUTHORITY_KEY_IDENTIFIER_NAME "authorityKeyIdentifierName"
 80#define CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL "authorityKeyIdentifierSerial"
 81
 82// validate the current time lies within 
 83// the validation period of the cert
 84#define VALIDATION_POLICY_TIME 1
 85
 86// validate that the CA, or some cert in the chain
 87// lies within the certificate store
 88#define VALIDATION_POLICY_TRUSTED 2
 89
 90// validate that the subject name of
 91// the cert contains the passed in hostname
 92// or validates against the hostname
 93#define VALIDATION_POLICY_HOSTNAME 4
 94
 95
 96// validate that the cert contains the SSL EKU
 97#define VALIDATION_POLICY_SSL_KU 8
 98
 99// validate that the cert contains the SSL EKU
100#define VALIDATION_POLICY_CA_KU 16
101
102#define VALIDATION_POLICY_CA_BASIC_CONSTRAINTS 32
103
104// validate that the cert is correct for SSL
105#define VALIDATION_POLICY_SSL (VALIDATION_POLICY_TIME | \
106                               VALIDATION_POLICY_HOSTNAME | \
107                               VALIDATION_POLICY_TRUSTED | \
108                               VALIDATION_POLICY_SSL_KU | \
109                               VALIDATION_POLICY_CA_BASIC_CONSTRAINTS | \
110                               VALIDATION_POLICY_CA_KU)
111
112
113
114
115
116
117class LLProtectedDataException
118{
119public:
120	LLProtectedDataException(const char *msg) 
121	{
122		LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL;
123		mMsg = (std::string)msg;
124	}
125	std::string getMessage() { return mMsg; }
126protected:
127	std::string mMsg;
128};
129
130// class LLCertificate
131// parent class providing an interface for certifiate.
132// LLCertificates are considered unmodifiable
133// Certificates are pulled out of stores, or created via
134// factory calls
135class LLCertificate : public LLThreadSafeRefCount
136{
137	LOG_CLASS(LLCertificate);
138public:
139	LLCertificate() {}
140	
141	virtual ~LLCertificate() {}
142	
143	// return a PEM encoded certificate.  The encoding
144	// includes the -----BEGIN CERTIFICATE----- and end certificate elements
145	virtual std::string getPem() const=0; 
146	
147	// return a DER encoded certificate
148	virtual std::vector<U8> getBinary() const=0;  
149	
150	// return an LLSD object containing information about the certificate
151	// such as its name, signature, expiry time, serial number
152	virtual void getLLSD(LLSD& llsd)=0; 
153	
154	// return an openSSL X509 struct for the certificate
155	virtual X509* getOpenSSLX509() const=0;
156
157};
158
159// class LLCertificateVector
160// base class for a list of certificates.
161
162
163class LLCertificateVector : public LLThreadSafeRefCount
164{
165	
166public:
167	
168	LLCertificateVector() {};
169	virtual ~LLCertificateVector() {};
170	
171	// base iterator implementation class, providing
172	// the functionality needed for the iterator class.
173	class iterator_impl : public LLThreadSafeRefCount
174	{
175	public:
176		iterator_impl() {};
177		virtual ~iterator_impl() {};
178		virtual void seek(bool incr)=0;
179		virtual LLPointer<iterator_impl> clone() const=0;
180		virtual bool equals(const LLPointer<iterator_impl>& _iter) const=0;
181		virtual LLPointer<LLCertificate> get()=0;
182	};
183	
184	// iterator class
185	class iterator
186	{
187	public:
188		iterator(LLPointer<iterator_impl> impl) : mImpl(impl) {}
189		iterator() : mImpl(NULL) {}
190		iterator(const iterator& _iter) {mImpl = _iter.mImpl->clone(); }
191		~iterator() {}
192		iterator& operator++() { if(mImpl.notNull()) mImpl->seek(true); return *this;}
193		iterator& operator--() { if(mImpl.notNull()) mImpl->seek(false); return *this;}
194		
195		iterator operator++(int) { iterator result = *this; if(mImpl.notNull()) mImpl->seek(true); return result;}
196		iterator operator--(int) { iterator result = *this; if(mImpl.notNull()) mImpl->seek(false); return result;}
197		LLPointer<LLCertificate> operator*() { return mImpl->get(); }		
198		
199		LLPointer<iterator_impl> mImpl;
200	protected:
201		friend bool operator==(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs);
202		bool equals(const iterator& _iter) const { return mImpl->equals(_iter.mImpl); }
203	};
204	
205	// numeric indexer
206	virtual LLPointer<LLCertificate> operator[](int)=0;
207	
208	// Iteration
209	virtual iterator begin()=0;
210	
211	virtual iterator end()=0;
212	
213	// find a cert given params
214	virtual iterator find(const LLSD& params) =0;
215	
216	// return the number of certs in the store
217	virtual int size() const = 0;	
218	
219	// append the cert to the store.  if a copy of the cert already exists in the store, it is removed first
220	virtual void  add(LLPointer<LLCertificate> cert)=0;
221	
222	// insert the cert to the store.  if a copy of the cert already exists in the store, it is removed first
223	virtual void  insert(iterator location, LLPointer<LLCertificate> cert)=0;	
224	
225	// remove a certificate from the store
226	virtual LLPointer<LLCertificate> erase(iterator cert)=0;	
227};
228
229// class LLCertificateChain
230// Class representing a chain of certificates in order, with the 
231// first element being the child cert.
232class LLCertificateChain : virtual public LLCertificateVector
233{	
234	
235public:
236	LLCertificateChain() {}
237	
238	virtual ~LLCertificateChain() {}
239	
240};
241
242// class LLCertificateStore
243// represents a store of certificates, typically a store of root CA
244// certificates.  The store can be persisted, and can be used to validate
245// a cert chain
246//
247class LLCertificateStore : virtual public LLCertificateVector
248{
249	
250public:
251	
252	LLCertificateStore() {}
253	virtual ~LLCertificateStore() {}
254	
255	// persist the store
256	virtual void save()=0;
257	
258	// return the store id
259	virtual std::string storeId() const=0;
260	
261	// validate a certificate chain given the params.
262	// Will throw exceptions on error
263	
264	virtual void validate(int validation_policy,
265						  LLPointer<LLCertificateChain> cert_chain,
266						  const LLSD& validation_params) =0;
267	
268};
269
270
271inline
272bool operator==(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs)
273{
274	return _lhs.equals(_rhs);
275}
276inline
277bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs)
278{
279	return !(_lhs == _rhs);
280}
281
282
283#define CRED_IDENTIFIER_TYPE_ACCOUNT "account"
284#define CRED_IDENTIFIER_TYPE_AGENT "agent"
285#define CRED_AUTHENTICATOR_TYPE_CLEAR "clear"
286#define CRED_AUTHENTICATOR_TYPE_HASH   "hash"
287//
288// LLCredential - interface for credentials providing the following functionality:
289// * Persistence of credential information based on grid (for saving username/password)
290// * Serialization to an OGP identifier/authenticator pair
291// 
292class LLCredential  : public LLThreadSafeRefCount
293{
294public:
295	
296	LLCredential() {}
297	
298	LLCredential(const std::string& grid)
299	{
300		mGrid = grid;
301		mIdentifier = LLSD::emptyMap();
302		mAuthenticator = LLSD::emptyMap();
303	}
304	
305	virtual ~LLCredential() {}
306	
307	virtual void setCredentialData(const LLSD& identifier, const LLSD& authenticator) 
308	{ 
309		mIdentifier = identifier;
310		mAuthenticator = authenticator;
311	}
312	virtual LLSD getIdentifier() { return mIdentifier; }
313	virtual void identifierType(std::string& idType);
314	virtual LLSD getAuthenticator() { return mAuthenticator; }
315	virtual void authenticatorType(std::string& authType);
316	virtual LLSD getLoginParams();
317	virtual std::string getGrid() { return mGrid; }
318	
319
320	virtual void clearAuthenticator() { mAuthenticator = LLSD(); } 
321	virtual std::string userID() const { return std::string("unknown");}
322	virtual std::string asString() const { return std::string("unknown");}
323	operator std::string() const { return asString(); }
324protected:
325	LLSD mIdentifier;
326	LLSD mAuthenticator;
327	std::string mGrid;
328};
329
330std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
331
332
333// All error handling is via exceptions.
334
335class LLCertException
336{
337public:
338	LLCertException(LLPointer<LLCertificate> cert, const char* msg)
339	{
340
341		mCert = cert;
342
343		LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL;
344		mMsg = (std::string)msg;
345	}
346	LLPointer<LLCertificate> getCert() { return mCert; }
347	std::string getMessage() { return mMsg; }
348protected:
349	LLPointer<LLCertificate> mCert;
350	std::string mMsg;
351};
352
353class LLInvalidCertificate : public LLCertException
354{
355public:
356	LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
357	{
358	}
359protected:
360};
361
362class LLCertValidationTrustException : public LLCertException
363{
364public:
365	LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
366	{
367	}
368protected:
369};
370
371class LLCertValidationHostnameException : public LLCertException
372{
373public:
374	LLCertValidationHostnameException(std::string hostname,
375									  LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidHostname")
376	{
377		mHostname = hostname;
378	}
379	
380	std::string getHostname() { return mHostname; }
381protected:
382	std::string mHostname;
383};
384
385class LLCertValidationExpirationException : public LLCertException
386{
387public:
388	LLCertValidationExpirationException(LLPointer<LLCertificate> cert,
389										LLDate current_time) : LLCertException(cert, "CertExpired")
390	{
391		mTime = current_time;
392	}
393	LLDate GetTime() { return mTime; }
394protected:
395	LLDate mTime;
396};
397
398class LLCertKeyUsageValidationException : public LLCertException
399{
400public:
401	LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
402	{
403	}
404protected:
405};
406
407class LLCertBasicConstraintsValidationException : public LLCertException
408{
409public:
410	LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
411	{
412	}
413protected:
414};
415
416class LLCertValidationInvalidSignatureException : public LLCertException
417{
418public:
419	LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
420	{
421	}
422protected:
423};
424
425// LLSecAPIHandler Class
426// Interface handler class for the various security storage handlers.
427class LLSecAPIHandler : public LLThreadSafeRefCount
428{
429public:
430	
431	
432	LLSecAPIHandler() {}
433	virtual ~LLSecAPIHandler() {}
434	
435	// initialize the SecAPIHandler
436	virtual void init() {};
437	
438	// instantiate a certificate from a pem string
439	virtual LLPointer<LLCertificate> getCertificate(const std::string& pem_cert)=0;
440	
441	
442	
443	// instiate a certificate from an openssl X509 structure
444	virtual LLPointer<LLCertificate> getCertificate(X509* openssl_cert)=0;
445	
446	// instantiate a chain from an X509_STORE_CTX
447	virtual LLPointer<LLCertificateChain> getCertificateChain(const X509_STORE_CTX* chain)=0;
448	
449	// instantiate a cert store given it's id.  if a persisted version
450	// exists, it'll be loaded.  If not, one will be created (but not
451	// persisted)
452	virtual LLPointer<LLCertificateStore> getCertificateStore(const std::string& store_id)=0;
453	
454	// persist data in a protected store
455	virtual void setProtectedData(const std::string& data_type,
456								  const std::string& data_id,
457								  const LLSD& data)=0;
458	
459	// retrieve protected data
460	virtual LLSD getProtectedData(const std::string& data_type,
461								  const std::string& data_id)=0;
462	
463	// delete a protected data item from the store
464	virtual void deleteProtectedData(const std::string& data_type,
465									 const std::string& data_id)=0;
466	
467	virtual LLPointer<LLCredential> createCredential(const std::string& grid,
468													 const LLSD& identifier, 
469													 const LLSD& authenticator)=0;
470	
471	virtual LLPointer<LLCredential> loadCredential(const std::string& grid)=0;
472	
473	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0;
474	
475	virtual void deleteCredential(LLPointer<LLCredential> cred)=0;
476	
477};
478
479void initializeSecHandler();
480				
481// retrieve a security api depending on the api type
482LLPointer<LLSecAPIHandler> getSecHandler(const std::string& handler_type);
483
484void registerSecHandler(const std::string& handler_type, 
485						LLPointer<LLSecAPIHandler>& handler);
486
487extern LLPointer<LLSecAPIHandler> gSecAPIHandler;
488
489
490int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
491
492
493#endif // LL_SECAPI_H