⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 2 页
字号:
            _sx_buffer_alloc_margin(buf, 0, pending);            ret = SSL_read(sc->ssl, &(buf->data[buf->len]), pending);            if (ret == 0)            {                /* ret will equal zero if the SSL stream was closed.                   (See the SSL_read manpage.) */                /* If the SSL Shutdown happened properly,                   (i.e. we got an SSL "close notify")                   then proccess the last packet recieved. */                if (SSL_get_shutdown(sc->ssl) == SSL_RECEIVED_SHUTDOWN)                {                  _sx_close(s);                  break;                }                /* If the SSL stream was just closed and not shutdown,                   drop the last packet recieved.                   WARNING: This may cause clients that use SSLv2 and                   earlier to not log out properly. */                err = SSL_get_error(sc->ssl, ret);                _sx_buffer_clear(buf);                if(err == SSL_ERROR_ZERO_RETURN) {                    /* ssl channel closed, we're done */                    _sx_close(s);                }                return -1;            }            else if(ret < 0) {                /* ret will be negative if the SSL stream needs                   more data, or if there was a SSL error.                   (See the SSL_read manpage.) */                err = SSL_get_error(sc->ssl, ret);                /* ssl block incomplete, need more */                if(err == SSL_ERROR_WANT_READ) {                    sc->last_state = SX_SSL_STATE_WANT_READ;                    break;                }                /* something's wrong */                _sx_buffer_clear(buf);                /* !!! need checks for renegotiation */                sc->last_state = SX_SSL_STATE_ERROR;                errstring = ERR_error_string(ERR_get_error(), NULL);                _sx_debug(ZONE, "openssl error: %s", errstring);                /* throw an error */                _sx_gen_error(sxe, SX_ERR_SSL, "SSL handshake error", errstring);                _sx_event(s, event_ERROR, (void *) &sxe);                _sx_error(s, stream_err_INTERNAL_SERVER_ERROR, errstring);                _sx_close(s);                /* !!! drop queue */                return -1;            }            buf->len += ret;        }    }    /* flag if stuff to write */    if(BIO_pending(sc->wbio) > 0 || (est > 0 && jqueue_size(sc->wq) > 0))        s->want_write = 1;    /* flag if we want to read */    if(sc->last_state == SX_SSL_STATE_WANT_READ || sc->last_state == SX_SSL_STATE_NONE)        s->want_read = 1;        if(buf->len == 0)        return 0;    return 1;}static void _sx_ssl_client(sx_t s, sx_plugin_t p) {    _sx_ssl_conn_t sc;    char *pemfile;    int ret;    /* only bothering if they asked for wrappermode */    if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)        return;    _sx_debug(ZONE, "preparing for ssl connect for %d", s->tag);    sc = (_sx_ssl_conn_t) malloc(sizeof(struct _sx_ssl_conn_st));    memset(sc, 0, sizeof(struct _sx_ssl_conn_st));    /* create the buffers */    sc->rbio = BIO_new(BIO_s_mem());    sc->wbio = BIO_new(BIO_s_mem());    /* new ssl conn */    sc->ssl = SSL_new((SSL_CTX *) p->private);    SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);    SSL_set_connect_state(sc->ssl);    /* alternate pemfile */    /* !!! figure out how to error correctly here - just returning will cause     *     us to send a normal unencrypted stream start while the server is     *     waiting for ClientHelo. the server will flag an error, but it won't     *     help the admin at all to figure out what happened */    pemfile = s->plugin_data[p->index]; s->plugin_data[p->index] = NULL;    if(pemfile != NULL) {        /* load the certificate */        ret = SSL_use_certificate_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);        if(ret != 1) {            _sx_debug(ZONE, "couldn't load alternate certificate from %s", pemfile);            SSL_free(sc->ssl);            free(sc);            free(pemfile);            return;        }        /* load the private key */        ret = SSL_use_PrivateKey_file(sc->ssl, pemfile, SSL_FILETYPE_PEM);        if(ret != 1) {            _sx_debug(ZONE, "couldn't load alternate private key from %s", pemfile);            SSL_free(sc->ssl);            free(sc);            free(pemfile);            return;        }        /* check the private key matches the certificate */        ret = SSL_check_private_key(sc->ssl);        if(ret != 1) {            _sx_debug(ZONE, "private key does not match certificate public key");            SSL_free(sc->ssl);            free(sc);            free(pemfile);            return;        }        _sx_debug(ZONE, "loaded alternate pemfile %s", pemfile);        free(pemfile);    }    /* buffer queue */    sc->wq = jqueue_new();    s->plugin_data[p->index] = (void *) sc;    /* bring the plugin online */    _sx_chain_io_plugin(s, p);}static void _sx_ssl_server(sx_t s, sx_plugin_t p) {    _sx_ssl_conn_t sc;    /* only bothering if they asked for wrappermode */    if(!(s->flags & SX_SSL_WRAPPER) || s->ssf > 0)        return;    _sx_debug(ZONE, "preparing for ssl accept for %d", s->tag);    sc = (_sx_ssl_conn_t) malloc(sizeof(struct _sx_ssl_conn_st));    memset(sc, 0, sizeof(struct _sx_ssl_conn_st));    /* create the buffers */    sc->rbio = BIO_new(BIO_s_mem());    sc->wbio = BIO_new(BIO_s_mem());    /* new ssl conn */    sc->ssl = SSL_new((SSL_CTX *) p->private);    SSL_set_bio(sc->ssl, sc->rbio, sc->wbio);    SSL_set_accept_state(sc->ssl);    /* buffer queue */    sc->wq = jqueue_new();    s->plugin_data[p->index] = (void *) sc;    /* bring the plugin online */    _sx_chain_io_plugin(s, p);}/** cleanup */static void _sx_ssl_free(sx_t s, sx_plugin_t p) {    _sx_ssl_conn_t sc = (_sx_ssl_conn_t) s->plugin_data[p->index];    sx_buf_t buf;    if(sc == NULL)        return;    log_debug(ZONE, "cleaning up conn state");    if(s->type == type_NONE) {        free(sc);        return;    }    if(sc->external_id != NULL) free(sc->external_id);    if(sc->ssl) SSL_free(sc->ssl);      /* frees wbio and rbio too */    while((buf = jqueue_pull(sc->wq)) != NULL)        _sx_buffer_free(buf);    free(sc);}static void _sx_ssl_unload(sx_plugin_t p) {    SSL_CTX_free((SSL_CTX *) p->private);}/** args: pemfile */int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args) {    char *pemfile, *cachain;    SSL_CTX *ctx;    int ret;    _sx_debug(ZONE, "initialising ssl plugin");    pemfile = va_arg(args, char *);    if(pemfile == NULL)        return 1;    if(p->private != NULL)        return 1;    cachain = va_arg(args, char *);    /* !!! output openssl error messages to the debug log */    /* openssl startup */    SSL_library_init();    SSL_load_error_strings();    /* create the context */    ctx = SSL_CTX_new(SSLv23_method());    if(ctx == NULL) {        _sx_debug(ZONE, "ssl context creation failed");        return 1;    }        /* load the certificate */    ret = SSL_CTX_use_certificate_file(ctx, pemfile, SSL_FILETYPE_PEM);    if(ret != 1) {        _sx_debug(ZONE, "couldn't load certificate from %s", pemfile);        SSL_CTX_free(ctx);        return 1;    }    /* load the private key */    ret = SSL_CTX_use_PrivateKey_file(ctx, pemfile, SSL_FILETYPE_PEM);    if(ret != 1) {        _sx_debug(ZONE, "couldn't load private key from %s", pemfile);        SSL_CTX_free(ctx);        return 1;    }    /* Load the CA chain, if configured */    if (cachain != NULL) {        ret = SSL_CTX_use_certificate_chain_file(ctx, cachain);        if(ret != 1) {            _sx_debug(ZONE, "WARNING: couldn't load CA chain");        }    }    /* check the private key matches the certificate */    ret = SSL_CTX_check_private_key(ctx);    if(ret != 1) {        _sx_debug(ZONE, "private key does not match certificate public key");        SSL_CTX_free(ctx);        return 1;    }    /* !!! XXX certs */    /*    do {        STACK_OF(X509_NAME) *cert_names;        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);        cert_names = SSL_load_client_CA_file("CA.pem");        SSL_CTX_set_client_CA_list(ctx, cert_names);    } while(0);    */    /* its good */    _sx_debug(ZONE, "ssl context initialised; certificate and key loaded from %s", pemfile);    p->magic = SX_SSL_MAGIC;    p->private = (void *) ctx;    p->unload = _sx_ssl_unload;    p->client = _sx_ssl_client;    p->server = _sx_ssl_server;    p->rio = _sx_ssl_rio;    p->wio = _sx_ssl_wio;    p->features = _sx_ssl_features;    p->process = _sx_ssl_process;    p->free = _sx_ssl_free;    return 0;}int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, char *pemfile) {    assert((int) p);    assert((int) s);    /* sanity */    if(s->type != type_CLIENT || s->state != state_STREAM) {        _sx_debug(ZONE, "wrong conn type or state for client starttls");        return 1;    }    /* check if we're already encrypted */    if(s->ssf > 0) {        _sx_debug(ZONE, "encrypted channel already established");        return 1;    }    _sx_debug(ZONE, "initiating starttls sequence");    /* save the given pemfile for later */    if(pemfile != NULL)        s->plugin_data[p->index] = (void *) strdup(pemfile);    /* go */    jqueue_push(s->wbufq, _sx_buffer_new("<starttls xmlns='" uri_TLS "'/>", strlen(uri_TLS) + 20, NULL, NULL), 0);    s->want_write = 1;    _sx_event(s, event_WANT_WRITE, NULL);    return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -