Update Red Hat Copyright Notices
[nbdkit.git] / filters / tls-fallback / tls-fallback.c
blob5787f9afaf37bb921050aa35ae7c42ebb2ac7a0d
1 /* nbdkit
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <string.h>
36 #include <assert.h>
38 #include <nbdkit-filter.h>
40 /* Needed to shut up newer gcc about use of strncpy on our message buffer */
41 #if __GNUC__ >= 8
42 #define NONSTRING __attribute__ ((nonstring))
43 #else
44 #define NONSTRING
45 #endif
47 static char message[512] NONSTRING = "This NBD server requires TLS "
48 "authentication before it will serve useful data.\n";
50 /* Called for each key=value passed on the command line. */
51 static int
52 tls_fallback_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
53 const char *key, const char *value)
55 if (strcmp (key, "tlsreadme") == 0) {
56 strncpy (message, value, sizeof message); /* Yes, we really mean strncpy */
57 return 0;
59 return next (nxdata, key, value);
62 #define tls_fallback_config_help \
63 "tlsreadme=<MESSAGE> Alternative contents for the plaintext dummy export.\n"
65 int
66 tls_fallback_get_ready (int thread_model)
68 if (thread_model == NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS) {
69 nbdkit_error ("the tls-fallback filter requires parallel connection "
70 "support");
71 return -1;
73 return 0;
76 static int
77 tls_fallback_list_exports (nbdkit_next_list_exports *next,
78 nbdkit_backend *nxdata,
79 int readonly, int is_tls,
80 struct nbdkit_exports *exports)
82 if (!is_tls)
83 return nbdkit_add_export (exports, "", NULL);
84 return next (nxdata, readonly, exports);
87 static const char *
88 tls_fallback_default_export (nbdkit_next_default_export *next,
89 nbdkit_backend *nxdata,
90 int readonly, int is_tls)
92 if (!is_tls)
93 return "";
94 return next (nxdata, readonly);
97 /* Helper for determining if this connection is insecure. This works
98 * because we can treat all handles on a binary basis: secure or
99 * insecure, which lets .open get away without allocating a more
100 * complex handle.
102 #define NOT_TLS (handle == &message)
104 static void *
105 tls_fallback_open (nbdkit_next_open *next, nbdkit_context *nxdata,
106 int readonly,
107 const char *exportname, int is_tls)
109 /* We do NOT want to call next() when insecure, because we don't
110 * know how long it will take. See also CVE-2019-14850 in
111 * nbdkit-security.pod. But that means that this filter must
112 * override every possible callback that can be reached during
113 * handshake, to avoid passing through a non-TLS call to a missing
114 * backend.
116 if (!is_tls)
117 return &message; /* See NOT_TLS for this choice of handle */
118 if (next (nxdata, readonly, exportname) == -1)
119 return NULL;
120 return NBDKIT_HANDLE_NOT_NEEDED;
123 /* When insecure, override any plugin .can_FOO not gated by another in
124 * order to avoid an information leak. (can_write gates can_trim,
125 * can_zero, can_fast_zero, and can_fua).
128 static const char *
129 tls_fallback_export_description (nbdkit_next *next, void *handle)
131 if (NOT_TLS)
132 return NULL;
133 return next->export_description (next);
136 static int64_t
137 tls_fallback_get_size (nbdkit_next *next,
138 void *handle)
140 if (NOT_TLS)
141 return sizeof message;
142 return next->get_size (next);
145 static int
146 tls_fallback_block_size (nbdkit_next *next,
147 void *handle,
148 uint32_t *minimum,
149 uint32_t *preferred,
150 uint32_t *maximum)
152 if (NOT_TLS) {
153 *minimum = *preferred = *maximum = 0;
154 return 0;
156 return next->block_size (next, minimum, preferred, maximum);
159 static int
160 tls_fallback_can_write (nbdkit_next *next,
161 void *handle)
163 if (NOT_TLS)
164 return 0;
165 return next->can_write (next);
168 static int
169 tls_fallback_can_flush (nbdkit_next *next,
170 void *handle)
172 if (NOT_TLS)
173 return 0;
174 return next->can_flush (next);
177 static int
178 tls_fallback_is_rotational (nbdkit_next *next,
179 void *handle)
181 if (NOT_TLS)
182 return 0;
183 return next->is_rotational (next);
186 static int
187 tls_fallback_can_extents (nbdkit_next *next,
188 void *handle)
190 if (NOT_TLS)
191 return 0;
192 return next->can_extents (next);
195 static int
196 tls_fallback_can_multi_conn (nbdkit_next *next,
197 void *handle)
199 if (NOT_TLS)
200 return 0;
201 return next->can_multi_conn (next);
204 static int
205 tls_fallback_can_cache (nbdkit_next *next,
206 void *handle)
208 if (NOT_TLS)
209 return NBDKIT_CACHE_NONE;
210 return next->can_cache (next);
213 static int
214 tls_fallback_pread (nbdkit_next *next,
215 void *handle, void *b, uint32_t count, uint64_t offs,
216 uint32_t flags, int *err)
218 if (NOT_TLS) {
219 memcpy (b, message + offs, count);
220 return 0;
222 return next->pread (next, b, count, offs, flags, err);
225 static struct nbdkit_filter filter = {
226 .name = "tls-fallback",
227 .longname = "nbdkit tls-fallback filter",
228 .config = tls_fallback_config,
229 .config_help = tls_fallback_config_help,
230 .get_ready = tls_fallback_get_ready,
231 .list_exports = tls_fallback_list_exports,
232 .default_export = tls_fallback_default_export,
233 .open = tls_fallback_open,
234 .export_description = tls_fallback_export_description,
235 .get_size = tls_fallback_get_size,
236 .block_size = tls_fallback_block_size,
237 .can_write = tls_fallback_can_write,
238 .can_flush = tls_fallback_can_flush,
239 .is_rotational = tls_fallback_is_rotational,
240 .can_extents = tls_fallback_can_extents,
241 .can_multi_conn = tls_fallback_can_multi_conn,
242 .can_cache = tls_fallback_can_cache,
243 .pread = tls_fallback_pread,
246 NBDKIT_REGISTER_FILTER (filter)