2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1999 University of Maryland at College Park
4 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: security.h,v 1.17 2006/05/26 14:00:58 martinea Exp $
37 struct security_handle;
42 * The Security API consists of handles (also called connections), each of
43 * which represents a connection to a particular host. A handle is implemented
44 * by a driver. Each handle supports a packet-based communication protocol, as
45 * well as an arbitrary number of bidirectional tcp-like streams.
49 * This is a type that gets passed to the security_recvpkt() and
50 * security_connect() callbacks. It details what the status of this callback
54 S_OK, /* the pkt_t was received fine */
55 S_TIMEOUT, /* no pkt_t was received within the time specified in the
56 * timeout argument to security_recvpkt() */
57 S_ERROR, /* an error occurred during reception. Call security_geterror()
58 * for more information */
66 * This structure defines a security driver. This driver abstracts
67 * common security actions behind a set of function pointers. Macros
70 typedef struct security_driver {
73 * The name of this driver, eg, "BSD", "BSDTCP", "KRB5", etc... This is
74 * used by security_getdriver() to associate a name with a driver type.
79 * This is the implementation of security_connect(). It actually sets up
80 * the connection, and then returns a structure describing the connection.
81 * The first element of this structure MUST be a security_handle_t, because
82 * it will be cast to that after it is passed up to the caller.
84 * The first argument is the host to connect to. The second argument is a
85 * function to call when a connection is made. The third argument is passed
88 * The callback takes three arguments. The first is the caller supplied
89 * void pointer. The second is a newly allocated security handle. The third
90 * is a security_status_t flag indicating the success or failure of the
93 void (*connect)(const char *, char *(*)(char *, void *),
94 void (*)(void *, struct security_handle *, security_status_t),
98 * This form sets up a callback that returns new handles as they are
99 * received. It is passed the input and output file descriptors and a
100 * callback. The callback takes a security handle argument and also an
101 * initial packet received for that handle.
103 void (*accept)(const struct security_driver *, char *(*)(char *, void *),
104 int, int, void (*)(struct security_handle *, pkt_t *), void *);
106 /* get the remote hostname */
107 char *(*get_authenticated_peer_name)(struct security_handle *handle);
110 * Frees up handles allocated by the previous methods
112 void (*close)(void *);
115 * This transmits a packet after adding the security information
116 * Returns 0 on success, negative on error.
118 ssize_t (*sendpkt)(void *, pkt_t *);
121 * This creates an event in the event handler for receiving pkt_t's on a
122 * security_handle. The given callback will be called with the given arg
123 * when the driver determines that it has data for that handle. The last
124 * argument is a timeout, in seconds. This may be -1 to indicate no
125 * timeout. This method should assume that the caller will invoke
128 * If there was an error or timeout, this will be indicated in the status
131 * Only one recvpkt request can exist per handle.
133 void (*recvpkt)(void *, void (*)(void *, pkt_t *, security_status_t), void
137 * Cancel an outstanding recvpkt request on a handle. Drivers should allow
138 * this to be run even if no recvpkt was scheduled, or if one was
139 * previously cancelled.
141 void (*recvpkt_cancel)(void *);
144 * Get a stream given a security handle. This function returns a object
145 * describing the stream. The first member of this object MUST be a
146 * security_stream_t, because it will be cast to that.
148 void *(*stream_server)(void *);
151 * Accept a stream created by stream_server
153 int (*stream_accept)(void *);
156 * Get a stream and connect it to a remote given a security handle and a
157 * stream id. This function returns a object describing the stream. The
158 * first member of this object MUST be a security_stream_t, because it will
161 void *(*stream_client)(void *, int);
164 * Close a stream opened with stream_server or stream_client
166 void (*stream_close)(void *);
169 * Authenticate a stream.
171 int (*stream_auth)(void *);
174 * Return a numeric id for a stream. This is to be used by stream_client
175 * on the other end of the connection to connect to this stream.
177 int (*stream_id)(void *);
182 int (*stream_write)(void *, const void *, size_t);
185 * Read asyncronously from a stream. Only one request can exist
188 void (*stream_read)(void *, void (*)(void *, void *, ssize_t), void *);
191 * Read syncronously from a stream.
193 ssize_t (*stream_read_sync)(void *, void **);
196 * Cancel a stream read request
198 void (*stream_read_cancel)(void *);
200 void (*close_connection)(void *, char *);
202 int (*data_encrypt)(void *, void *, ssize_t, void **, ssize_t *);
203 int (*data_decrypt)(void *, void *, ssize_t, void **, ssize_t *);
206 /* Given a security type ("KRB4", "BSD", "SSH", etc), returns a pointer to that
207 * type's security_driver_t, or NULL if no driver exists. */
208 const security_driver_t *security_getdriver(const char *);
215 * This structure is a handle to a connection to a host for transmission
216 * of protocol packets (pkt_t's). The underlying security type defines
217 * the actual protocol and transport.
219 * This handle is reference counted so that it can be used inside of
220 * security streams after it has been closed by our callers.
222 typedef struct security_handle {
223 const security_driver_t *driver;
227 /* void security_connect(
228 * const security_driver_t *driver,
229 * const char *hostname,
230 * char *(*conf_fn)(char *, void *),
231 * void (*fn)(void *, security_handle_t *, security_status_t),
235 * Given a security driver, and a hostname, calls back with a security_handle_t
236 * that can be used to communicate with that host. The status arg to the
237 * callback is reflects the success of the request. Error messages can be had
238 * via security_geterror(). The conf_fn is used to determine configuration
239 * information, with its second argument being the datap. If conf_fn is NULL,
240 * no configuration information is available.
242 #define security_connect(driver, hostname, conf_fn, fn, arg, datap) \
243 (*(driver)->connect)(hostname, conf_fn, fn, arg, datap)
245 /* void security_accept(
246 * const security_driver_t *driver,
247 * char *(*conf_fn)(char *, void *),
250 * void (*fn)(security_handle_t *, pkt_t *),
253 * Given a security driver, an input file descriptor, and an output file
254 * descriptor, and a callback, when new connections are detected on the given
255 * file descriptors, the function is called with a newly created security
256 * handle and the initial packet received. This is amandad's interface for
257 * accepting incoming connections from the Amanda server. The file descriptors
258 * are typically 0 and 1 (stdin/stdout). This function uses the event
259 * interface, and only works properly when event_loop() is called later in the
262 #define security_accept(driver, conf_fn, in, out, fn, datap) \
263 (*(driver)->accept)(driver, conf_fn, in, out, fn, datap)
265 /* char *security_get_authenticated_peer_name(
266 * security_handle_t *handle);
268 * Returns the fully qualified, authenticated hostname of the peer, or
269 * "localhost" for a local system. The string is statically allocated and need
270 * not be freed. The string will never be NULL, but may be an empty string if
271 * the remote identity is not known, not defined, or could not be
274 #define security_get_authenticated_peer_name(handle) \
275 (*(handle)->driver->get_authenticated_peer_name)(handle)
277 /* Closes a security stream created by a security_connect() or
278 * security_accept() and frees up resources associated with it. */
279 void security_close(security_handle_t *);
281 /* ssize_t security_sendpkt(security_handle_t *, const pkt_t *);
283 * Transmits a pkt_t over a security handle. Returns 0 on success, or negative
284 * on error. A descriptive error message can be obtained via
285 * security_geterror(). */
286 #define security_sendpkt(handle, pkt) \
287 (*(handle)->driver->sendpkt)(handle, pkt)
289 /* void security_recvpkt(
290 * security_handle_t *handle,
291 * void (*fn)(void *, pkt_t *, security_status_t),
295 * Requests that when incoming packets arrive for this handle, the given
296 * function is called with the given argument, the received packet, and the
297 * status of the reception. If a packet does not arrive within the number of
298 * seconds specified in the 'timeout' argument, RECV_TIMEOUT is passed in the
299 * status argument of the timeout. On receive error, the callback's status
300 * argument will be set to RECV_ERROR. An error message can be retrieved via
301 * security_geterror(). On successful reception, RECV_OK will be passed in the
302 * status argument, and the pkt argument will point to a valid packet. This
303 * function uses the event interface. Callbacks will only be generated when
304 * event_loop() is called. */
305 #define security_recvpkt(handle, fn, arg, timeout) \
306 (*(handle)->driver->recvpkt)(handle, fn, arg, timeout)
308 /* void security_recvpkt_cancel(security_handle_t *);
310 * Cancels a previous recvpkt request for this handle. */
311 #define security_recvpkt_cancel(handle) \
312 (*(handle)->driver->recvpkt_cancel)(handle)
314 /* const char *security_geterror(security_handle_t *);
316 * Returns a descriptive error message for the last error condition on this
318 #define security_geterror(handle) ((handle)->error)
320 /* Sets the string that security_geterror() returns. For use by security
322 void security_seterror(security_handle_t *, const char *, ...)
325 /* Initializes a security_handle_t. This is meant to be called only by security
326 * drivers to initialize the common part of a newly allocated
327 * security_handle_t. */
328 void security_handleinit(security_handle_t *, const security_driver_t *);
335 * This structure is a handle to a stream connection to a host for
336 * transmission of random data such as dumps or index data.
338 typedef struct security_stream {
339 const security_driver_t *driver;
343 /* Initializes a security_stream_t. This is meant to be called only by security
344 * drivers to initialize the common part of a newly allocated
345 * security_stream_t. */
346 void security_streaminit(security_stream_t *, const security_driver_t *);
348 /* const char *security_stream_geterror(security_stream_t *);
350 * Returns a descriptive error message for the last error condition on this
352 #define security_stream_geterror(stream) ((stream)->error)
354 /* Sets the string that security_stream_geterror() returns. */
355 void security_stream_seterror(security_stream_t *, const char *, ...)
358 /* security_stream_t *security_stream_server(security_handle_t *);
360 * Creates the server end of a security stream, and will prepare to receive a
361 * connection from the host on the other end of the security handle passed.
362 * Returns a security_stream_t on success, and NULL on error. Error messages
363 * can be obtained by calling security_geterror() on the security handle
364 * associated with this stream. */
365 #define security_stream_server(handle) \
366 (*(handle)->driver->stream_server)(handle)
368 /* int security_stream_accept(security_stream_t *);
370 * Given a security stream created by security_stream_server, blocks until a
371 * connection is made from the remote end. After calling stream_server,
372 * stream_accept must be called on the stream before it is fully connected.
373 * Returns 0 on success, and -1 on error. Error messages can be obtained by
374 * calling security_stream_geterror().
376 #define security_stream_accept(stream) \
377 (*(stream)->driver->stream_accept)(stream)
379 /* security_stream_t *security_stream_client(security_handle_t *, int);
381 * Creates the client end of a security stream, and connects it to the machine
382 * on the other end of the security handle. The 'id' argument identifies which
383 * stream on the other end to connect to, and should have come from
384 * security_stream_id on the other end of the connection. Returns a
385 * security_stream_t on success, and NULL on error. Error messages can be
386 * obtained by calling security_geterror() on the security handle associated
387 * with this stream. */
388 #define security_stream_client(handle, id) \
389 (*(handle)->driver->stream_client)(handle, id)
391 /* Closes a security stream and frees up resources associated with it. */
392 void security_stream_close(security_stream_t *);
394 /* int security_stream_auth(security_stream_t *);
396 * Authenticate a connected security stream. This should be called by the
397 * target after security_stream_accept returns successfully, and by the client
398 * after security_stream_connect returns successfullly. Returns 0 on success,
399 * and -1 on error. Error messages can be obtained by calling
400 * security_stream_geterror().
402 #define security_stream_auth(stream) \
403 (*(stream)->driver->stream_auth)(stream)
405 /* int security_stream_id(security_stream_t *);
407 * Returns an identifier which can be used to connect to this security stream
408 * with security_stream_client(). Typical usage is for one end of a connection
409 * to create a stream with security_stream_server(), and then transmit the id
410 * for that stream to the other side. The other side will then connect to that
411 * id with security_stream_client(). */
412 #define security_stream_id(stream) \
413 (*(stream)->driver->stream_id)(stream)
415 /* int security_stream_write(security_stream_t *, const void *, size_t);
417 * Writes a chunk of data to the security stream. Returns 0 on success, or
418 * negative on error. Error messages can be obtained by calling
419 * security_stream_geterror().
421 #define security_stream_write(stream, buf, size) \
422 (*(stream)->driver->stream_write)(stream, buf, size)
424 /* void security_stream_read(
425 * security_stream_t *stream,
426 * void (*fn)(void *, void *, size_t),
429 * Requests that when data is ready to be read on this stream, the given
430 * function is called with the given arg, a buffer full of data, and the size
431 * of that buffer. On error, the bufsize will be negative. An error message can
432 * be retrieved by calling security_stream_geterror(). This function uses the
433 * event interface. Callbacks will only be generated while in event_loop(). */
434 #define security_stream_read(stream, fn, arg) \
435 (*(stream)->driver->stream_read)(stream, fn, arg)
437 /* void security_stream_read_sync(security_stream_t *, void **);
439 * Return a buffer of data read from the stream. This function will block until
440 * something can be read, but other event will be fired. A pointer to the data
441 * is returned in *buf and the size of the buffer is returned. On error, the
442 * size will be negative. An error message can be retrieved by calling
443 * security_stream_geterror(). This function uses the event interface. */
444 #define security_stream_read_sync(stream, buf) \
445 (*(stream)->driver->stream_read_sync)(stream, buf)
447 /* void security_stream_read_cancel(security_stream_t *);
449 * Cancels a previous read request. */
450 #define security_stream_read_cancel(stream) \
451 (*(stream)->driver->stream_read_cancel)(stream)
453 /* void security_close_connection(security_handle_t *, hostname *);
455 * Close a security handle, freeing associated resources. The hostname
456 * argument is ignored. */
457 #define security_close_connection(handle, hostname) \
458 (*(handle)->driver->close_connection)(handle, hostname)
460 #endif /* SECURITY_H */