Thanks Dave !

Your suggestion and demo code are pretty good !

And I also read the source code of " SSL_CTX_load_verify_locations" api and
find that:
We can imitate the implement of " X509_load_cert_crl_file" function in
X509_load_cert_crl_file file

int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
        STACK_OF(X509_INFO) *inf;
        X509_INFO *itmp;
        BIO *in;
        int i, count = 0;
        if(type != X509_FILETYPE_PEM)
                return X509_load_cert_file(ctx, file, type);
        in = BIO_new_file(file, "r");
        if(!in) {
                X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_SYS_LIB);
                return 0;
        }
        inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
        BIO_free(in);
        if(!inf) {
                X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB);
                return 0;
        }
        for(i = 0; i < sk_X509_INFO_num(inf); i++) {
                itmp = sk_X509_INFO_value(inf, i);
                if(itmp->x509) {
                        X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
                        count++;
                }
                if(itmp->crl) {
                        X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
                        count++;
                }
        }
        sk_X509_INFO_pop_free(inf, X509_INFO_free);
        return count;
}

only need some little change, we can create a new function named "
SSL_CTX_use_certificate_chain" 
which complies with the naming conventions like " SSL_CTX_use_certificate".

Int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const unsigned char *d, long
len)
{
                BIO *in;
        X509_INFO *itmp;
                int i, count = 0;
                in = BIO_new_mem_buf( (void *)d, len );
                if( !in )
                {
                        <set the error code>
                        return 0;
                }
                inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
                BIO_free(in);
                if(!inf) {
                                <set the error code>
                return 0;
        }
                for(i = 0; i < sk_X509_INFO_num(inf); i++) {
                            itmp = sk_X509_INFO_value(inf, i);
                if(itmp->x509) {
                                        if( ! SSL_CTX_add_extra_chain_cert(
ctx, itmp->x509) )){
                                                <set the error code>
                                                <how to handle error>
                                                break;
                                        }
                                        count++
                                }
                                ..... <something else if needed>
                }
                return count;
}

Best wishes


Miles.zhaof

-----邮件原件-----
发件人: owner-openssl-us...@openssl.org [mailto:owner-openssl-users@openssl.
org] 代表 Dave Thompson
发送时间: 2012年12月21日 14:01
收件人: openssl-users@openssl.org
主题: RE: how to load a certs chain from memory, thanks

>From: owner-openssl-us...@openssl.org On Behalf Of
miles.zh...@aliyun-inc.com
>Sent: Thursday, 20 December, 2012 22:10

>I want to load a certs chain from memory ( ie. From a std::string variable 
>with the certs chain's content loading from the mysql db ).

>The content of certs chain is like a CAfile.

Not entirely. Both are a sequence of certs, but the certs in a chain 
should be related and those in a trustore mostly should not. Also 
an openssl CAfile or use_chain_file must be PEM, but other chain storage 
(like pkcs7) need not -- but if you're going to put it in a std::string, 
and maybe store as varchar or text in db, you probably do want PEM.

>Because loading from memory, can not call the
"SSL_CTX_load_verify_locations" api.
>So I call "SSL_CTX_add_extra_chain_cert" instead of
"SSL_CTX_load_verify_locations", 
>but "SSL_CTX_add_extra_chain_cert" only load the first cert in the chain,
not all of them.

You can call add_extra_chain_cert more than once. The problem is 
your code only *reads* the first cert in the sequence.

>And I can't get the number of certs in a chain. The content of chain 
>is uploaded from webpage.

>Following is the demo code: <snip>

What you need to do is parse each cert and call add_extra_chain_cert.
If the data is a sequence of PEM-format certs, just create a memBIO with 
the whole thing and then loop PEM_read_bio'ing from there until it 
returns failure. If you want to know how many certs there are, keep 
a counter of the number of times the loop executes.

Google "openssl certificate chain memory buffer" the first hit is false 
(it's about *one* cert in memory, but has "related" links about chains), 
but 2 4 and 5 are all a similar question from Aravind GJ, and answer by me 
with (minimal) code, last year on this list. (It should also be possible 
to search the list archives directly, but I never bother.)

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to