hammer2 - Messaging layer separation work part 2
[dragonfly.git] / lib / libdmsg / dmsg.h
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 /***************************************************************************
55  *                              CRYPTO HANDSHAKE                           *
56  ***************************************************************************
57  *
58  * The initial public-key exchange is implementing by transmitting a
59  * 512-byte buffer to the other side in a symmetrical fashion.  This
60  * buffer contains the following:
61  *
62  * (1) A random session key.  512 bits is specified.  We use aes_256_cbc()
63  *     and initialize the key with the first 256 bits and the iv[] with
64  *     the second.  Note that the transmitted and received session
65  *     keys are XOR'd together to create the session key used for
66  *     communications (so even if the verifier is compromised the session
67  *     will still be gobbly gook if the public key has not been completely
68  *     broken).
69  *
70  * (2) A verifier to determine that the decode was successful.  It encodes
71  *     an XOR of each group of 4 bytes from the session key.
72  *
73  * (3) Additional configuration and additional random data.
74  *
75  *     - The hammer2 message header magic for endian detect
76  *
77  *     - The hammer2 protocol version.  The two sides agree on the
78  *       smaller of the two.
79  *
80  *     - All unused fields (junk*) are filled with random data.
81  *
82  * This structure must be exactly 512 bytes and expects to use 256-byte
83  * RSA keys.
84  */
85 struct dmsg_handshake {
86         char pad1[8];           /* 000 */
87         uint16_t magic;         /* 008 DMSG_HDR_MAGIC for endian detect */
88         uint16_t version;       /* 00A hammer2 protocol version */
89         uint32_t flags;         /* 00C protocol extension flags */
90         uint8_t sess[64];       /* 010 512-bit session key */
91         uint8_t verf[16];       /* 050 verifier = ~sess */
92         char quickmsg[32];      /* 060 reason for connecting */
93         char junk080[128];      /* 080-0FF */
94         char pad2[8];           /* 100-107 */
95         char junk100[256-8];    /* 108-1FF */
96 };
97
98 typedef struct dmsg_handshake dmsg_handshake_t;
99
100
101 #define DMSG_CRYPTO_CHUNK_SIZE          DMSG_ALIGN
102 #define DMSG_MAX_IV_SIZE                32
103
104 #define DMSG_CRYPTO_GCM_IV_FIXED_SIZE   4
105 #define DMSG_CRYPTO_GCM_IV_SIZE         12
106 #define DMSG_CRYPTO_GCM_KEY_SIZE        32
107 #define DMSG_CRYPTO_GCM_TAG_SIZE        16
108
109 #define DMSG_CRYPTO_ALGO_GCM_IDX        0
110
111 #define DMSG_CRYPTO_ALGO                DMSG_CRYPTO_ALGO_GCM_IDX
112
113 /*
114  * master service thread info
115  */
116 struct dmsg_master_service_info {
117         int     fd;
118         int     detachme;
119 };
120
121 typedef struct dmsg_master_service_info dmsg_master_service_info_t;
122
123 /***************************************************************************
124  *                              LOW LEVEL MESSAGING                        *
125  ***************************************************************************
126  *
127  * dmsg_msg - A standalone copy of a message, typically referenced by
128  *               or embedded in other structures, or used with I/O queues.
129  *
130  * These structures are strictly temporary, so they do not have to be
131  * particularly optimized for size.  All possible message headers are
132  * directly embedded (any), and the message may contain a reference
133  * to allocated auxillary data.  The structure is recycled quite often
134  * by a connection.
135  *
136  * This structure is typically not used for storing persistent message
137  * state (see dmsg_persist for that).
138  */
139 struct dmsg_iocom;
140 struct dmsg_persist;
141 struct dmsg_state;
142 struct dmsg_router;
143 struct dmsg_msg;
144
145 TAILQ_HEAD(dmsg_state_queue, dmsg_state);
146 TAILQ_HEAD(dmsg_msg_queue, dmsg_msg);
147 RB_HEAD(dmsg_state_tree, dmsg_state);
148 RB_HEAD(dmsg_router_tree, dmsg_router);
149
150 struct h2span_link;
151 struct h2span_relay;
152 struct h2span_conn;
153
154 struct dmsg_state {
155         RB_ENTRY(dmsg_state) rbnode;            /* indexed by msgid */
156         struct dmsg_iocom *iocom;
157         struct dmsg_router *router;             /* if routed */
158         uint32_t        txcmd;                  /* mostly for CMDF flags */
159         uint32_t        rxcmd;                  /* mostly for CMDF flags */
160         uint64_t        msgid;                  /* {spanid,msgid} uniq */
161         int             flags;
162         int             error;
163         struct dmsg_msg *msg;
164         void (*func)(struct dmsg_msg *);
165         union {
166                 void *any;
167                 struct h2span_link *link;
168                 struct h2span_conn *conn;
169                 struct h2span_relay *relay;
170         } any;
171 };
172
173 #define DMSG_STATE_INSERTED     0x0001
174 #define DMSG_STATE_DYNAMIC      0x0002
175 #define DMSG_STATE_NODEID       0x0004          /* manages a node id */
176
177 struct dmsg_msg {
178         TAILQ_ENTRY(dmsg_msg) qentry;
179         struct dmsg_router *router;
180         struct dmsg_state *state;
181         size_t          hdr_size;
182         size_t          aux_size;
183         char            *aux_data;
184         dmsg_any_t      any;
185 };
186
187 typedef struct dmsg_state dmsg_state_t;
188 typedef struct dmsg_msg dmsg_msg_t;
189 typedef struct dmsg_msg_queue dmsg_msg_queue_t;
190
191 int dmsg_state_cmp(dmsg_state_t *state1, dmsg_state_t *state2);
192 RB_PROTOTYPE(dmsg_state_tree, dmsg_state, rbnode, dmsg_state_cmp);
193
194 /*
195  * dmsg_ioq - An embedded component of dmsg_conn, holds state
196  * for the buffering and parsing of incoming and outgoing messages.
197  *
198  * cdx - beg  - processed buffer data, encrypted or decrypted
199  * end - cdn  - unprocessed buffer data not yet encrypted or decrypted
200  */
201 struct dmsg_ioq {
202         enum { DMSG_MSGQ_STATE_HEADER1,
203                DMSG_MSGQ_STATE_HEADER2,
204                DMSG_MSGQ_STATE_AUXDATA1,
205                DMSG_MSGQ_STATE_AUXDATA2,
206                DMSG_MSGQ_STATE_ERROR } state;
207         size_t          fifo_beg;               /* buffered data */
208         size_t          fifo_cdx;               /* cdx-beg processed */
209         size_t          fifo_cdn;               /* end-cdn unprocessed */
210         size_t          fifo_end;
211         size_t          hbytes;                 /* header size */
212         size_t          abytes;                 /* aux_data size */
213         int             error;
214         int             seq;                    /* salt sequencer */
215         int             msgcount;
216         EVP_CIPHER_CTX  ctx;
217         char            iv[DMSG_MAX_IV_SIZE]; /* encrypt or decrypt iv[] */
218         dmsg_msg_t      *msg;
219         dmsg_msg_queue_t msgq;
220         char            buf[DMSG_BUF_SIZE];     /* staging buffer */
221 };
222
223 typedef struct dmsg_ioq dmsg_ioq_t;
224
225 #define DMSG_IOQ_ERROR_SYNC             1       /* bad magic / out of sync */
226 #define DMSG_IOQ_ERROR_EOF              2       /* unexpected EOF */
227 #define DMSG_IOQ_ERROR_SOCK             3       /* read() error on socket */
228 #define DMSG_IOQ_ERROR_FIELD            4       /* invalid field */
229 #define DMSG_IOQ_ERROR_HCRC             5       /* core header crc bad */
230 #define DMSG_IOQ_ERROR_XCRC             6       /* ext header crc bad */
231 #define DMSG_IOQ_ERROR_ACRC             7       /* aux data crc bad */
232 #define DMSG_IOQ_ERROR_STATE            8       /* bad state */
233 #define DMSG_IOQ_ERROR_NOPEER           9       /* bad socket peer */
234 #define DMSG_IOQ_ERROR_NORKEY           10      /* no remote keyfile found */
235 #define DMSG_IOQ_ERROR_NOLKEY           11      /* no local keyfile found */
236 #define DMSG_IOQ_ERROR_KEYXCHGFAIL      12      /* key exchange failed */
237 #define DMSG_IOQ_ERROR_KEYFMT           13      /* key file format problem */
238 #define DMSG_IOQ_ERROR_BADURANDOM       14      /* /dev/urandom is bad */
239 #define DMSG_IOQ_ERROR_MSGSEQ           15      /* message sequence error */
240 #define DMSG_IOQ_ERROR_EALREADY         16      /* ignore this message */
241 #define DMSG_IOQ_ERROR_TRANS            17      /* state transaction issue */
242 #define DMSG_IOQ_ERROR_IVWRAP           18      /* IVs exhaused */
243 #define DMSG_IOQ_ERROR_MACFAIL          19      /* MAC of encr alg failed */
244 #define DMSG_IOQ_ERROR_ALGO             20      /* Misc. encr alg error */
245
246 #define DMSG_IOQ_MAXIOVEC    16
247
248 /*
249  * dmsg_router - governs the routing of a message.  Passed into
250  *                  dmsg_msg_write.
251  *
252  * The router is either connected to an iocom (socket) directly, or
253  * connected to a SPAN transaction (h2span_link structure for outgoing)
254  * or to a SPAN transaction (h2span_relay structure for incoming).
255  */
256 struct dmsg_router {
257         RB_ENTRY(dmsg_router) rbnode;   /* indexed by target */
258         struct dmsg_iocom *iocom;
259         struct h2span_link   *link;             /* may be NULL */
260         struct h2span_relay  *relay;            /* may be NULL */
261         void    (*signal_callback)(struct dmsg_router *);
262         void    (*rcvmsg_callback)(struct dmsg_msg *);
263         void    (*altmsg_callback)(struct dmsg_iocom *);
264         void    (*dbgmsg_callback)(dmsg_msg_t *msg);
265         struct dmsg_state_tree staterd_tree; /* active messages */
266         struct dmsg_state_tree statewr_tree; /* active messages */
267         dmsg_msg_queue_t txmsgq;                /* tx msgq from remote */
268         uint64_t        target;                 /* for routing */
269         int             flags;
270         int             refs;                   /* refs prevent destruction */
271 };
272
273 #define DMSG_ROUTER_CONNECTED           0x0001  /* on global RB tree */
274 #define DMSG_ROUTER_DELETED             0x0002  /* parent structure destroyed */
275
276 typedef struct dmsg_router dmsg_router_t;
277
278 int dmsg_router_cmp(dmsg_router_t *router1, dmsg_router_t *router2);
279 RB_PROTOTYPE(dmsg_router_tree, dmsg_router, rbnode, dmsg_router_cmp);
280
281 /*
282  * dmsg_iocom - governs a messaging stream connection
283  */
284 struct dmsg_iocom {
285         dmsg_ioq_t      ioq_rx;
286         dmsg_ioq_t      ioq_tx;
287         dmsg_msg_queue_t freeq;         /* free msgs hdr only */
288         dmsg_msg_queue_t freeq_aux;             /* free msgs w/aux_data */
289         int     sock_fd;                        /* comm socket or pipe */
290         int     alt_fd;                         /* thread signal, tty, etc */
291         int     wakeupfds[2];                   /* pipe wakes up iocom thread */
292         int     flags;
293         int     rxmisc;
294         int     txmisc;
295         struct dmsg_router *router;
296         pthread_mutex_t mtx;                    /* mutex for state*tree/rmsgq */
297 };
298
299 typedef struct dmsg_iocom dmsg_iocom_t;
300
301 #define DMSG_IOCOMF_EOF         0x00000001      /* EOF or ERROR on desc */
302 #define DMSG_IOCOMF_RREQ        0x00000002      /* request read-data event */
303 #define DMSG_IOCOMF_WREQ        0x00000004      /* request write-avail event */
304 #define DMSG_IOCOMF_RWORK       0x00000008      /* immediate work pending */
305 #define DMSG_IOCOMF_WWORK       0x00000010      /* immediate work pending */
306 #define DMSG_IOCOMF_PWORK       0x00000020      /* immediate work pending */
307 #define DMSG_IOCOMF_ARWORK      0x00000040      /* immediate work pending */
308 #define DMSG_IOCOMF_AWWORK      0x00000080      /* immediate work pending */
309 #define DMSG_IOCOMF_SWORK       0x00000100      /* immediate work pending */
310 #define DMSG_IOCOMF_CRYPTED     0x00000200      /* encrypt enabled */
311
312 /*
313  * Crypto algorithm table and related typedefs.
314  */
315
316 typedef int (*algo_init_fn)(dmsg_ioq_t *, char *, int, char *, int, int);
317 typedef int (*algo_enc_fn)(dmsg_ioq_t *, char *, char *, int, int *);
318 typedef int (*algo_dec_fn)(dmsg_ioq_t *, char *, char *, int, int *);
319
320 struct crypto_algo {
321         const char      *name;
322         int             keylen;
323         int             taglen;
324         algo_init_fn    init;
325         algo_enc_fn     enc_chunk;
326         algo_dec_fn     dec_chunk;
327 };
328
329 /*
330  * icrc
331  */
332 uint32_t dmsg_icrc32(const void *buf, size_t size);
333 uint32_t dmsg_icrc32c(const void *buf, size_t size, uint32_t crc);
334
335 /*
336  * debug
337  */
338 const char *dmsg_basecmd_str(uint32_t cmd);
339 const char *dmsg_msg_str(dmsg_msg_t *msg);
340
341 /*
342  * subs
343  */
344 void *dmsg_alloc(size_t bytes);
345 void dmsg_free(void *ptr);
346 const char *dmsg_uuid_to_str(uuid_t *uuid, char **strp);
347 int dmsg_connect(const char *hostname);
348
349 /*
350  * Msg support functions
351  */
352 void dmsg_bswap_head(dmsg_hdr_t *head);
353 void dmsg_ioq_init(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
354 void dmsg_ioq_done(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
355 void dmsg_iocom_init(dmsg_iocom_t *iocom, int sock_fd, int alt_fd,
356                         void (*state_func)(dmsg_router_t *),
357                         void (*rcvmsg_func)(dmsg_msg_t *),
358                         void (*altmsg_func)(dmsg_iocom_t *));
359 void dmsg_router_restate(dmsg_router_t *router,
360                         void (*state_func)(dmsg_router_t *),
361                         void (*rcvmsg_func)(dmsg_msg_t *),
362                         void (*altmsg_func)(dmsg_iocom_t *));
363 void dmsg_router_signal(dmsg_router_t *router);
364 void dmsg_iocom_done(dmsg_iocom_t *iocom);
365 dmsg_msg_t *dmsg_msg_alloc(dmsg_router_t *router,
366                         size_t aux_size, uint32_t cmd,
367                         void (*func)(dmsg_msg_t *), void *data);
368 void dmsg_msg_reply(dmsg_msg_t *msg, uint32_t error);
369 void dmsg_msg_result(dmsg_msg_t *msg, uint32_t error);
370 void dmsg_state_reply(dmsg_state_t *state, uint32_t error);
371
372 void dmsg_msg_free(dmsg_msg_t *msg);
373
374 void dmsg_iocom_core(dmsg_iocom_t *iocom);
375 dmsg_msg_t *dmsg_ioq_read(dmsg_iocom_t *iocom);
376 void dmsg_msg_write(dmsg_msg_t *msg);
377
378 void dmsg_iocom_drain(dmsg_iocom_t *iocom);
379 void dmsg_iocom_flush1(dmsg_iocom_t *iocom);
380 void dmsg_iocom_flush2(dmsg_iocom_t *iocom);
381
382 void dmsg_state_cleanuprx(dmsg_iocom_t *iocom, dmsg_msg_t *msg);
383 void dmsg_state_free(dmsg_state_t *state);
384
385 dmsg_router_t *dmsg_router_alloc(void);
386 void dmsg_router_connect(dmsg_router_t *router);
387 void dmsg_router_disconnect(dmsg_router_t **routerp);
388
389 /*
390  * Msg protocol functions
391  */
392 void dmsg_msg_lnk_signal(dmsg_router_t *router);
393 void dmsg_msg_lnk(dmsg_msg_t *msg);
394 void dmsg_msg_dbg(dmsg_msg_t *msg);
395 void dmsg_shell_tree(dmsg_router_t *router, char *cmdbuf __unused);
396
397 /*
398  * Crypto functions
399  */
400 void dmsg_crypto_setup(void);
401 void dmsg_crypto_negotiate(dmsg_iocom_t *iocom);
402 void dmsg_crypto_decrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
403 int dmsg_crypto_encrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq,
404                         struct iovec *iov, int n, size_t *nactp);
405
406 /*
407  * Service daemon functions
408  */
409 void *dmsg_master_service(void *data);
410 void dmsg_router_printf(dmsg_router_t *router, const char *ctl, ...);
411
412 extern int DMsgDebugOpt;