⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cert.cxx

📁 MiniSip Client with DomainKeys Authentication, Sip, Audio communications, Echo Cancel
💻 CXX
字号:
/* *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program 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 Library General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Copyright (C) 2004  * * Authors: Erik Eliasson <eliasson@it.kth.se> *          Johan Bilien <jobi@via.ecp.fr>*/#include<config.h>#include<libmcrypto/gnutls/cert.h>#include<gnutls/openssl.h>#include<iostream>using namespace std;Certificate::Certificate():/*MObject("Certificate"),*/privateKey(NULL),cert(NULL){        gnutls_global_init();}#if 0Certificate::Certificate( X509 * openssl_cert ):/*MObject("Certificate"),*/privateKey(NULL){	if( openssl_cert == NULL ){		throw new CertificateException;	}		cert = openssl_cert;}#endifCertificate::Certificate( const string certFilename ):/*MObject("Certificate"),*/privateKey(NULL){        gnutls_global_init();	openFromFile( certFilename );}Certificate::Certificate( const string certFilename, const string privateKeyFilename )/*:MObject("Certificate")*/{        gnutls_global_init();	openFromFile( certFilename );	set_pk( privateKeyFilename );	}Certificate::Certificate( unsigned char * derCert, int length ):privateKey(NULL){        int ret;        gnutls_datum certData;		gnutls_global_init();        	ret = gnutls_x509_crt_init( &cert );        if( ret != 0 ){		throw new CertificateExceptionInit( 			"Could not initialize the certificate structure" );        }	certData.data = derCert;	certData.size = length;        	ret = gnutls_x509_crt_import( cert, &certData, GNUTLS_X509_FMT_DER );        if( ret != 0 ){		throw new CertificateException( 			"Could not import the given certificate" );        }}	Certificate::~Certificate(){	if( cert != NULL ){		gnutls_x509_crt_deinit( cert );	}		cert = NULL;		if( privateKey != NULL ){		gnutls_x509_privkey_deinit( privateKey );	}		privateKey = NULL;}void Certificate::openFromFile( string fileName ){	int fd;        void * certBuf = NULL;        size_t length;        struct stat fileStat;        gnutls_datum certData;        fd = open( CERT_FILE, O_RDONLY );        if( fd == -1 ){		throw new CertificateExceptionFile( 			"Could not open the given certificate file" );        }        ret = fstat( fd, &fileStat );        if( ret == -1 ){		throw new CertificateExceptionFile( 			"Could not stat the given certificate file" );        }        length = fileStat.st_size;        certBuf = mmap( 0, length, PROT_READ, MAP_SHARED, fd, 0 );        if( certBuf == NULL ){		throw new CertificateExceptionInit( 			"Could not mmap the certificate file" );        }        certData.data = certBuf;        certData.size = length;        ret = gnutls_x509_crt_init( &cert );        if( ret != 0 ){		throw new CertificateExceptionInit( 			"Could not initialize the certificate structure" );        }        ret = gnutls_x509_crt_import( cert, &certData, GNUTLS_X509_FMT_PEM );        if( ret != 0 ){		throw new CertificateExceptionFile( 			"Could not import the given certificate" );        }        munmap( certBuf, length );        close( fd );	file = certFilename;}void Certificate::signData( unsigned char * data, int dataLength,	    		   unsigned char * sign, int * signLength ){	int err;		if( privateKey == NULL ){		sign = NULL;		*sign_length = 0;		throw new CertificateException(			"A private key is needed to sign data" );	}		err = gnutls_x509_privkey_sign_data( 			privateKey, 			GNUTLS_MAC_SHA /*FIXME*/			0,			dataStruct,			sign, signLength );	if( err < 0 ){		throw new CertificateException(			"Signature of data failed" );	}}int Certificate::verifSign( unsigned char * sign, int signLength,			    unsigned char * data, int dataLength ){	int err;	gnutls_datum dataStruct;	gnutls_datum signStruct;	dataStruct.data = data;	dataStruct.size = dataLength;		signStruct.sign = sign;	signStruct.size = signLength;		if( cert == NULL ){		throw new CertificateException(			"No certificate open while verifying a signature" );	}		err = gnutls_x509_crt_verify_data( cert, 0, dataStruct, signStruct );	return err;}void Certificate::getDer( unsigned char * output, unsigned int * length ){		int ret;	ret = gnutls_x509_crt_export( *cert, GNUTLS_X509_FMT_DER, 			output, length );	if( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ){		throw new CertificateExceptionBuffer(			"Given buffer is to short" );	}	if( ret < 0 ){		throw new CertificateException(			"An error occured while exporting the certificate" );	}}string Certificate::getName(){	int ret;	char * buf;	size_t * size;	buf = (char *)malloc( 1024 );	if( buf == NULL ){		throw new CertificateExceptionInit(			"Not enough memory" );	}		ret = gnutls_x509_crt_get_dn( cert, buf, size );	/* This should not happen very often */	if( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ){		free( buf );		gnutls_x509_crt_get_dn( cert, NULL, size );		buf = (char *) malloc( size );		if( buf == NULL ){			throw new CertificateExceptionInit(				"Not enough memory" );		}		ret = gnutls_x509_crt_get_dn( cert, buf, size );	}	if( ret < 0 ){		throw new CertificateException(			"An error occured in getName()" );	}	string output( buf, length );	free( buf );	return output;}string Certificate::getCn(){	int ret;	char * buf;	size_t * size;	buf = (char *)malloc( 1024 );	if( buf == NULL ){		throw new CertificateExceptionInit(			"Not enough memory" );	}		ret = gnutls_x509_crt_get_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, buf, size );	/* This should not happen very often */	if( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ){		free( buf );		gnutls_x509_crt_get_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, NULL, size );		buf = (char *) malloc( size );		if( buf == NULL ){			throw new CertificateExceptionInit(				"Not enough memory" );		}		ret = gnutls_x509_crt_get_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, buf, size );	}	if( ret < 0 ){		throw new CertificateException(			"An error occured in getName()" );	}	string output( buf, length );	free( buf );	return output;	}string Certificate::getIssuer(){	int ret;	char * buf;	size_t * size;	buf = (char *)malloc( 1024 );	if( buf == NULL ){		throw new CertificateExceptionInit(			"Not enough memory" );	}		ret = gnutls_x509_crt_get_issuer( cert, buf, size );	/* This should not happen very often */	if( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ){		free( buf );		gnutls_x509_crt_get_issuer( cert, NULL, size );		buf = (char *) malloc( size );		if( buf == NULL ){			throw new CertificateExceptionInit(				"Not enough memory" );		}		ret = gnutls_x509_crt_get_issuer( cert, buf, size );	}	if( ret < 0 ){		throw new CertificateException(			"An error occured in getName()" );	}	string output( buf, length );	free( buf );	return output;}string Certificate::getIssuerCn(){	int ret;	char * buf;	size_t * size;	buf = (char *)malloc( 1024 );	if( buf == NULL ){		throw new CertificateExceptionInit(			"Not enough memory" );	}		ret = gnutls_x509_crt_get_issuer_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, buf, size );	/* This should not happen very often */	if( ret == GNUTLS_E_SHORT_MEMORY_BUFFER ){		free( buf );		gnutls_x509_crt_get_issuer_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, NULL, size );		buf = (char *) malloc( size );		if( buf == NULL ){			throw new CertificateExceptionInit(				"Not enough memory" );		}		ret = gnutls_x509_crt_get_issuer_dn_by_oid( cert, 			GNUTLS_OID_X520_COMMON_NAME, 0, buf, size );	}	if( ret < 0 ){		throw new CertificateException(			"An error occured in getName()" );	}	string output( buf, length );	free( buf );	return output;}string Certificate::getFile(){	return file;}string Certificate::getPkFile(){	return pkFile;}void Certificate::setPk( string file ){	int fd;        void * pkBuf = NULL;        size_t length;        struct stat fileStat;        gnutls_datum pkData;	byte_t publicKeyId[20];	byte_t privateKeyId[20];	size_t idLength;        fd = open( file.c_str(), O_RDONLY );        if( fd == -1 ){		throw new CertificateExceptionFile( 			"Could not open the given private key file" );        }        ret = fstat( fd, &fileStat );        if( ret == -1 ){		throw new CertificateExceptionFile( 			"Could not stat the given private key file" );        }        length = fileStat.st_size;        pkBuf = mmap( 0, length, PROT_READ, MAP_SHARED, fd, 0 );        if( pkBuf == NULL ){		throw new CertificateExceptionInit( 			"Could not mmap the certificate file" );        }        pkData.data = pkBuf;        pkData.size = length;        ret = gnutls_x509_privkey_init( &privateKey );        if( ret != 0 ){		throw new CertificateExceptionInit( 			"Could not initialize the private key structure" );        }        ret = gnutls_x509_privkey_import( privateKey, &pkData, 			GNUTLS_X509_FMT_PEM );        if( ret != 0 ){		throw new CertificateExceptionFile( 			"Could not import the given private key" );        }        munmap( pkBuf, length );        close( fd );	/* Check that the private key matches the Certificate */	idLength = 20;	ret = gnutls_x509_crt_get_key_id( cert, 0, publicKeyId, &idLength );	if( ret < 0 ){		throw new CertificateException(			"An error occured when computing the key id" );	}		ret = gnutls_x509_privkey_get_key_id( cert, 0, privateKeyId, &idLength );		if( ret < 0 ){		throw new CertificateException(			"An error occured when computing the key id" );	}	for( i = 0; i < idLength; i++ ){		if( privateKeyId[i] != publicKeyId[i] ){			throw new CertificateExceptionPkey(				"The private key " + file + 				" does not match the certificate " + this->file				);		}	}	pkFile = file;}int Certificate::control( CaDb * certDb ){	int result;	X509_STORE_CTX cert_store_ctx;	if( X509_STORE_CTX_init( &cert_store_ctx, certDb->get_db(), cert ,NULL ) < 0 ){		fprintf(stderr, "Could not initialize X509_STORE_CTX");		exit( 1 );	}	result = X509_verify_cert( &cert_store_ctx );#ifdef DEBUG_OUTPUT	if( result == 0 ){		cerr << result << endl;		cerr << X509_verify_cert_error_string( cert_store_ctx.error ) << endl;	}#endif	return result;}	CaDb::CaDb(){	caList = NULL;	items_index = items.begin();}CaDb::~CaDb(){	if( caList != NULL ){		free( caList );	}}void CaDb::lock(){        mLock.lock();}void CaDb::unlock(){        mLock.unlock();}gnutls_x509_crt_t * CaDb::getDb(){	return caList;}#if 0void CaDb::addDirectory( string dir ){	X509_LOOKUP * lookup = NULL;	CaDbItem * item = new CaDbItem();		lookup = X509_STORE_add_lookup( 			certDb, X509_LOOKUP_hash_dir() );	if( lookup == NULL )		throw new CertificateExceptionInit(			string("Could not create a directory lookup") );		if( !X509_LOOKUP_add_dir( lookup, dir.c_str(), X509_FILETYPE_PEM ) )		throw new CertificateExceptionFile(			"Could not open the directory "+dir );	item->item = dir;	item->type = CERT_DB_ITEM_TYPE_DIR;		items.push_back( item );	items_index = items.begin();}#endifvoid CaDb::addFile( string file ){	Certificate cert( file );			item->item = file;	item->type = CERT_DB_ITEM_TYPE_FILE;		items.push_back( item );	items_index = items.begin();}void CaDb::add_Certificate( Certificate * cert ){	CaDbItem * item = new CaDbItem();	X509_STORE_add_cert( certDb, cert->get_openssl_Certificate() );		item->item = "";	item->type = CERT_DB_ITEM_TYPE_OTHER;		items.push_back( item );	items_index = items.begin();}void CaDb::remove( CaDbItem * removedItem ){	initIndex();	while( items_index != items.end() ){		if( *(*items_index) == *removedItem ){			items.erase( items_index );			initIndex();			return;		}		items_index ++;	}	initIndex();}list<CaDbItem *> &CaDb::get_items(){	return items;}void CaDb::initIndex(){	items_index = items.begin();}CaDbItem * CaDb::get_next(){	CaDbItem * tmp;		if( items_index == items.end() ){		items_index = items.begin();		return NULL;	}	tmp = *items_index;	items_index ++;	return tmp;}CertificateChain::CertificateChain()/*:MObject("CertificateChain")*/{//	pthread_mutex_init( &mLock, NULL );	item = certList.begin();}CertificateChain::CertificateChain( MRef<Certificate *> cert )/*: MObject("CertificateChain")*/{		certList.push_back( cert );	item = certList.begin();}CertificateChain::~CertificateChain(){}void CertificateChain::lock(){        mLock.lock();}void CertificateChain::unlock(){        mLock.unlock();}bool CertificateChain::isEmpty(){	return certList.empty();}void CertificateChain::addCertificate( MRef<Certificate *> cert ){		if( !certList.empty() ){		MRef<Certificate *> lastCert = *(--certList.end());		if( lastCert->get_issuer() != cert->get_name() ){			throw new CertificateExceptionChain(			 	"The previous Certificate in the chain is not"				"issued by the given one" );		}	}		certList.push_back( cert );	item = certList.begin();}void CertificateChain::removeLast(){	certList.erase( -- certList.end() );	item = certList.begin();}void CertificateChain::initIndex(){	item = certList.begin();}int CertificateChain::control( MRef<CaDb *> certDb){	int result;	X509_STORE_CTX cert_store_ctx;	/* The first one, the one to verify */	X509 * cert;	/* Chain of Certificates */	STACK_OF(X509) * certStack;	list< MRef<Certificate *> >::iterator i = certList.begin();	if( i == certList.end() ){		cerr << "Certificate: Empty list of Certificates"			"to verify" << endl;		return 0;	}	cert = (*i)->get_openssl_Certificate();	certStack = sk_X509_new_null();	i++;	for( ; i != certList.end(); i++ ){		sk_X509_push( certStack, (*i)->get_openssl_Certificate() );	}	if( X509_STORE_CTX_init( &cert_store_ctx, certDb->getDb(), cert, certStack ) < 0 ){		fprintf(stderr, "Could not initialize X509_STORE_CTX");		exit( 1 );	}	result = X509_verify_cert( &cert_store_ctx );#ifdef DEBUG_OUTPUT	if( result == 0 ){		cerr << result << endl;		cerr << X509_verify_cert_error_string( cert_store_ctx.error ) << endl;	}#endif	return result;}MRef<Certificate *> CertificateChain::get_next(){	MRef<Certificate *> ret;		if( item == certList.end() ){		item = certList.begin();		return NULL;	}	ret = *item;	item ++;	return ret;}MRef<Certificate *> CertificateChain::get_first(){	if( certList.size() == 0 ){		return NULL;	}		return *(certList.begin());}void CertificateChain::clear(){	certList.clear();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -