?? certmng.cpp
字號:
else
{
if ( m_lpfnGet_Dn_Value == NULL )
{
CError::Interface()->Handle_Error ( 0, "回調函數指針不能為NULL" );
return -1;
}
if ( m_lpfnGet_Dn_Value ( text, def, buf, n_min, n_max, m_pVoid ) == -1 && buf[0] == '\n' )
{
BUF_strlcpy ( buf, def, sizeof buf );
}
else if ( buf[0] == '.' && buf[1] == '\n' )
return 0;
}
if ( buf[0] == '\0' ) return 0;
if ( ( buf[0] == '.' ) && ( buf[1] == '\n' || buf[1] == '\0' ) )
return 0;
nLen = strlen ( buf );
buf[nLen] = '\0';
if ( ! X509_REQ_add1_attr_by_NID ( req, nid, char_set, (unsigned char *)buf, -1 ) )
{
CError::Interface()->Handle_Error ( 0, "增加%s屬性失敗", buf );
return -1;
}
return 0;
}
// 讀取證書,從文件或給定的字符串中轉換
X509 * CCertMng::Load_Cert ( int in_type, const char * in, int format )
{
ASN1_HEADER * ah = 0;
BUF_MEM * buf = 0;
X509 * x = 0;
BIO * bio_cert = 0;
int errcode;
if ( in == 0 )
return NULL;
if ( ( bio_cert = Bio_Read ( in_type, in, strlen(in) )) == NULL )
{
CError::Interface ()->Handle_Error ( 0, "讀取證書失敗:%s", in );
goto end;
}
switch ( format )
{
case FORMAT_ASN1:
x = d2i_X509_bio ( bio_cert, NULL );
break;
case FORMAT_NETSCAPE:
{
unsigned char *p,*op;
int size=0, i;
const int fix_len = 1024 * 10;
buf=BUF_MEM_new();
for (;;)
{
if ( ( buf == NULL ) ||
( ! BUF_MEM_grow ( buf, size + fix_len ) ) )
goto end;
i = BIO_read ( bio_cert, &(buf->data[size]), fix_len );
size += i;
if ( i == 0 ) break;
if ( i < 0 ) goto end;
}
op = p = (unsigned char *)buf->data;
if ( (ah = d2i_ASN1_HEADER ( NULL, &p, (long)size) ) == NULL)
goto end;
if ( (ah->header == NULL) ||
( ah->header->data == NULL) ||
( strncmp ( NETSCAPE_CERT_HDR, (char *)ah->header->data, ah->header->length) != 0))
{
CError::Interface ()->Handle_Error ( 0, "證書格式頭不正確" );
goto end;
}
p = op;
ah->meth = X509_asn1_meth();
if ( (ah=d2i_ASN1_HEADER( &ah, &p, (long)size)) == NULL)
goto end;
x = (X509 *)ah->data;
}
break;
case FORMAT_PEM:
x = PEM_read_bio_X509_AUX ( bio_cert, NULL,
(pem_password_cb *)password_callback, NULL);
if (x == NULL) {
errcode = ERR_GET_REASON(ERR_peek_error());
CError::Interface()->Handle_Error(errcode, "讀取證書文件失敗:%s", ERR_reason_error_string(errcode));
if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
ERR_clear_error();
else
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
goto end;
}
break;
case FORMAT_PKCS12:
{
PKCS12 * p12 = d2i_PKCS12_bio ( bio_cert, NULL );
PKCS12_parse ( p12, NULL, NULL, &x, NULL );
PKCS12_free ( p12 );
}
break;
default:
CError::Interface()->Handle_Error ( 0, "證書的類型不正確:%d", format );
break;
}
end:
if ( ah ) ASN1_HEADER_free ( ah );
if ( bio_cert ) BIO_free ( bio_cert );
if ( buf ) BUF_MEM_free ( buf );
return x;
}
//用CA證書為其他證書簽名
int CCertMng::Sign_Cert ( conv_tool::OPERATORS_MAP mapOpt,
xmlChar ** ppszXML, int *pnLen )
{
int result = 0;
int ret = -1;
X509_REQ * req = 0;
X509 * x509 = 0,
* xca509 = 0;
EVP_PKEY * pKey = 0,
* pcaKey = 0;
ASN1_OBJECT * objtmp = 0;
ASN1_INTEGER * sn = 0;
X509_STORE * ctx = 0;
const EVP_MD * md_alg = 0, * md_digest = EVP_md5();
int infmt = FORMAT_PEM,
outfmt = FORMAT_PEM,
keyfmt = FORMAT_PEM,
cafmt = FORMAT_PEM,
cakeyfmt = FORMAT_PEM;
int days = DEF_DAYS;
int in_type = FILE_TYPE;
int out_type = FILE_TYPE;
long nErrLine = 0;
bool is_pubkey = false, is_req = false, is_newsn = false;
string sin, sout, skeyfile, scafile, scakey;
string sext, salias, sserial;
CONF * extcnf = 0;
char * p = 0;
conv_tool::OPERATORS_MAP::iterator it;
if ( ( it = mapOpt.find ( IN_FORMAT ) ) != mapOpt.end () )
infmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( OUT_FORMAT ) ) != mapOpt.end () )
outfmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( KEY_FORMAT ) ) != mapOpt.end () )
keyfmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( CA_FORMAT ) ) != mapOpt.end () )
cafmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( CAKEY_FORMAT ) ) != mapOpt.end () )
cakeyfmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IN_TYPE ) ) != mapOpt.end () )
in_type = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( OUT_TYPE ) ) != mapOpt.end () )
out_type = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( DAYS ) ) != mapOpt.end () )
days = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_PUBKEY ) ) != mapOpt.end () )
is_pubkey = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_REQ ) ) != mapOpt.end () )
is_req = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_NEWSN ) ) != mapOpt.end () )
is_newsn = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( KEY ) ) != mapOpt.end () )
skeyfile = it->second;
if ( ( it = mapOpt.find ( IN_FILE ) ) != mapOpt.end () )
sin = it->second;
if ( ( it = mapOpt.find ( OUT_FILE ) ) != mapOpt.end () )
sout = it->second;
if ( ( it = mapOpt.find ( CA_FILE ) ) != mapOpt.end () )
scafile = it->second;
if ( ( it = mapOpt.find ( CAKEY_FILE ) ) != mapOpt.end () )
scakey = it->second;
if ( ( it = mapOpt.find ( EXTENTIONS ) ) != mapOpt.end () )
sext = it->second;
if ( ( it = mapOpt.find ( CA_SERIAL ) ) != mapOpt.end () )
sserial = it->second;
if ( ( it = mapOpt.find ( SERIAL ) ) != mapOpt.end () )
sn = s2i_ASN1_INTEGER ( NULL, (char*)it->second.c_str() );
if ( ( it = mapOpt.find ( ALIAS ) ) != mapOpt.end () )
salias = it->second;
if ( ( it = mapOpt.find ( MD_DIGEST ) ) != mapOpt.end () )
md_alg = EVP_get_digestbyname ( (char*)it->second.c_str() );
if ( md_alg )
md_digest = md_alg;
//讀取隨機數
CRandMng::Interface ()->Rand_Load_File ( m_szRandFile );
if ( scafile.length () == 0 )
{
CError::Interface ()->Handle_Error ( 0, "缺少參數,沒有CA證書" );
goto end;
}
if ( ( ctx = X509_STORE_new () ) == NULL ) goto end;
if ( ! X509_STORE_set_default_paths ( ctx ) ) goto end;
if ( ( scakey.length () == 0 ) &&
( scafile.length() > 0 ) &&
( cafmt == FORMAT_PEM ) )
{
scakey = scafile;
}
if ( m_szConfFile.length () > 0 )
{
X509V3_CTX ctx2;
extcnf = NCONF_new ( NULL );
if ( NCONF_load ( extcnf, m_szConfFile.c_str(), &nErrLine ) == 0 )
{
CError::Interface()->Handle_Error ( 0, "讀取配置文件失敗:%s:%d", m_szConfFile.c_str(), nErrLine );
goto end;
}
if ( Load_Config ( extcnf ) < 0 ) goto end;
if ( sext.length () == 0 )
{
p = NCONF_get_string ( extcnf, DEF_SECTION, DEF_EXTENSIONS );
if ( p )
sext = p;
else
sext = DEF_SECTION;
}
X509V3_set_ctx_test ( &ctx2 );
X509V3_set_nconf ( &ctx2, extcnf );
if ( ! X509V3_EXT_add_nconf ( extcnf, &ctx2, (char*)sext.c_str(), NULL ) )
{
CError::Interface ()->Handle_Error ( 0, "增加擴展屬性失敗:%s", sext.c_str() );
goto end;
}
}
if ( is_req )
{
if ( ( req = Load_Request ( in_type, sin.c_str() ) ) == NULL ) goto end;
if ( ( x509 = Request2X509 ( req, sn, days ) ) == NULL ) goto end;
}
else
x509 = Load_Cert ( in_type, sin.c_str(), infmt );
if ( ( xca509 = Load_Cert ( FILE_TYPE, scafile.c_str(), cafmt ) ) == NULL ) goto end;
if ( salias.length () > 0 )
X509_alias_set1 ( x509, (unsigned char *)salias.c_str(), -1 );
//讀取CA的KEY
if ( ( pcaKey = Load_Key ( (char*)scakey.c_str(), scakey.length(), cakeyfmt ) ) == NULL )
goto end;
//簽名
if ( 0 == x509_Sign ( ctx, scafile.c_str(), md_digest, x509, xca509,
pcaKey, (char*)sserial.c_str(), is_newsn, days, extcnf, sext.c_str(), sn ) )
{
//輸出
if ( Out_X509 ( x509, out_type, sout.c_str(), outfmt, ppszXML, pnLen ) == -1 )
{
CError::Interface ()->Handle_Error ( 0, "輸出操作失敗:%s", sout.c_str() );
goto end;
}
ret = 0;
}
end:
CRandMng::Interface ()->Rand_Write_File ( m_szRandFile );
if ( extcnf ) NCONF_free ( extcnf );
if ( ctx ) X509_STORE_free ( ctx );
if ( req ) X509_REQ_free ( req );
if ( x509 ) X509_free ( x509 );
if ( xca509 ) X509_free ( xca509 );
if ( pKey ) EVP_PKEY_free ( pKey );
if ( pcaKey ) EVP_PKEY_free ( pcaKey );
if ( sn ) ASN1_INTEGER_free ( sn );
return ret;
}
//用CA證書為憑證申請簽名
int CCertMng::x509_Sign ( X509_STORE * ctx, const char * cafile, const EVP_MD * digest,
X509 * x, X509 * xca, EVP_PKEY * pKey, const char * serial, bool create_sn, long days,
CONF * conf, const char * ext_section, ASN1_INTEGER * sn )
{
int ret = -1;
ASN1_INTEGER * ai = 0;
X509_STORE_CTX xsc;
EVP_PKEY * upKey = 0;
//復制CA的KEY
upKey = X509_get_pubkey ( xca );
EVP_PKEY_copy_parameters ( upKey, pKey );
EVP_PKEY_free ( upKey );
if ( ! X509_STORE_CTX_init ( &xsc, ctx, x, NULL ) )
{
CError::Interface ()->Handle_Error ( 0, "初始化x509失敗" );
goto end;
}
//序列號
if ( sn )
ai = sn;
else if ( ( ai = X509_Load_Serial ( cafile, serial, create_sn ) ) == NULL )
goto end;
X509_STORE_CTX_set_cert ( &xsc, x );
//驗證需要簽名的證書
/*if ( ! X509_verify_cert ( &xsc ) )
{
CError::Interface ()->Handle_Error ( 0, "證書錯誤" );
goto end;
}*/
if ( CA_Sign ( x, xca, pKey, ai, days, digest, conf, ext_section ) == -1 )
{
CError::Interface ()->Handle_Error ( 0, "簽名失敗" );
goto end;
}
ret = 0;
end:
X509_STORE_CTX_cleanup ( & xsc );
if ( ai ) ASN1_INTEGER_free ( ai );
return ret;
}
//用CA證書為其他證書簽名
int
CCertMng::CA_Sign ( X509 * x, X509 * xca,
EVP_PKEY * pKey,
ASN1_INTEGER * ai,
long days, const EVP_MD * digest,
CONF * conf, const char * extsec )
{
int ret = -1;
//檢查CA
if ( ! X509_check_private_key ( xca, pKey ) )
{
CError::Interface ()->Handle_Error ( 0, "CA證書和KEY不匹配" );
goto end;
}
//用CA簽名
if ( ! X509_set_issuer_name ( x, X509_get_subject_name ( xca ) ) ) goto end;
if ( ! X509_set_serialNumber ( x, ai ) ) goto end;
if ( X509_gmtime_adj ( X509_get_notBefore ( x ), 0L ) == NULL ) goto end;
if ( X509_gmtime_adj ( X509_get_notAfter ( x ), (long)60*60*24*days ) == NULL) goto end;
if ( conf )
{
X509V3_CTX ctx;
X509_set_version ( x, 2 ); /* version 3 certificate */
X509V3_set_ctx ( & ctx, xca, x, NULL, NULL, 0);
X509V3_set_nconf ( & ctx, conf );
if ( ! X509V3_EXT_add_nconf ( conf, & ctx, (char*)extsec, x ) ) goto end;
}
if ( ! X509_sign ( x, pKey, digest ) ) goto end;
ret = 0;
end:
return ret;
}
//輸出證書,輸出格式為文件或返回XML
int CCertMng::Out_X509 ( X509 * x,
int out_type,
const char * outfile,
int outfmt,
xmlChar **ppszXML, int * pnLen )
{
int ret = -1;
int result = 0;
BUF_MEM * bm = 0;
BIO * out = 0;
//生成IO,如果輸出文件名為空,則輸出到內存中
if ( (out = Bio_Write ( out_type, outfile ) ) < 0 )
goto end;
//根據輸出格式寫證書, 寫到BIO結構
switch ( outfmt )
{
case FORMAT_ASN1:
result = i2d_X509_bio ( out, x );
break;
case FORMAT_PEM:
result = PEM_write_bio_X509 ( out, x );
break;
default:
CError::Interface ()->Handle_Error ( 0, "輸出格式不正確:%d", outfmt );
break;
}
if ( ! result )
{
CError::Interface ()->Handle_Error ( 0, "寫證書失敗" );
goto end;
}
//如果輸出格式不是文件的話,從BIO提出MEM生成XML
if ( out_type != FILE_TYPE )
{
conv_tool::OPERATORS_MAP mapret;
std::string sout_put;
int nLen = 0;
char chLen[127];
if ( Get_BioStr( out, sout_put, & nLen ) < 0 )
goto end;
itoa ( nLen, chLen, 10 );
mapret.insert ( std::make_pair ( std::string ( CERT_FILE ), sout_put ) );
mapret.insert ( std::make_pair ( std::string ( CERT_LENGTH ), std::string ( chLen ) ) );
if ( conv_tool::Map2XML ( mapret, ppszXML, pnLen ) == -1 )
{
CError::Interface()->Handle_Error ( 0, "轉換成XML失敗" );
goto end;
}
}
ret = 0;
end:
if ( out ) BIO_free ( out );
return ret;
}
//生成證書所需要的序列號(從序列號文件讀取)
ASN1_INTEGER *
CCertMng::X509_Load_Serial ( const char * cafile, const char * snfile, bool create)
{
char * buf = 0, *p = 0;
ASN1_INTEGER * ai = 0;
BIGNUM * bnsn = 0;
size_t size;
//文件長度
size = (snfile == NULL ) ?
( strlen ( cafile ) + strlen ( POSTFIX ) + 1 ) : (strlen ( snfile ) + 1 );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -