4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
38 #include <nbdkit-filter.h>
40 /* Needed to shut up newer gcc about use of strncpy on our message buffer */
42 #define NONSTRING __attribute__ ((nonstring))
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. */
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 */
59 return next (nxdata
, key
, value
);
62 #define tls_fallback_config_help \
63 "tlsreadme=<MESSAGE> Alternative contents for the plaintext dummy export.\n"
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 "
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
)
83 return nbdkit_add_export (exports
, "", NULL
);
84 return next (nxdata
, readonly
, exports
);
88 tls_fallback_default_export (nbdkit_next_default_export
*next
,
89 nbdkit_backend
*nxdata
,
90 int readonly
, int is_tls
)
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
102 #define NOT_TLS (handle == &message)
105 tls_fallback_open (nbdkit_next_open
*next
, nbdkit_context
*nxdata
,
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
117 return &message
; /* See NOT_TLS for this choice of handle */
118 if (next (nxdata
, readonly
, exportname
) == -1)
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).
129 tls_fallback_export_description (nbdkit_next
*next
, void *handle
)
133 return next
->export_description (next
);
137 tls_fallback_get_size (nbdkit_next
*next
,
141 return sizeof message
;
142 return next
->get_size (next
);
146 tls_fallback_block_size (nbdkit_next
*next
,
153 *minimum
= *preferred
= *maximum
= 0;
156 return next
->block_size (next
, minimum
, preferred
, maximum
);
160 tls_fallback_can_write (nbdkit_next
*next
,
165 return next
->can_write (next
);
169 tls_fallback_can_flush (nbdkit_next
*next
,
174 return next
->can_flush (next
);
178 tls_fallback_is_rotational (nbdkit_next
*next
,
183 return next
->is_rotational (next
);
187 tls_fallback_can_extents (nbdkit_next
*next
,
192 return next
->can_extents (next
);
196 tls_fallback_can_multi_conn (nbdkit_next
*next
,
201 return next
->can_multi_conn (next
);
205 tls_fallback_can_cache (nbdkit_next
*next
,
209 return NBDKIT_CACHE_NONE
;
210 return next
->can_cache (next
);
214 tls_fallback_pread (nbdkit_next
*next
,
215 void *handle
, void *b
, uint32_t count
, uint64_t offs
,
216 uint32_t flags
, int *err
)
219 memcpy (b
, message
+ offs
, count
);
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
)