summary refs log tree commit diff
path: root/tls_bio_cb.c
blob: 9dd435ac7b1c4582cb3a7e851c27f1f623003de8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* $OpenBSD: tls_bio_cb.c,v 1.20 2022/01/10 23:39:48 tb Exp $ */
/*
 * Copyright (c) 2016 Tobias Pape <tobias@netshed.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <openssl/bio.h>

#include <tls.h>
#include "tls_internal.h"

static int bio_cb_write(BIO *bio, const char *buf, int num);
static int bio_cb_read(BIO *bio, char *buf, int size);
static int bio_cb_puts(BIO *bio, const char *str);
static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr);

static BIO_METHOD *bio_cb_method;

static pthread_mutex_t bio_cb_method_lock = PTHREAD_MUTEX_INITIALIZER;

static void
bio_cb_method_init(void)
{
	BIO_METHOD *bio_method;

	if (bio_cb_method != NULL)
		return;

	bio_method = BIO_meth_new(BIO_TYPE_MEM, "libtls_callbacks");
	if (bio_method == NULL)
		return;

	BIO_meth_set_write(bio_method, bio_cb_write);
	BIO_meth_set_read(bio_method, bio_cb_read);
	BIO_meth_set_puts(bio_method, bio_cb_puts);
	BIO_meth_set_ctrl(bio_method, bio_cb_ctrl);

	bio_cb_method = bio_method;
}

static BIO_METHOD *
bio_s_cb(void)
{
	if (bio_cb_method != NULL)
		return (bio_cb_method);

	pthread_mutex_lock(&bio_cb_method_lock);
	bio_cb_method_init();
	pthread_mutex_unlock(&bio_cb_method_lock);

	return (bio_cb_method);
}

static int
bio_cb_puts(BIO *bio, const char *str)
{
	return (bio_cb_write(bio, str, strlen(str)));
}

static long
bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr)
{
	long ret = 1;

	switch (cmd) {
	case BIO_CTRL_GET_CLOSE:
		ret = (long)BIO_get_shutdown(bio);
		break;
	case BIO_CTRL_SET_CLOSE:
		BIO_set_shutdown(bio, (int)num);
		break;
	case BIO_CTRL_DUP:
	case BIO_CTRL_FLUSH:
		break;
	case BIO_CTRL_INFO:
	case BIO_CTRL_GET:
	case BIO_CTRL_SET:
	default:
		ret = BIO_ctrl(BIO_next(bio), cmd, num, ptr);
	}

	return (ret);
}

static int
bio_cb_write(BIO *bio, const char *buf, int num)
{
	struct tls *ctx = BIO_get_data(bio);
	int rv;

	BIO_clear_retry_flags(bio);
	rv = (ctx->write_cb)(ctx, buf, num, ctx->cb_arg);
	if (rv == TLS_WANT_POLLIN) {
		BIO_set_retry_read(bio);
		rv = -1;
	} else if (rv == TLS_WANT_POLLOUT) {
		BIO_set_retry_write(bio);
		rv = -1;
	}
	return (rv);
}

static int
bio_cb_read(BIO *bio, char *buf, int size)
{
	struct tls *ctx = BIO_get_data(bio);
	int rv;

	BIO_clear_retry_flags(bio);
	rv = (ctx->read_cb)(ctx, buf, size, ctx->cb_arg);
	if (rv == TLS_WANT_POLLIN) {
		BIO_set_retry_read(bio);
		rv = -1;
	} else if (rv == TLS_WANT_POLLOUT) {
		BIO_set_retry_write(bio);
		rv = -1;
	}
	return (rv);
}

int
tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb,
    void *cb_arg)
{
	const BIO_METHOD *bio_cb;
	BIO *bio;
	int rv = -1;

	if (read_cb == NULL || write_cb == NULL) {
		tls_set_errorx(ctx, "no callbacks provided");
		goto err;
	}

	ctx->read_cb = read_cb;
	ctx->write_cb = write_cb;
	ctx->cb_arg = cb_arg;

	if ((bio_cb = bio_s_cb()) == NULL) {
		tls_set_errorx(ctx, "failed to create callback method");
		goto err;
	}
	if ((bio = BIO_new(bio_cb)) == NULL) {
		tls_set_errorx(ctx, "failed to create callback i/o");
		goto err;
	}
	BIO_set_data(bio, ctx);
	BIO_set_init(bio, 1);

	SSL_set_bio(ctx->ssl_conn, bio, bio);

	rv = 0;

 err:
	return (rv);
}
not access $HOMEJason A. Donenfeld It's a bit tedious to have to do this here too. If we encounter other issues with $HOME down the line, I'll look into adding some nice utility functions to handle this, or perhaps giving up on the hope that we could keep $HOME defined for scripts. This commit additionally adds a test case, should the issue surface again. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> 2013-04-27t0001: validate Git -rcN version numbers correctlyJohn Keeping When creating the GIT-VERSION-FILE that we use to test that the version of Git in git/ is the same as in the CGit Makefile, Git applies the transform "s/-/./g" to the version string. This doesn't affect released versions but does change RC version numbers such as 1.8.3-rc0. While CGit should only refer to a released Git version in general, it is useful to developers who want to test upcoming Git releases if the tests do work with RCs, so change t0001 to apply the same transform to our Makefile version before comparing it to the contents of GIT-VERSION-FILE. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-27git: update to 1.8.2.2John Keeping No changes required, just bump the submodule and Makefile version. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-17scan-tree: fix regression in section-from-path=-1John Keeping Commit fb3655d (use struct strbuf instead of static buffers - 2013-04-06) introduced a regression in the "section-from-path" handling when the configured value is negative. By changing the "rel" variable so that it includes a trailing slash, counting slashes from the end of the string no longer gives the same answer as it did before. Fix this by ensuring that "rel" does not have a trailing slash. Reported-by: Julius Plenz <plenz@cis.fu-berlin.de> Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-15t0001: ignore ".dirty" suffix on Git versionJohn Keeping When testing modifications in Git that affect CGit, it is annoying to have t0001 failing simply because the Git version has a ".dirty" suffix when the version of Git there does indeed match that specified in the CGit makefile. Stop this by stripping the ".dirty" suffix from the GIT_VERSION variable. Note that this brings the "Git version" behaviour in line with the "submodule version" case which does not check if the working tree in git/ is modified. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-15tests: set TEST_OUTPUT_DIRECTORY to the CGit test directoryJohn Keeping By default, Git's test suite puts the trash directories and test-results directory into its own directory, not that containing the tests being run. This is less convenient for inspecting test failures, so set the output directory to CGit's tests/ directory instead. Note that there is currently a bug in Git whereby it will create the trash directories in our tests/ directory regardless of the value of TEST_OUTPUT_DIRECTORY, and then fail to remove them once the tests are done. This change does currently affect the location of the test-results/ directory though. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-15t0109: test more URLsJohn Keeping In order to ensure that we don't access $HOME at some point after initial startup when rendering a specific view, run the strace test on a range of different pages. This ensures that we don't end up reading a configuration later for some specific view. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-10cgitrc.5.txt: Specify when scan-path must be defined before.Jason A. Donenfeld Several options must be specified prior to scan-path. This is consistant source of user confusion. Document these facts. Suggested-by: Lukas Fleischer <cgit@cryptocrack.de> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> 2013-04-10ui-snapshot.c: Prepend "V" when guessing ref namesLukas Fleischer In cgit_print_snapshot_links() we strip leading "v" and "V", while we currently only prepend a lower case "v" when parsing a snapshot file name. This results in broken snapshot links for tags that start with an upper case "V". Avoid this by prepending a "V" as a fallback. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10t0107: Skip ZIP tests if unzip(1) isn't availableLukas Fleischer Note that we cannot use skip_all here since some tests have already been executed when ZIP tests are reached. Use test prerequisites to skip everything using unzip(1) if the binary is not available instead. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10tests/: Do not use `sed -i`Lukas Fleischer "-i" isn't part of the POSIX standard and doesn't work on several platforms such as OpenBSD. Use a temporary file instead. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10Add branch-sort and repo.branch-sort options.Jason A. Donenfeld When set to "name", branches are sorted by name, which is the current default. When set to "age", branches are sorted by the age of the repository. This feature was requested by Konstantin Ryabitsev for use on kernel.org. Proposed-by: Konstantin Ryabitsev <mricon@kernel.org> 2013-04-10t0109: chain operations with &&John Keeping Without '&&' between operations, we will not detect if strace or cgit exit with an error status, which would cause a false positive test status in this case. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-10cgit.c: Do not restore unset environment variablesLukas Fleischer getenv() returns a NULL pointer if the specified variable name cannot be found in the environment. However, some setenv() implementations crash if a NULL pointer is passed as second argument. Only restore variables that are not NULL. See commit d96d2c98ebc4c2d3765f5b35c4142e0e828a421b for a related patch. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-09t0107: Use `tar -z` for gzip'ed archivesLukas Fleischer