📄 ssl.c
字号:
_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 + -