Пример #1
0
static const char *do_verify(const char *hostname, const char *commonName, ...)
{
#ifdef DISABLED_TEST
	struct tls ctx;
	struct tls_cert cert;
	struct tls_cert_general_name names[20], *alt;
	union { struct in_addr ip4; struct in6_addr ip6; } addrbuf[20];
	int addrpos = 0, ret;
	va_list ap;
	const char *aname;

	memset(&ctx, 0, sizeof(ctx));
	memset(&addrbuf, 0, sizeof(addrbuf));
	memset(&cert, 0, sizeof(cert));
	memset(&names, 0, sizeof(names));

	cert.subject.common_name = commonName;
	cert.subject_alt_names = names;

	va_start(ap, commonName);
	while (1) {
		aname = va_arg(ap, char *);
		if (!aname)
			break;
		alt = &names[cert.subject_alt_name_count++];
		if (!memcmp(aname, "dns:", 4)) {
			alt->name_type = TLS_CERT_GNAME_DNS;
			alt->name_value = aname + 4;
		} else if (!memcmp(aname, "ip4:", 4)) {
			alt->name_type = TLS_CERT_GNAME_IPv4;
			alt->name_value = &addrbuf[addrpos++];
			if (inet_pton(AF_INET, aname + 4, (void*)alt->name_value) != 1)
				return aname;
		} else if (!memcmp(aname, "ip6:", 4)) {
			alt->name_type = TLS_CERT_GNAME_IPv6;
			alt->name_value = &addrbuf[addrpos++];
			if (inet_pton(AF_INET6, aname + 4, (void*)alt->name_value) != 1)
				return aname;
		} else {
			return aname;
		}
	}
	va_end(ap);

	ret = tls_check_servername(&ctx, &cert, hostname);
	if (ctx.errmsg)
		free(ctx.errmsg);
	if (ret == 0)
		return "OK";
	if (ret == -1)
		return "FAIL";
#endif
	return "Unexpected code";
}
Пример #2
0
int
tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
    const char *servername)
{
	union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
	X509 *cert = NULL;
	int ret, err;

	if (ctx->flags & TLS_CONNECTING)
		goto connecting;

	if ((ctx->flags & TLS_CLIENT) == 0) {
		tls_set_error(ctx, "not a client context");
		goto err;
	}

	if (fd_read < 0 || fd_write < 0) {
		tls_set_error(ctx, "invalid file descriptors");
		return (-1);
	}

	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
		tls_set_error(ctx, "ssl context failure");
		goto err;
	}

	if (tls_configure_ssl(ctx) != 0)
		goto err;

	if (ctx->config->verify_name) {
		if (servername == NULL) {
			tls_set_error(ctx, "server name not specified");
			goto err;
		}
	}

	if (ctx->config->verify_cert) {
		SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);

		if (ctx->config->ca_mem != NULL) {
			if (ctx->config->ca_len > INT_MAX) {
				tls_set_error(ctx, "ca too long");
				goto err;
			}

			if (SSL_CTX_load_verify_mem(ctx->ssl_ctx,
			    ctx->config->ca_mem, ctx->config->ca_len) != 1) {
				tls_set_error(ctx,
				    "ssl verify memory setup failure");
				goto err;
			}
		} else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
		    ctx->config->ca_file, ctx->config->ca_path) != 1) {
			tls_set_error(ctx, "ssl verify setup failure");
			goto err;
		}
		if (ctx->config->verify_depth >= 0)
			SSL_CTX_set_verify_depth(ctx->ssl_ctx,
			    ctx->config->verify_depth);
	}

	if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
		tls_set_error(ctx, "ssl connection failure");
		goto err;
	}
	if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
	    SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
		tls_set_error(ctx, "ssl file descriptor failure");
		goto err;
	}

	/*
	 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
	 * permitted in "HostName".
	 */
	if (servername != NULL &&
	    inet_pton(AF_INET, servername, &addrbuf) != 1 &&
	    inet_pton(AF_INET6, servername, &addrbuf) != 1) {
		if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
			tls_set_error(ctx, "server name indication failure");
			goto err;
		}
	}

 connecting:
	if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
		err = tls_ssl_error(ctx, ret, "connect");
		if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) {
			ctx->flags |= TLS_CONNECTING;
			return (err);
		}
		goto err;
	}
	ctx->flags &= ~TLS_CONNECTING;

	if (ctx->config->verify_name) {
		cert = SSL_get_peer_certificate(ctx->ssl_conn);
		if (cert == NULL) {
			tls_set_error(ctx, "no server certificate");
			goto err;
		}
		if ((ret = tls_check_servername(ctx, cert, servername)) != 0) {
			if (ret != -2)
				tls_set_error(ctx, "name `%s' not present in"
				    " server certificate", servername);
			goto err;
		}
	}

	return (0);

err:
	X509_free(cert);

	return (-1);
}