ssl_lib.c
来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 2,062 行 · 第 1/4 页
C
2,062 行
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(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); }int SSL_SESSION_cmp(SSL_SESSION *a,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)); }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=NULL; ret->remove_session_cb=NULL; ret->get_session_cb=NULL; 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=NULL; ret->app_verify_arg=NULL; ret->read_ahead=0; ret->verify_mode=SSL_VERIFY_NONE; ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */ ret->default_verify_callback=NULL; if ((ret->cert=ssl_cert_new()) == NULL) goto err; ret->default_passwd_callback=NULL; ret->default_passwd_callback_userdata=NULL; ret->client_cert_cb=NULL; ret->sessions=lh_new(SSL_SESSION_hash,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; } 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(ssl_ctx_meth,(char *)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); }static void SSL_COMP_free(SSL_COMP *comp) { OPENSSL_free(comp); }void 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 CRYPTO_free_ex_data(ssl_ctx_meth,(char *)a,&a->ex_data); if (a->sessions != NULL) { SSL_CTX_flush_sessions(a,0); 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 (a->comp_methods != NULL) sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free); 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)(),char *arg) { /* now * int (*cb)(X509_STORE_CTX *), * but should be * int (*cb)(X509_STORE_CTX *, void *arg) */ ctx->app_verify_callback=cb; ctx->app_verify_arg=arg; /* never used */ }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; /* This needs cleaning up EAY EAY EAY */ X509_STORE_set_verify_cb_func(ctx->cert_store,cb); }void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) { ctx->verify_depth=depth; }void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) { CERT_PKEY *cpk; int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign; int rsa_enc_export,dh_rsa_export,dh_dsa_export; int rsa_tmp_export,dh_tmp_export,kl; unsigned long mask,emask; if (c == NULL) return; kl=SSL_C_EXPORT_PKEYLENGTH(cipher);#ifndef NO_RSA rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL); rsa_tmp_export=(c->rsa_tmp_cb != NULL || (rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl));#else rsa_tmp=rsa_tmp_export=0;#endif#ifndef NO_DH dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL); dh_tmp_export=(c->dh_tmp_cb != NULL || (dh_tmp && DH_size(c->dh_tmp)*8 <= kl));#else dh_tmp=dh_tmp_export=0;#endif cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); dh_rsa= (cpk->x509 != NULL && cpk->privatekey != NULL); dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_DH_DSA]);/* FIX THIS EAY EAY EAY */ dh_dsa= (cpk->x509 != NULL && cpk->privatekey != NULL); dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); mask=0; emask=0;#ifdef CIPHER_DEBUG printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", rsa_tmp,rsa_tmp_export,dh_tmp, rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);#endif if (rsa_enc || (rsa_tmp && rsa_sign)) mask|=SSL_kRSA; if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc))) emask|=SSL_kRSA;#if 0 /* The match needs to be both kEDH and aRSA or aDSA, so don't worry */ if ( (dh_tmp || dh_rsa || dh_dsa) && (rsa_enc || rsa_sign || dsa_sign)) mask|=SSL_kEDH; if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && (rsa_enc || rsa_sign || dsa_sign)) emask|=SSL_kEDH;#endif if (dh_tmp_export) emask|=SSL_kEDH; if (dh_tmp) mask|=SSL_kEDH; if (dh_rsa) mask|=SSL_kDHr; if (dh_rsa_export) emask|=SSL_kDHr; if (dh_dsa) mask|=SSL_kDHd; if (dh_dsa_export) emask|=SSL_kDHd; if (rsa_enc || rsa_sign) { mask|=SSL_aRSA; emask|=SSL_aRSA; } if (dsa_sign) { mask|=SSL_aDSS; emask|=SSL_aDSS; } mask|=SSL_aNULL; emask|=SSL_aNULL; c->mask=mask; c->export_mask=emask; c->valid=1; }/* THIS NEEDS CLEANING UP */X509 *ssl_get_server_send_cert(SSL *s) { unsigned long alg,mask,kalg; CERT *c; int i,is_export; c=s->cert; ssl_set_cert_masks(c, s->s3->tmp.new_cipher); alg=s->s3->tmp.new_cipher->algorithms; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); mask=is_export?c->export_mask:c->mask; kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK); if (kalg & SSL_kDHr) i=SSL_PKEY_DH_RSA; else if (kalg & SSL_kDHd) i=SSL_PKEY_DH_DSA; else if (kalg & SSL_aDSS) i=SSL_PKEY_DSA_SIGN; else if (kalg & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) i=SSL_PKEY_RSA_SIGN; else i=SSL_PKEY_RSA_ENC; } else /* if (kalg & SSL_aNULL) */ { SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,SSL_R_INTERNAL_ERROR); return(NULL); } if (c->pkeys[i].x509 == NULL) return(NULL); return(c->pkeys[i].x509); }EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher) { unsigned long alg; CERT *c; alg=cipher->algorithms; c=s->cert; if ((alg & SSL_aDSS) && (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); else if (alg & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey); else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey); else return(NULL); } else /* if (alg & SSL_aNULL) */ { SSLerr(SSL_F_SSL_GET_SIGN_PKEY,SSL_R_INTERNAL_ERROR); return(NULL); } }void ssl_update_cache(SSL *s,int mode) { int i; /* If the session_id_length is 0, we are not supposed to cache it, * and it would be rather hard to do anyway :-) */ if (s->session->session_id_length == 0) return; if ((s->ctx->session_cache_mode & mode) && (!s->hit) && SSL_CTX_add_session(s->ctx,s->session) && (s->ctx->new_session_cb != NULL)) { CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); if (!s->ctx->new_session_cb(s,s->session)) SSL_SESSION_free(s->session); } /* auto flush every 255 connections */ i=s->ctx->session_cache_mode; if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { if ( (((mode & SSL_SESS_CACHE_CLIENT) ?s->ctx->stats.sess_connect_good :s->ctx->stats.sess_accept_good) & 0xff) == 0xff) { SSL_CTX_flush_sessions(s->ctx,time(NULL)); } } }SSL_METHOD *SSL_get_ssl_method(SSL *s) { return(s->method); }int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth) { int conn= -1; int ret=1; if (s->method != meth) { if (s->handshake_func != NULL) conn=(s->handshake_func == s->method->ssl_connect); if (s->method->version == meth->version) s->method=meth; else { s->method->ssl_free(s); s->method=meth; ret=s->method->ssl_new(s); } if (conn == 1) s->handshake_func=meth->ssl_connect; else if (conn == 0) s->handshake_func=meth->ssl_accept; } return(ret); }int SSL_get_error(SSL *s,int i) { int reason; unsigned long l; BIO *bio; if (i > 0) return(SSL_ERROR_NONE); /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake * etc, where we do encode the error */ if ((l=ERR_peek_error()) != 0) { if (ERR_GET_LIB(l) == ERR_LIB_SYS) return(SSL_ERROR_SYSCALL); else return(SSL_ERROR_SSL); } if ((i < 0) && SSL_want_read(s)) { bio=SSL_get_rbio(s); if (BIO_should_read(bio)) return(SSL_ERROR_WANT_READ); else if (BIO_should_write(bio)) /* This one doesn't make too much sense ... We never try * to write to the rbio, and an application program where * rbio and wbio are separate couldn't even know what it * should wait for. * However if we ever set s->rwstate incorrectly * (so that we have SSL_want_read(s) instead of * SSL_want_write(s)) and rbio and wbio *are* the same, * this test works around that bug; so it might be safer * to keep it. */ return(SSL_ERROR_WANT_WRITE); else if (BIO_should_io_special(bio)) { reason=BIO_get_retry_reason(bio); if (reason == BIO_RR_CONNECT) return(SSL_ERROR_WANT_CONNECT); else return(SSL_ERROR_SYSCALL); /* unknown */ } } if ((i < 0) && SSL_want_write(s))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?