📄 tport_tls.c
字号:
return 1;}#endiftls_t *tls_init_slave(tls_t *master, int sock){ tls_t *tls = tls_clone(master); if (!tls) return tls; assert(sock != -1); tls->bio_con = BIO_new_socket(sock, BIO_NOCLOSE); tls->con = SSL_new(tls->ctx); if (tls->con == NULL) { BIO_printf(tls->bio_err, "tls_init_slave: SSL_new failed\n"); ERR_print_errors(tls->bio_err); tls_free(tls); errno = EIO; return NULL; } SSL_set_bio(tls->con, tls->bio_con, tls->bio_con); SSL_set_accept_state(tls->con); SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); tls_read(tls); /* XXX - works only with non-blocking sockets */ return tls;}tls_t *tls_init_client(tls_t *master, int sock){ tls_t *tls = tls_clone(master); if (!tls) return tls; tls->bio_con = BIO_new_socket(sock, BIO_NOCLOSE); tls->con = SSL_new(tls->ctx); if (tls->con == NULL || tls->bio_con == NULL) { BIO_printf(tls->bio_err, "tls_init_client: SSL_new failed\n"); ERR_print_errors(tls->bio_err); tls_free(tls); errno = EIO; return NULL; } SSL_set_bio(tls->con, tls->bio_con, tls->bio_con); SSL_set_connect_state(tls->con); SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); tls_read(tls); /* XXX - works only with non-blocking sockets */ return tls;}static char *tls_strdup(char const *s){ if (s) { int len = strlen(s); char *d = malloc(len + 1); if (d) memcpy(d, s, len + 1); return d; } return NULL;}staticint tls_post_connection_check(tls_t *tls){ X509 *cert; int extcount; int k, i, j, error; if (!tls) return -1; cert = SSL_get_peer_certificate(tls->con); if (!cert) return X509_V_OK; extcount = X509_get_ext_count(cert); for (k = 0; k < TLS_MAX_HOSTS && tls->hosts[k]; k++) ; /* Find matching subjectAltName.DNS */ for (i = 0; i < extcount; i++) { X509_EXTENSION *ext; char const *name; X509V3_EXT_METHOD *vp; STACK_OF(CONF_VALUE) *values; CONF_VALUE *value; void *d2i; ext = X509_get_ext(cert, i); name = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (strcmp(name, "subjectAltName") != 0) continue; vp = X509V3_EXT_get(ext); if (!vp) continue; d2i = X509V3_EXT_d2i(ext); values = vp->i2v(vp, d2i, NULL); for (j = 0; j < sk_CONF_VALUE_num(values); j++) { value = sk_CONF_VALUE_value(values, j); if (strcmp(value->name, "DNS") == 0) { if (k < TLS_MAX_HOSTS) { tls->hosts[k] = tls_strdup(value->value); k += tls->hosts[k] != NULL; } } else if (strcmp(value->name, "URI") == 0) { char const *uri = strchr(value->value, ':'); if (uri ++ && k < TLS_MAX_HOSTS) { tls->hosts[k] = tls_strdup(uri); k += tls->hosts[k] != NULL; } } } } if (k < TLS_MAX_HOSTS) { X509_NAME *subject; char name[256]; subject = X509_get_subject_name(cert); if (subject) { if (X509_NAME_get_text_by_NID(subject, NID_commonName, name, sizeof name) > 0) { name[(sizeof name) - 1] = '\0'; for (i = 0; tls->hosts[i]; i++) if (strcasecmp(tls->hosts[i], name) == 0) break; if (i == k) tls->hosts[k++] = tls_strdup(name); } } } X509_free(cert); error = SSL_get_verify_result(tls->con); if (error == X509_V_OK) tls->verified = 1; return error;}int tls_check_hosts(tls_t *tls, char const *hosts[TLS_MAX_HOSTS]){ int i, j; if (tls == NULL) { errno = EINVAL; return -1; } if (!tls->verified) { errno = EAGAIN; return -1; } if (!hosts) return 0; for (i = 0; hosts[i]; i++) { for (j = 0; tls->hosts[j]; j++) { if (strcasecmp(hosts[i], tls->hosts[j]) == 0) break; } if (tls->hosts[j] == NULL) { errno = EACCES; return -1; } } return 0;}int tls_read(tls_t *tls){ int ret, err; char *what; if (tls == NULL) { errno = EINVAL; return -1; } if (0) fprintf(stderr, "tls_read(%p) called on %s (events %u)\n", tls, tls->type == tls_slave ? "server" : "client", tls->read_events); if (tls->read_buffer_len) return tls->read_buffer_len; tls->read_events = POLLIN; ret = SSL_read(tls->con, tls->read_buffer, tls_buffer_size); what = "SSL_read"; if (!tls->verified) { what = "certificate"; err = tls_post_connection_check(tls); if (err != X509_V_OK && err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_WANT_READ) { BIO_printf(tls->bio_err, "tls_read: server certificate doesn't verify\n"); } } if (ret > 0) { tls->read_buffer_len = ret; return ret; } err = SSL_get_error(tls->con, ret); switch (err) { case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: tls->read_events = err == SSL_ERROR_WANT_WRITE ? POLLOUT : POLLIN; errno = EAGAIN; return -1; case SSL_ERROR_ZERO_RETURN: return 0; default: BIO_printf(tls->bio_err, "tls_read: %s failed: %d %s\n", what, err, ERR_error_string(err, NULL)); ERR_print_errors(tls->bio_err); errno = EIO; return -1; }}void *tls_read_buffer(tls_t *tls, int N){ assert(N == tls->read_buffer_len); tls->read_buffer_len = 0; return tls->read_buffer;}int tls_pending(tls_t const *tls){ return tls && tls->con && SSL_pending(tls->con);}int tls_want_read(tls_t *tls, int events){ if (tls && (events & tls->read_events)) { int ret = tls_read(tls); if (ret >= 0) return 1; else if (errno == EAGAIN) return 0; else return -1; } return 0;}int tls_write(tls_t *tls, void *buf, int size){ int ret, err; if (0) fprintf(stderr, "tls_write(%p) called on %s\n", tls, tls && tls->type == tls_slave ? "server" : "client"); if (tls == NULL || buf == NULL) { errno = EINVAL; return -1; } if (tls->write_buffer) { assert(buf == tls->write_buffer); assert(size >= tls->write_buffer_len); assert(tls->write_events == 0); if (tls->write_events || buf != tls->write_buffer || size < tls->write_buffer_len) { errno = EIO; return -1; } ret = tls->write_buffer_len; tls->write_buffer = NULL; tls->write_buffer_len = 0; return ret; } if (size == 0) return 0; tls->write_events = 0; if (!tls->verified) { if (tls_post_connection_check(tls) != X509_V_OK) { BIO_printf(tls->bio_err, "tls_read: server certificate doesn't verify\n"); } } ret = SSL_write(tls->con, buf, size); if (ret >= 0) return ret; err = SSL_get_error(tls->con, ret); switch(err) { case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: tls->write_buffer = buf, tls->write_buffer_len = size; tls->write_events = err == SSL_ERROR_WANT_WRITE ? POLLOUT : POLLIN; errno = EAGAIN; return -1; default: BIO_printf(tls->bio_err, "tls_write: SSL_write failed: %d %s\n", err, ERR_error_string(err, NULL)); ERR_print_errors(tls->bio_err); errno = EIO; return -1; }}int tls_want_write(tls_t *tls, int events){ if (tls && (events & tls->write_events)) { int ret; void *buf = tls->write_buffer; int size = tls->write_buffer_len; tls->write_events = 0; tls->write_buffer = NULL; tls->write_buffer_len = 0; ret = tls_write(tls, buf, size); if (ret >= 0) return tls->write_buffer = buf, tls->write_buffer_len = ret; else if (errno == EAGAIN) return 0; else return -1; } return 0;}int tls_events(tls_t const *tls, int mask){ if (!tls) return mask; if (tls->type == tls_master) return mask; return (mask & ~(POLLIN|POLLOUT)) | ((mask & POLLIN) ? tls->read_events : 0) | ((mask & POLLOUT) ? tls->write_events : 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -