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 
91 struct 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 
99 struct 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  */
126 struct 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 
187 struct 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 
201 struct 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 
215 struct 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_WAIT(list)	do {					\
252 	mtx_lock(list##_lock);						\
253 	while (TAILQ_EMPTY(list))					\
254 		cv_wait(list##_cond, list##_lock);			\
255 	mtx_unlock(list##_lock);					\
256 } while (0)
257 
258 extern const char *cfgpath;
259 extern bool sigexit_received;
260 extern struct pidfh *pfh;
261 
262 void descriptors_cleanup(struct adist_host *adhost);
263 void descriptors_assert(const struct adist_host *adhost, int pjdlogmode);
264 
265 void adist_sender(struct adist_config *config, struct adist_host *adhost);
266 void adist_receiver(struct adist_config *config, struct adist_host *adhost);
267 
268 struct adist_config *yy_config_parse(const char *config, bool exitonerror);
269 void yy_config_free(struct adist_config *config);
270 
271 void yyerror(const char *);
272 int yylex(void);
273 
274 #endif	/* !_AUDITDISTD_H_ */
275