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

📄 tport_tls.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
  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) {    tls_log_errors(1, "tls_clone", 0);    tls_free(tls);    errno = EIO;    return NULL;  }  SSL_set_bio(tls->con, tls->bio_con, tls->bio_con);  if (accept)    SSL_set_accept_state(tls->con);  else    SSL_set_connect_state(tls->con);  SSL_set_mode(tls->con, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);  su_setblocking(sock, 0);  tls_read(tls); /* XXX - works only with non-blocking sockets */  return tls;}tls_t *tls_init_slave(tls_t *master, int sock){  int accept;  return tls_clone(master, sock, accept = 1);}tls_t *tls_init_client(tls_t *master, int sock){  int accept;  return tls_clone(master, sock, accept = 0);}static char *tls_strdup(char const *s){  if (s) {    size_t len = strlen(s) + 1;    char *d = malloc(len);    if (d)      memcpy(d, s, len);    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;}staticint tls_error(tls_t *tls, int ret, char const *who,	      void *buf, int size){  int events = 0;  int err = SSL_get_error(tls->con, ret);  switch (err) {  case SSL_ERROR_WANT_WRITE:    events = SU_WAIT_OUT;    break;  case SSL_ERROR_WANT_READ:    events = SU_WAIT_IN;    break;  case SSL_ERROR_ZERO_RETURN:    return 0;  case SSL_ERROR_SYSCALL:    if (SSL_get_shutdown(tls->con) & SSL_RECEIVED_SHUTDOWN)      return 0;			/* EOS */    if (errno == 0)      return 0;			/* EOS */    return -1;  default:    tls_log_errors(1, who, err);    errno = EIO;    return -1;  }  if (buf) {    tls->write_events = events;    tls->write_buffer = buf, tls->write_buffer_len = size;  }  else {    tls->read_events = events;  }  errno = EAGAIN;  return -1;}ssize_t tls_read(tls_t *tls){  ssize_t ret;  if (tls == NULL) {    errno = EINVAL;    return -1;  }  if (0)    SU_DEBUG_1(("tls_read(%p) called on %s (events %u)\n", (void *)tls,	    tls->type == tls_slave ? "server" : "client",	    tls->read_events));  if (tls->read_buffer_len)    return (ssize_t)tls->read_buffer_len;  tls->read_events = SU_WAIT_IN;  ret = SSL_read(tls->con, tls->read_buffer, tls_buffer_size);  if (ret <= 0)    return tls_error(tls, ret, "tls_read: SSL_read", NULL, 0);  if (!tls->verified) {    int err = tls_post_connection_check(tls);    if (err != X509_V_OK && 	err != SSL_ERROR_SYSCALL &&	err != SSL_ERROR_WANT_WRITE &&	err != SSL_ERROR_WANT_READ) {      SU_DEBUG_1((		 "%s: server certificate doesn't verify\n", 		 "tls_read"));    }  }  return (ssize_t)(tls->read_buffer_len = ret);}void *tls_read_buffer(tls_t *tls, size_t 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);}/** Check if data is available in TCP connection. * *  * * @retval -1 upon an error * @retval 0 end-of-stream * @retval 1 nothing to read  * @retval 2 there is data to read */int tls_want_read(tls_t *tls, int events){  if (tls && (events & tls->read_events)) {    int ret = tls_read(tls);    if (ret > 0)      return 2;    else if (ret == 0)      return 0;    else if (errno == EAGAIN)      return 3;			/* ??? */    else      return -1;  }  return 1;}ssize_t tls_write(tls_t *tls, void *buf, size_t size){  ssize_t ret;  if (0)     SU_DEBUG_1(("tls_write(%p, %p, "MOD_ZU") called on %s\n", 	    (void *)tls, buf, size,	    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) {      SU_DEBUG_1((		 "tls_read: server certificate doesn't verify\n"));    }  }  ret = SSL_write(tls->con, buf, size);  if (ret < 0)    return tls_error(tls, ret, "tls_write: SSL_write", buf, size);  return ret;}int tls_want_write(tls_t *tls, int events){  if (tls && (events & tls->write_events)) {    int ret;    void *buf = tls->write_buffer;    size_t size = tls->write_buffer_len;    tls->write_events = 0;    /* remove buf */    tls->write_buffer = NULL;    tls->write_buffer_len = 0;    ret = tls_write(tls, buf, size);    if (ret >= 0)      /* Restore buf */      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 & ~(SU_WAIT_IN|SU_WAIT_OUT)) |    ((mask & SU_WAIT_IN) ? tls->read_events : 0) |     ((mask & SU_WAIT_OUT) ? tls->write_events : 0);}

⌨️ 快捷键说明

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