1/*-
2 * Copyright (c) 2012 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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 the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef	_AUDITDISTD_H_
31#define	_AUDITDISTD_H_
32
33#include <sys/param.h>
34#include <sys/queue.h>
35#include <sys/socket.h>
36
37#include <arpa/inet.h>
38
39#include <netinet/in.h>
40
41#include <dirent.h>
42#include <limits.h>
43#include <pthread.h>
44#include <stdbool.h>
45#include <stdint.h>
46
47#include <compat/compat.h>
48
49#include "proto.h"
50
51/*
52 * Version history:
53 * 0 - initial version
54 */
55#define	ADIST_VERSION	0
56
57#define	ADIST_ROLE_UNDEF	0
58#define	ADIST_ROLE_SENDER	1
59#define	ADIST_ROLE_RECEIVER	2
60
61#define	ADIST_USER			"auditdistd"
62#define	ADIST_TIMEOUT			20
63#define	ADIST_CONFIG			"/etc/security/auditdistd.conf"
64#define	ADIST_TCP_PORT			"7878"
65#define	ADIST_LISTEN_TLS_TCP4		"tls://0.0.0.0:" ADIST_TCP_PORT
66#define	ADIST_LISTEN_TLS_TCP6		"tls://[::]:" ADIST_TCP_PORT
67#define	ADIST_PIDFILE			"/var/run/auditdistd.pid"
68#define	ADIST_DIRECTORY_SENDER		"/var/audit/dist"
69#define	ADIST_DIRECTORY_RECEIVER	"/var/audit/remote"
70#define	ADIST_CERTFILE			"/etc/security/auditdistd.cert.pem"
71#define	ADIST_KEYFILE			"/etc/security/auditdistd.key.pem"
72
73#define	ADIST_ERROR_WRONG_ORDER		1
74#define	ADIST_ERROR_INVALID_NAME	2
75#define	ADIST_ERROR_OPEN_OLD		3
76#define	ADIST_ERROR_CREATE		4
77#define	ADIST_ERROR_OPEN		5
78#define	ADIST_ERROR_READ		6
79#define	ADIST_ERROR_WRITE		7
80#define	ADIST_ERROR_RENAME		8
81
82#define	ADIST_ADDRSIZE		1024
83#define	ADIST_HOSTSIZE		256
84#define	ADIST_PATHSIZE		256
85#define	ADIST_PASSWORDSIZE	128
86#define	ADIST_FINGERPRINTSIZE	256
87
88/* Number of seconds to sleep between reconnect retries or keepalive packets. */
89#define	ADIST_KEEPALIVE	10
90
91struct adist_listen {
92	/* Address to listen on. */
93	char	 adl_addr[ADIST_ADDRSIZE];
94	/* Protocol-specific data. */
95	struct proto_conn *adl_conn;
96	TAILQ_ENTRY(adist_listen) adl_next;
97};
98
99struct adist_config {
100	/* Our name. */
101	char	adc_name[ADIST_HOSTSIZE];
102	/* PID file path. */
103	char	adc_pidfile[PATH_MAX];
104	/* Connection timeout. */
105	int	adc_timeout;
106	/* Path to receiver's certificate file. */
107	char	adc_certfile[PATH_MAX];
108	/* Path to receiver's private key file. */
109	char	adc_keyfile[PATH_MAX];
110	/* List of addresses to listen on. */
111	TAILQ_HEAD(, adist_listen) adc_listen;
112	/* List of hosts. */
113	TAILQ_HEAD(, adist_host) adc_hosts;
114};
115
116#define	ADIST_COMPRESSION_NONE	0
117#define	ADIST_COMPRESSION_LZF	1
118
119#define	ADIST_CHECKSUM_NONE	0
120#define	ADIST_CHECKSUM_CRC32	1
121#define	ADIST_CHECKSUM_SHA256	2
122
123/*
124 * Structure that describes single host (either sender or receiver).
125 */
126struct adist_host {
127	/* Host name. */
128	char	adh_name[ADIST_HOSTSIZE];
129	/* Host role: ADIST_ROLE_{SENDER,RECEIVER}. */
130	int	adh_role;
131	/* Protocol version negotiated. */
132	int	adh_version;
133
134	/* Local address to bind to. */
135	char	adh_localaddr[ADIST_ADDRSIZE];
136	/* Address of the remote component. */
137	char	adh_remoteaddr[ADIST_ADDRSIZE];
138	/* Connection with remote host. */
139	struct proto_conn *adh_remote;
140	/* Connection was reestablished, reset the state. */
141	bool	adh_reset;
142
143	/*
144	 * Directory from which audit trail files should be send in
145	 * ADIST_ROLE_SENDER case or stored into in ADIST_ROLE_RECEIVER case.
146	 */
147	char	adh_directory[PATH_MAX];
148	/* Compression algorithm. Currently unused. */
149	int	adh_compression;
150	/* Checksum algorithm. Currently unused. */
151	int	adh_checksum;
152
153	/* Sender's password. */
154	char	adh_password[ADIST_PASSWORDSIZE];
155	/* Fingerprint of receiver's public key. */
156	char	adh_fingerprint[ADIST_FINGERPRINTSIZE];
157
158	/* PID of child worker process. 0 - no child. */
159	pid_t	adh_worker_pid;
160	/* Connection requests from sender to main. */
161	struct proto_conn *adh_conn;
162
163	/* Receiver-specific fields. */
164	char	 adh_trail_name[ADIST_PATHSIZE];
165	int	 adh_trail_fd;
166	int	 adh_trail_dirfd;
167	DIR	*adh_trail_dirfp;
168	/* Sender-specific fields. */
169	uint64_t adh_trail_offset;
170
171	/* Next resource. */
172	TAILQ_ENTRY(adist_host) adh_next;
173};
174
175#define	ADIST_BYTEORDER_UNDEFINED	0
176#define	ADIST_BYTEORDER_LITTLE_ENDIAN	1
177#define	ADIST_BYTEORDER_BIG_ENDIAN	2
178
179#if _BYTE_ORDER == _LITTLE_ENDIAN
180#define	ADIST_BYTEORDER	ADIST_BYTEORDER_LITTLE_ENDIAN
181#elif _BYTE_ORDER == _BIG_ENDIAN
182#define	ADIST_BYTEORDER	ADIST_BYTEORDER_BIG_ENDIAN
183#else
184#error Unknown byte order.
185#endif
186
187struct adpkt {
188	uint8_t		adp_byteorder;
189#define	ADIST_CMD_UNDEFINED	0
190#define	ADIST_CMD_OPEN		1
191#define	ADIST_CMD_APPEND	2
192#define	ADIST_CMD_CLOSE		3
193#define	ADIST_CMD_KEEPALIVE	4
194#define	ADIST_CMD_ERROR		5
195	uint8_t		adp_cmd;
196	uint64_t	adp_seq;
197	uint32_t	adp_datasize;
198	unsigned char	adp_data[0];
199} __packed;
200
201struct adreq {
202	int			adr_error;
203	TAILQ_ENTRY(adreq)	adr_next;
204	struct adpkt		adr_packet;
205};
206
207#define	adr_byteorder	adr_packet.adp_byteorder
208#define	adr_cmd		adr_packet.adp_cmd
209#define	adr_seq		adr_packet.adp_seq
210#define	adr_datasize	adr_packet.adp_datasize
211#define	adr_data	adr_packet.adp_data
212
213#define	ADPKT_SIZE(adreq)	(sizeof((adreq)->adr_packet) + (adreq)->adr_datasize)
214
215struct adrep {
216	uint8_t		adrp_byteorder;
217	uint64_t	adrp_seq;
218	uint16_t	adrp_error;
219} __packed;
220
221#define	ADIST_QUEUE_SIZE	16
222#define	ADIST_BUF_SIZE		65536
223
224#define	QUEUE_TAKE(adreq, list, timeout)	do {			\
225	mtx_lock(list##_lock);						\
226	if ((timeout) == 0) {						\
227		while (((adreq) = TAILQ_FIRST(list)) == NULL)		\
228			cv_wait(list##_cond, list##_lock);		\
229	} else {							\
230		(adreq) = TAILQ_FIRST(list);				\
231		if ((adreq) == NULL) {					\
232			cv_timedwait(list##_cond, list##_lock,		\
233			    (timeout));					\
234			(adreq) = TAILQ_FIRST(list);			\
235		}							\
236	}								\
237	if ((adreq) != NULL)						\
238		TAILQ_REMOVE((list), (adreq), adr_next);		\
239	mtx_unlock(list##_lock);					\
240} while (0)
241#define	QUEUE_INSERT(adreq, list)	do {				\
242	bool _wakeup;							\
243									\
244	mtx_lock(list##_lock);						\
245	_wakeup = TAILQ_EMPTY(list);					\
246	TAILQ_INSERT_TAIL((list), (adreq), adr_next);			\
247	mtx_unlock(list##_lock);					\
248	if (_wakeup)							\
249		cv_signal(list##_cond);					\
250} while (0)
251#define	QUEUE_CONCAT2(tolist, fromlist1, fromlist2)	do {		\
252	bool _wakeup;							\
253									\
254	mtx_lock(tolist##_lock);					\
255	_wakeup = TAILQ_EMPTY(tolist);					\
256	mtx_lock(fromlist1##_lock);					\
257	TAILQ_CONCAT((tolist), (fromlist1), adr_next);			\
258	mtx_unlock(fromlist1##_lock);					\
259	mtx_lock(fromlist2##_lock);					\
260	TAILQ_CONCAT((tolist), (fromlist2), adr_next);			\
261	mtx_unlock(fromlist2##_lock);					\
262	mtx_unlock(tolist##_lock);					\
263	if (_wakeup)							\
264		cv_signal(tolist##_cond);				\
265} while (0)
266#define	QUEUE_WAIT(list)	do {					\
267	mtx_lock(list##_lock);						\
268	while (TAILQ_EMPTY(list))					\
269		cv_wait(list##_cond, list##_lock);			\
270	mtx_unlock(list##_lock);					\
271} while (0)
272
273extern const char *cfgpath;
274extern bool sigexit_received;
275extern struct pidfh *pfh;
276
277void descriptors_cleanup(struct adist_host *adhost);
278void descriptors_assert(const struct adist_host *adhost, int pjdlogmode);
279
280void adist_sender(struct adist_config *config, struct adist_host *adhost);
281void adist_receiver(struct adist_config *config, struct adist_host *adhost);
282
283struct adist_config *yy_config_parse(const char *config, bool exitonerror);
284void yy_config_free(struct adist_config *config);
285
286void yyerror(const char *);
287int yylex(void);
288
289#endif	/* !_AUDITDISTD_H_ */
290