📄 ssl.c
字号:
oldkey=keytable[keylen].key;
keytable[keylen].key=make_temp_key(keylen);
keytable[keylen].timeout=now+KEY_CACHE_TIME;
if(oldkey)
RSA_free(oldkey);
}
retval=keytable[keylen].key;
} else { /* Temp key > 2048 bits. Is it possible? */
if(longtime<now || longlen!=keylen) {
oldkey=longkey;
longkey=make_temp_key(keylen);
longtime=now+KEY_CACHE_TIME;
longlen=keylen;
if(oldkey)
RSA_free(oldkey);
}
retval=longkey;
}
leave_critical_section(CRIT_KEYGEN);
return retval;
}
static RSA *make_temp_key(int keylen) {
RSA *result;
log(LOG_DEBUG, "Generating %d bit temporary RSA key...", keylen);
#if SSLEAY_VERSION_NUMBER >= 0x0900
result=RSA_generate_key(keylen, RSA_F4, NULL, NULL);
#else
result=RSA_generate_key(keylen, RSA_F4, NULL);
#endif
log(LOG_DEBUG, "Temporary RSA key created");
return result;
}
#endif /* NO_RSA */
static void verify_init(void) {
X509_LOOKUP *lookup;
if(options.verify_level<0)
return; /* No certificate verification */
if(options.verify_level>1 && !options.ca_file && !options.ca_dir) {
log(LOG_ERR, "Either CApath or CAfile "
"has to be used for authentication");
exit(1);
}
if(options.ca_file) {
if(!SSL_CTX_load_verify_locations(ctx, options.ca_file, NULL)) {
log(LOG_ERR, "Error loading verify certificates from %s",
options.ca_file);
sslerror("SSL_CTX_load_verify_locations");
exit(1);
}
#if 0
SSL_CTX_set_client_CA_list(ctx,
SSL_load_client_CA_file(options.ca_file));
#endif
log(LOG_DEBUG, "Loaded verify certificates from %s",
options.ca_file);
}
if(options.ca_dir) {
if(!SSL_CTX_load_verify_locations(ctx, NULL, options.ca_dir)) {
log(LOG_ERR, "Error setting verify directory to %s",
options.ca_dir);
sslerror("SSL_CTX_load_verify_locations");
exit(1);
}
log(LOG_DEBUG, "Verify directory set to %s", options.ca_dir);
}
if(options.crl_file || options.crl_dir) { /* setup CRL store */
revocation_store=X509_STORE_new();
if(!revocation_store) {
sslerror("X509_STORE_new");
exit(1);
}
if(options.crl_file) {
lookup=X509_STORE_add_lookup(revocation_store,
X509_LOOKUP_file());
if(!lookup) {
sslerror("X509_STORE_add_lookup");
exit(1);
}
if(!X509_LOOKUP_load_file(lookup, options.crl_file,
X509_FILETYPE_PEM)) {
log(LOG_ERR, "Error loading CRLs from %s",
options.crl_file);
sslerror("X509_LOOKUP_load_file");
exit(1);
}
log(LOG_DEBUG, "Loaded CRLs from %s", options.crl_file);
}
if(options.crl_dir) {
lookup=X509_STORE_add_lookup(revocation_store,
X509_LOOKUP_hash_dir());
if(!lookup) {
sslerror("X509_STORE_add_lookup");
exit(1);
}
if(!X509_LOOKUP_add_dir(lookup, options.crl_dir,
X509_FILETYPE_PEM)) {
log(LOG_ERR, "Error setting CRL directory to %s",
options.crl_dir);
sslerror("X509_LOOKUP_add_dir");
exit(1);
}
log(LOG_DEBUG, "CRL directory set to %s", options.crl_dir);
}
}
SSL_CTX_set_verify(ctx, options.verify_level==SSL_VERIFY_NONE ?
SSL_VERIFY_PEER : options.verify_level, verify_callback);
if(options.ca_dir && options.verify_use_only_my)
log(LOG_NOTICE, "Peer certificate location %s", options.ca_dir);
}
static int verify_callback(int preverify_ok, X509_STORE_CTX *callback_ctx) {
/* our verify callback function */
char txt[STRLEN];
X509_OBJECT ret;
X509_NAME_oneline(X509_get_subject_name(callback_ctx->current_cert),
txt, STRLEN);
safestring(txt);
if(options.verify_level==SSL_VERIFY_NONE) {
log(LOG_NOTICE, "VERIFY IGNORE: depth=%d, %s",
callback_ctx->error_depth, txt);
return 1; /* Accept connection */
}
if(!preverify_ok) {
/* Remote site specified a certificate, but it's not correct */
log(LOG_WARNING, "VERIFY ERROR: depth=%d, error=%s: %s",
callback_ctx->error_depth,
X509_verify_cert_error_string (callback_ctx->error), txt);
return 0; /* Reject connection */
}
if(options.verify_use_only_my && callback_ctx->error_depth==0 &&
X509_STORE_get_by_subject(callback_ctx, X509_LU_X509,
X509_get_subject_name(callback_ctx->current_cert), &ret)!=1) {
log(LOG_WARNING, "VERIFY ERROR ONLY MY: no cert for %s", txt);
return 0; /* Reject connection */
}
if(revocation_store && !crl_callback(callback_ctx))
return 0; /* Reject connection */
/* errnum = X509_STORE_CTX_get_error(ctx); */
log(LOG_NOTICE, "VERIFY OK: depth=%d, %s", callback_ctx->error_depth, txt);
return 1; /* Accept connection */
}
/* Based on BSD-style licensed code of mod_ssl */
static int crl_callback(X509_STORE_CTX *callback_ctx) {
#ifndef HAVE_YASSL /* yassl add, no rev list support yet */
X509_STORE_CTX store_ctx;
X509_OBJECT obj;
X509_NAME *subject;
X509_NAME *issuer;
X509 *xs;
X509_CRL *crl;
X509_REVOKED *revoked;
EVP_PKEY *pubkey;
long serial;
BIO *bio;
int i, n, rc;
char *cp;
char *cp2;
ASN1_TIME *t;
/* Determine certificate ingredients in advance */
xs = X509_STORE_CTX_get_current_cert(callback_ctx);
subject = X509_get_subject_name(xs);
issuer = X509_get_issuer_name(xs);
/* Try to retrieve a CRL corresponding to the _subject_ of
* the current certificate in order to verify it's integrity. */
memset((char *)&obj, 0, sizeof(obj));
X509_STORE_CTX_init(&store_ctx, revocation_store, NULL, NULL);
rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
X509_STORE_CTX_cleanup(&store_ctx);
crl=obj.data.crl;
if(rc>0 && crl) {
/* Log information about CRL
* (A little bit complicated because of ASN.1 and BIOs...) */
bio=BIO_new(BIO_s_mem());
BIO_printf(bio, "lastUpdate: ");
ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
BIO_printf(bio, ", nextUpdate: ");
ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
n=BIO_pending(bio);
cp=malloc(n+1);
n=BIO_read(bio, cp, n);
cp[n]='\0';
BIO_free(bio);
cp2=X509_NAME_oneline(subject, NULL, 0);
log(LOG_NOTICE, "CA CRL: Issuer: %s, %s", cp2, cp);
OPENSSL_free(cp2);
free(cp);
/* Verify the signature on this CRL */
pubkey=X509_get_pubkey(xs);
if(X509_CRL_verify(crl, pubkey)<=0) {
log(LOG_WARNING, "Invalid signature on CRL");
X509_STORE_CTX_set_error(callback_ctx,
X509_V_ERR_CRL_SIGNATURE_FAILURE);
X509_OBJECT_free_contents(&obj);
if(pubkey)
EVP_PKEY_free(pubkey);
return 0; /* Reject connection */
}
if(pubkey)
EVP_PKEY_free(pubkey);
/* Check date of CRL to make sure it's not expired */
t=X509_CRL_get_nextUpdate(crl);
if(!t) {
log(LOG_WARNING, "Found CRL has invalid nextUpdate field");
X509_STORE_CTX_set_error(callback_ctx,
X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
X509_OBJECT_free_contents(&obj);
return 0; /* Reject connection */
}
if(X509_cmp_current_time(t)<0) {
log(LOG_WARNING, "Found CRL is expired - "
"revoking all certificates until you get updated CRL");
X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
X509_OBJECT_free_contents(&obj);
return 0; /* Reject connection */
}
X509_OBJECT_free_contents(&obj);
}
/* Try to retrieve a CRL corresponding to the _issuer_ of
* the current certificate in order to check for revocation. */
memset((char *)&obj, 0, sizeof(obj));
X509_STORE_CTX_init(&store_ctx, revocation_store, NULL, NULL);
rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
X509_STORE_CTX_cleanup(&store_ctx);
crl=obj.data.crl;
if(rc>0 && crl) {
/* Check if the current certificate is revoked by this CRL */
#if SSL_LIBRARY_VERSION < 0x00904000
n=sk_num(X509_CRL_get_REVOKED(crl));
#else
n=sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
#endif
for(i=0; i<n; i++) {
#if SSL_LIBRARY_VERSION < 0x00904000
revoked=(X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
#else
revoked=sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
#endif
if(ASN1_INTEGER_cmp(revoked->serialNumber,
X509_get_serialNumber(xs)) == 0) {
serial=ASN1_INTEGER_get(revoked->serialNumber);
cp=X509_NAME_oneline(issuer, NULL, 0);
log(LOG_NOTICE, "Certificate with serial %ld (0x%lX) "
"revoked per CRL from issuer %s", serial, serial, cp);
OPENSSL_free(cp);
X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REVOKED);
X509_OBJECT_free_contents(&obj);
return 0; /* Reject connection */
}
}
X509_OBJECT_free_contents(&obj);
}
#endif /* yassl add end */
return 1; /* Accept connection */
}
#if SSLEAY_VERSION_NUMBER >= 0x00907000L
static void info_callback(const SSL *s, int where, int ret) {
#else
static void info_callback(SSL *s, int where, int ret) {
#endif
if(where & SSL_CB_LOOP)
log(LOG_DEBUG, "SSL state (%s): %s",
where & SSL_ST_CONNECT ? "connect" :
where & SSL_ST_ACCEPT ? "accept" :
"undefined", SSL_state_string_long(s));
else if(where & SSL_CB_ALERT)
log(LOG_DEBUG, "SSL alert (%s): %s: %s",
where & SSL_CB_READ ? "read" : "write",
SSL_alert_type_string_long(ret),
SSL_alert_desc_string_long(ret));
else if(where==SSL_CB_HANDSHAKE_DONE)
print_stats();
}
static void print_stats(void) { /* print statistics */
log(LOG_DEBUG, "%4ld items in the session cache",
SSL_CTX_sess_number(ctx));
log(LOG_DEBUG, "%4ld client connects (SSL_connect())",
SSL_CTX_sess_connect(ctx));
log(LOG_DEBUG, "%4ld client connects that finished",
SSL_CTX_sess_connect_good(ctx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
log(LOG_DEBUG, "%4ld client renegotiatations requested",
SSL_CTX_sess_connect_renegotiate(ctx));
#endif
log(LOG_DEBUG, "%4ld server connects (SSL_accept())",
SSL_CTX_sess_accept(ctx));
log(LOG_DEBUG, "%4ld server connects that finished",
SSL_CTX_sess_accept_good(ctx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
log(LOG_DEBUG, "%4ld server renegotiatiations requested",
SSL_CTX_sess_accept_renegotiate(ctx));
#endif
log(LOG_DEBUG, "%4ld session cache hits", SSL_CTX_sess_hits(ctx));
log(LOG_DEBUG, "%4ld session cache misses", SSL_CTX_sess_misses(ctx));
log(LOG_DEBUG, "%4ld session cache timeouts", SSL_CTX_sess_timeouts(ctx));
}
void sslerror(char *txt) { /* SSL Error handler */
unsigned long err;
char string[120];
err=ERR_get_error();
if(!err) {
log(LOG_ERR, "%s: Peer suddenly disconnected", txt);
return;
}
sslerror_stack();
ERR_error_string(err, string);
log(LOG_ERR, "%s: %lX: %s", txt, err, string);
}
static void sslerror_stack(void) { /* recursive dump of the error stack */
unsigned long err;
char string[120];
err=ERR_get_error();
if(!err)
return;
sslerror_stack();
ERR_error_string(err, string);
log(LOG_ERR, "error stack: %lX : %s", err, string);
}
/* End of ssl.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -