Ticket #1: jabber.patch

File jabber.patch, 19.8 KB (added by Simon, 8 months ago)

Updated version that runs atoi on s2s default verify-mode

  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/c2s/c2s.h jabberd-2.1.23+sa/c2s/c2s.h
    old new  
    111111 
    112112    /** starttls pemfile */ 
    113113    char                *host_pemfile; 
    114114 
     115    /** certificate chain */ 
     116    char                *host_cachain; 
     117 
    115118    /** verify-mode  */ 
    116119    int                 host_verify_mode; 
    117120 
    118121    /** require starttls */ 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/c2s/main.c jabberd-2.1.23+sa/c2s/main.c
    old new  
    240240        host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(c2s->hosts), id); 
    241241 
    242242        host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile"); 
    243243 
     244        host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain"); 
     245 
    244246        host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0); 
    245247 
    246248#ifdef HAVE_SSL 
    247         if(c2s->sx_ssl == NULL && host->host_pemfile != NULL) { 
    248             c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, host->host_pemfile, NULL, host->host_verify_mode); 
     249        if(host->host_pemfile != NULL) { 
    249250            if(c2s->sx_ssl == NULL) { 
    250                 log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); 
    251                 host->host_pemfile = NULL; 
     251                c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode); 
     252                if(c2s->sx_ssl == NULL) { 
     253                    log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); 
     254                    host->host_pemfile = NULL; 
     255                } 
     256            } else { 
     257                if(sx_ssl_server_addcert(c2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode) != 0) { 
     258                    log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); 
     259                    host->host_pemfile = NULL; 
     260                } 
    252261            } 
    253262        } 
    254263#endif 
    255264 
     
    636645 
    637646#ifdef HAVE_SSL 
    638647    /* get the ssl context up and running */ 
    639648    if(c2s->local_pemfile != NULL) { 
    640         c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, c2s->local_pemfile, NULL, c2s->local_verify_mode); 
     649        c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, NULL, c2s->local_pemfile, NULL, c2s->local_verify_mode); 
    641650        if(c2s->sx_ssl == NULL) { 
    642651            log_write(c2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to clients"); 
    643652            c2s->local_pemfile = NULL; 
    644653        } 
    645654    } 
    646655 
    647656    /* try and get something online, so at least we can encrypt to the router */ 
    648657    if(c2s->sx_ssl == NULL && c2s->router_pemfile != NULL) { 
    649         c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, c2s->router_pemfile, NULL, NULL); 
     658        c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, NULL, c2s->router_pemfile, NULL, NULL); 
    650659        if(c2s->sx_ssl == NULL) { 
    651660            log_write(c2s->log, LOG_ERR, "failed to load router SSL pemfile, channel to router will not be SSL encrypted"); 
    652661            c2s->router_pemfile = NULL; 
    653662        } 
  • resolver/resolver.c

    diff -r -U4 jabberd-2.1.23/resolver/resolver.c jabberd-2.1.23+sa/resolver/resolver.c
    old new  
    597597    r->sx_env = sx_env_new(); 
    598598 
    599599#ifdef HAVE_SSL 
    600600    if(r->router_pemfile != NULL) { 
    601         r->sx_ssl = sx_env_plugin(r->sx_env, sx_ssl_init, r->router_pemfile, NULL, NULL); 
     601        r->sx_ssl = sx_env_plugin(r->sx_env, sx_ssl_init, NULL, r->router_pemfile, NULL, NULL); 
    602602        if(r->sx_ssl == NULL) { 
    603603            log_write(r->log, LOG_ERR, "failed to load SSL pemfile, SSL disabled"); 
    604604            r->router_pemfile = NULL; 
    605605        } 
  • router/main.c

    diff -r -U4 jabberd-2.1.23/router/main.c jabberd-2.1.23+sa/router/main.c
    old new  
    393393    r->sx_env = sx_env_new(); 
    394394 
    395395#ifdef HAVE_SSL 
    396396    if(r->local_pemfile != NULL) { 
    397         r->sx_ssl = sx_env_plugin(r->sx_env, sx_ssl_init, r->local_pemfile, NULL, NULL); 
     397        r->sx_ssl = sx_env_plugin(r->sx_env, sx_ssl_init, NULL, r->local_pemfile, NULL, NULL); 
    398398        if(r->sx_ssl == NULL) 
    399399            log_write(r->log, LOG_ERR, "failed to load SSL pemfile, SSL disabled"); 
    400400    } 
    401401#endif 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/s2s/main.c jabberd-2.1.23+sa/s2s/main.c
    old new  
    1919 */ 
    2020 
    2121#include "s2s.h" 
    2222 
     23#include <stringprep.h> 
     24 
    2325static sig_atomic_t s2s_shutdown = 0; 
    2426sig_atomic_t s2s_lost_router = 0; 
    2527static sig_atomic_t s2s_logrotate = 0; 
    2628 
     
    137139    if(s2s->local_secret == NULL) 
    138140        s2s->local_secret = "secret"; 
    139141 
    140142    s2s->local_pemfile = config_get_one(s2s->config, "local.pemfile", 0); 
    141     if (s2s->local_pemfile != NULL) 
    142         log_debug(ZONE,"loaded local pemfile for peer s2s connections"); 
     143    s2s->local_cachain = config_get_one(s2s->config, "local.cachain", 0); 
     144    s2s->local_verify_mode = j_atoi(config_get_one(s2s->config, "local.verify-mode", 0), 0); 
    143145 
    144146    s2s->io_max_fds = j_atoi(config_get_one(s2s->config, "io.max_fds", 0), 1024); 
    145147 
    146148    s2s->stanza_size_limit = j_atoi(config_get_one(s2s->config, "io.limits.stanzasize", 0), 0); 
     
    151153    s2s->check_idle = j_atoi(config_get_one(s2s->config, "check.idle", 0), 86400); 
    152154 
    153155} 
    154156 
     157static void _s2s_hosts_expand(s2s_t s2s) 
     158{ 
     159    char *realm; 
     160    config_elem_t elem; 
     161    char id[1024]; 
     162    int i; 
     163 
     164    elem = config_get(s2s->config, "local.id"); 
     165    for(i = 0; i < elem->nvalues; i++) { 
     166        host_t host = (host_t) pmalloco(xhash_pool(s2s->hosts), sizeof(struct host_st)); 
     167        if(!host) { 
     168            log_write(s2s->log, LOG_ERR, "cannot allocate memory for new host, aborting"); 
     169            exit(1); 
     170        } 
     171 
     172        realm = j_attr((const char **) elem->attrs[i], "realm"); 
     173 
     174        /* stringprep ids (domain names) so that they are in canonical form */ 
     175        strncpy(id, elem->values[i], 1024); 
     176        id[1023] = '\0'; 
     177        if (stringprep_nameprep(id, 1024) != 0) { 
     178            log_write(s2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id); 
     179            exit(1); 
     180        } 
     181 
     182        host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(s2s->hosts), id); 
     183 
     184        host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile"); 
     185 
     186        host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain"); 
     187 
     188        host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0); 
     189 
     190#ifdef HAVE_SSL 
     191        if(host->host_pemfile != NULL) { 
     192            if(s2s->sx_ssl == NULL) { 
     193                s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode); 
     194                if(s2s->sx_ssl == NULL) { 
     195                    log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); 
     196                    host->host_pemfile = NULL; 
     197                } 
     198            } else { 
     199                if(sx_ssl_server_addcert(s2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode) != 0) { 
     200                    log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); 
     201                    host->host_pemfile = NULL; 
     202                } 
     203            } 
     204        } 
     205#endif 
     206 
     207        /* insert into vHosts xhash */ 
     208        xhash_put(s2s->hosts, pstrdup(xhash_pool(s2s->hosts), id), host); 
     209 
     210        log_write(s2s->log, LOG_NOTICE, "[%s] configured; realm=%s", id, host->realm); 
     211    } 
     212} 
     213 
    155214static int _s2s_router_connect(s2s_t s2s) { 
    156215    log_write(s2s->log, LOG_NOTICE, "attempting connection to router at %s, port=%d", s2s->router_ip, s2s->router_port); 
    157216 
    158217    s2s->fd = mio_connect(s2s->mio, s2s->router_port, s2s->router_ip, s2s_router_mio_callback, (void *) s2s); 
     
    486545 
    487546#ifdef HAVE_SSL 
    488547    /* get the ssl context up and running */ 
    489548    if(s2s->local_pemfile != NULL) { 
    490         s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, s2s->local_pemfile, s2s->local_cachain, s2s->local_verify_mode); 
     549        s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, NULL, s2s->local_pemfile, s2s->local_cachain, s2s->local_verify_mode); 
    491550 
    492551        if(s2s->sx_ssl == NULL) { 
    493552            log_write(s2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to peers"); 
    494553            s2s->local_pemfile = NULL; 
     
    497556    } 
    498557 
    499558    /* try and get something online, so at least we can encrypt to the router */ 
    500559    if(s2s->sx_ssl == NULL && s2s->router_pemfile != NULL) { 
    501         s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, s2s->router_pemfile, NULL, NULL); 
     560        s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, NULL, s2s->router_pemfile, NULL, NULL); 
    502561        if(s2s->sx_ssl == NULL) { 
    503562            log_write(s2s->log, LOG_ERR, "failed to load router SSL pemfile, channel to router will not be SSL encrypted"); 
    504563            s2s->router_pemfile = NULL; 
    505564        } 
     
    511570    if(s2s->sx_sasl == NULL) { 
    512571        log_write(s2s->log, LOG_ERR, "failed to initialise SASL context, aborting"); 
    513572        exit(1); 
    514573    } 
    515              
     574            
     575    /* hosts mapping */ 
     576    s2s->hosts = xhash_new(1021); 
     577    _s2s_hosts_expand(s2s); 
     578 
    516579    s2s->sx_db = sx_env_plugin(s2s->sx_env, s2s_db_init); 
    517580 
    518581    s2s->mio = mio_new(s2s->io_max_fds); 
    519582 
     
    664727    xhash_free(s2s->out); 
    665728    xhash_free(s2s->in); 
    666729    xhash_free(s2s->in_accept); 
    667730    xhash_free(s2s->dnscache); 
     731    xhash_free(s2s->hosts); 
    668732 
    669733    prep_cache_free(s2s->pc); 
    670734 
    671735    jqueue_free(s2s->dead); 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/s2s/out.c jabberd-2.1.23+sa/s2s/out.c
    old new  
    283283 
    284284#ifdef HAVE_SSL 
    285285            /* Send a stream version of 1.0 if we can do STARTTLS */ 
    286286            if(out->s2s->sx_ssl != NULL && out->s2s->local_pemfile != NULL) { 
    287                 sx_client_init(out->s, S2S_DB_HEADER, uri_SERVER, pkt->to->domain, NULL, "1.0"); 
     287                sx_client_init(out->s, S2S_DB_HEADER, uri_SERVER, pkt->to->domain, pkt->from->domain, "1.0"); 
    288288            } else { 
    289289                sx_client_init(out->s, S2S_DB_HEADER, uri_SERVER, NULL, NULL, NULL); 
    290290            } 
    291291#else 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/s2s/s2s.h jabberd-2.1.23+sa/s2s/s2s.h
    old new  
    3232# include <sys/stat.h> 
    3333#endif 
    3434 
    3535/* forward decl */ 
     36typedef struct host_st      *host_t; 
    3637typedef struct s2s_st       *s2s_t; 
    3738typedef struct pkt_st       *pkt_t; 
    3839typedef struct conn_st      *conn_t; 
    3940typedef struct dnscache_st  *dnscache_t; 
    4041 
     42struct host_st { 
     43    /** our realm */ 
     44    char                *realm; 
     45 
     46    /** starttls pemfile */ 
     47    char                *host_pemfile; 
     48 
     49    /** certificate chain */ 
     50    char                *host_cachain; 
     51 
     52    /** verify-mode  */ 
     53    int                 host_verify_mode; 
     54}; 
     55 
    4156struct s2s_st { 
    4257    /** our id (hostname) with the router */ 
    4358    char                *id; 
    4459 
     
    105120 
    106121    /** verify-mode  */ 
    107122    int                 local_verify_mode; 
    108123 
     124    /** hosts mapping */ 
     125    xht                 hosts; 
     126 
    109127    /** max file descriptors */ 
    110128    int                 io_max_fds; 
    111129 
    112130    /** maximum stanza size */ 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/sm/main.c jabberd-2.1.23+sa/sm/main.c
    old new  
    309309    sm->sx_env = sx_env_new(); 
    310310 
    311311#ifdef HAVE_SSL 
    312312    if(sm->router_pemfile != NULL) { 
    313         sm->sx_ssl = sx_env_plugin(sm->sx_env, sx_ssl_init, sm->router_pemfile, NULL, NULL); 
     313        sm->sx_ssl = sx_env_plugin(sm->sx_env, sx_ssl_init, NULL, sm->router_pemfile, NULL, NULL); 
    314314        if(sm->sx_ssl == NULL) { 
    315315            log_write(sm->log, LOG_ERR, "failed to load SSL pemfile, SSL disabled"); 
    316316            sm->router_pemfile = NULL; 
    317317        } 
  • sx/plugins.h

    diff -r -U4 jabberd-2.1.23/sx/plugins.h jabberd-2.1.23+sa/sx/plugins.h
    old new  
    5959 
    6060/** init function */ 
    6161JABBERD2_API int                         sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args); 
    6262 
     63/** add cert function */ 
     64JABBERD2_API int                         sx_ssl_server_addcert(sx_plugin_t p, char *name, char *pemfile, char *cachain, int mode); 
     65 
    6366/** trigger for client starttls */ 
    6467JABBERD2_API int                         sx_ssl_client_starttls(sx_plugin_t p, sx_t s, char *pemfile); 
    6568 
    6669/* previous states */ 
  • jabberd-2.1.

    diff -r -U4 jabberd-2.1.23/sx/ssl.c jabberd-2.1.23+sa/sx/ssl.c
    old new  
    6666    return preverify_ok; 
    6767 } 
    6868 
    6969static void _sx_ssl_starttls_notify_proceed(sx_t s, void *arg) { 
     70    char *to = NULL; 
    7071    _sx_debug(ZONE, "preparing for starttls"); 
    7172 
     73    /* store the destination so we can select an ssl context */ 
     74    if(s->req_to != NULL) to = strdup(s->req_to); 
     75 
    7276    _sx_reset(s); 
    7377 
     78    /* restore destination */ 
     79    if(s->req_to == NULL) 
     80        s->req_to = to; 
     81    else /* ? */ 
     82        free(to); 
     83 
    7484    /* start listening */ 
    7585    sx_server_init(s, s->flags | SX_SSL_WRAPPER); 
    7686} 
    7787 
     
    482492} 
    483493 
    484494static void _sx_ssl_client(sx_t s, sx_plugin_t p) { 
    485495    _sx_ssl_conn_t sc; 
     496    SSL_CTX *ctx; 
    486497    char *pemfile = NULL; 
    487498    int ret; 
    488499 
    489500    /* only bothering if they asked for wrappermode */ 
    490501    if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0) 
    491502        return; 
    492503 
    493     _sx_debug(ZONE, "preparing for ssl connect for %d", s->tag); 
     504    _sx_debug(ZONE, "preparing for ssl connect for %d from %s", s->tag, s->req_from); 
     505 
     506    /* find the ssl context for this source */ 
     507    ctx = xhash_get((xht) p->private, s->req_from); 
     508    if(ctx == NULL) { 
     509        _sx_debug(ZONE, "using default ssl context for %d", s->tag); 
     510        ctx = xhash_get((xht) p->private, "*"); 
     511    } else { 
     512        _sx_debug(ZONE, "using configured ssl context for %d", s->tag); 
     513    } 
     514    assert((int) (ctx != NULL)); 
    494515 
    495516    sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st)); 
    496517 
    497518    /* create the buffers */ 
    498519    sc->rbio = BIO_new(BIO_s_mem()); 
    499520    sc->wbio = BIO_new(BIO_s_mem()); 
    500521 
    501522    /* new ssl conn */ 
    502     sc->ssl = SSL_new((SSL_CTX *) p->private); 
     523    sc->ssl = SSL_new(ctx); 
    503524    SSL_set_bio(sc->ssl, sc->rbio, sc->wbio); 
    504525    SSL_set_connect_state(sc->ssl); 
    505526    SSL_set_ssl_method(sc->ssl, TLSv1_client_method()); 
    506527 
     
    563584} 
    564585 
    565586static void _sx_ssl_server(sx_t s, sx_plugin_t p) { 
    566587    _sx_ssl_conn_t sc; 
     588    SSL_CTX *ctx; 
    567589 
    568590    /* only bothering if they asked for wrappermode */ 
    569591    if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0) 
    570592        return; 
    571593 
    572     _sx_debug(ZONE, "preparing for ssl accept for %d", s->tag); 
     594    _sx_debug(ZONE, "preparing for ssl accept for %d to %s", s->tag, s->req_to); 
     595 
     596    /* find the ssl context for this destination */ 
     597    ctx = xhash_get((xht) p->private, s->req_to); 
     598    if(ctx == NULL) { 
     599        _sx_debug(ZONE, "using default ssl context for %d", s->tag); 
     600        ctx = xhash_get((xht) p->private, "*"); 
     601    } else { 
     602        _sx_debug(ZONE, "using configured ssl context for %d", s->tag); 
     603    } 
     604    assert((int) (ctx != NULL)); 
    573605 
    574606    sc = (_sx_ssl_conn_t) calloc(1, sizeof(struct _sx_ssl_conn_st)); 
    575607 
    576608    /* create the buffers */ 
    577609    sc->rbio = BIO_new(BIO_s_mem()); 
    578610    sc->wbio = BIO_new(BIO_s_mem()); 
    579611 
    580612    /* new ssl conn */ 
    581     sc->ssl = SSL_new((SSL_CTX *) p->private); 
     613    sc->ssl = SSL_new(ctx); 
    582614    SSL_set_bio(sc->ssl, sc->rbio, sc->wbio); 
    583615    SSL_set_accept_state(sc->ssl); 
    584616 
    585617    /* empty external_id */ 
     
    626658    s->plugin_data[p->index] = NULL; 
    627659} 
    628660 
    629661static void _sx_ssl_unload(sx_plugin_t p) { 
    630     SSL_CTX_free((SSL_CTX *) p->private); 
     662    xht contexts = (xht) p->private; 
     663    void *ctx; 
     664 
     665    if(xhash_iter_first(contexts)) 
     666        do { 
     667            xhash_iter_get(contexts, NULL, &ctx); 
     668            SSL_CTX_free((SSL_CTX *) ctx); 
     669        } while(xhash_iter_next(contexts)); 
     670 
     671    xhash_free(contexts); 
    631672} 
    632673 
    633674int sx_openssl_initialized = 0; 
    634675 
    635 /** args: pemfile, cachain, mode */ 
     676/** args: name, pemfile, cachain, mode */ 
    636677int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) { 
    637     char *pemfile, *cachain; 
    638     SSL_CTX *ctx; 
     678    char *name, *pemfile, *cachain; 
    639679    int ret; 
    640680    int mode; 
    641681 
    642682    _sx_debug(ZONE, "initialising ssl plugin"); 
    643683 
     684    name = va_arg(args, char *); 
    644685    pemfile = va_arg(args, char *); 
    645686    if(pemfile == NULL) 
    646687        return 1; 
    647688 
     
    653694 
    654695    /* !!! output openssl error messages to the debug log */ 
    655696 
    656697    /* openssl startup */ 
    657     SSL_library_init(); 
    658     SSL_load_error_strings(); 
    659  
     698    if(!sx_openssl_initialized) { 
     699        SSL_library_init(); 
     700        SSL_load_error_strings(); 
     701    } 
    660702    sx_openssl_initialized = 1; 
    661703 
     704    ret = sx_ssl_server_addcert(p, name, pemfile, cachain, mode); 
     705    if(ret) 
     706        return 1; 
     707 
     708    p->magic = SX_SSL_MAGIC; 
     709 
     710    p->unload = _sx_ssl_unload; 
     711 
     712    p->client = _sx_ssl_client; 
     713    p->server = _sx_ssl_server; 
     714    p->rio = _sx_ssl_rio; 
     715    p->wio = _sx_ssl_wio; 
     716    p->features = _sx_ssl_features; 
     717    p->process = _sx_ssl_process; 
     718    p->free = _sx_ssl_free; 
     719 
     720    return 0; 
     721} 
     722 
     723/** args: name, pemfile, cachain, mode */ 
     724int sx_ssl_server_addcert(sx_plugin_t p, char *name, char *pemfile, char *cachain, int mode) { 
     725    xht contexts = (xht) p->private; 
     726    SSL_CTX *ctx; 
     727    SSL_CTX *tmp; 
     728    int ret; 
     729 
     730    if(!sx_openssl_initialized) { 
     731        _sx_debug(ZONE, "ssl plugin not initialised"); 
     732        return 1; 
     733    } 
     734 
     735    if(name == NULL) 
     736        name = "*"; 
     737 
     738    if(pemfile == NULL) 
     739        return 1; 
     740 
     741    /* !!! output openssl error messages to the debug log */ 
     742 
    662743    /* create the context */ 
    663744    ctx = SSL_CTX_new(SSLv23_method()); 
    664745    if(ctx == NULL) { 
    665746        _sx_debug(ZONE, "ssl context creation failed"); 
     
    697778        SSL_CTX_free(ctx); 
    698779        return 1; 
    699780    } 
    700781 
    701     _sx_debug(ZONE, "Setting verify mode to %02x", mode); 
     782    _sx_debug(ZONE, "setting ssl context '%s' verify mode to %02x", name, mode); 
    702783    SSL_CTX_set_verify(ctx, mode, _sx_ssl_verify_callback); 
    703784 
    704     /* its good */ 
    705     _sx_debug(ZONE, "ssl context initialised; certificate and key loaded from %s", pemfile); 
    706  
    707     p->magic = SX_SSL_MAGIC; 
     785    /* create hash and create default context */ 
     786    if(contexts == NULL) { 
     787        contexts = xhash_new(1021); 
     788        p->private = (void *) contexts; 
     789 
     790        /* this is the first context, if it's not the default then make a copy of it as the default */ 
     791        if(!(name[0] == '*' && name[1] == 0)) { 
     792            int ret = sx_ssl_server_addcert(p, "*", pemfile, cachain, mode); 
     793 
     794            if(ret) { 
     795                /* uh-oh */ 
     796                xhash_free(contexts); 
     797                p->private = NULL; 
     798                return 1; 
     799            } 
     800        } 
     801    } 
    708802 
    709     p->private = (void *) ctx; 
     803    _sx_debug(ZONE, "ssl context '%s' initialised; certificate and key loaded from %s", name, pemfile); 
    710804 
    711     p->unload = _sx_ssl_unload; 
     805    /* remove an existing context with the same name before replacing it */ 
     806    tmp = xhash_get(contexts, name); 
     807    if(tmp != NULL) 
     808        SSL_CTX_free((SSL_CTX *) tmp); 
    712809 
    713     p->client = _sx_ssl_client; 
    714     p->server = _sx_ssl_server; 
    715     p->rio = _sx_ssl_rio; 
    716     p->wio = _sx_ssl_wio; 
    717     p->features = _sx_ssl_features; 
    718     p->process = _sx_ssl_process; 
    719     p->free = _sx_ssl_free; 
     810    xhash_put(contexts, name, ctx); 
    720811 
    721812    return 0; 
    722813} 
    723814