xref: /dragonfly/lib/libdmsg/dmsg.h (revision e5a92d33)
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/types.h>
36 #include <sys/queue.h>
37 #include <sys/tree.h>
38 #include <sys/dmsg.h>
39 
40 #include <pthread.h>
41 
42 #if 0
43 #include <openssl/rsa.h>	/* public/private key functions */
44 #include <openssl/pem.h>	/* public/private key file load */
45 #endif
46 #include <openssl/err.h>
47 #include <openssl/evp.h>	/* aes_256_cbc functions */
48 
49 #define DMSG_DEFAULT_DIR	"/etc/hammer2"
50 #define DMSG_PATH_REMOTE	DMSG_DEFAULT_DIR "/remote"
51 
52 #define DMSG_LISTEN_PORT	987
53 
54 #define dm_printf(level, ctl, ...)		\
55 	if (DMsgDebugOpt >= (level))		\
56 		fprintf(stderr, "libdmsg: " ctl, __VA_ARGS__)
57 #define dmx_printf(level, ctl, ...)		\
58 	if (DMsgDebugOpt >= (level))		\
59 		fprintf(stderr, ctl, __VA_ARGS__)
60 #define dmio_printf(iocom, level, ctl, ...)	\
61 	if (DMsgDebugOpt >= (level))		\
62 		fprintf(stderr, "libdmsg: " ctl, __VA_ARGS__)
63 
64 
65 /***************************************************************************
66  *				CRYPTO HANDSHAKE			   *
67  ***************************************************************************
68  *
69  * The initial public-key exchange is implementing by transmitting a
70  * 512-byte buffer to the other side in a symmetrical fashion.  This
71  * buffer contains the following:
72  *
73  * (1) A random session key.  512 bits is specified.  We use aes_256_cbc()
74  *     and initialize the key with the first 256 bits and the iv[] with
75  *     the second.  Note that the transmitted and received session
76  *     keys are XOR'd together to create the session key used for
77  *     communications (so even if the verifier is compromised the session
78  *     will still be gobbly gook if the public key has not been completely
79  *     broken).
80  *
81  * (2) A verifier to determine that the decode was successful.  It encodes
82  *     an XOR of each group of 4 bytes from the session key.
83  *
84  * (3) Additional configuration and additional random data.
85  *
86  *     - The hammer2 message header magic for endian detect
87  *
88  *     - The hammer2 protocol version.  The two sides agree on the
89  *	 smaller of the two.
90  *
91  *     - All unused fields (junk*) are filled with random data.
92  *
93  * This structure must be exactly 512 bytes and expects to use 256-byte
94  * RSA keys.
95  */
96 struct dmsg_handshake {
97 	char pad1[8];		/* 000 */
98 	uint16_t magic;		/* 008 DMSG_HDR_MAGIC for endian detect */
99 	uint16_t version;	/* 00A hammer2 protocol version */
100 	uint32_t flags;		/* 00C protocol extension flags */
101 	uint8_t sess[64];	/* 010 512-bit session key */
102 	uint8_t verf[16];	/* 050 verifier = ~sess */
103 	char quickmsg[32];	/* 060 reason for connecting */
104 	char junk080[128];	/* 080-0FF */
105 	char pad2[8];		/* 100-107 */
106 	char junk100[256-8];	/* 108-1FF */
107 };
108 
109 typedef struct dmsg_handshake dmsg_handshake_t;
110 
111 
112 #define DMSG_CRYPTO_CHUNK_SIZE		DMSG_ALIGN
113 #define DMSG_MAX_IV_SIZE		32
114 
115 #define DMSG_CRYPTO_GCM_IV_FIXED_SIZE	4
116 #define DMSG_CRYPTO_GCM_IV_SIZE		12
117 #define DMSG_CRYPTO_GCM_KEY_SIZE	32
118 #define DMSG_CRYPTO_GCM_TAG_SIZE	16
119 
120 #define DMSG_CRYPTO_ALGO_GCM_IDX	0
121 
122 #define DMSG_CRYPTO_ALGO		DMSG_CRYPTO_ALGO_GCM_IDX
123 
124 /***************************************************************************
125  *				LOW LEVEL MESSAGING			   *
126  ***************************************************************************
127  *
128  * dmsg_msg - A standalone copy of a message, typically referenced by
129  *		 or embedded in other structures, or used with I/O queues.
130  *
131  * These structures are strictly temporary, so they do not have to be
132  * particularly optimized for size.  All possible message headers are
133  * directly embedded (any), and the message may contain a reference
134  * to allocated auxillary data.  The structure is recycled quite often
135  * by a connection.
136  */
137 struct dmsg_iocom;
138 struct dmsg_state;
139 struct dmsg_msg;
140 
141 TAILQ_HEAD(dmsg_state_queue, dmsg_state);
142 TAILQ_HEAD(dmsg_msg_queue, dmsg_msg);
143 RB_HEAD(dmsg_state_tree, dmsg_state);
144 
145 struct h2span_link;
146 struct h2span_relay;
147 struct h2span_conn;
148 
149 /*
150  * This represents a media, managed by LNK_CONN connection state
151  */
152 TAILQ_HEAD(dmsg_media_queue, dmsg_media);
153 
154 struct dmsg_media {
155 	TAILQ_ENTRY(dmsg_media) entry;
156 	uuid_t  media_id;
157 	int     refs;
158 	void	*usrhandle;
159 };
160 
161 typedef struct dmsg_media dmsg_media_t;
162 
163 /*
164  * The state structure is ref-counted.  The iocom cannot go away while
165  * state structures are active.  However, the related h2span_* linkages
166  * can be destroyed and NULL'd out if the state is terminated in both
167  * directions.
168  */
169 struct dmsg_state {
170 	RB_ENTRY(dmsg_state) rbnode;		/* by state->msgid */
171 	struct dmsg_state	*scan;		/* scan check */
172 	TAILQ_HEAD(, dmsg_state) subq;		/* active stacked states */
173 	TAILQ_ENTRY(dmsg_state) entry;		/* on parent subq */
174 	struct dmsg_iocom *iocom;
175 	struct dmsg_state *parent;		/* transaction stacking */
176 	struct dmsg_state *relay;		/* routing */
177 	uint32_t	icmd;			/* command creating state */
178 	uint32_t	txcmd;			/* mostly for CMDF flags */
179 	uint32_t	rxcmd;			/* mostly for CMDF flags */
180 	uint64_t	msgid;
181 	int		flags;
182 	int		error;
183 	unsigned int	refs;			/* prevent destruction */
184 	void (*func)(struct dmsg_msg *);
185 	union {
186 		void *any;
187 		struct h2span_link *link;
188 		struct h2span_conn *conn;
189 		struct h2span_relay *relay;
190 	} any;
191 	dmsg_media_t	*media;
192 };
193 
194 #define DMSG_STATE_SUBINSERTED	0x0001
195 #define DMSG_STATE_DYNAMIC	0x0002
196 #define DMSG_STATE_UNUSED0004	0x0004
197 #define DMSG_STATE_ABORTING	0x0008
198 #define DMSG_STATE_OPPOSITE	0x0010		/* initiated by other end */
199 #define DMSG_STATE_CIRCUIT	0x0020		/* LNK_SPAN special case */
200 #define DMSG_STATE_DYING	0x0040		/* indicates circuit failure */
201 #define DMSG_STATE_RBINSERTED	0x0080
202 #define DMSG_STATE_NEW		0x0400		/* defer abort processing */
203 #define DMSG_STATE_ROOT		0x8000		/* iocom->state0 */
204 
205 /*
206  * This is the core in-memory representation of a message structure.
207  * state is the local representation of the transactional state and
208  * will point to &iocom->state0 for non-transactional messages.
209  *
210  * Message headers are embedded while auxillary data is separately allocated.
211  * The 'any' portion of the message is allocated dynamically based on
212  * hdr_size.
213  */
214 struct dmsg_msg {
215 	TAILQ_ENTRY(dmsg_msg) qentry;
216 	struct dmsg_state *state;		/* message state */
217 	size_t		hdr_size;
218 	size_t		aux_size;
219 	char		*aux_data;
220 	uint32_t	tcmd;			/* easy-switch cmd */
221 	dmsg_any_t 	any;			/* must be last element */
222 };
223 
224 typedef struct dmsg_state dmsg_state_t;
225 typedef struct dmsg_msg dmsg_msg_t;
226 typedef struct dmsg_msg_queue dmsg_msg_queue_t;
227 
228 int dmsg_state_cmp(dmsg_state_t *state1, dmsg_state_t *state2);
229 RB_PROTOTYPE(dmsg_state_tree, dmsg_state, rbnode, dmsg_state_cmp);
230 
231 /*
232  * dmsg_ioq - An embedded component of dmsg_conn, holds state
233  * for the buffering and parsing of incoming and outgoing messages.
234  *
235  * cdx - beg  - processed buffer data, encrypted or decrypted
236  * end - cdn  - unprocessed buffer data not yet encrypted or decrypted
237  */
238 struct dmsg_ioq {
239 	enum { DMSG_MSGQ_STATE_HEADER1,
240 	       DMSG_MSGQ_STATE_HEADER2,
241 	       DMSG_MSGQ_STATE_AUXDATA1,
242 	       DMSG_MSGQ_STATE_AUXDATA2,
243 	       DMSG_MSGQ_STATE_ERROR } state;
244 	size_t		fifo_beg;		/* buffered data */
245 	size_t		fifo_cdx;		/* cdx-beg processed */
246 	size_t		fifo_cdn;		/* end-cdn unprocessed */
247 	size_t		fifo_end;
248 	size_t		hbytes;			/* header size */
249 	size_t		abytes;			/* aligned aux_data size */
250 	size_t		unaligned_aux_size;	/* actual aux_data size */
251 	int		error;
252 	int		seq;			/* salt sequencer */
253 	int		msgcount;
254 	EVP_CIPHER_CTX	ctx;
255 	char		iv[DMSG_MAX_IV_SIZE]; /* encrypt or decrypt iv[] */
256 	dmsg_msg_t	*msg;
257 	dmsg_msg_queue_t msgq;
258 	char		buf[DMSG_BUF_SIZE];	/* staging buffer */
259 };
260 
261 typedef struct dmsg_ioq dmsg_ioq_t;
262 
263 #define DMSG_IOQ_ERROR_SYNC		1	/* bad magic / out of sync */
264 #define DMSG_IOQ_ERROR_EOF		2	/* unexpected EOF */
265 #define DMSG_IOQ_ERROR_SOCK		3	/* read() error on socket */
266 #define DMSG_IOQ_ERROR_FIELD		4	/* invalid field */
267 #define DMSG_IOQ_ERROR_HCRC		5	/* core header crc bad */
268 #define DMSG_IOQ_ERROR_XCRC		6	/* ext header crc bad */
269 #define DMSG_IOQ_ERROR_ACRC		7	/* aux data crc bad */
270 #define DMSG_IOQ_ERROR_STATE		8	/* bad state */
271 #define DMSG_IOQ_ERROR_NOPEER		9	/* bad socket peer */
272 #define DMSG_IOQ_ERROR_NORKEY		10	/* no remote keyfile found */
273 #define DMSG_IOQ_ERROR_NOLKEY		11	/* no local keyfile found */
274 #define DMSG_IOQ_ERROR_KEYXCHGFAIL	12	/* key exchange failed */
275 #define DMSG_IOQ_ERROR_KEYFMT		13	/* key file format problem */
276 #define DMSG_IOQ_ERROR_BADURANDOM	14	/* /dev/urandom is bad */
277 #define DMSG_IOQ_ERROR_MSGSEQ		15	/* message sequence error */
278 #define DMSG_IOQ_ERROR_EALREADY		16	/* ignore this message */
279 #define DMSG_IOQ_ERROR_TRANS		17	/* state transaction issue */
280 #define DMSG_IOQ_ERROR_IVWRAP		18	/* IVs exhaused */
281 #define DMSG_IOQ_ERROR_MACFAIL		19	/* MAC of encr alg failed */
282 #define DMSG_IOQ_ERROR_ALGO		20	/* Misc. encr alg error */
283 #define DMSG_IOQ_ERROR_UNUSED21		21
284 #define DMSG_IOQ_ERROR_BAD_CIRCUIT	22	/* unconfigured circuit */
285 #define DMSG_IOQ_ERROR_UNUSED23		23
286 #define DMSG_IOQ_ERROR_ASSYM		24	/* Assymetric path */
287 
288 #define DMSG_IOQ_MAXIOVEC    16
289 
290 /*
291  * dmsg_iocom - governs a messaging stream connection
292  */
293 struct dmsg_iocom {
294 	char		*label;			/* label for error reporting */
295 	dmsg_ioq_t	ioq_rx;
296 	dmsg_ioq_t	ioq_tx;
297 	dmsg_state_t	state0;			/* root state for stacking */
298 	struct dmsg_state_tree  staterd_tree;   /* active transactions */
299 	struct dmsg_state_tree  statewr_tree;   /* active transactions */
300 	int	sock_fd;			/* comm socket or pipe */
301 	int	alt_fd;				/* thread signal, tty, etc */
302 	int	wakeupfds[2];			/* pipe wakes up iocom thread */
303 	unsigned int	flags;
304 	int	rxmisc;
305 	int	txmisc;
306 	void	(*signal_callback)(struct dmsg_iocom *);
307 	void	(*altmsg_callback)(struct dmsg_iocom *);
308 	void	(*rcvmsg_callback)(dmsg_msg_t *msg);
309 	void	(*usrmsg_callback)(dmsg_msg_t *msg, int unmanaged);
310 	dmsg_msg_queue_t txmsgq;		/* tx msgq from remote */
311 	struct h2span_conn *conn;		/* if LNK_CONN active */
312 	uint64_t	conn_msgid;		/* LNK_CONN circuit */
313 	pthread_mutex_t	mtx;			/* mutex for state*tree/rmsgq */
314 };
315 
316 typedef struct dmsg_iocom dmsg_iocom_t;
317 
318 #define DMSG_IOCOMF_EOF		0x00000001	/* EOF or ERROR on desc */
319 #define DMSG_IOCOMF_RREQ	0x00000002	/* request read-data event */
320 #define DMSG_IOCOMF_WREQ	0x00000004	/* request write-avail event */
321 #define DMSG_IOCOMF_RWORK	0x00000008	/* immediate work pending */
322 #define DMSG_IOCOMF_WWORK	0x00000010	/* immediate work pending */
323 #define DMSG_IOCOMF_PWORK	0x00000020	/* immediate work pending */
324 #define DMSG_IOCOMF_ARWORK	0x00000040	/* immediate work pending */
325 #define DMSG_IOCOMF_AWWORK	0x00000080	/* immediate work pending */
326 #define DMSG_IOCOMF_SWORK	0x00000100	/* immediate work pending */
327 #define DMSG_IOCOMF_CRYPTED	0x00000200	/* encrypt enabled */
328 #define DMSG_IOCOMF_CLOSEALT	0x00000400	/* close alt_fd */
329 
330 /*
331  * Crypto algorithm table and related typedefs.
332  */
333 typedef int (*algo_init_fn)(dmsg_ioq_t *, char *, int, char *, int, int);
334 typedef int (*algo_enc_fn)(dmsg_ioq_t *, char *, char *, int, int *);
335 typedef int (*algo_dec_fn)(dmsg_ioq_t *, char *, char *, int, int *);
336 
337 struct crypto_algo {
338 	const char	*name;
339 	int		keylen;
340 	int		taglen;
341 	algo_init_fn	init;
342 	algo_enc_fn	enc_chunk;
343 	algo_dec_fn	dec_chunk;
344 };
345 
346 /*
347  * Master service thread info
348  */
349 struct dmsg_master_service_info {
350 	int	fd;
351 	int	altfd;
352 	int	noclosealt;
353 	int	detachme;
354 	char	*label;
355 	void	*handle;
356 	void	(*altmsg_callback)(dmsg_iocom_t *iocom);
357 	void	(*usrmsg_callback)(dmsg_msg_t *msg, int unmanaged);
358 	void	(*exit_callback)(void *handle);
359 };
360 
361 typedef struct dmsg_master_service_info dmsg_master_service_info_t;
362 
363 struct iovec;	/* forward decl for dmsg_crypto_encrypt() prototype */
364 
365 /*
366  * node callbacks
367  */
368 #define DMSG_NODEOP_ADD		1
369 #define DMSG_NODEOP_DEL		2
370 
371 /*
372  * icrc
373  */
374 #define dmsg_icrc32(buf, size)		iscsi_crc32((buf), (size))
375 #define dmsg_icrc32c(buf, size, crc)	iscsi_crc32_ext((buf), (size), (crc))
376 
377 /*
378  * debug
379  */
380 const char *dmsg_basecmd_str(uint32_t cmd);
381 const char *dmsg_msg_str(dmsg_msg_t *msg);
382 
383 /*
384  * subs
385  */
386 void *dmsg_alloc(size_t bytes);
387 void dmsg_free(void *ptr);
388 const char *dmsg_uuid_to_str(uuid_t *uuid, char **strp);
389 const char *dmsg_peer_type_to_str(uint8_t type);
390 int dmsg_connect(const char *hostname);
391 
392 /*
393  * Msg support functions
394  */
395 void dmsg_bswap_head(dmsg_hdr_t *head);
396 void dmsg_ioq_init(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
397 void dmsg_ioq_done(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
398 void dmsg_iocom_init(dmsg_iocom_t *iocom, int sock_fd, int alt_fd,
399 			void (*state_func)(dmsg_iocom_t *iocom),
400 			void (*rcvmsg_func)(dmsg_msg_t *msg),
401 			void (*usrmsg_func)(dmsg_msg_t *msg, int unmanaged),
402 			void (*altmsg_func)(dmsg_iocom_t *iocom));
403 void dmsg_iocom_restate(dmsg_iocom_t *iocom,
404 			void (*state_func)(dmsg_iocom_t *iocom),
405 			void (*rcvmsg_func)(dmsg_msg_t *msg));
406 void dmsg_iocom_label(dmsg_iocom_t *iocom, const char *ctl, ...);
407 void dmsg_iocom_signal(dmsg_iocom_t *iocom);
408 void dmsg_iocom_done(dmsg_iocom_t *iocom);
409 dmsg_msg_t *dmsg_msg_alloc(dmsg_state_t *state, size_t aux_size,
410 			uint32_t cmd,
411 			void (*func)(dmsg_msg_t *), void *data);
412 dmsg_msg_t *dmsg_msg_alloc_locked(dmsg_state_t *state, size_t aux_size,
413 			uint32_t cmd,
414 			void (*func)(dmsg_msg_t *), void *data);
415 void dmsg_msg_reply(dmsg_msg_t *msg, uint32_t error);
416 void dmsg_msg_result(dmsg_msg_t *msg, uint32_t error);
417 void dmsg_state_reply(dmsg_state_t *state, uint32_t error);
418 void dmsg_state_result(dmsg_state_t *state, uint32_t error);
419 
420 void dmsg_msg_free(dmsg_msg_t *msg);
421 
422 void dmsg_iocom_core(dmsg_iocom_t *iocom);
423 dmsg_msg_t *dmsg_ioq_read(dmsg_iocom_t *iocom);
424 void dmsg_msg_write(dmsg_msg_t *msg);
425 
426 void dmsg_iocom_drain(dmsg_iocom_t *iocom);
427 void dmsg_iocom_flush1(dmsg_iocom_t *iocom);
428 void dmsg_iocom_flush2(dmsg_iocom_t *iocom);
429 
430 void dmsg_state_relay(dmsg_msg_t *msg);
431 void dmsg_state_cleanuprx(dmsg_iocom_t *iocom, dmsg_msg_t *msg);
432 void dmsg_state_hold(dmsg_state_t *state);
433 void dmsg_state_drop(dmsg_state_t *state);
434 
435 /*
436  * Msg protocol functions
437  */
438 void dmsg_msg_lnk_signal(dmsg_iocom_t *iocom);
439 void dmsg_msg_lnk(dmsg_msg_t *msg);
440 void dmsg_msg_dbg(dmsg_msg_t *msg);
441 void dmsg_shell_tree(dmsg_iocom_t *iocom, char *cmdbuf __unused);
442 int dmsg_debug_findspan(uint64_t msgid, dmsg_state_t **statep);
443 dmsg_state_t *dmsg_findspan(const char *label);
444 
445 
446 /*
447  * Crypto functions
448  */
449 void dmsg_crypto_setup(void);
450 void dmsg_crypto_negotiate(dmsg_iocom_t *iocom);
451 void dmsg_crypto_decrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
452 int dmsg_crypto_encrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq,
453 			struct iovec *iov, int n, size_t *nactp);
454 
455 /*
456  * Service daemon functions
457  */
458 void *dmsg_master_service(void *data);
459 void dmsg_printf(dmsg_iocom_t *iocom, const char *ctl, ...) __printflike(2, 3);
460 
461 extern int DMsgDebugOpt;
462