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

📄 tport_tls.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 2 页
字号:
  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 + -