📄 ssl_lib.c
字号:
return(ctx->stats.sess_connect); case SSL_CTRL_SESS_CONNECT_GOOD: return(ctx->stats.sess_connect_good); case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: return(ctx->stats.sess_connect_renegotiate); case SSL_CTRL_SESS_ACCEPT: return(ctx->stats.sess_accept); case SSL_CTRL_SESS_ACCEPT_GOOD: return(ctx->stats.sess_accept_good); case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: return(ctx->stats.sess_accept_renegotiate); case SSL_CTRL_SESS_HIT: return(ctx->stats.sess_hit); case SSL_CTRL_SESS_CB_HIT: return(ctx->stats.sess_cb_hit); case SSL_CTRL_SESS_MISSES: return(ctx->stats.sess_miss); case SSL_CTRL_SESS_TIMEOUTS: return(ctx->stats.sess_timeout); case SSL_CTRL_SESS_CACHE_FULL: return(ctx->stats.sess_cache_full); case SSL_CTRL_OPTIONS: return(ctx->options|=larg); case SSL_CTRL_MODE: return(ctx->mode|=larg); default: return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); } }long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) { switch(cmd) { case SSL_CTRL_SET_MSG_CALLBACK: ctx->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); return 1; default: return(ctx->method->ssl_ctx_callback_ctrl(ctx,cmd,fp)); } }int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b) { long l; l=a->id-b->id; if (l == 0L) return(0); else return((l > 0)?1:-1); }int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap, const SSL_CIPHER * const *bp) { long l; l=(*ap)->id-(*bp)->id; if (l == 0L) return(0); else return((l > 0)?1:-1); }/** return a STACK of the ciphers available for the SSL and in order of * preference */STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) { if (s != NULL) { if (s->cipher_list != NULL) { return(s->cipher_list); } else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) { return(s->ctx->cipher_list); } } return(NULL); }/** return a STACK of the ciphers available for the SSL and in order of * algorithm id */STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) { if (s != NULL) { if (s->cipher_list_by_id != NULL) { return(s->cipher_list_by_id); } else if ((s->ctx != NULL) && (s->ctx->cipher_list_by_id != NULL)) { return(s->ctx->cipher_list_by_id); } } return(NULL); }/** The old interface to get the same thing as SSL_get_ciphers() */const char *SSL_get_cipher_list(const SSL *s,int n) { SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *sk; if (s == NULL) return(NULL); sk=SSL_get_ciphers(s); if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n)) return(NULL); c=sk_SSL_CIPHER_value(sk,n); if (c == NULL) return(NULL); return(c->name); }/** specify the ciphers to be used by default by the SSL_CTX */int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, &ctx->cipher_list_by_id,str); /* ssl_create_cipher_list may return an empty stack if it * was unable to find a cipher matching the given rule string * (for example if the rule string specifies a cipher which * has been disabled). This is not an error as far as * ssl_create_cipher_list is concerned, and hence * ctx->cipher_list and ctx->cipher_list_by_id has been * updated. */ if (sk == NULL) return 0; else if (sk_SSL_CIPHER_num(sk) == 0) { SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); return 0; } return 1; }/** specify the ciphers to be used by the SSL */int SSL_set_cipher_list(SSL *s,const char *str) { STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, &s->cipher_list_by_id,str); /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) return 0; else if (sk_SSL_CIPHER_num(sk) == 0) { SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); return 0; } return 1; }/* works well for SSLv2, not so good for SSLv3 */char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) { char *p; const char *cp; STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *c; int i; if ((s->session == NULL) || (s->session->ciphers == NULL) || (len < 2)) return(NULL); p=buf; sk=s->session->ciphers; for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { /* Decrement for either the ':' or a '\0' */ len--; c=sk_SSL_CIPHER_value(sk,i); for (cp=c->name; *cp; ) { if (len-- == 0) { *p='\0'; return(buf); } else *(p++)= *(cp++); } *(p++)=':'; } p[-1]='\0'; return(buf); }int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, int (*put_cb)(const SSL_CIPHER *, unsigned char *)) { int i,j=0; SSL_CIPHER *c; unsigned char *q;#ifndef OPENSSL_NO_KRB5 int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);#endif /* OPENSSL_NO_KRB5 */ if (sk == NULL) return(0); q=p; for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { c=sk_SSL_CIPHER_value(sk,i);#ifndef OPENSSL_NO_KRB5 if ((c->algorithms & SSL_KRB5) && nokrb5) continue;#endif /* OPENSSL_NO_KRB5 */ j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p); p+=j; } return(p-q); }STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, STACK_OF(SSL_CIPHER) **skp) { SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *sk; int i,n; n=ssl_put_cipher_by_char(s,NULL,NULL); if ((num%n) != 0) { SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); return(NULL); } if ((skp == NULL) || (*skp == NULL)) sk=sk_SSL_CIPHER_new_null(); /* change perhaps later */ else { sk= *skp; sk_SSL_CIPHER_zero(sk); } for (i=0; i<num; i+=n) { c=ssl_get_cipher_by_char(s,p); p+=n; if (c != NULL) { if (!sk_SSL_CIPHER_push(sk,c)) { SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE); goto err; } } } if (skp != NULL) *skp=sk; return(sk);err: if ((skp == NULL) || (*skp == NULL)) sk_SSL_CIPHER_free(sk); return(NULL); }unsigned long SSL_SESSION_hash(const SSL_SESSION *a) { unsigned long l; l=(unsigned long) ((unsigned int) a->session_id[0] )| ((unsigned int) a->session_id[1]<< 8L)| ((unsigned long)a->session_id[2]<<16L)| ((unsigned long)a->session_id[3]<<24L); return(l); }/* NB: If this function (or indeed the hash function which uses a sort of * coarser function than this one) is changed, ensure * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being * able to construct an SSL_SESSION that will collide with any existing session * with a matching session ID. */int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b) { if (a->ssl_version != b->ssl_version) return(1); if (a->session_id_length != b->session_id_length) return(1); return(memcmp(a->session_id,b->session_id,a->session_id_length)); }/* These wrapper functions should remain rather than redeclaring * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each * variable. The reason is that the functions aren't static, they're exposed via * ssl.h. */static IMPLEMENT_LHASH_HASH_FN(SSL_SESSION_hash, SSL_SESSION *)static IMPLEMENT_LHASH_COMP_FN(SSL_SESSION_cmp, SSL_SESSION *)SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) { SSL_CTX *ret=NULL; if (meth == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED); return(NULL); } if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); goto err; } ret=(SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX)); if (ret == NULL) goto err; memset(ret,0,sizeof(SSL_CTX)); ret->method=meth; ret->cert_store=NULL; ret->session_cache_mode=SSL_SESS_CACHE_SERVER; ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; ret->session_cache_head=NULL; ret->session_cache_tail=NULL; /* We take the system default */ ret->session_timeout=meth->get_timeout(); ret->new_session_cb=0; ret->remove_session_cb=0; ret->get_session_cb=0; ret->generate_session_id=0; memset((char *)&ret->stats,0,sizeof(ret->stats)); ret->references=1; ret->quiet_shutdown=0;/* ret->cipher=NULL;*//* ret->s2->challenge=NULL; ret->master_key=NULL; ret->key_arg=NULL; ret->s2->conn_id=NULL; */ ret->info_callback=NULL; ret->app_verify_callback=0; ret->app_verify_arg=NULL; ret->max_cert_list=SSL_MAX_CERT_LIST_DEFAULT; ret->read_ahead=0; ret->msg_callback=0; ret->msg_callback_arg=NULL; ret->verify_mode=SSL_VERIFY_NONE;#if 0 ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */#endif ret->sid_ctx_length=0; ret->default_verify_callback=NULL; if ((ret->cert=ssl_cert_new()) == NULL) goto err; ret->default_passwd_callback=0; ret->default_passwd_callback_userdata=NULL; ret->client_cert_cb=0; ret->app_gen_cookie_cb=0; ret->app_verify_cookie_cb=0; ret->sessions=lh_new(LHASH_HASH_FN(SSL_SESSION_hash), LHASH_COMP_FN(SSL_SESSION_cmp)); if (ret->sessions == NULL) goto err; ret->cert_store=X509_STORE_new(); if (ret->cert_store == NULL) goto err; ssl_create_cipher_list(ret->method, &ret->cipher_list,&ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST); if (ret->cipher_list == NULL || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS); goto err2; } ret->param = X509_VERIFY_PARAM_new(); if (!ret->param) goto err; if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES); goto err2; } if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES); goto err2; } if ((ret->sha1=EVP_get_digestbyname("ssl3-sha1")) == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES); goto err2; } if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL) goto err; CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); ret->extra_certs=NULL; ret->comp_methods=SSL_COMP_get_compression_methods(); return(ret);err: SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);err2: if (ret != NULL) SSL_CTX_free(ret); return(NULL); }#if 0static void SSL_COMP_free(SSL_COMP *comp) { OPENSSL_free(comp); }#endifvoid SSL_CTX_free(SSL_CTX *a) { int i; if (a == NULL) return; i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX);#ifdef REF_PRINT REF_PRINT("SSL_CTX",a);#endif if (i > 0) return;#ifdef REF_CHECK if (i < 0) { fprintf(stderr,"SSL_CTX_free, bad reference count\n"); abort(); /* ok */ }#endif if (a->param) X509_VERIFY_PARAM_free(a->param); /* * Free internal session cache. However: the remove_cb() may reference * the ex_data of SSL_CTX, thus the ex_data store can only be removed * after the sessions were flushed. * As the ex_data handling routines might also touch the session cache, * the most secure solution seems to be: empty (flush) the cache, then * free ex_data, then finally free the cache. * (See ticket [openssl.org #212].) */ if (a->sessions != NULL) SSL_CTX_flush_sessions(a,0); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); if (a->sessions != NULL) lh_free(a->sessions); if (a->cert_store != NULL) X509_STORE_free(a->cert_store); if (a->cipher_list != NULL) sk_SSL_CIPHER_free(a->cipher_list); if (a->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(a->cipher_list_by_id); if (a->cert != NULL) ssl_cert_free(a->cert); if (a->client_CA != NULL) sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free); if (a->extra_certs != NULL) sk_X509_pop_free(a->extra_certs,X509_free);#if 0 /* This should never be done, since it removes a global database */ if (a->comp_methods != NULL) sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free);#else a->comp_methods = NULL;#endif OPENSSL_free(a); }void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { ctx->default_passwd_callback=cb; }void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u) { ctx->default_passwd_callback_userdata=u; }void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg) { ctx->app_verify_callback=cb; ctx->app_verify_arg=arg; }void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) { ctx->verify_mode=mode; ctx->default_verify_callback=cb; }void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) { X509_VERIFY_PARAM_set_depth(ctx->param, depth); }void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -