(linenum→info "unix/slp.c:2238")

openssl/0.9.8g/ssl/ssl_sess.c

    1: /* ssl/ssl_sess.c */
    2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
    3:  * All rights reserved.
    4:  *
    5:  * This package is an SSL implementation written
    6:  * by Eric Young (eay@cryptsoft.com).
    7:  * The implementation was written so as to conform with Netscapes SSL.
    8:  * 
    9:  * This library is free for commercial and non-commercial use as long as
   10:  * the following conditions are aheared to.  The following conditions
   11:  * apply to all code found in this distribution, be it the RC4, RSA,
   12:  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
   13:  * included with this distribution is covered by the same copyright terms
   14:  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
   15:  * 
   16:  * Copyright remains Eric Young's, and as such any Copyright notices in
   17:  * the code are not to be removed.
   18:  * If this package is used in a product, Eric Young should be given attribution
   19:  * as the author of the parts of the library used.
   20:  * This can be in the form of a textual message at program startup or
   21:  * in documentation (online or textual) provided with the package.
   22:  * 
   23:  * Redistribution and use in source and binary forms, with or without
   24:  * modification, are permitted provided that the following conditions
   25:  * are met:
   26:  * 1. Redistributions of source code must retain the copyright
   27:  *    notice, this list of conditions and the following disclaimer.
   28:  * 2. Redistributions in binary form must reproduce the above copyright
   29:  *    notice, this list of conditions and the following disclaimer in the
   30:  *    documentation and/or other materials provided with the distribution.
   31:  * 3. All advertising materials mentioning features or use of this software
   32:  *    must display the following acknowledgement:
   33:  *    "This product includes cryptographic software written by
   34:  *     Eric Young (eay@cryptsoft.com)"
   35:  *    The word 'cryptographic' can be left out if the rouines from the library
   36:  *    being used are not cryptographic related :-).
   37:  * 4. If you include any Windows specific code (or a derivative thereof) from 
   38:  *    the apps directory (application code) you must include an acknowledgement:
   39:  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
   40:  * 
   41:  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
   42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   51:  * SUCH DAMAGE.
   52:  * 
   53:  * The licence and distribution terms for any publically available version or
   54:  * derivative of this code cannot be changed.  i.e. this code cannot simply be
   55:  * copied and put under another distribution licence
   56:  * [including the GNU Public Licence.]
   57:  */
   58: 
   59: #include <stdio.h>
   60: #include <openssl/lhash.h>
   61: #include <openssl/rand.h>
   62: #include "ssl_locl.h"
   63: 
   64: static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
   65: static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
   66: static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
   67: 
   68: SSL_SESSION *SSL_get_session(const SSL *ssl)
   69: /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
   70:         {
   71:         return(ssl->session);
   72:         }
   73: 
   74: SSL_SESSION *SSL_get1_session(SSL *ssl)
   75: /* variant of SSL_get_session: caller really gets something */
   76:         {
   77:         SSL_SESSION *sess;
   78:         /* Need to lock this all up rather than just use CRYPTO_add so that
   79:          * somebody doesn't free ssl->session between when we check it's
   80:          * non-null and when we up the reference count. */
   81:         CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
   82:         sess = ssl->session;
   83:         if(sess)
   84:                 sess->references++;
   85:         CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
   86:         return(sess);
   87:         }
   88: 
   89: int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
   90:              CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
   91:         {
   92:         return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
   93:                         new_func, dup_func, free_func);
   94:         }
   95: 
   96: int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
   97:         {
   98:         return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
   99:         }
  100: 
  101: void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
  102:         {
  103:         return(CRYPTO_get_ex_data(&s->ex_data,idx));
  104:         }
  105: 
  106: SSL_SESSION *SSL_SESSION_new(void)
  107:         {
  108:         SSL_SESSION *ss;
  109: 
  110:         ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
  111:         if (ss == NULL)
  112:                 {
  113:                 SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
  114:                 return(0);
  115:                 }
  116:         memset(ss,0,sizeof(SSL_SESSION));
  117: 
  118:         ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
  119:         ss->references=1;
  120:         ss->timeout=60*5+4; /* 5 minute timeout by default */
  121:         ss->time=(unsigned long)time(NULL);
  122:         ss->prev=NULL;
  123:         ss->next=NULL;
  124:         ss->compress_meth=0;
  125: #ifndef OPENSSL_NO_TLSEXT
  126:         ss->tlsext_hostname = NULL; 
  127: #endif
  128:         CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
  129:         return(ss);
  130:         }
  131: 
  132: const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
  133:         {
  134:         if(len)
  135:                 *len = s->session_id_length;
  136:         return s->session_id;
  137:         }
  138: 
  139: /* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
  140:  * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
  141:  * until we have no conflict is going to complete in one iteration pretty much
  142:  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  143:  * and we still can't avoid a conflict - well that's a reasonable point to call
  144:  * it quits. Either the RAND code is broken or someone is trying to open roughly
  145:  * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
  146:  * store that many sessions is perhaps a more interesting question ... */
  147: 
  148: #define MAX_SESS_ID_ATTEMPTS 10
  149: static int def_generate_session_id(const SSL *ssl, unsigned char *id,
  150:                                 unsigned int *id_len)
  151: {
  152:         unsigned int retry = 0;
  153:         do
  154:                 if (RAND_pseudo_bytes(id, *id_len) <= 0)
  155:                         return 0;
  156:         while(SSL_has_matching_session_id(ssl, id, *id_len) &&
  157:                 (++retry < MAX_SESS_ID_ATTEMPTS));
  158:         if(retry < MAX_SESS_ID_ATTEMPTS)
  159:                 return 1;
  160:         /* else - woops a session_id match */
  161:         /* XXX We should also check the external cache --
  162:          * but the probability of a collision is negligible, and
  163:          * we could not prevent the concurrent creation of sessions
  164:          * with identical IDs since we currently don't have means
  165:          * to atomically check whether a session ID already exists
  166:          * and make a reservation for it if it does not
  167:          * (this problem applies to the internal cache as well).
  168:          */
  169:         return 0;
  170: }
  171: 
  172: int ssl_get_new_session(SSL *s, int session)
  173:         {
  174:         /* This gets used by clients and servers. */
  175: 
  176:         unsigned int tmp;
  177:         SSL_SESSION *ss=NULL;
  178:         GEN_SESSION_CB cb = def_generate_session_id;
  179: 
  180:         if ((ss=SSL_SESSION_new()) == NULL) return(0);
  181: 
  182:         /* If the context has a default timeout, use it */
  183:         if (s->ctx->session_timeout == 0)
  184:                 ss->timeout=SSL_get_default_timeout(s);
  185:         else
  186:                 ss->timeout=s->ctx->session_timeout;
  187: 
  188:         if (s->session != NULL)
  189:                 {
  190:                 SSL_SESSION_free(s->session);
  191:                 s->session=NULL;
  192:                 }
  193: 
  194:         if (session)
  195:                 {
  196:                 if (s->version == SSL2_VERSION)
  197:                         {
  198:                         ss->ssl_version=SSL2_VERSION;
  199:                         ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
  200:                         }
  201:                 else if (s->version == SSL3_VERSION)
  202:                         {
  203:                         ss->ssl_version=SSL3_VERSION;
  204:                         ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
  205:                         }
  206:                 else if (s->version == TLS1_VERSION)
  207:                         {
  208:                         ss->ssl_version=TLS1_VERSION;
  209:                         ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
  210:                         }
  211:                 else if (s->version == DTLS1_VERSION)
  212:                         {
  213:                         ss->ssl_version=DTLS1_VERSION;
  214:                         ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
  215:                         }
  216:                 else
  217:                         {
  218:                         SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
  219:                         SSL_SESSION_free(ss);
  220:                         return(0);
  221:                         }
  222: #ifndef OPENSSL_NO_TLSEXT
  223:                 /* If RFC4507 ticket use empty session ID */
  224:                 if (s->tlsext_ticket_expected)
  225:                         {
  226:                         ss->session_id_length = 0;
  227:                         goto sess_id_done;
  228:                         }
  229: #endif
  230:                 /* Choose which callback will set the session ID */
  231:                 CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
  232:                 if(s->generate_session_id)
  233:                         cb = s->generate_session_id;
  234:                 else if(s->ctx->generate_session_id)
  235:                         cb = s->ctx->generate_session_id;
  236:                 CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
  237:                 /* Choose a session ID */
  238:                 tmp = ss->session_id_length;
  239:                 if(!cb(s, ss->session_id, &tmp))
  240:                         {
  241:                         /* The callback failed */
  242:                         SSLerr(SSL_F_SSL_GET_NEW_SESSION,
  243:                                 SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
  244:                         SSL_SESSION_free(ss);
  245:                         return(0);
  246:                         }
  247:                 /* Don't allow the callback to set the session length to zero.
  248:                  * nor set it higher than it was. */
  249:                 if(!tmp || (tmp > ss->session_id_length))
  250:                         {
  251:                         /* The callback set an illegal length */
  252:                         SSLerr(SSL_F_SSL_GET_NEW_SESSION,
  253:                                 SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
  254:                         SSL_SESSION_free(ss);
  255:                         return(0);
  256:                         }
  257:                 /* If the session length was shrunk and we're SSLv2, pad it */
  258:                 if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
  259:                         memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
  260:                 else
  261:                         ss->session_id_length = tmp;
  262:                 /* Finally, check for a conflict */
  263:                 if(SSL_has_matching_session_id(s, ss->session_id,
  264:                                                 ss->session_id_length))
  265:                         {
  266:                         SSLerr(SSL_F_SSL_GET_NEW_SESSION,
  267:                                 SSL_R_SSL_SESSION_ID_CONFLICT);
  268:                         SSL_SESSION_free(ss);
  269:                         return(0);
  270:                         }
  271: #ifndef OPENSSL_NO_TLSEXT
  272:                 sess_id_done:
  273:                 if (s->tlsext_hostname) {
  274:                         ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
  275:                         if (ss->tlsext_hostname == NULL) {
  276:                                 SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
  277:                                 SSL_SESSION_free(ss);
  278:                                 return 0;
  279:                                 }
  280:                         }
  281: #endif
  282:                 }
  283:         else
  284:                 {
  285:                 ss->session_id_length=0;
  286:                 }
  287: 
  288:         if (s->sid_ctx_length > sizeof ss->sid_ctx)
  289:                 {
  290:                 SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
  291:                 SSL_SESSION_free(ss);
  292:                 return 0;
  293:                 }
  294:         memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
  295:         ss->sid_ctx_length=s->sid_ctx_length;
  296:         s->session=ss;
  297:         ss->ssl_version=s->version;
  298:         ss->verify_result = X509_V_OK;
  299: 
  300:         return(1);
  301:         }
  302: 
  303: int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
  304:                         const unsigned char *limit)
  305:         {
  306:         /* This is used only by servers. */
  307: 
  308:         SSL_SESSION *ret=NULL;
  309:         int fatal = 0;
  310: #ifndef OPENSSL_NO_TLSEXT
  311:         int r;
  312: #endif
  313:   
  314:         if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
  315:                 goto err;
  316: #ifndef OPENSSL_NO_TLSEXT
  317:         r = tls1_process_ticket(s, session_id, len, limit, &ret);
  318:         if (r == -1)
  319:                 {
  320:                 fatal = 1;
  321:                 goto err;
  322:                 }
  323:         else if (r == 0 || (!ret && !len))
  324:                 goto err;
  325:         else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
  326: #else
  327:         if (len == 0)
  328:                 goto err;
  329:         if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
  330: #endif
  331:                 {
  332:                 SSL_SESSION data;
  333:                 data.ssl_version=s->version;
  334:                 data.session_id_length=len;
  335:                 if (len == 0)
  336:                         return 0;
  337:                 memcpy(data.session_id,session_id,len);
  338:                 CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
  339:                 ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
  340:                 if (ret != NULL)
  341:                     /* don't allow other threads to steal it: */
  342:                     CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
  343:                 CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
  344:                 }
  345: 
  346:         if (ret == NULL)
  347:                 {
  348:                 int copy=1;
  349:         
  350:                 s->ctx->stats.sess_miss++;
  351:                 ret=NULL;
  352:                 if (s->ctx->get_session_cb != NULL
  353:                     && (ret=s->ctx->get_session_cb(s,session_id,len,&copy))
  354:                        != NULL)
  355:                         {
  356:                         s->ctx->stats.sess_cb_hit++;
  357: 
  358:                         /* Increment reference count now if the session callback
  359:                          * asks us to do so (note that if the session structures
  360:                          * returned by the callback are shared between threads,
  361:                          * it must handle the reference count itself [i.e. copy == 0],
  362:                          * or things won't be thread-safe). */
  363:                         if (copy)
  364:                                 CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
  365: 
  366:                         /* Add the externally cached session to the internal
  367:                          * cache as well if and only if we are supposed to. */
  368:                         if(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
  369:                                 /* The following should not return 1, otherwise,
  370:                                  * things are very strange */
  371:                                 SSL_CTX_add_session(s->ctx,ret);
  372:                         }
  373:                 if (ret == NULL)
  374:                         goto err;
  375:                 }
  376: 
  377:         /* Now ret is non-NULL, and we own one of its reference counts. */
  378: 
  379:         if (ret->sid_ctx_length != s->sid_ctx_length
  380:             || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
  381:                 {
  382:                 /* We've found the session named by the client, but we don't
  383:                  * want to use it in this context. */
  384: 
  385: #if 0 /* The client cannot always know when a session is not appropriate,
  386:        * so we shouldn't generate an error message. */
  387: 
  388:                 SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
  389: #endif
  390:                 goto err; /* treat like cache miss */
  391:                 }
  392:         
  393:         if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
  394:                 {
  395:                 /* We can't be sure if this session is being used out of
  396:                  * context, which is especially important for SSL_VERIFY_PEER.
  397:                  * The application should have used SSL[_CTX]_set_session_id_context.
  398:                  *
  399:                  * For this error case, we generate an error instead of treating
  400:                  * the event like a cache miss (otherwise it would be easy for
  401:                  * applications to effectively disable the session cache by
  402:                  * accident without anyone noticing).
  403:                  */
  404:                 
  405:                 SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
  406:                 fatal = 1;
  407:                 goto err;
  408:                 }
  409: 
  410:         if (ret->cipher == NULL)
  411:                 {
  412:                 unsigned char buf[5],*p;
  413:                 unsigned long l;
  414: 
  415:                 p=buf;
  416:                 l=ret->cipher_id;
  417:                 l2n(l,p);
  418:                 if ((ret->ssl_version>>8) == SSL3_VERSION_MAJOR)
  419:                         ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
  420:                 else 
  421:                         ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
  422:                 if (ret->cipher == NULL)
  423:                         goto err;
  424:                 }
  425: 
  426: 
  427: #if 0 /* This is way too late. */
  428: 
  429:         /* If a thread got the session, then 'swaped', and another got
  430:          * it and then due to a time-out decided to 'OPENSSL_free' it we could
  431:          * be in trouble.  So I'll increment it now, then double decrement
  432:          * later - am I speaking rubbish?. */
  433:         CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
  434: #endif
  435: 
  436:         if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
  437:                 {
  438:                 s->ctx->stats.sess_timeout++;
  439:                 /* remove it from the cache */
  440:                 SSL_CTX_remove_session(s->ctx,ret);
  441:                 goto err;
  442:                 }
  443: 
  444:         s->ctx->stats.sess_hit++;
  445: 
  446:         /* ret->time=time(NULL); */ /* rezero timeout? */
  447:         /* again, just leave the session 
  448:          * if it is the same session, we have just incremented and
  449:          * then decremented the reference count :-) */
  450:         if (s->session != NULL)
  451:                 SSL_SESSION_free(s->session);
  452:         s->session=ret;
  453:         s->verify_result = s->session->verify_result;
  454:         return(1);
  455: 
  456:  err:
  457:         if (ret != NULL)
  458:                 SSL_SESSION_free(ret);
  459:         if (fatal)
  460:                 return -1;
  461:         else
  462:                 return 0;
  463:         }
  464: 
  465: int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
  466:         {
  467:         int ret=0;
  468:         SSL_SESSION *s;
  469: 
  470:         /* add just 1 reference count for the SSL_CTX's session cache
  471:          * even though it has two ways of access: each session is in a
  472:          * doubly linked list and an lhash */
  473:         CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
  474:         /* if session c is in already in cache, we take back the increment later */
  475: 
  476:         CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
  477:         s=(SSL_SESSION *)lh_insert(ctx->sessions,c);
  478:         
  479:         /* s != NULL iff we already had a session with the given PID.
  480:          * In this case, s == c should hold (then we did not really modify
  481:          * ctx->sessions), or we're in trouble. */
  482:         if (s != NULL && s != c)
  483:                 {
  484:                 /* We *are* in trouble ... */
  485:                 SSL_SESSION_list_remove(ctx,s);
  486:                 SSL_SESSION_free(s);
  487:                 /* ... so pretend the other session did not exist in cache
  488:                  * (we cannot handle two SSL_SESSION structures with identical
  489:                  * session ID in the same cache, which could happen e.g. when
  490:                  * two threads concurrently obtain the same session from an external
  491:                  * cache) */
  492:                 s = NULL;
  493:                 }
  494: 
  495:         /* Put at the head of the queue unless it is already in the cache */
  496:         if (s == NULL)
  497:                 SSL_SESSION_list_add(ctx,c);
  498: 
  499:         if (s != NULL)
  500:                 {
  501:                 /* existing cache entry -- decrement previously incremented reference
  502:                  * count because it already takes into account the cache */
  503: 
  504:                 SSL_SESSION_free(s); /* s == c */
  505:                 ret=0;
  506:                 }
  507:         else
  508:                 {
  509:                 /* new cache entry -- remove old ones if cache has become too large */
  510:                 
  511:                 ret=1;
  512: 
  513:                 if (SSL_CTX_sess_get_cache_size(ctx) > 0)
  514:                         {
  515:                         while (SSL_CTX_sess_number(ctx) >
  516:                                 SSL_CTX_sess_get_cache_size(ctx))
  517:                                 {
  518:                                 if (!remove_session_lock(ctx,
  519:                                         ctx->session_cache_tail, 0))
  520:                                         break;
  521:                                 else
  522:                                         ctx->stats.sess_cache_full++;
  523:                                 }
  524:                         }
  525:                 }
  526:         CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
  527:         return(ret);
  528:         }
  529: 
  530: int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
  531: {
  532:         return remove_session_lock(ctx, c, 1);
  533: }
  534: 
  535: static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
  536:         {
  537:         SSL_SESSION *r;
  538:         int ret=0;
  539: 
  540:         if ((c != NULL) && (c->session_id_length != 0))
  541:                 {
  542:                 if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
  543:                 if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c)
  544:                         {
  545:                         ret=1;
  546:                         r=(SSL_SESSION *)lh_delete(ctx->sessions,c);
  547:                         SSL_SESSION_list_remove(ctx,c);
  548:                         }
  549: 
  550:                 if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
  551: 
  552:                 if (ret)
  553:                         {
  554:                         r->not_resumable=1;
  555:                         if (ctx->remove_session_cb != NULL)
  556:                                 ctx->remove_session_cb(ctx,r);
  557:                         SSL_SESSION_free(r);
  558:                         }