PageRenderTime 127ms CodeModel.GetById 17ms app.highlight 98ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llsechandler_basic.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1662 lines | 1216 code | 191 blank | 255 comment | 231 complexity | 0c2d74058ecbeee207fbeeac54b092cd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llsechandler_basic.cpp
   3 * @brief Security API for services such as certificate handling
   4 * secure local storage, etc.
   5 *
   6 * $LicenseInfo:firstyear=2003&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
  29#include "llviewerprecompiledheaders.h"
  30#include "llsecapi.h"
  31#include "llsechandler_basic.h"
  32#include "llsdserialize.h"
  33#include "llviewernetwork.h"
  34#include "llxorcipher.h"
  35#include "llfile.h"
  36#include "lldir.h"
  37#include "llviewercontrol.h"
  38#include <vector>
  39#include <ios>
  40#include <openssl/ossl_typ.h>
  41#include <openssl/x509.h>
  42#include <openssl/x509v3.h>
  43#include <openssl/pem.h>
  44#include <openssl/asn1.h>
  45#include <openssl/rand.h>
  46#include <openssl/err.h>
  47#include <iostream>
  48#include <iomanip>
  49#include <time.h>
  50#include "llmachineid.h"
  51
  52
  53
  54// 128 bits of salt data...
  55#define STORE_SALT_SIZE 16 
  56#define BUFFER_READ_SIZE 256
  57std::string cert_string_from_asn1_string(ASN1_STRING* value);
  58std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value);
  59
  60LLSD _basic_constraints_ext(X509* cert);
  61LLSD _key_usage_ext(X509* cert);
  62LLSD _ext_key_usage_ext(X509* cert);
  63LLSD _subject_key_identifier_ext(X509 *cert);
  64LLSD _authority_key_identifier_ext(X509* cert);
  65
  66LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) 
  67{
  68	
  69	// BIO_new_mem_buf returns a read only bio, but takes a void* which isn't const
  70	// so we need to cast it.
  71	BIO * pem_bio = BIO_new_mem_buf((void*)pem_cert.c_str(), pem_cert.length());
  72	if(pem_bio == NULL)
  73	{
  74		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
  75		throw LLInvalidCertificate(this);
  76	}
  77	mCert = NULL;
  78	PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
  79	BIO_free(pem_bio);
  80	if (!mCert)
  81	{
  82		throw LLInvalidCertificate(this);
  83	}
  84}
  85
  86
  87LLBasicCertificate::LLBasicCertificate(X509* pCert) 
  88{
  89	if (!pCert || !pCert->cert_info)
  90	{
  91		throw LLInvalidCertificate(this);
  92	}	
  93	mCert = X509_dup(pCert);
  94}
  95
  96LLBasicCertificate::~LLBasicCertificate() 
  97{
  98	if(mCert)
  99	{
 100		X509_free(mCert);
 101	}
 102}
 103
 104//
 105// retrieve the pem using the openssl functionality
 106std::string LLBasicCertificate::getPem() const
 107{ 
 108	char * pem_bio_chars = NULL;
 109	// a BIO is the equivalent of a 'std::stream', and
 110	// can be a file, mem stream, whatever.  Grab a memory based
 111	// BIO for the result
 112	BIO *pem_bio = BIO_new(BIO_s_mem());
 113	if (!pem_bio)
 114	{
 115		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;		
 116		return std::string();
 117	}
 118	PEM_write_bio_X509(pem_bio, mCert);
 119	int length = BIO_get_mem_data(pem_bio, &pem_bio_chars);
 120	std::string result = std::string(pem_bio_chars, length);
 121	BIO_free(pem_bio);
 122	return result;
 123}
 124
 125// get the DER encoding for the cert
 126// DER is a binary encoding format for certs...
 127std::vector<U8> LLBasicCertificate::getBinary() const
 128{ 
 129	U8 * der_bio_data = NULL;
 130	// get a memory bio 
 131	BIO *der_bio = BIO_new(BIO_s_mem());
 132	if (!der_bio)
 133	{
 134		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;			
 135		return std::vector<U8>();
 136	}
 137	i2d_X509_bio(der_bio, mCert);
 138	int length = BIO_get_mem_data(der_bio, &der_bio_data);
 139	std::vector<U8> result(length);
 140	// vectors are guranteed to be a contiguous chunk of memory.
 141	memcpy(&result[0], der_bio_data,  length);
 142	BIO_free(der_bio);
 143	return result;
 144}
 145
 146
 147void LLBasicCertificate::getLLSD(LLSD &llsd)
 148{
 149	if (mLLSDInfo.isUndefined())
 150	{
 151		_initLLSD();
 152	}
 153	llsd = mLLSDInfo;
 154}
 155
 156// Initialize the LLSD info for the certificate
 157LLSD& LLBasicCertificate::_initLLSD()
 158{ 
 159
 160	// call the various helpers to build the LLSD
 161	mLLSDInfo[CERT_SUBJECT_NAME] = cert_name_from_X509_NAME(X509_get_subject_name(mCert));
 162	mLLSDInfo[CERT_ISSUER_NAME] = cert_name_from_X509_NAME(X509_get_issuer_name(mCert));
 163	mLLSDInfo[CERT_SUBJECT_NAME_STRING] = cert_string_name_from_X509_NAME(X509_get_subject_name(mCert));
 164	mLLSDInfo[CERT_ISSUER_NAME_STRING] = cert_string_name_from_X509_NAME(X509_get_issuer_name(mCert));
 165	ASN1_INTEGER *sn = X509_get_serialNumber(mCert);
 166	if (sn != NULL)
 167	{
 168		mLLSDInfo[CERT_SERIAL_NUMBER] = cert_string_from_asn1_integer(sn);
 169	}
 170	
 171	mLLSDInfo[CERT_VALID_TO] = cert_date_from_asn1_time(X509_get_notAfter(mCert));
 172	mLLSDInfo[CERT_VALID_FROM] = cert_date_from_asn1_time(X509_get_notBefore(mCert));
 173	mLLSDInfo[CERT_SHA1_DIGEST] = cert_get_digest("sha1", mCert);
 174	mLLSDInfo[CERT_MD5_DIGEST] = cert_get_digest("md5", mCert);
 175	// add the known extensions
 176	mLLSDInfo[CERT_BASIC_CONSTRAINTS] = _basic_constraints_ext(mCert);
 177	mLLSDInfo[CERT_KEY_USAGE] = _key_usage_ext(mCert);
 178	mLLSDInfo[CERT_EXTENDED_KEY_USAGE] = _ext_key_usage_ext(mCert);
 179	mLLSDInfo[CERT_SUBJECT_KEY_IDENTFIER] = _subject_key_identifier_ext(mCert);
 180	mLLSDInfo[CERT_AUTHORITY_KEY_IDENTIFIER] = _authority_key_identifier_ext(mCert);
 181	return mLLSDInfo; 
 182}
 183
 184// Retrieve the basic constraints info
 185LLSD _basic_constraints_ext(X509* cert)
 186{
 187	LLSD result;
 188	BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL);
 189	if(bs)
 190	{
 191		result = LLSD::emptyMap();
 192		// Determines whether the cert can be used as a CA
 193		result[CERT_BASIC_CONSTRAINTS_CA] = (bool)bs->ca;
 194	
 195		if(bs->pathlen) 
 196		{
 197			// the pathlen determines how deep a certificate chain can be from
 198			// this CA
 199			if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
 200			   || !bs->ca) 
 201			{
 202				result[CERT_BASIC_CONSTRAINTS_PATHLEN] = 0;
 203			} 
 204			else 
 205			{
 206				result[CERT_BASIC_CONSTRAINTS_PATHLEN] = (int)ASN1_INTEGER_get(bs->pathlen);
 207			}
 208		}
 209
 210	}
 211	return result;
 212}
 213
 214// retrieve the key usage, which specifies how the cert can be used.
 215// 
 216LLSD _key_usage_ext(X509* cert)
 217{
 218	LLSD result;
 219	ASN1_STRING *usage_str = (ASN1_STRING *)X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL);
 220	if(usage_str)
 221	{
 222		result = LLSD::emptyArray();
 223		long usage = 0;
 224		if(usage_str->length > 0) 
 225		{
 226			usage = usage_str->data[0];
 227			if(usage_str->length > 1)
 228			{
 229				usage |= usage_str->data[1] << 8;
 230			}
 231		}
 232		ASN1_STRING_free(usage_str);
 233		if(usage)
 234		{
 235			if(usage & KU_DIGITAL_SIGNATURE) result.append(LLSD((std::string)CERT_KU_DIGITAL_SIGNATURE));
 236			if(usage & KU_NON_REPUDIATION) result.append(LLSD((std::string)CERT_KU_NON_REPUDIATION));
 237			if(usage & KU_KEY_ENCIPHERMENT) result.append(LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT));
 238			if(usage & KU_DATA_ENCIPHERMENT) result.append(LLSD((std::string)CERT_KU_DATA_ENCIPHERMENT));
 239			if(usage & KU_KEY_AGREEMENT) result.append(LLSD((std::string)CERT_KU_KEY_AGREEMENT));
 240			if(usage & KU_KEY_CERT_SIGN) result.append(LLSD((std::string)CERT_KU_CERT_SIGN));			
 241			if(usage & KU_CRL_SIGN) result.append(LLSD((std::string)CERT_KU_CRL_SIGN));	
 242			if(usage & KU_ENCIPHER_ONLY) result.append(LLSD((std::string)CERT_KU_ENCIPHER_ONLY));				
 243			if(usage & KU_DECIPHER_ONLY) result.append(LLSD((std::string)CERT_KU_DECIPHER_ONLY));		
 244		}
 245	}
 246	return result;
 247}
 248
 249// retrieve the extended key usage for the cert
 250LLSD _ext_key_usage_ext(X509* cert)
 251{
 252	LLSD result;
 253	EXTENDED_KEY_USAGE *eku = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL);
 254	if(eku)
 255	{
 256		result = LLSD::emptyArray();
 257		while(sk_ASN1_OBJECT_num(eku))
 258		{
 259			ASN1_OBJECT *usage = sk_ASN1_OBJECT_pop(eku);
 260			if(usage)
 261			{
 262				int nid = OBJ_obj2nid(usage);
 263				if (nid)
 264				{
 265					std::string sn = OBJ_nid2sn(nid);
 266					result.append(sn);
 267				}
 268				ASN1_OBJECT_free(usage);
 269			}
 270		}
 271	}
 272	return result;
 273}
 274
 275// retrieve the subject key identifier of the cert
 276LLSD _subject_key_identifier_ext(X509 *cert)
 277{
 278	LLSD result;
 279	ASN1_OCTET_STRING *skeyid = (ASN1_OCTET_STRING *)X509_get_ext_d2i(cert, NID_subject_key_identifier, NULL, NULL);
 280	if(skeyid)
 281	{
 282		result = cert_string_from_octet_string(skeyid);
 283	}
 284	return result;
 285}
 286
 287// retrieve the authority key identifier of the cert
 288LLSD _authority_key_identifier_ext(X509* cert)
 289{
 290	LLSD result;
 291	AUTHORITY_KEYID *akeyid = (AUTHORITY_KEYID *)X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
 292	if(akeyid)
 293	{
 294		result = LLSD::emptyMap();
 295		if(akeyid->keyid)
 296		{
 297			result[CERT_AUTHORITY_KEY_IDENTIFIER_ID] = cert_string_from_octet_string(akeyid->keyid);
 298		}
 299		if(akeyid->serial)
 300		{
 301			result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);
 302		}	
 303	}
 304	
 305	// we ignore the issuer name in the authority key identifier, we check the issue name via
 306	// the the issuer name entry in the cert.
 307	
 308
 309	return result;
 310}
 311
 312// retrieve an openssl x509 object,
 313// which must be freed by X509_free
 314X509* LLBasicCertificate::getOpenSSLX509() const
 315{ 
 316	return X509_dup(mCert); 
 317}  
 318
 319// generate a single string containing the subject or issuer
 320// name of the cert.
 321std::string cert_string_name_from_X509_NAME(X509_NAME* name)
 322{
 323	char * name_bio_chars = NULL;
 324	// get a memory bio
 325	BIO *name_bio = BIO_new(BIO_s_mem());
 326	// stream the name into the bio.  The name will be in the 'short name' format
 327	X509_NAME_print_ex(name_bio, name, 0, XN_FLAG_RFC2253);
 328	int length = BIO_get_mem_data(name_bio, &name_bio_chars);
 329	std::string result = std::string(name_bio_chars, length);
 330	BIO_free(name_bio);
 331	return result;
 332}
 333
 334// generate an LLSD from a certificate name (issuer or subject name).  
 335// the name will be strings indexed by the 'long form'
 336LLSD cert_name_from_X509_NAME(X509_NAME* name)
 337{
 338	LLSD result = LLSD::emptyMap();
 339	int name_entries = X509_NAME_entry_count(name);
 340	for (int entry_index=0; entry_index < name_entries; entry_index++) 
 341	{
 342		char buffer[32];
 343		X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, entry_index);
 344		
 345		std::string name_value = std::string((const char*)M_ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), 
 346											 M_ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry)));
 347
 348		ASN1_OBJECT* name_obj = X509_NAME_ENTRY_get_object(entry);		
 349		OBJ_obj2txt(buffer, sizeof(buffer), name_obj, 0);
 350		std::string obj_buffer_str = std::string(buffer);
 351		result[obj_buffer_str] = name_value;
 352	}
 353	
 354	return result;
 355}
 356
 357// Generate a string from an ASN1 integer.  ASN1 Integers are
 358// bignums, so they can be 'infinitely' long, therefore we
 359// cannot simply use a conversion to U64 or something.
 360// We retrieve as a readable string for UI
 361
 362std::string cert_string_from_asn1_integer(ASN1_INTEGER* value)
 363{
 364	std::string result;
 365	BIGNUM *bn = ASN1_INTEGER_to_BN(value, NULL);
 366	if(bn)
 367	{
 368		char * ascii_bn = BN_bn2hex(bn);
 369
 370		if(ascii_bn)
 371		{
 372			result = ascii_bn;
 373			OPENSSL_free(ascii_bn);
 374		}
 375		BN_free(bn);
 376	}
 377	return result;
 378}
 379
 380// Generate a string from an OCTET string.
 381// we retrieve as a 
 382
 383std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value)
 384{
 385	
 386	std::stringstream result;
 387	result << std::hex << std::setprecision(2);
 388	for (int i=0; i < value->length; i++)
 389	{
 390		if (i != 0) 
 391		{
 392			result << ":";
 393		}
 394		result  << std::setfill('0') << std::setw(2) << (int)value->data[i];
 395	}
 396	return result.str();
 397}
 398
 399// Generate a string from an ASN1 integer.  ASN1 Integers are
 400// bignums, so they can be 'infinitely' long, therefore we
 401// cannot simply use a conversion to U64 or something.
 402// We retrieve as a readable string for UI
 403
 404std::string cert_string_from_asn1_string(ASN1_STRING* value)
 405{
 406	char * string_bio_chars = NULL;
 407	std::string result;
 408	// get a memory bio
 409	BIO *string_bio = BIO_new(BIO_s_mem());
 410	if(!string_bio)
 411	{
 412		// stream the name into the bio.  The name will be in the 'short name' format
 413		ASN1_STRING_print_ex(string_bio, value, ASN1_STRFLGS_RFC2253);
 414		int length = BIO_get_mem_data(string_bio, &string_bio_chars);
 415		result = std::string(string_bio_chars, length);
 416		BIO_free(string_bio);
 417	}
 418	else
 419	{
 420		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
 421	}
 422	
 423	return result;
 424}
 425
 426// retrieve a date structure from an ASN1 time, for 
 427// validity checking.
 428LLDate cert_date_from_asn1_time(ASN1_TIME* asn1_time)
 429{
 430	
 431	struct tm timestruct = {0};
 432	int i = asn1_time->length;
 433	
 434	if (i < 10)
 435	{
 436		return LLDate();
 437	}	
 438	// convert the date from the ASN1 time (which is a string in ZULU time), to
 439	// a timeval.
 440	timestruct.tm_year = (asn1_time->data[0]-'0') * 10 + (asn1_time->data[1]-'0');
 441	
 442	/* Deal with Year 2000 */
 443	if (timestruct.tm_year < 70)
 444		timestruct.tm_year += 100;
 445	
 446	timestruct.tm_mon = (asn1_time->data[2]-'0') * 10 + (asn1_time->data[3]-'0') - 1;
 447	timestruct.tm_mday = (asn1_time->data[4]-'0') * 10 + (asn1_time->data[5]-'0');
 448	timestruct.tm_hour = (asn1_time->data[6]-'0') * 10 + (asn1_time->data[7]-'0');
 449	timestruct.tm_min = (asn1_time->data[8]-'0') * 10 + (asn1_time->data[9]-'0');
 450	timestruct.tm_sec = (asn1_time->data[10]-'0') * 10 + (asn1_time->data[11]-'0');
 451
 452#if LL_WINDOWS
 453	return LLDate((F64)_mkgmtime(&timestruct));
 454#else // LL_WINDOWS
 455	return LLDate((F64)timegm(&timestruct));
 456#endif // LL_WINDOWS
 457}
 458
 459													   
 460// Generate a string containing a digest.  The digest time is 'ssh1' or
 461// 'md5', and the resulting string is of the form "aa:12:5c:' and so on
 462std::string cert_get_digest(const std::string& digest_type, X509 *cert)
 463{
 464	unsigned char digest_data[BUFFER_READ_SIZE];
 465	unsigned int len = sizeof(digest_data);
 466	std::stringstream result;
 467	const EVP_MD* digest = NULL;
 468	// we could use EVP_get_digestbyname, but that requires initializer code which
 469	// would require us to complicate things by plumbing it into the system.
 470	if (digest_type == "md5")
 471	{
 472		digest = EVP_md5();
 473	}
 474	else if (digest_type == "sha1")
 475	{
 476		digest = EVP_sha1();
 477	}
 478	else
 479	{
 480		return std::string();
 481	}
 482
 483	X509_digest(cert, digest, digest_data, &len);
 484	result << std::hex << std::setprecision(2);
 485	for (unsigned int i=0; i < len; i++)
 486	{
 487		if (i != 0) 
 488		{
 489			result << ":";
 490		}
 491		result  << std::setfill('0') << std::setw(2) << (int)digest_data[i];
 492	}
 493	return result.str();
 494}
 495
 496
 497// class LLBasicCertificateVector
 498// This class represents a list of certificates, implemented by a vector of certificate pointers.
 499// it contains implementations of the virtual functions for iterators, search, add, remove, etc.
 500//
 501
 502//  Find a certificate in the list.
 503// It will find a cert that has minimally the params listed, with the values being the same
 504LLBasicCertificateVector::iterator LLBasicCertificateVector::find(const LLSD& params)
 505{
 506	BOOL found = FALSE;
 507	// loop through the entire vector comparing the values in the certs
 508	// against those passed in via the params.
 509	// params should be a map.  Only the items specified in the map will be
 510	// checked, but they must match exactly, even if they're maps or arrays.
 511	
 512	for(iterator cert = begin();
 513		cert != end();
 514		cert++)
 515	{
 516
 517		found= TRUE;
 518		LLSD cert_info;
 519		(*cert)->getLLSD(cert_info);
 520			for (LLSD::map_const_iterator param = params.beginMap();
 521			 param != params.endMap();
 522			 param++)
 523		{
 524
 525			if (!cert_info.has((std::string)param->first) || 
 526				(!valueCompareLLSD(cert_info[(std::string)param->first], param->second)))
 527			{
 528				found = FALSE;
 529				break;
 530			}
 531		}
 532		if (found)
 533		{
 534			return (cert);
 535		}
 536	}
 537	return end();
 538}
 539
 540// Insert a certificate into the store.  If the certificate already 
 541// exists in the store, nothing is done.
 542void  LLBasicCertificateVector::insert(iterator _iter, 
 543				       LLPointer<LLCertificate> cert)
 544{
 545	LLSD cert_info;
 546	cert->getLLSD(cert_info);
 547	if (cert_info.isMap() && cert_info.has(CERT_SHA1_DIGEST))
 548	{
 549		LLSD existing_cert_info = LLSD::emptyMap();
 550		existing_cert_info[CERT_MD5_DIGEST] = cert_info[CERT_MD5_DIGEST];
 551		if(find(existing_cert_info) == end())
 552		{
 553			BasicIteratorImpl *basic_iter = dynamic_cast<BasicIteratorImpl*>(_iter.mImpl.get());
 554			llassert(basic_iter);
 555			if (basic_iter)
 556			{
 557				mCerts.insert(basic_iter->mIter, cert);
 558			}
 559		}
 560	}
 561}
 562
 563// remove a certificate from the store
 564LLPointer<LLCertificate> LLBasicCertificateVector::erase(iterator _iter)
 565{
 566	
 567	if (_iter != end())
 568	{
 569		BasicIteratorImpl *basic_iter = dynamic_cast<BasicIteratorImpl*>(_iter.mImpl.get());
 570		LLPointer<LLCertificate> result = (*_iter);
 571		mCerts.erase(basic_iter->mIter);
 572		return result;
 573	}
 574	return NULL;
 575}
 576
 577
 578//
 579// LLBasicCertificateStore
 580// This class represents a store of CA certificates.  The basic implementation
 581// uses a pem file such as the legacy CA.pem stored in the existing 
 582// SL implementation.
 583LLBasicCertificateStore::LLBasicCertificateStore(const std::string& filename)
 584{
 585	mFilename = filename;
 586	load_from_file(filename);
 587}
 588
 589void LLBasicCertificateStore::load_from_file(const std::string& filename)
 590{
 591	// scan the PEM file extracting each certificate
 592	if (!LLFile::isfile(filename))
 593	{
 594		return;
 595	}
 596	
 597	BIO* file_bio = BIO_new(BIO_s_file());
 598	if(file_bio)
 599	{
 600		if (BIO_read_filename(file_bio, filename.c_str()) > 0)
 601		{	
 602			X509 *cert_x509 = NULL;
 603			while((PEM_read_bio_X509(file_bio, &cert_x509, 0, NULL)) && 
 604				  (cert_x509 != NULL))
 605			{
 606				try
 607				{
 608					add(new LLBasicCertificate(cert_x509));
 609				}
 610				catch (...)
 611				{
 612					LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL;
 613				}
 614				X509_free(cert_x509);
 615				cert_x509 = NULL;
 616			}
 617			BIO_free(file_bio);
 618		}
 619	}
 620	else
 621	{
 622		LL_WARNS("SECAPI") << "Could not allocate a file BIO" << LL_ENDL;
 623	}
 624}
 625
 626
 627LLBasicCertificateStore::~LLBasicCertificateStore()
 628{
 629}
 630
 631
 632// persist the store
 633void LLBasicCertificateStore::save()
 634{
 635	llofstream file_store(mFilename, llofstream::binary);
 636	if(!file_store.fail())
 637	{
 638		for(iterator cert = begin();
 639			cert != end();
 640			cert++)
 641		{
 642			std::string pem = (*cert)->getPem();
 643			if(!pem.empty())
 644			{
 645				file_store << (*cert)->getPem() << std::endl;
 646			}
 647		}
 648		file_store.close();
 649	}
 650	else
 651	{
 652		LL_WARNS("SECAPI") << "Could not open certificate store " << mFilename << "for save" << LL_ENDL;
 653	}
 654}
 655
 656// return the store id
 657std::string LLBasicCertificateStore::storeId() const
 658{
 659	// this is the basic handler which uses the CA.pem store,
 660	// so we ignore this.
 661	return std::string("");
 662}
 663
 664
 665//
 666// LLBasicCertificateChain
 667// This class represents a chain of certs, each cert being signed by the next cert
 668// in the chain.  Certs must be properly signed by the parent
 669LLBasicCertificateChain::LLBasicCertificateChain(const X509_STORE_CTX* store)
 670{
 671
 672	// we're passed in a context, which contains a cert, and a blob of untrusted
 673	// certificates which compose the chain.
 674	if((store == NULL) || (store->cert == NULL))
 675	{
 676		LL_WARNS("SECAPI") << "An invalid store context was passed in when trying to create a certificate chain" << LL_ENDL;
 677		return;
 678	}
 679	// grab the child cert
 680	LLPointer<LLCertificate> current = new LLBasicCertificate(store->cert);
 681
 682	add(current);
 683	if(store->untrusted != NULL)
 684	{
 685		// if there are other certs in the chain, we build up a vector
 686		// of untrusted certs so we can search for the parents of each
 687		// consecutive cert.
 688		LLBasicCertificateVector untrusted_certs;
 689		for(int i = 0; i < sk_X509_num(store->untrusted); i++)
 690		{
 691			LLPointer<LLCertificate> cert = new LLBasicCertificate(sk_X509_value(store->untrusted, i));
 692			untrusted_certs.add(cert);
 693
 694		}		
 695		while(untrusted_certs.size() > 0)
 696		{
 697			LLSD find_data = LLSD::emptyMap();
 698			LLSD cert_data;
 699			current->getLLSD(cert_data);
 700			// we simply build the chain via subject/issuer name as the
 701			// client should not have passed in multiple CA's with the same 
 702			// subject name.  If they did, it'll come out in the wash during
 703			// validation.
 704			find_data[CERT_SUBJECT_NAME_STRING] = cert_data[CERT_ISSUER_NAME_STRING]; 
 705			LLBasicCertificateVector::iterator issuer = untrusted_certs.find(find_data);
 706			if (issuer != untrusted_certs.end())
 707			{
 708				current = untrusted_certs.erase(issuer);
 709				add(current);
 710			}
 711			else
 712			{
 713				break;
 714			}
 715		}
 716	}
 717}
 718
 719
 720// subdomain wildcard specifiers can be divided into 3 parts
 721// the part before the first *, the part after the first * but before
 722// the second *, and the part after the second *.
 723// It then iterates over the second for each place in the string
 724// that it matches.  ie if the subdomain was testfoofoobar, and
 725// the wildcard was test*foo*bar, it would match test, then
 726// recursively match foofoobar and foobar
 727
 728bool _cert_subdomain_wildcard_match(const std::string& subdomain,
 729									const std::string& wildcard)
 730{
 731	// split wildcard into the portion before the *, and the portion after
 732
 733	int wildcard_pos = wildcard.find_first_of('*');	
 734	// check the case where there is no wildcard.
 735	if(wildcard_pos == wildcard.npos)
 736	{
 737		return (subdomain == wildcard);
 738	}
 739	
 740	// we need to match the first part of the subdomain string up to the wildcard
 741	// position
 742	if(subdomain.substr(0, wildcard_pos) != wildcard.substr(0, wildcard_pos))
 743	{
 744		// the first portions of the strings didn't match
 745		return FALSE;
 746	}
 747	
 748	// as the portion of the wildcard string before the * matched, we need to check the
 749	// portion afterwards.  Grab that portion.
 750	std::string new_wildcard_string = wildcard.substr( wildcard_pos+1, wildcard.npos);
 751	if(new_wildcard_string.empty())
 752	{
 753		// we had nothing after the *, so it's an automatic match
 754		return TRUE;
 755	}
 756	
 757	// grab the portion of the remaining wildcard string before the next '*'.  We need to find this
 758	// within the remaining subdomain string. and then recursively check.
 759	std::string new_wildcard_match_string = new_wildcard_string.substr(0, new_wildcard_string.find_first_of('*'));
 760	
 761	// grab the portion of the subdomain after the part that matched the initial wildcard portion
 762	std::string new_subdomain = subdomain.substr(wildcard_pos, subdomain.npos);
 763	
 764	// iterate through the current subdomain, finding instances of the match string.
 765	int sub_pos = new_subdomain.find_first_of(new_wildcard_match_string);
 766	while(sub_pos != std::string::npos)
 767	{
 768		new_subdomain = new_subdomain.substr(sub_pos, std::string::npos);
 769		if(_cert_subdomain_wildcard_match(new_subdomain, new_wildcard_string))
 770		{
 771			return TRUE;
 772		}
 773		sub_pos = new_subdomain.find_first_of(new_wildcard_match_string, 1);
 774
 775
 776	}
 777	// didn't find any instances of the match string that worked in the subdomain, so fail.
 778	return FALSE;
 779}
 780
 781
 782// RFC2459 does not address wildcards as part of it's name matching
 783// specification, and there is no RFC specifying wildcard matching,
 784// RFC2818 does a few statements about wildcard matching, but is very 
 785// general.  Generally, wildcard matching is per implementation, although
 786// it's pretty similar.
 787// in our case, we use the '*' wildcard character only, within each
 788// subdomain.  The hostname and the CN specification should have the
 789// same number of subdomains.
 790// We then iterate that algorithm over each subdomain.
 791bool _cert_hostname_wildcard_match(const std::string& hostname, const std::string& common_name)
 792{
 793	std::string new_hostname = hostname;
 794	std::string new_cn = common_name;
 795	
 796	// find the last '.' in the hostname and the match name.
 797	int subdomain_pos = new_hostname.find_last_of('.');
 798	int subcn_pos = new_cn.find_last_of('.');
 799	
 800	// if the last char is a '.', strip it
 801	if(subdomain_pos == (new_hostname.length()-1))
 802	{
 803		new_hostname = new_hostname.substr(0, subdomain_pos);
 804		subdomain_pos = new_hostname.find_last_of('.');
 805	}
 806	if(subcn_pos == (new_cn.length()-1))
 807	{
 808		new_cn = new_cn.substr(0, subcn_pos);
 809		subcn_pos = new_cn.find_last_of('.');
 810	}	
 811
 812	// Check to see if there are any further '.' in the string.  
 813	while((subcn_pos != std::string::npos) && (subdomain_pos != std::string::npos))
 814	{
 815		// snip out last subdomain in both the match string and the hostname
 816		// The last bit for 'my.current.host.com' would be 'com'  
 817		std::string cn_part = new_cn.substr(subcn_pos+1, std::string::npos);
 818		std::string hostname_part = new_hostname.substr(subdomain_pos+1, std::string::npos);
 819		
 820		if(!_cert_subdomain_wildcard_match(new_hostname.substr(subdomain_pos+1, std::string::npos),
 821										   cn_part))
 822		{
 823			return FALSE;
 824		}
 825		new_hostname = new_hostname.substr(0, subdomain_pos);
 826		new_cn = new_cn.substr(0, subcn_pos);
 827		subdomain_pos = new_hostname.find_last_of('.');
 828		subcn_pos = new_cn.find_last_of('.');
 829	}	
 830	// check to see if the most significant portion of the common name is '*'.  If so, we can
 831	// simply return success as child domains are also matched.
 832	if(new_cn == "*")
 833	{
 834		// if it's just a '*' we support all child domains as well, so '*.
 835		return TRUE;
 836	}
 837	
 838	return _cert_subdomain_wildcard_match(new_hostname, new_cn);
 839
 840}
 841
 842// validate that the LLSD array in llsd_set contains the llsd_value 
 843bool _LLSDArrayIncludesValue(const LLSD& llsd_set, LLSD llsd_value)
 844{
 845	for(LLSD::array_const_iterator set_value = llsd_set.beginArray();
 846		set_value != llsd_set.endArray();
 847		set_value++)
 848	{
 849		if(valueCompareLLSD((*set_value), llsd_value))
 850		{
 851			return TRUE;
 852		}
 853	}
 854	return FALSE;
 855}
 856
 857void _validateCert(int validation_policy,
 858				  LLPointer<LLCertificate> cert,
 859				  const LLSD& validation_params,
 860				  int depth)
 861{
 862
 863	LLSD current_cert_info;
 864	cert->getLLSD(current_cert_info);		
 865	// check basic properties exist in the cert
 866	if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
 867	{
 868		throw LLCertException(cert, "Cert doesn't have a Subject Name");				
 869	}
 870	
 871	if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
 872	{
 873		throw LLCertException(cert, "Cert doesn't have an Issuer Name");				
 874	}
 875	
 876	// check basic properties exist in the cert
 877	if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
 878	{
 879		throw LLCertException(cert, "Cert doesn't have an expiration period");				
 880	}
 881	if (!current_cert_info.has(CERT_SHA1_DIGEST))
 882	{
 883		throw LLCertException(cert, "No SHA1 digest");
 884	}
 885
 886	if (validation_policy & VALIDATION_POLICY_TIME)
 887	{
 888
 889		LLDate validation_date(time(NULL));
 890		if(validation_params.has(CERT_VALIDATION_DATE))
 891		{
 892			validation_date = validation_params[CERT_VALIDATION_DATE];
 893		}
 894		
 895		if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
 896		   (validation_date > current_cert_info[CERT_VALID_TO].asDate()))
 897		{
 898			throw LLCertValidationExpirationException(cert, validation_date);
 899		}
 900	}
 901	if (validation_policy & VALIDATION_POLICY_SSL_KU)
 902	{
 903		if (current_cert_info.has(CERT_KEY_USAGE) && current_cert_info[CERT_KEY_USAGE].isArray() &&
 904			(!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
 905									   LLSD((std::string)CERT_KU_DIGITAL_SIGNATURE))) ||
 906			!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
 907									  LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
 908		{
 909			throw LLCertKeyUsageValidationException(cert);
 910		}
 911		// only validate EKU if the cert has it
 912		if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&	   
 913		   (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE], 
 914									LLSD((std::string)CERT_EKU_SERVER_AUTH))))
 915		{
 916			throw LLCertKeyUsageValidationException(cert);			
 917		}
 918	}
 919	if (validation_policy & VALIDATION_POLICY_CA_KU)
 920	{
 921		if (current_cert_info.has(CERT_KEY_USAGE) && current_cert_info[CERT_KEY_USAGE].isArray() &&
 922			(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], 
 923									   (std::string)CERT_KU_CERT_SIGN)))
 924			{
 925				throw LLCertKeyUsageValidationException(cert);						
 926			}
 927	}
 928	
 929	// validate basic constraints
 930	if ((validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS) &&
 931		current_cert_info.has(CERT_BASIC_CONSTRAINTS) && 
 932		current_cert_info[CERT_BASIC_CONSTRAINTS].isMap())
 933	{
 934		if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
 935		   !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
 936		{
 937				throw LLCertBasicConstraintsValidationException(cert);
 938		}
 939		if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
 940			((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
 941			 (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
 942		{
 943			throw LLCertBasicConstraintsValidationException(cert);					
 944		}
 945	}
 946}
 947
 948bool _verify_signature(LLPointer<LLCertificate> parent, 
 949					   LLPointer<LLCertificate> child)
 950{
 951	bool verify_result = FALSE; 
 952	LLSD cert1, cert2;
 953	parent->getLLSD(cert1);
 954	child->getLLSD(cert2);
 955	X509 *signing_cert = parent->getOpenSSLX509();
 956	X509 *child_cert = child->getOpenSSLX509();
 957	if((signing_cert != NULL) && (child_cert != NULL))
 958	{
 959		EVP_PKEY *pkey = X509_get_pubkey(signing_cert);
 960		
 961		
 962		if(pkey)
 963		{
 964			int verify_code = X509_verify(child_cert, pkey);
 965			verify_result = ( verify_code > 0);
 966			EVP_PKEY_free(pkey);
 967		}
 968		else
 969		{
 970			LL_WARNS("SECAPI") << "Could not validate the cert chain signature, as the public key of the signing cert could not be retrieved" << LL_ENDL;
 971		}
 972
 973	}
 974	else
 975	{
 976		LL_WARNS("SECAPI") << "Signature verification failed as there are no certs in the chain" << LL_ENDL;
 977	}
 978	if(child_cert)
 979	{
 980		X509_free(child_cert);
 981	}
 982	if(signing_cert)
 983	{
 984		X509_free(signing_cert);
 985	}
 986	return verify_result;
 987}
 988
 989
 990// validate the certificate chain against a store.
 991// There are many aspects of cert validatioin policy involved in
 992// trust validation.  The policies in this validation algorithm include
 993// * Hostname matching for SSL certs
 994// * Expiration time matching
 995// * Signature validation
 996// * Chain trust (is the cert chain trusted against the store)
 997// * Basic constraints
 998// * key usage and extended key usage
 999// TODO: We should add 'authority key identifier' for chaining.
1000// This algorithm doesn't simply validate the chain by itself
1001// and verify the last cert is in the certificate store, or points
1002// to a cert in the store.  It validates whether any cert in the chain
1003// is trusted in the store, even if it's not the last one.
1004void LLBasicCertificateStore::validate(int validation_policy,
1005									   LLPointer<LLCertificateChain> cert_chain,
1006									   const LLSD& validation_params)
1007{
1008	// If --no-verify-ssl-cert was passed on the command line, stop right now.
1009	if (gSavedSettings.getBOOL("NoVerifySSLCert")) return;
1010
1011	if(cert_chain->size() < 1)
1012	{
1013		throw LLCertException(NULL, "No certs in chain");
1014	}
1015	iterator current_cert = cert_chain->begin();
1016	LLSD 	current_cert_info;
1017	LLSD validation_date;
1018	if (validation_params.has(CERT_VALIDATION_DATE))
1019	{
1020		validation_date = validation_params[CERT_VALIDATION_DATE];
1021	}
1022
1023	if (validation_policy & VALIDATION_POLICY_HOSTNAME)
1024	{
1025		(*current_cert)->getLLSD(current_cert_info);
1026		if(!validation_params.has(CERT_HOSTNAME))
1027		{
1028			throw LLCertException((*current_cert), "No hostname passed in for validation");			
1029		}
1030		if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
1031		{
1032			throw LLInvalidCertificate((*current_cert));				
1033		}
1034		
1035		LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << 
1036		     "against the cert CN " << current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString() << LL_ENDL;
1037		if(!_cert_hostname_wildcard_match(validation_params[CERT_HOSTNAME].asString(),
1038										  current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString()))
1039		{
1040			throw LLCertValidationHostnameException(validation_params[CERT_HOSTNAME].asString(),
1041													(*current_cert));
1042		}
1043	}
1044
1045	// check the cache of already validated certs
1046	X509* cert_x509 = (*current_cert)->getOpenSSLX509();
1047	if(!cert_x509)
1048	{
1049		throw LLInvalidCertificate((*current_cert));			
1050	}
1051	std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
1052	t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash);
1053	if(cache_entry != mTrustedCertCache.end())
1054	{
1055		LL_DEBUGS("SECAPI") << "Found cert in cache" << LL_ENDL;	
1056		// this cert is in the cache, so validate the time.
1057		if (validation_policy & VALIDATION_POLICY_TIME)
1058		{
1059			LLDate validation_date(time(NULL));
1060			if(validation_params.has(CERT_VALIDATION_DATE))
1061			{
1062				validation_date = validation_params[CERT_VALIDATION_DATE];
1063			}
1064			
1065			if((validation_date < cache_entry->second.first) ||
1066			   (validation_date > cache_entry->second.second))
1067			{
1068				throw LLCertValidationExpirationException((*current_cert), validation_date);
1069			}
1070		}
1071		// successfully found in cache
1072		return;
1073	}
1074	if(current_cert_info.isUndefined())
1075	{
1076		(*current_cert)->getLLSD(current_cert_info);
1077	}
1078	LLDate from_time = current_cert_info[CERT_VALID_FROM].asDate();
1079	LLDate to_time = current_cert_info[CERT_VALID_TO].asDate();
1080	int depth = 0;
1081	LLPointer<LLCertificate> previous_cert;
1082	// loop through the cert chain, validating the current cert against the next one.
1083	while(current_cert != cert_chain->end())
1084	{
1085		
1086		int local_validation_policy = validation_policy;
1087		if(current_cert == cert_chain->begin())
1088		{
1089			// for the child cert, we don't validate CA stuff
1090			local_validation_policy &= ~(VALIDATION_POLICY_CA_KU | 
1091										 VALIDATION_POLICY_CA_BASIC_CONSTRAINTS);
1092		}
1093		else
1094		{
1095			// for non-child certs, we don't validate SSL Key usage
1096			local_validation_policy &= ~VALIDATION_POLICY_SSL_KU;				
1097			if(!_verify_signature((*current_cert),
1098								  previous_cert))
1099			{
1100			   throw LLCertValidationInvalidSignatureException(previous_cert);
1101			}
1102		}
1103		_validateCert(local_validation_policy,
1104					  (*current_cert),
1105					  validation_params,
1106					  depth);
1107		
1108		// look for a CA in the CA store that may belong to this chain.
1109		LLSD cert_search_params = LLSD::emptyMap();		
1110		// is the cert itself in the store?
1111		cert_search_params[CERT_SHA1_DIGEST] = current_cert_info[CERT_SHA1_DIGEST];
1112		LLCertificateStore::iterator found_store_cert = find(cert_search_params);
1113		if(found_store_cert != end())
1114		{
1115			mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
1116			return;
1117		}
1118		
1119		// is the parent in the cert store?
1120			
1121		cert_search_params = LLSD::emptyMap();
1122		cert_search_params[CERT_SUBJECT_NAME_STRING] = current_cert_info[CERT_ISSUER_NAME_STRING];
1123		if (current_cert_info.has(CERT_AUTHORITY_KEY_IDENTIFIER))
1124		{
1125			LLSD cert_aki = current_cert_info[CERT_AUTHORITY_KEY_IDENTIFIER];
1126			if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_ID))
1127			{
1128				cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_ID];
1129			}
1130			if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL))
1131			{
1132				cert_search_params[CERT_SERIAL_NUMBER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL];
1133			}
1134		}
1135		found_store_cert = find(cert_search_params);
1136		
1137		if(found_store_cert != end())
1138		{
1139			// validate the store cert against the depth
1140			_validateCert(validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS,
1141						  (*found_store_cert),
1142						  LLSD(),
1143						  depth);
1144			
1145			// verify the signature of the CA
1146			if(!_verify_signature((*found_store_cert),
1147								  (*current_cert)))
1148			{
1149				throw LLCertValidationInvalidSignatureException(*current_cert);
1150			}			
1151			// successfully validated.
1152			mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);		
1153			return;
1154		}
1155		previous_cert = (*current_cert);
1156		current_cert++;
1157		depth++;
1158		if(current_cert != cert_chain->end())
1159		{
1160			(*current_cert)->getLLSD(current_cert_info);
1161		}
1162	}
1163	if (validation_policy & VALIDATION_POLICY_TRUSTED)
1164	{
1165		// we reached the end without finding a trusted cert.
1166		throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]);
1167
1168	}
1169	mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);	
1170}
1171
1172
1173// LLSecAPIBasicHandler Class
1174// Interface handler class for the various security storage handlers.
1175
1176// We read the file on construction, and write it on destruction.  This
1177// means multiple processes cannot modify the datastore.
1178LLSecAPIBasicHandler::LLSecAPIBasicHandler(const std::string& protected_data_file,
1179										   const std::string& legacy_password_path)
1180{
1181	mProtectedDataFilename = protected_data_file;
1182	mProtectedDataMap = LLSD::emptyMap();
1183	mLegacyPasswordPath = legacy_password_path;
1184
1185}
1186
1187LLSecAPIBasicHandler::LLSecAPIBasicHandler()
1188{
1189}
1190
1191
1192void LLSecAPIBasicHandler::init()
1193{
1194	mProtectedDataMap = LLSD::emptyMap();
1195	if (mProtectedDataFilename.length() == 0)
1196	{
1197		mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
1198															"bin_conf.dat");
1199		mLegacyPasswordPath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "password.dat");
1200	
1201		mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
1202															"bin_conf.dat");	
1203		std::string store_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
1204														"CA.pem");
1205		
1206		
1207		LL_DEBUGS("SECAPI") << "Loading certificate store from " << store_file << LL_ENDL;
1208		mStore = new LLBasicCertificateStore(store_file);
1209		
1210		// grab the application CA.pem file that contains the well-known certs shipped
1211		// with the product
1212		std::string ca_file_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
1213		llinfos << "app path " << ca_file_path << llendl;
1214		LLPointer<LLBasicCertificateStore> app_ca_store = new LLBasicCertificateStore(ca_file_path);
1215		
1216		// push the applicate CA files into the store, therefore adding any new CA certs that 
1217		// updated
1218		for(LLCertificateVector::iterator i = app_ca_store->begin();
1219			i != app_ca_store->end();
1220			i++)
1221		{
1222			mStore->add(*i);
1223		}
1224		
1225	}
1226	_readProtectedData(); // initialize mProtectedDataMap
1227						  // may throw LLProtectedDataException if saved datamap is not decryptable
1228}
1229LLSecAPIBasicHandler::~LLSecAPIBasicHandler()
1230{
1231	_writeProtectedData();
1232}
1233
1234void LLSecAPIBasicHandler::_readProtectedData()
1235{	
1236	// attempt to load the file into our map
1237	LLPointer<LLSDParser> parser = new LLSDXMLParser();
1238	llifstream protected_data_stream(mProtectedDataFilename.c_str(), 
1239									llifstream::binary);
1240
1241	if (!protected_data_stream.fail()) {
1242		int offset;
1243		U8 salt[STORE_SALT_SIZE];
1244		U8 buffer[BUFFER_READ_SIZE];
1245		U8 decrypted_buffer[BUFFER_READ_SIZE];
1246		int decrypted_length;	
1247		unsigned char unique_id[MAC_ADDRESS_BYTES];
1248        LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
1249		LLXORCipher cipher(unique_id, sizeof(unique_id));
1250
1251		// read in the salt and key
1252		protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
1253		offset = 0;
1254		if (protected_data_stream.gcount() < STORE_SALT_SIZE)
1255		{
1256			throw LLProtectedDataException("Config file too short.");
1257		}
1258
1259		cipher.decrypt(salt, STORE_SALT_SIZE);		
1260
1261		// totally lame.  As we're not using the OS level protected data, we need to
1262		// at least obfuscate the data.  We do this by using a salt stored at the head of the file
1263		// to encrypt the data, therefore obfuscating it from someone using simple existing tools.
1264		// We do include the MAC address as part of the obfuscation, which would require an
1265		// attacker to get the MAC address as well as the protected store, which improves things
1266		// somewhat.  It would be better to use the password, but as this store
1267		// will be used to store the SL password when the user decides to have SL remember it, 
1268		// so we can't use that.  OS-dependent store implementations will use the OS password/storage 
1269		// mechanisms and are considered to be more secure.
1270		// We've a strong intent to move to OS dependent protected data stores.
1271		
1272
1273		// read in the rest of the file.
1274		EVP_CIPHER_CTX ctx;
1275		EVP_CIPHER_CTX_init(&ctx);
1276		EVP_DecryptInit(&ctx, EVP_rc4(), salt, NULL);
1277		// allocate memory:
1278		std::string decrypted_data;	
1279		
1280		while(protected_data_stream.good()) {
1281			// read data as a block:
1282			protected_data_stream.read((char *)buffer, BUFFER_READ_SIZE);
1283			
1284			EVP_DecryptUpdate(&ctx, decrypted_buffer, &decrypted_length, 
1285							  buffer, protected_data_stream.gcount());
1286			decrypted_data.append((const char *)decrypted_buffer, protected_data_stream.gcount());
1287		}
1288		
1289		// RC4 is a stream cipher, so we don't bother to EVP_DecryptFinal, as there is
1290		// no block padding.
1291		EVP_CIPHER_CTX_cleanup(&ctx);
1292		std::istringstream parse_stream(decrypted_data);
1293		if (parser->parse(parse_stream, mProtectedDataMap, 
1294						  LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
1295		{
1296			throw LLProtectedDataException("Config file cannot be decrypted.");
1297		}
1298	}
1299}
1300
1301void LLSecAPIBasicHandler::_writeProtectedData()
1302{	
1303	std::ostringstream formatted_data_ostream;
1304	U8 salt[STORE_SALT_SIZE];
1305	U8 buffer[BUFFER_READ_SIZE];
1306	U8 encrypted_buffer[BUFFER_READ_SIZE];
1307
1308	
1309	if(mProtectedDataMap.isUndefined())
1310	{
1311		LLFile::remove(mProtectedDataFilename);
1312		return;
1313	}
1314	// create a string with the formatted data.
1315	LLSDSerialize::toXML(mProtectedDataMap, formatted_data_ostream);
1316	std::istringstream formatted_data_istream(formatted_data_ostream.str());
1317	// generate the seed
1318	RAND_bytes(salt, STORE_SALT_SIZE);
1319
1320	
1321	// write to a temp file so we don't clobber the initial file if there is
1322	// an error.
1323	std::string tmp_filename = mProtectedDataFilename + ".tmp";
1324	
1325	llofstream protected_data_stream(tmp_filename.c_str(), 
1326										llofstream::binary);
1327	try
1328	{
1329		
1330		EVP_CIPHER_CTX ctx;
1331		EVP_CIPHER_CTX_init(&ctx);
1332		EVP_EncryptInit(&ctx, EVP_rc4(), salt, NULL);
1333		unsigned char unique_id[MAC_ADDRESS_BYTES];
1334        LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
1335		LLXORCipher cipher(unique_id, sizeof(unique_id));
1336		cipher.encrypt(salt, STORE_SALT_SIZE);
1337		protected_data_stream.write((const char *)salt, STORE_SALT_SIZE);
1338
1339		while (formatted_data_istream.good())
1340		{
1341			formatted_data_istream.read((char *)buffer, BUFFER_READ_SIZE);
1342			if(formatted_data_istream.gcount() == 0)
1343			{
1344				break;
1345			}
1346			int encrypted_length;
1347			EVP_EncryptUpdate(&ctx, encrypted_buffer, &encrypted_length, 
1348						  buffer, formatted_data_istream.gcount());
1349			protected_data_stream.write((const char *)encrypted_buffer, encrypted_length);
1350		}
1351		
1352		// no EVP_EncrypteFinal, as this is a stream cipher
1353		EVP_CIPHER_CTX_cleanup(&ctx);
1354
1355		protected_data_stream.close();
1356	}
1357	catch (...)
1358	{
1359		// it's good practice to clean up any secure information on error
1360		// (even though this file isn't really secure.  Perhaps in the future
1361		// it may be, however.
1362		LLFile::remove(tmp_filename);
1363		throw LLProtectedDataException("Error writing Protected Data Store");
1364	}
1365
1366	// move the temporary file to the specified file location.
1367	if((((LLFile::isfile(mProtectedDataFilename) != 0) && 
1368		 (LLFile::remove(mProtectedDataFilename) != 0))) || 
1369	   (LLFile::rename(tmp_filename, mProtectedDataFilename)))
1370	{
1371		LLFile::remove(tmp_filename);
1372		throw LLProtectedDataException("Could not overwrite protected data store");
1373	}
1374}
1375		
1376// instantiate a certificate from a pem string
1377LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)
1378{
1379	LLPointer<LLCertificate> result = new LLBasicCertificate(pem_cert);
1380	return result;
1381}
1382		
1383
1384		
1385// instiate a certificate from an openssl X509 structure
1386LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(X509* openssl_cert)
1387{
1388	LLPointer<LLCertificate> result = new LLBasicCertificate(openssl_cert);
1389	return result;		
1390}
1391		
1392// instantiate a chain from an X509_STORE_CTX
1393LLPointer<LLCertificateChain> LLSecAPIBasicHandler::getCertificateChain(const X509_STORE_CTX* chain)
1394{
1395	LLPointer<LLCertificateChain> result = new LLBasicCertificateChain(chain);
1396	return result;
1397}
1398		
1399// instantiate a cert store given it's id.  if a persisted version
1400// exists, it'll be loaded.  If not, one will be created (but not
1401// persisted)
1402LLPointer<LLCertificateStore> LLSecAPIBasicHandler::getCertificateStore(const std::string& store_id)
1403{
1404	return mStore;
1405}
1406		
1407// retrieve protected data
1408LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type,
1409											const std::string& data_id)
1410{
1411
1412	if (mProtectedDataMap.has(data_type) && 
1413		mProtectedDataMap[data_type].isMap() && 
1414		mProtectedDataMap[data_type].has(data_id))
1415	{
1416		return mProtectedDataMap[data_type][data_id];
1417	}
1418																				
1419	return LLSD();
1420}
1421
1422void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type,
1423											   const std::string& data_id)
1424{
1425	if (mProtectedDataMap.has(data_type) &&
1426		mProtectedDataMap[data_type].isMap() &&
1427		mProtectedDataMap[data_type].has(data_id))
1428		{
1429			mProtectedDataMap[data_type].erase(data_id);
1430		}
1431}
1432
1433
1434//
1435// persist data in a protected store
1436//
1437void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type,
1438											const std::string& data_id,
1439											const LLSD& data)
1440{
1441	if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {
1442		mProtectedDataMap[data_type] = LLSD::emptyMap();
1443	}
1444	
1445	mProtectedDataMap[data_type][data_id] = data; 
1446}
1447
1448//
1449// Create a credential object from an identifier and authenticator.  credentials are
1450// per grid.
1451LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid,
1452															   const LLSD& identifier, 
1453															   const LLSD& authenticator)
1454{
1455	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
1456	result->setCredentialData(identifier, authenticator);
1457	return result;
1458}
1459
1460// Load a credential from the credential store, given the grid
1461LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid)
1462{
1463	LLSD credential = getProtectedData("credential", grid);
1464	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid);
1465	if(credential.isMap() && 
1466	   credential.has("identifier"))
1467	{
1468
1469		LLSD identifier = credential["identifier"];
1470		LLSD authenticator;
1471		if (credential.has("authenticator"))
1472		{
1473			authenticator = credential["authenticator"];
1474		}
1475		result->setCredentialData(identifier, authenticator);
1476	}
1477	else
1478	{
1479		// credential was not in protected storage, so pull the credential
1480		// from the legacy store.
1481		std::string first_name = gSavedSettings.getString("FirstName");
1482		std::string last_name = gSavedSettings.getString("LastName");
1483		
1484		if ((first_name != "") &&
1485			(last_name != ""))
1486		{
1487			LLSD identifier = LLSD::emptyMap();
1488			LLSD authenticator;
1489			identifier["type"] = "agent";
1490			identifier["first_name"] = first_name;
1491			identifier["last_name"] = last_name;
1492			
1493			std::string legacy_password = _legacyLoadPassword();
1494			if (legacy_password.length() > 0)
1495			{
1496				authenticator = LLSD::emptyMap();
1497				authenticator["type"] = "hash";
1498				authenticator["algorithm"] = "md5";
1499				authenticator["secret"] = legacy_password;
1500			}
1501			result->setCredentialData(identifier, authenticator);
1502		}		
1503	}
1504	return result;
1505}
1506
1507// Save the credential to the credential store.  Save the authenticator also if requested.
1508// That feature is used to implement the 'remember password' functionality.
1509void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)
1510{
1511	LLSD credential = LLSD::emptyMap();
1512	credential["identifier"] = cred->getIdentifier(); 
1513	if (save_authenticator) 
1514	{
1515		credential["authenticator"] = cred->getAuthenticator();
1516	}
1517	LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL;
1518	setProtectedData("credential", cred->getGrid(), credential);
1519	//*TODO: If we're saving Agni credentials, should we write the
1520	// credentials to the legacy password.dat/etc?
1521	_writeProtectedData();
1522}
1523
1524// Remove a credential from the credential store.
1525void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred)
1526{
1527	LLSD undefVal;
1528	deleteProtectedData("credential", cred->getGrid());
1529	cred->setCredentialData(undefVal, undefVal);
1530	_writeProtectedData();
1531}
1532
1533// load the legacy hash for agni, and decrypt it given the 
1534// mac address
1535std::string LLSecAPIBasicHandler::_legacyLoadPassword()
1536{
1537	const S32 HASHED_LENGTH = 32;	
1538	std::vector<U8> buffer(HASHED_LENGTH);
1539	llifstream password_file(mLegacyPasswordPath, llifstream::binary);
1540	
1541	if(password_file.fail())
1542	{
1543		return std::string("");
1544	}
1545	
1546	password_file.read((char*)&buffer[0], buffer.size());
1547	if(password_file.gcount() != buffer.size())
1548	{
1549		return std::string("");
1550	}
1551	
1552	// Decipher with MAC address
1553	unsigned char unique_id[MAC_ADDRESS_BYTES];
1554    LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
1555	LLXORCipher cipher(unique_id, sizeof(unique_id));
1556	cipher.decrypt(&buffer[0], buffer.size());
1557	
1558	return std::string((const char*)&buffer[0], buffer.size());
1559}
1560
1561
1562// return an identifier for the user
1563std::string LLSecAPIBasicCredential::userID() const
1564{
1565	if (!mIdentifier.isMap())
1566	{
1567		return mGrid + "(null)";
1568	}
1569	else if ((std::string)mIdentifier["type"] == "agent")
1570	{
1571		return  (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"];
1572	}
1573	else if ((std::string)mIdentifier["type"] == "account")
1574	{
1575		return (std::string)mIdentifier["account_name"];
1576	}
1577
1578	return "unknown";
1579
1580}
1581
1582// return a printable user identifier
1583std::string LLSecAPIBasicCredential::asString() const
1584{
1585	if (!mIdentifier.isMap())
1586	{
1587		return mGrid + ":(null)";
1588	}
1589	else if ((std::string)mIdentifier["type"] == "agent")
1590	{
1591		return mGrid + ":" + (std::string)mIdentifier["first_name"] + " " + (std::string)mIdentifier["last_name"];
1592	}
1593	else if ((std::string)mIdentifier["type"] == "account")
1594	{
1595		return mGrid + ":" + (std::string)mIdentifier["account_name"];
1596	}
1597
1598	return mGrid + ":(unknown type)";
1599}
1600
1601
1602bool valueCompareLLSD(const LLSD& lhs, const LLSD& rhs)
1603{
1604	if (lhs.type() != rhs.type())
1605	{
1606		return FALSE;
1607	}
1608    if (lhs.isMap())
1609	{
1610		// iterate through the map, verifying the right hand side has all of the
1611		// values that the left hand side has.
1612		for (LLSD::map_const_iterator litt = lhs.beginMap();
1613			 litt != lhs.endMap();
1614			 litt++)
1615		{
1616			if (!rhs.has(litt->first))
1617			{
1618				return FALSE;
1619			}
1620		}
1621		
1622		// Now validate that the left hand side has everything the
1623		// right hand side has, and that the values are equal.
1624		for (LLSD::map_const_iterator ritt = rhs.beginMap();
1625			 ritt != rhs.endMap();
1626			 ritt++)
1627		{
1628			if (!lhs.has(ritt->first))
1629			{
1630				return FALSE;
1631			}
1632			if (!valueCompareLLSD(lhs[ritt->first], ritt->s

Large files files are truncated, but you can click here to view the full file