?? certmng.cpp
字號:
if ( ( buf = (char *)OPENSSL_malloc ( size ) ) == NULL )
{
CError::Interface ()->Handle_Error ( 0, "內存不足(malloc操作失敗)" );
goto end;
}
if ( snfile == NULL )
{
BUF_strlcpy ( buf, cafile, size );
for ( p = buf; *p; p++ )
if ( *p == '.' )
{
*p = '\0';
break;
}
BUF_strlcat ( buf, POSTFIX, size );
}
else
BUF_strlcpy ( buf, snfile, size );
//構造序列號
bnsn = BN_new ();
ai = ASN1_INTEGER_new ();
if ( ! bnsn || ! ai )
{
CError::Interface ()->Handle_Error ( 0, "內存不足(BN_new操作失敗)" );
goto end;
}
//讀取序列號
if ( ( bnsn = X509_sn::Load_Serial ( snfile, create, NULL ) ) == NULL )
goto end;
//遞增
if ( ! BN_add_word ( bnsn, 1 ) ) goto end;
//保存序列號
X509_sn::Save_Serial ( snfile, NULL, bnsn, &ai );
end:
if ( buf ) OPENSSL_free ( buf );
if ( bnsn ) BN_free ( bnsn );
return ai;
}
//把申請憑證(request)轉換為對應的證書(X509)
X509 * CCertMng::Request2X509 ( X509_REQ * req, ASN1_INTEGER * sn, long days )
{
X509_CINF * ci = 0;
X509 * x509 = 0;
EVP_PKEY * pKey = 0;
if ( req == NULL ) return NULL;
if ( ( x509 = X509_new () ) == NULL ) return NULL;
ci = x509->cert_info;
if ( sn )
{
if ( ! X509_set_serialNumber ( x509, sn ) ) goto end;
}
else if ( ! ASN1_INTEGER_set ( X509_get_serialNumber ( x509 ), 0 ) ) goto end;
if ( ! X509_set_issuer_name ( x509, req->req_info->subject ) ) goto end;
if ( ! X509_set_subject_name ( x509, req->req_info->subject ) ) goto end;
X509_gmtime_adj ( X509_get_notBefore (x509), 0 );
X509_gmtime_adj ( X509_get_notAfter (x509), (long)60*60*24*days );
pKey = X509_REQ_get_pubkey ( req );
X509_set_pubkey ( x509, pKey );
EVP_PKEY_free ( pKey );
end:
return x509;
}
//讀取憑證
X509_REQ * CCertMng::Load_Request ( int in_type, const char * in )
{
EVP_PKEY * pKey = 0;
BIO * bio_in = 0;
X509_REQ * req = 0;
if ( in == 0 )
goto end;
//判斷輸入格式
if ( ( bio_in = Bio_Read ( in_type, in, strlen ( in ) ) ) == NULL )
{
CError::Interface()->Handle_Error( 0, "讀取憑證信息失敗%s", in );
goto end;
}
if ( NULL == ( req = PEM_read_bio_X509_REQ ( bio_in, NULL, NULL, NULL ) ) )
goto end;
if ( ( req->req_info == NULL) ||
( req->req_info->pubkey == NULL) ||
( req->req_info->pubkey->public_key == NULL) ||
( req->req_info->pubkey->public_key->data == NULL ) )
{
CError::Interface ()->Handle_Error ( 0, "憑證申請沒用包含合法的公鑰" );
goto end;
}
if ( ( pKey = X509_REQ_get_pubkey ( req ) ) == NULL) goto end;
if ( X509_REQ_verify ( req, pKey ) <= 0 )
{
CError::Interface ()->Handle_Error ( 0, "簽名和憑證不匹配" );
X509_REQ_free ( req );
req = 0;
}
end:
if ( bio_in ) BIO_free ( bio_in );
if ( pKey ) EVP_PKEY_free ( pKey );
return req;
}
//輸出公鑰
int CCertMng::Out_Pubkey ( X509_REQ * req, BIO * out )
{
if ( req == NULL )
return -1;
EVP_PKEY * pubkey = 0;
pubkey = X509_REQ_get_pubkey ( req );
if ( !pubkey )
{
CError::Interface ()->Handle_Error ( 0, "獲取公鑰失敗" );
return -1;
}
PEM_write_bio_PUBKEY ( out, pubkey );
EVP_PKEY_free ( pubkey );
return 0;
}
//證書驗證
int CCertMng::Verify_Cert ( conv_tool::OPERATORS_MAP mapOpt )
{
string scapath, scafile, scertfile;
string suntrust, strust;
STACK_OF ( X509 ) * untrusted = 0, * trusted = 0;
X509_STORE * xs_ctx = 0;
X509_LOOKUP * xl = 0;
int vflags = 0, result, type = FILE_TYPE;
int ret = 0;
char seps[] = "; ";
char * stok = 0;
conv_tool::OPERATORS_MAP::iterator it;
if ( ! ( xs_ctx = X509_STORE_new ( ) ) ) {
CError::Interface ()->Handle_Error ( 0, "X509_Store_new操作失敗");
goto end;
}
//設置回調函數
X509_STORE_set_verify_cb_func ( xs_ctx, verify_callback );
//獲取參數
if ( ( it = mapOpt.find ( CA_PATH ) ) != mapOpt.end() )
scapath = it->second;
if ( ( it = mapOpt.find ( CA_FILE ) ) != mapOpt.end () )
scafile = it->second;
if ( ( it = mapOpt.find ( CERT_FILE ) ) != mapOpt.end () )
scertfile = it->second;
if((it = mapOpt.find(IN_TYPE)) != mapOpt.end() )
type = atoi(it->second.c_str());
if ( ( it = mapOpt.find ( UNTRUST ) ) != mapOpt.end () )
suntrust = it->second;
if ( ( it = mapOpt.find ( TRUST ) ) != mapOpt.end () )
strust = it->second;
if ( ( it = mapOpt.find ( IGNORE_CERT ) ) != mapOpt.end () )
vflags != X509_V_FLAG_IGNORE_CRITICAL;
if ( ( it = mapOpt.find ( ISSUER_CHECK ) ) != mapOpt.end () )
vflags != X509_V_FLAG_CB_ISSUER_CHECK;
if ( ( it = mapOpt.find ( CRL_CHECK ) ) != mapOpt.end () )
vflags != X509_V_FLAG_CRL_CHECK;
if ( ( it = mapOpt.find ( CRL_CHECKALL ) ) != mapOpt.end () )
vflags != X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
if ( scertfile.length () == 0 )
{
CError::Interface ()->Handle_Error ( 0, "沒有要驗證的證書文件" );
goto end;
}
if ( ( xl = X509_STORE_add_lookup ( xs_ctx, X509_LOOKUP_file () ) ) == NULL ) {
CError::Interface ()->Handle_Error ( 0, "X509_STORE_add_lookup()操作失敗");
goto end;
}
if ( scafile.length() > 0 )
{
result = X509_LOOKUP_load_file ( xl, (char*)scafile.c_str(), X509_FILETYPE_PEM );
if ( !result )
{
CError::Interface ()->Handle_Error ( 0, "讀取文件失敗:%s", scafile.c_str() );
goto end;
}
}
else
X509_LOOKUP_load_file ( xl, NULL, X509_FILETYPE_DEFAULT );
if ( ( xl = X509_STORE_add_lookup ( xs_ctx, X509_LOOKUP_hash_dir () ) ) == NULL) {
CError::Interface ()->Handle_Error ( 0, "X509_STORE_add_lookup()操作失敗%d", __LINE__);
goto end;
}
//讀取其他文件
if ( suntrust.length () > 0 )
{
if ( ( untrusted = Load_UnTrusted ( suntrust.c_str() ) ) == NULL )
goto end;
}
if ( strust.length () > 0 )
{
if ( ( trusted = Load_UnTrusted ( strust.c_str() ) ) == NULL )
goto end;
}
if( type == FILE_TYPE )
{
stok = strtok ( (char*)scertfile.c_str(), seps );
while ( stok != NULL )
{
if(!(ret = Check_Cert ( xs_ctx, stok, type, untrusted, trusted, vflags )))
break;
stok = strtok ( NULL, seps );
}
}
else
ret = Check_Cert(xs_ctx, scertfile.c_str(), type, untrusted, trusted, vflags );
end:
if ( xs_ctx ) X509_STORE_free ( xs_ctx );
if ( untrusted ) sk_X509_pop_free(untrusted, X509_free);
if ( trusted ) sk_X509_pop_free ( trusted, X509_free );
return ret;
}
//讀取CRL
STACK_OF ( X509 ) *
CCertMng::Load_UnTrusted ( const char * certfile )
{
STACK_OF(X509_INFO) * sk = NULL;
STACK_OF(X509) * stack = NULL, *ret = NULL;
BIO * in = NULL;
X509_INFO * xi = 0;
if( ! ( stack = sk_X509_new_null()))
goto end;
if( ! ( in = BIO_new_file ( certfile, "r" ) ) )
{
CError::Interface ()->Handle_Error ( 0, "打開文件失敗:%s", certfile );
goto end;
}
/* This loads from a file, a stack of x509/crl/pkey sets */
if ( ! ( sk = PEM_X509_INFO_read_bio ( in, NULL, NULL, NULL ) ) )
{
CError::Interface ()->Handle_Error ( 0, "讀取文件失敗:%s", certfile );
goto end;
}
/* scan over it and pull out the certs */
while ( sk_X509_INFO_num ( sk ) )
{
xi = sk_X509_INFO_shift ( sk );
if ( xi->x509 != NULL )
{
sk_X509_push ( stack, xi->x509 );
xi->x509 = NULL;
}
X509_INFO_free(xi);
}
if( ! sk_X509_num ( stack ) )
{
CError::Interface ()->Handle_Error ( 0, "文件%s不包含證書信息", certfile );
sk_X509_free ( stack );
goto end;
}
ret = stack;
end:
if ( in ) BIO_free(in);
if ( sk ) sk_X509_INFO_free(sk);
return ret;
}
//檢查證書(包括CRL)
int CCertMng::Check_Cert ( X509_STORE * ctx, const char * certfile, int type,
STACK_OF(X509) *uchain,
STACK_OF(X509) *tchain, int vflags )
{
int ret = 0;
X509 * x = 0;
X509_STORE_CTX * xsc = 0;
if ( ( x = Load_Cert ( type, certfile, FORMAT_PEM ) ) == NULL ) goto end;
if ( ( xsc = X509_STORE_CTX_new () ) == NULL ) goto end;
X509_STORE_set_flags ( ctx, vflags );
if ( ! X509_STORE_CTX_init ( xsc, ctx, x, uchain ) ) goto end;
if ( tchain )
X509_STORE_CTX_trusted_stack ( xsc, tchain );
ret = X509_verify_cert ( xsc );
end:
if ( xsc ) X509_STORE_CTX_free ( xsc );
if ( x ) X509_free ( x );
return ret;
}
//證書驗證回調函數
int CCertMng::verify_callback ( int ok, X509_STORE_CTX * ctx )
{
if ( ! ok )
{
if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1;
/* since we are just checking the certificates, it is
* ok if they are self signed. But we should still warn
* the user.
*/
if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
/* Continue after extension errors too */
if (ctx->error == X509_V_ERR_INVALID_CA) ok=1;
if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1;
if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1;
if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1;
if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1;
if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1;
}
return ok;
}
// 讀取文件或字符串,返回BIO指針
BIO * CCertMng::Bio_Read (int in_type, const char * in, int len )
{
BIO * bio_in = 0;
if ( in_type == FILE_TYPE )
{
if ( ( bio_in = BIO_new ( BIO_s_file () ) ) == NULL )
goto end;
if ( BIO_read_filename ( bio_in, in ) < 0 )
{
BIO_free ( bio_in );
bio_in = NULL;
goto end;
}
}
else
{
if ( ( bio_in = BIO_new( BIO_s_mem() ) ) == NULL )
goto end;
if ( BIO_write ( bio_in, in, len ) < 0 )
{
BIO_free ( bio_in );
bio_in = NULL;
goto end;
}
}
end:
return bio_in;
}
//生成輸出的BIO,根據類型判斷輸出是否是文件或者BUFFER
BIO * CCertMng::Bio_Write( int out_type, const char *out)
{
BIO * bio_out = 0;
if ( out == NULL )
goto end;
if ( out_type == FILE_TYPE )
{
bio_out = BIO_new ( BIO_s_file () );
if ( BIO_write_filename ( bio_out, ( char*)out ) <= 0 )
{
BIO_free ( bio_out );
bio_out = 0;
goto end;
}
}
else
bio_out = BIO_new ( BIO_s_mem () );
end:
return bio_out;
}
//從BIO中提取MEM指針,再本節BUF_MEM的地址和長度,把BIO中保存的內容取出到STR
int CCertMng::Get_BioStr( BIO * bio_out, std::string & sout, int * pnLen )
{
BUF_MEM * buf_mem = 0;
char * buf = 0;
int len = 0;
int ret = -1;
if ( bio_out == NULL )
goto end;
BIO_get_mem_ptr ( bio_out, &buf_mem );
BIO_set_close ( bio_out, BIO_NOCLOSE );
len = buf_mem->length;
buf = (char*)OPENSSL_malloc( len + 1 );
memset ( buf, 0, len + 1 );
memcpy ( buf, buf_mem->data, len );
sout = std::string ( buf );
*pnLen = len;
OPENSSL_free ( buf );
ret = 0;
end:
return ret;
}
/*檢查證書是否和私鑰以及公鑰匹配,如果沒有私鑰參數,則只對證書及公鑰進行檢查*/
/*其中私鑰可以為CA證書的私鑰*/
int CCertMng::IsMatch(conv_tool::OPERATORS_MAP mapOpt)
{
std::string scert;
std::string skey;
int type = FILE_TYPE, ret = 0;
EVP_PKEY * pkey = NULL, * pukey = NULL;
X509 * xcert = NULL;
conv_tool::OPERATORS_MAP::iterator it;
if( ( it=mapOpt.find( CERT_FILE ) ) !=mapOpt.end() )
scert = it->second;
if ( (it=mapOpt.find( KEY ) ) != mapOpt.end() )
skey = it->second;
if ( (it=mapOpt.find( IN_TYPE ) ) != mapOpt.end() )
type = atoi( it->second.c_str() );
if ( skey.length() != 0 )
pkey = Load_Key((char*)skey.c_str(), skey.length(), FORMAT_PEM, type );
//沒有證書則返回
if ( scert.length() == 0 )
goto end;
xcert = Load_Cert ( type, scert.c_str(), FORMAT_PEM);
pukey = X509_get_pubkey (xcert);
//公鑰不匹配則直接返回
if ( !(ret = X509_verify ( xcert, pukey ) ))
goto end;
//檢查私鑰
if ( pkey )
ret = X509_verify ( xcert, pkey );
end:
if ( pkey ) EVP_PKEY_free(pkey);
if ( pukey ) EVP_PKEY_free(pukey);
if ( xcert ) X509_free(xcert);
return ret;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -