📄 ssl_sess.c
字号:
/* If a thread got the session, then 'swaped', and another got * it and then due to a time-out decided to 'OPENSSL_free' it we could * be in trouble. So I'll increment it now, then double decrement * later - am I speaking rubbish?. */ CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);#endif if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */ { s->ctx->stats.sess_timeout++; /* remove it from the cache */ SSL_CTX_remove_session(s->ctx,ret); goto err; } s->ctx->stats.sess_hit++; /* ret->time=time(NULL); */ /* rezero timeout? */ /* again, just leave the session * if it is the same session, we have just incremented and * then decremented the reference count :-) */ if (s->session != NULL) SSL_SESSION_free(s->session); s->session=ret; s->verify_result = s->session->verify_result; return(1); err: if (ret != NULL) SSL_SESSION_free(ret); if (fatal) return -1; else return 0; }int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { int ret=0; SSL_SESSION *s; /* add just 1 reference count for the SSL_CTX's session cache * even though it has two ways of access: each session is in a * doubly linked list and an lhash */ CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); /* if session c is in already in cache, we take back the increment later */ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); s=(SSL_SESSION *)lh_insert(ctx->sessions,c); /* s != NULL iff we already had a session with the given PID. * In this case, s == c should hold (then we did not really modify * ctx->sessions), or we're in trouble. */ if (s != NULL && s != c) { /* We *are* in trouble ... */ SSL_SESSION_list_remove(ctx,s); SSL_SESSION_free(s); /* ... so pretend the other session did not exist in cache * (we cannot handle two SSL_SESSION structures with identical * session ID in the same cache, which could happen e.g. when * two threads concurrently obtain the same session from an external * cache) */ s = NULL; } /* Put at the head of the queue unless it is already in the cache */ if (s == NULL) SSL_SESSION_list_add(ctx,c); if (s != NULL) { /* existing cache entry -- decrement previously incremented reference * count because it already takes into account the cache */ SSL_SESSION_free(s); /* s == c */ ret=0; } else { /* new cache entry -- remove old ones if cache has become too large */ ret=1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) { while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) break; else ctx->stats.sess_cache_full++; } } } CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); return(ret); }int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c){ return remove_session_lock(ctx, c, 1);}static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) { SSL_SESSION *r; int ret=0; if ((c != NULL) && (c->session_id_length != 0)) { if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c) { ret=1; r=(SSL_SESSION *)lh_delete(ctx->sessions,c); SSL_SESSION_list_remove(ctx,c); } if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (ret) { r->not_resumable=1; if (ctx->remove_session_cb != NULL) ctx->remove_session_cb(ctx,r); SSL_SESSION_free(r); } } else ret=0; return(ret); }void SSL_SESSION_free(SSL_SESSION *ss) { int i; if(ss == NULL) return; i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);#ifdef REF_PRINT REF_PRINT("SSL_SESSION",ss);#endif if (i > 0) return;#ifdef REF_CHECK if (i < 0) { fprintf(stderr,"SSL_SESSION_free, bad reference count\n"); abort(); /* ok */ }#endif CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg); OPENSSL_cleanse(ss->master_key,sizeof ss->master_key); OPENSSL_cleanse(ss->session_id,sizeof ss->session_id); if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); if (ss->peer != NULL) X509_free(ss->peer); if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers); OPENSSL_cleanse(ss,sizeof(*ss)); OPENSSL_free(ss); }int SSL_set_session(SSL *s, SSL_SESSION *session) { int ret=0; SSL_METHOD *meth; if (session != NULL) { meth=s->ctx->method->get_ssl_method(session->ssl_version); if (meth == NULL) meth=s->method->get_ssl_method(session->ssl_version); if (meth == NULL) { SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD); return(0); } if (meth != s->method) { if (!SSL_set_ssl_method(s,meth)) return(0); if (s->ctx->session_timeout == 0) session->timeout=SSL_get_default_timeout(s); else session->timeout=s->ctx->session_timeout; }#ifndef OPENSSL_NO_KRB5 if (s->kssl_ctx && !s->kssl_ctx->client_princ && session->krb5_client_princ_len > 0) { s->kssl_ctx->client_princ = (char *)malloc(session->krb5_client_princ_len + 1); memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ, session->krb5_client_princ_len); s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0'; }#endif /* OPENSSL_NO_KRB5 */ /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); if (s->session != NULL) SSL_SESSION_free(s->session); s->session=session; s->verify_result = s->session->verify_result; /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ ret=1; } else { if (s->session != NULL) { SSL_SESSION_free(s->session); s->session=NULL; } meth=s->ctx->method; if (meth != s->method) { if (!SSL_set_ssl_method(s,meth)) return(0); } ret=1; } return(ret); }long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) { if (s == NULL) return(0); s->timeout=t; return(1); }long SSL_SESSION_get_timeout(const SSL_SESSION *s) { if (s == NULL) return(0); return(s->timeout); }long SSL_SESSION_get_time(const SSL_SESSION *s) { if (s == NULL) return(0); return(s->time); }long SSL_SESSION_set_time(SSL_SESSION *s, long t) { if (s == NULL) return(0); s->time=t; return(t); }long SSL_CTX_set_timeout(SSL_CTX *s, long t) { long l; if (s == NULL) return(0); l=s->session_timeout; s->session_timeout=t; return(l); }long SSL_CTX_get_timeout(const SSL_CTX *s) { if (s == NULL) return(0); return(s->session_timeout); }typedef struct timeout_param_st { SSL_CTX *ctx; long time; LHASH *cache; } TIMEOUT_PARAM;static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p) { if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ { /* The reason we don't call SSL_CTX_remove_session() is to * save on locking overhead */ lh_delete(p->cache,s); SSL_SESSION_list_remove(p->ctx,s); s->not_resumable=1; if (p->ctx->remove_session_cb != NULL) p->ctx->remove_session_cb(p->ctx,s); SSL_SESSION_free(s); } }static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *)void SSL_CTX_flush_sessions(SSL_CTX *s, long t) { unsigned long i; TIMEOUT_PARAM tp; tp.ctx=s; tp.cache=s->sessions; if (tp.cache == NULL) return; tp.time=t; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); i=tp.cache->down_load; tp.cache->down_load=0; lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp); tp.cache->down_load=i; CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); }int ssl_clear_bad_session(SSL *s) { if ( (s->session != NULL) && !(s->shutdown & SSL_SENT_SHUTDOWN) && !(SSL_in_init(s) || SSL_in_before(s))) { SSL_CTX_remove_session(s->ctx,s->session); return(1); } else return(0); }/* locked by SSL_CTX in the calling function */static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) { if ((s->next == NULL) || (s->prev == NULL)) return; if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { /* last element in list */ if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { /* only one element in list */ ctx->session_cache_head=NULL; ctx->session_cache_tail=NULL; } else { ctx->session_cache_tail=s->prev; s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail); } } else { if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { /* first element in list */ ctx->session_cache_head=s->next; s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head); } else { /* middle of list */ s->next->prev=s->prev; s->prev->next=s->next; } } s->prev=s->next=NULL; }static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) { if ((s->next != NULL) && (s->prev != NULL)) SSL_SESSION_list_remove(ctx,s); if (ctx->session_cache_head == NULL) { ctx->session_cache_head=s; ctx->session_cache_tail=s; s->prev=(SSL_SESSION *)&(ctx->session_cache_head); s->next=(SSL_SESSION *)&(ctx->session_cache_tail); } else { s->next=ctx->session_cache_head; s->next->prev=s; s->prev=(SSL_SESSION *)&(ctx->session_cache_head); ctx->session_cache_head=s; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -