static selene_error_t * sln_io_alert(selene_t *s, sln_alert_level_e level, sln_alert_description_e desc) { sln_bucket_t *btls = NULL; sln_bucket_t *balert = NULL; sln_msg_alert_t alert; sln_msg_tls_t tls; alert.level = level; alert.description = desc; SELENE_ERR(sln_alert_unparse(s, &alert, &balert)); tls.content_type = SLN_CONTENT_TYPE_ALERT; tls.version_major = 3; tls.version_minor = 1; tls.length = balert->size; SELENE_ERR(sln_tls_unparse_header(s, &tls, &btls)); SLN_BRIGADE_INSERT_TAIL(s->bb.out_enc, btls); SLN_BRIGADE_INSERT_TAIL(s->bb.out_enc, balert); return SELENE_SUCCESS; }
/* Based on Node's SSL_CTX_use_certificate_chain, in src/node_crypto.cc */ selene_error_t *read_certificate_chain(selene_conf_t *conf, BIO *in, selene_cert_chain_t **p_certs) { X509 *x = NULL; selene_cert_chain_t *chain; selene_cert_t *tmpc; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { return selene_error_create(SELENE_ENOMEM, "Failed to parse certificate"); } SELENE_ERR(sln_cert_chain_create(conf, &chain)); SELENE_ERR(sln_cert_create(conf, x, 0, &tmpc)); SLN_CERT_CHAIN_INSERT_TAIL(chain, tmpc); { /** * If we could set up our certificate, now proceed to * the CA certificates. */ X509 *ca; unsigned long err; while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { SELENE_ERR(sln_cert_create(conf, ca, 0, &tmpc)); SLN_CERT_CHAIN_INSERT_TAIL(chain, tmpc); } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ /* TODO: handle parse errors of the ca certs */ ERR_clear_error(); } } *p_certs = chain; return SELENE_SUCCESS; }
selene_error_t *sln_tls_toss_bucket(selene_t *s, sln_content_type_e content_type, sln_bucket_t *bout) { sln_msg_tls_t tls; sln_parser_baton_t *baton = s->backend_baton; sln_bucket_t *btls = NULL; sln_bucket_t *benc = NULL; if (content_type == SLN_CONTENT_TYPE_HANDSHAKE) { sln_digest_update(baton->md5_handshake_digest, bout->data, bout->size); sln_digest_update(baton->sha1_handshake_digest, bout->data, bout->size); } SELENE_ERR(sln_tls_params_update_mac(s, bout)); SELENE_ERR(sln_tls_params_encrypt(s, bout, &benc)); tls.content_type = content_type; sln_parser_tls_set_current_version(s, &tls.version_major, &tls.version_minor); if (benc != NULL) { tls.length = benc->size; } else { tls.length = bout->size; } SELENE_ERR(sln_tls_serialize_header(s, &tls, &btls)); SLN_BRIGADE_INSERT_TAIL(s->bb.out_enc, btls); if (benc != NULL) { SLN_BRIGADE_INSERT_TAIL(s->bb.out_enc, benc); } else { SLN_BRIGADE_INSERT_TAIL(s->bb.out_enc, bout); } return SELENE_SUCCESS; }
static selene_error_t *have_cleartext(selene_t *s, selene_event_e event, void *baton) { char buf[8096]; size_t blen = 0; size_t remaining = 0; do { SELENE_ERR( selene_io_out_clear_bytes(s, &buf[0], sizeof(buf), &blen, &remaining)); if (blen > 0) { fwrite(buf, blen, 1, stdout); fflush(stdout); } } while (remaining > 0); return SELENE_SUCCESS; }
selene_error_t *selene_conf_cert_chain_add(selene_conf_t *conf, const char *certificate, const char *pkey) { selene_cert_chain_t *certs = NULL; BIO *bio = BIO_new(BIO_s_mem()); int r = BIO_write(bio, certificate, strlen(certificate)); if (r <= 0) { BIO_free(bio); return selene_error_createf( SELENE_ENOMEM, "Attempting to parse Cert Chain certificate, BIO_write returned: %d", r); } /* TODO: private key */ SELENE_ERR(read_certificate_chain(conf, bio, &certs)); SLN_ARRAY_PUSH(conf->certs, selene_cert_chain_t *) = certs; return SELENE_SUCCESS; }
static selene_error_t *want_pull(selene_t *s, selene_event_e event, void *baton) { int rv = 0; char buf[8096]; size_t blen = 0; size_t remaining = 0; server_t *srv = (server_t *)baton; do { SELENE_ERR( selene_io_out_enc_bytes(s, &buf[0], sizeof(buf), &blen, &remaining)); if (blen > 0) { setblocking(srv->sock); rv = write(srv->sock, buf, blen); if (rv < 0) { srv->write_err = errno; break; } } } while (remaining > 0); return SELENE_SUCCESS; }
selene_error_t * selene_conf_use_reasonable_defaults(selene_conf_t *conf) { selene_cipher_suite_list_t *ciphers = NULL; SELENE_ERR(selene_cipher_suite_list_create(&ciphers)); SELENE_ERR(selene_cipher_suite_list_add(ciphers, SELENE_CS_RSA_WITH_RC4_128_SHA)); SELENE_ERR(selene_cipher_suite_list_add(ciphers, SELENE_CS_RSA_WITH_AES_128_CBC_SHA)); SELENE_ERR(selene_cipher_suite_list_add(ciphers, SELENE_CS_RSA_WITH_AES_256_CBC_SHA)); SELENE_ERR(selene_conf_cipher_suites(conf, ciphers)); selene_cipher_suite_list_destroy(ciphers); SELENE_ERR(selene_conf_protocols(conf, SELENE_PROTOCOL_SSL30 | SELENE_PROTOCOL_TLS10 | SELENE_PROTOCOL_TLS11 | SELENE_PROTOCOL_TLS12)); return SELENE_SUCCESS; }
selene_error_t* sln_native_handshake_state_machine(selene_t *s, sln_native_baton_t *baton) { selene_error_t* err; enter_state_machine: slnDbg(s, "enter handshake_state_machine=%d", baton->handshake); switch (baton->handshake) { case SLN_NATIVE_HANDSHAKE_CLIENT_SEND_HELLO: err = sln_native_io_handshake_client_hello(s, baton); if (err) { return err; } baton->handshake = SLN_NATIVE_HANDSHAKE_CLIENT_WAIT_SERVER_HELLO_DONE; break; case SLN_NATIVE_HANDSHAKE_CLIENT_WAIT_SERVER_HELLO_DONE: break; case SLN_NATIVE_HANDSHAKE_CLIENT_SEND_FINISHED: break; case SLN_NATIVE_HANDSHAKE_CLIENT_WAIT_SERVER_FINISHED: break; case SLN_NATIVE_HANDSHAKE_CLIENT_APPDATA: break; /*** * Start Server Methods. */ case SLN_NATIVE_HANDSHAKE_SERVER_WAIT_CLIENT_HELLO: if (!SLN_BRIGADE_EMPTY(s->bb.in_enc)) { err = sln_native_io_tls_read(s, baton); if (err) { return err; } } if (!SLN_BRIGADE_EMPTY(baton->in_handshake)) { err = sln_native_io_handshake_read_client_hello(s, baton); if (err) { return err; } if (baton->handshake != SLN_NATIVE_HANDSHAKE_SERVER_WAIT_CLIENT_HELLO) { goto enter_state_machine; } } break; case SLN_NATIVE_HANDSHAKE_SERVER_SEND_SERVER_HELLO_DONE: break; case SLN_NATIVE_HANDSHAKE_SERVER_WAIT_CLIENT_FINISHED: break; case SLN_NATIVE_HANDSHAKE_SERVER_SNED_FINISHED: break; case SLN_NATIVE_HANDSHAKE_SERVER_APPDATA: break; case SLN_NATIVE_HANDSHAKE__UNUSED0: case SLN_NATIVE_HANDSHAKE__MAX: /* TODO: better handle this */ abort(); break; //default: } if (!SLN_BRIGADE_EMPTY(s->bb.out_enc)) { slnDbg(s, "Encrypted data waiting"); SELENE_ERR(selene_publish(s, SELENE_EVENT_IO_OUT_ENC)); } if (!SLN_BRIGADE_EMPTY(s->bb.out_cleartext)) { slnDbg(s, "Cleartext data waiting"); SELENE_ERR(selene_publish(s, SELENE_EVENT_IO_OUT_CLEAR)); } slnDbg(s, "exit handshake_state_machine=%d", baton->handshake); return SELENE_SUCCESS; }