通过Source Insight查看openssl的源代码,可发现SSL建立的来龙去脉。
1. 先看SSL_NEW.
static int ssl_new(BIO *bi)
{
BIO_SSL *bs;
bs = (BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL));
if (bs == NULL) {
BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
return (0);
}
memset(bs, 0, sizeof(BIO_SSL));
bi->init = 0;
bi->ptr = (char *)bs;
bi->flags = 0;
return (1);
}
bs为BIO_SSL指针,指向OPENSSL_malloc的返回值,即地址,OPENSSL_malloc的作用是什么?再追踪:
# define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__),原来是CRYPTO_malloc,再追踪:
void *CRYPTO_malloc(int num, const char *file, int line)
{
void *ret = NULL;
if (num <= 0)
return NULL;
if (allow_customize)
allow_customize = 0;
if (malloc_debug_func != NULL) {
if (allow_customize_debug)
allow_customize_debug = 0;
malloc_debug_func(NULL, num, file, line, 0);
}
ret = malloc_ex_func(num, file, line);
#ifdef LEVITTE_DEBUG_MEM
fprintf(stderr, "LEVITTE_DEBUG_MEM: > 0x%p (%d)\n", ret, num);
#endif
if (malloc_debug_func != NULL)
malloc_debug_func(ret, num, file, line, 1);
#ifndef OPENSSL_CPUID_OBJ
/*
* Create a dependency on the value of ‘cleanse_ctr‘ so our memory
* sanitisation function can‘t be optimised out. NB: We only do this for
* >2Kb so the overhead doesn‘t bother us.
*/
if (ret && (num > 2048)) {
extern unsigned char cleanse_ctr;
((unsigned char *)ret)[0] = cleanse_ctr;
}
#endif
return ret;
}
实体函数出现了。关键代码就一句: ret = malloc_ex_func(num, file, line);
malloc_ex_func最终引向常用的malloc函数,但是openssl对内存管理提供了很方便的查询/管理接口,后话。
SSL-NEW的作用就是申请了一块存放 BIO_SSL的空间,并初始化bi;
2. 再看ssl_free。
static int ssl_free(BIO *a)
{
BIO_SSL *bs;
if (a == NULL)
return (0);
bs = (BIO_SSL *)a->ptr;
if (bs->ssl != NULL)
SSL_shutdown(bs->ssl);
if (a->shutdown) {
if (a->init && (bs->ssl != NULL))
SSL_free(bs->ssl);
a->init = 0;
a->flags = 0;
}
if (a->ptr != NULL)
OPENSSL_free(a->ptr);
return (1);
}
这个函数应该是释放内存空间的,追踪验证一下。
int SSL_shutdown(SSL *s)
{
/*
* Note that this function behaves differently from what one might
* expect. Return values are 0 for no success (yet), 1 for success; but
* calling it once is usually not enough, even if blocking I/O is used
* (see ssl3_shutdown).
*/
if (s->handshake_func == 0) {
SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
return -1;
}
if ((s != NULL) && !SSL_in_init(s))
return (s->method->ssl_shutdown(s));
else
return (1);
}
看代码,发现函数的目的与预想的很不同;有趣的是,这个函数需多个调用才能完成ssl链接的关闭。why? 再追踪,
到了int ssl3_shutdown(SSL *s)这里;目的是确保SSL链接确实结束。这个函数似乎没有回收内存的代码,只是关闭SSL链接。