Commit | Line | Data |
---|---|---|
9da480be MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Common definitions for YAID | |
4 | * | |
5 | * (c) 2012 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of Yet Another Ident Daemon (YAID). | |
11 | * | |
12 | * YAID is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or | |
15 | * (at your option) any later version. | |
16 | * | |
17 | * YAID is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with YAID; if not, write to the Free Software Foundation, | |
24 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
25 | */ | |
26 | ||
27 | #ifndef YAID_H | |
28 | #define YAID_H | |
29 | ||
30 | #ifdef __cplusplus | |
31 | extern "C" { | |
32 | #endif | |
33 | ||
34 | /*----- Header files ------------------------------------------------------*/ | |
35 | ||
bf4d9761 MW |
36 | #include "config.h" |
37 | ||
9da480be MW |
38 | #include <assert.h> |
39 | #include <ctype.h> | |
40 | #include <errno.h> | |
41 | #include <limits.h> | |
42 | #include <stdarg.h> | |
43 | #include <stdio.h> | |
44 | #include <string.h> | |
45 | #include <string.h> | |
4f8fdcc1 | 46 | #include <time.h> |
9da480be MW |
47 | |
48 | #include <sys/types.h> | |
4f8fdcc1 | 49 | #include <sys/time.h> |
9da480be MW |
50 | #include <unistd.h> |
51 | #include <fcntl.h> | |
52 | ||
74716d82 | 53 | #include <grp.h> |
9da480be MW |
54 | #include <pwd.h> |
55 | ||
56 | #include <sys/socket.h> | |
57 | #include <netinet/in.h> | |
58 | #include <arpa/inet.h> | |
74716d82 | 59 | #include <netdb.h> |
9da480be | 60 | |
9da480be MW |
61 | #include <syslog.h> |
62 | ||
63 | #include <mLib/bits.h> | |
64 | #include <mLib/conn.h> | |
74716d82 | 65 | #include <mLib/daemonize.h> |
9da480be MW |
66 | #include <mLib/darray.h> |
67 | #include <mLib/dstr.h> | |
bf4d9761 | 68 | #include <mLib/fdflags.h> |
9da480be | 69 | #include <mLib/fwatch.h> |
bc23d2c7 | 70 | #include <mLib/macros.h> |
74716d82 | 71 | #include <mLib/mdwopt.h> |
9da480be MW |
72 | #include <mLib/quis.h> |
73 | #include <mLib/report.h> | |
74 | #include <mLib/sel.h> | |
75 | #include <mLib/selbuf.h> | |
74716d82 | 76 | #include <mLib/sig.h> |
9da480be | 77 | |
c3794524 | 78 | /*----- Address family handling -------------------------------------------*/ |
bf4d9761 | 79 | |
c3794524 MW |
80 | /* The maximum length of an address formatted as a text string, including the |
81 | * terminating null byte. | |
82 | */ | |
83 | #define ADDRLEN 64 | |
bf4d9761 | 84 | |
c3794524 MW |
85 | /* A list of address types. */ |
86 | #define ADDRTYPES(_) \ | |
87 | _(ipv4, IPV4) \ | |
88 | _(ipv6, IPV6) | |
9da480be | 89 | |
c3794524 MW |
90 | /* Address types for the various families, in the form acceptable to |
91 | * inet_ntop(3) and inet_pton(3). */ | |
92 | #define TYPE_IPV4 struct in_addr | |
93 | #define TYPE_IPV6 struct in6_addr | |
9da480be | 94 | |
c3794524 | 95 | /* A union of address types. */ |
9da480be | 96 | union addr { |
c3794524 MW |
97 | #define UMEMB(ty, TY) TYPE_##TY ty; |
98 | ADDRTYPES(UMEMB) | |
99 | #undef UMEMB | |
9da480be MW |
100 | }; |
101 | ||
c3794524 | 102 | /* A socket holds an address and a port number. */ |
9da480be | 103 | struct socket { |
c3794524 MW |
104 | union addr addr; /* The address */ |
105 | unsigned port; /* The port, in /host/ byte order */ | |
9da480be MW |
106 | }; |
107 | ||
c3794524 MW |
108 | /* An address pattern consists of an address and a prefix length: the |
109 | * pattern matches an address if they agree in the first LEN bits. | |
110 | */ | |
bf4d9761 | 111 | struct addrpat { |
c3794524 MW |
112 | union addr addr; /* The base address */ |
113 | unsigned len; /* The prefix length */ | |
bf4d9761 MW |
114 | }; |
115 | ||
c3794524 MW |
116 | /* A port pattern matches a port if the port is within the stated (inclusive) |
117 | * bounds. | |
118 | */ | |
bf4d9761 MW |
119 | struct portpat { |
120 | unsigned lo, hi; | |
121 | }; | |
122 | ||
c3794524 MW |
123 | /* A socket pattern consists simply of an address pattern and a port pattern: |
124 | * it matches a socket componentwise. | |
125 | */ | |
bf4d9761 MW |
126 | struct sockpat { |
127 | struct addrpat addr; | |
128 | struct portpat port; | |
129 | }; | |
130 | ||
c3794524 MW |
131 | /* The table of address-type operations. Each address family has one of |
132 | * these, so that most of the program doesn't need to worry about these | |
133 | * details. | |
134 | */ | |
bf4d9761 | 135 | struct addrops { |
c3794524 MW |
136 | int af; /* The AF_* constant */ |
137 | const char *name; /* Name of the protocol, for logs */ | |
138 | unsigned len; /* Length of an address, in bits */ | |
139 | const union addr *any; /* A wildcard address */ | |
140 | const struct addrops_sys *sys; /* Pointer to system-specific ops */ | |
141 | ||
bf4d9761 | 142 | int (*addreq)(const union addr *, const union addr *); |
c3794524 MW |
143 | /* Return nonzero if the two addresses are equal. */ |
144 | ||
bf4d9761 | 145 | int (*match_addrpat)(const struct addrpat *, const union addr *); |
c3794524 MW |
146 | /* Return nonzero if the pattern matches the address. */ |
147 | ||
bf4d9761 | 148 | void (*socket_to_sockaddr)(const struct socket *s, void *, size_t *); |
c3794524 MW |
149 | /* Convert a socket structure to a `struct sockaddr', and return the |
150 | * size of the latter. | |
151 | */ | |
152 | ||
bf4d9761 | 153 | void (*sockaddr_to_addr)(const void *, union addr *); |
c3794524 MW |
154 | /* Extract the address from a `struct sockaddr'. */ |
155 | ||
bf4d9761 | 156 | int (*init_listen_socket)(int); |
c3794524 MW |
157 | /* Perform any necessary extra operations on a socket which is going |
158 | * to be used to listen for incoming connections. | |
159 | */ | |
bf4d9761 MW |
160 | }; |
161 | ||
c3794524 MW |
162 | /* A handy constant for each address family. These are more useful than the |
163 | * AF_* constants in that they form a dense sequence. | |
164 | */ | |
bf4d9761 | 165 | enum { |
3b1bed1d | 166 | #define DEFADDR(ty, TY) ADDR_##TY, |
bf4d9761 MW |
167 | ADDRTYPES(DEFADDR) |
168 | #undef DEFADDR | |
169 | ADDR_LIMIT | |
170 | }; | |
171 | ||
c3794524 MW |
172 | /* The table of address operations, indexed by the ADDR_* constants defined |
173 | * just above. | |
174 | */ | |
bf4d9761 | 175 | extern const struct addrops addroptab[]; |
c3794524 MW |
176 | |
177 | /* System-specific operations, provided by the system-specific code for its | |
178 | * own purposes. | |
179 | */ | |
180 | #define OPS_SYS(ty, TY) \ | |
bf4d9761 MW |
181 | extern const struct addrops_sys addrops_sys_##ty; |
182 | ADDRTYPES(OPS_SYS) | |
183 | #undef OPS_SYS | |
184 | ||
c3794524 MW |
185 | /* Answer whether the sockets SA and SB are equal. */ |
186 | extern int sockeq(const struct addrops */*ao*/, | |
187 | const struct socket */*sa*/, const struct socket */*sb*/); | |
188 | ||
189 | /* Write a textual description of S to the string D. */ | |
190 | extern void dputsock(dstr */*d*/, const struct addrops */*ao*/, | |
191 | const struct socket */*s*/); | |
192 | ||
193 | /*----- Queries and responses ---------------------------------------------*/ | |
194 | ||
195 | /* Constants for describing the `L'ocal and `R'emote ends of a connection. */ | |
9da480be MW |
196 | enum { L, R, NDIR }; |
197 | ||
c3794524 | 198 | /* Response types, and the data needed to represent any associated data. A |
1e00cfaa | 199 | * U_(MEMB, TYPE) constructs a union member; an N_ means no associated data. |
c3794524 | 200 | */ |
9da480be | 201 | #define RESPONSE(_) \ |
1e00cfaa MW |
202 | _(ERROR, U_(error, unsigned)) \ |
203 | _(UID, U_(uid, uid_t)) \ | |
204 | _(NAT, U_(nat, struct socket)) | |
9da480be | 205 | |
c3794524 MW |
206 | enum { |
207 | #define DEFENUM(what, branch) R_##what, | |
208 | RESPONSE(DEFENUM) | |
209 | #undef DEFENUM | |
210 | R_LIMIT | |
211 | }; | |
212 | ||
213 | /* Protocol error tokens. */ | |
9da480be MW |
214 | #define ERROR(_) \ |
215 | _(INVPORT, "INVALID-PORT") \ | |
216 | _(NOUSER, "NO-USER") \ | |
217 | _(HIDDEN, "HIDDEN-USER") \ | |
218 | _(UNKNOWN, "UNKNOWN-ERROR") | |
9da480be MW |
219 | |
220 | enum { | |
221 | #define DEFENUM(err, tok) E_##err, | |
222 | ERROR(DEFENUM) | |
223 | #undef DEFENUM | |
224 | E_LIMIT | |
225 | }; | |
226 | ||
c3794524 | 227 | extern const char *const errtok[]; |
9da480be | 228 | |
c3794524 MW |
229 | /* The query structure keeps together the parameters to the client's query |
230 | * and our response to it. | |
231 | */ | |
9da480be | 232 | struct query { |
c3794524 MW |
233 | const struct addrops *ao; /* Address family operations */ |
234 | struct socket s[NDIR]; /* The local and remote ends */ | |
235 | unsigned resp; /* Our response type */ | |
236 | union { /* A union of response data */ | |
9da480be | 237 | #define DEFBRANCH(WHAT, branch) branch |
1e00cfaa MW |
238 | #define U_(memb, ty) ty memb; |
239 | #define N_ | |
9da480be | 240 | RESPONSE(DEFBRANCH) |
1e00cfaa MW |
241 | #undef U_ |
242 | #undef N_ | |
9da480be MW |
243 | #undef DEFBRANCH |
244 | } u; | |
245 | } query; | |
246 | ||
c3794524 MW |
247 | /*----- Common utility functions ------------------------------------------*/ |
248 | ||
249 | /* Format and log MSG somewhere sensible, at the syslog(3) priority PRIO. | |
250 | * Prefix it with a description of the query Q, if non-null. | |
251 | */ | |
bc23d2c7 MW |
252 | extern void PRINTF_LIKE(3, 4) |
253 | logmsg(const struct query */*q*/, int /*prio*/, const char */*msg*/, ...); | |
9da480be | 254 | |
c3794524 MW |
255 | /*----- System-specific connection identification code --------------------*/ |
256 | ||
257 | /* Find out who is responsible for the connection described in the query Q. | |
258 | * Write the answer to Q. Errors are logged and reported via the query | |
259 | * structure. | |
260 | */ | |
261 | extern void identify(struct query */*q*/); | |
262 | ||
263 | /* Initialize the system-specific code. */ | |
264 | extern void init_sys(void); | |
265 | ||
266 | /*----- Policy management -------------------------------------------------*/ | |
267 | ||
268 | /* The possible policy actions and their names. */ | |
9da480be MW |
269 | #define ACTIONS(_) \ |
270 | _(USER, "user") \ | |
271 | _(TOKEN, "token") \ | |
272 | _(NAME, "name") \ | |
273 | _(DENY, "deny") \ | |
274 | _(HIDE, "hide") \ | |
275 | _(LIE, "lie") | |
276 | ||
277 | enum { | |
278 | #define DEFENUM(tag, word) A_##tag, | |
279 | ACTIONS(DEFENUM) | |
280 | #undef DEFENUM | |
281 | A_LIMIT | |
282 | }; | |
283 | ||
c3794524 | 284 | /* A policy action. */ |
9da480be MW |
285 | struct action { |
286 | unsigned act; | |
287 | union { | |
c3794524 MW |
288 | unsigned user; /* Bitmask of permitted actions */ |
289 | char *lie; /* The user name to impersonate */ | |
9da480be MW |
290 | } u; |
291 | }; | |
292 | ||
c039c936 MW |
293 | /* A user pattern matches a user if the uid is within the given bounds. */ |
294 | struct userpat { | |
295 | unsigned lo, hi; | |
296 | }; | |
297 | ||
c3794524 MW |
298 | /* A policy rule: if the query matches the pattern, then perform the |
299 | * action. | |
300 | */ | |
9da480be | 301 | struct policy { |
bf4d9761 | 302 | const struct addrops *ao; |
9da480be | 303 | struct sockpat sp[NDIR]; |
c039c936 | 304 | struct userpat up; |
9da480be MW |
305 | struct action act; |
306 | }; | |
c3794524 MW |
307 | #define POLICY_INIT(a) { .act.act = a } |
308 | DA_DECL(policy_v, struct policy); | |
9da480be | 309 | |
c3794524 MW |
310 | /* Initialize a policy structure. In this state, it doesn't actually have |
311 | * any resources allocated (so can be simply discarded) but it's safe to free | |
312 | * (using `free_policy'). | |
313 | */ | |
314 | extern void init_policy(struct policy */*p*/); | |
9da480be | 315 | |
c3794524 MW |
316 | /* Free a policy structure, resetting it to its freshly-initialized state. |
317 | * This function is idempotent. | |
318 | */ | |
319 | extern void free_policy(struct policy */*p*/); | |
320 | ||
321 | /* Print a policy rule to standard output. */ | |
322 | extern void print_policy(const struct policy */*p*/); | |
323 | ||
324 | /* Return true if the query matches the patterns in the policy rule. */ | |
325 | extern int match_policy(const struct policy */*p*/, | |
326 | const struct query */*q*/); | |
327 | ||
328 | /*----- Parsing policy files ----------------------------------------------*/ | |
9da480be | 329 | |
c3794524 MW |
330 | /* Possible results from a parse. */ |
331 | enum { | |
332 | T_OK, /* Successful: results returned */ | |
333 | T_EOL, /* End-of-line found immediately */ | |
b9eb1a36 MW |
334 | T_ERROR, /* Some kind of error occurred */ |
335 | T_EOF /* End-of-file found immediately */ | |
c3794524 | 336 | }; |
9da480be | 337 | |
c3794524 MW |
338 | /* A context for parsing a policy file. */ |
339 | struct policy_file { | |
340 | FILE *fp; /* The file to read from */ | |
341 | const struct query *q; /* A query to use for logging */ | |
342 | const char *name; /* The name of the file */ | |
343 | const char *what; /* A description of the file */ | |
344 | int err; /* Have there been any errors? */ | |
345 | int lno; /* The current line number */ | |
346 | struct policy p; /* Parsed policy rule goes here */ | |
347 | }; | |
bf4d9761 | 348 | |
c3794524 MW |
349 | /* Open a policy file by NAME. The description WHAT and query Q are used for |
350 | * formatting error messages for the log. | |
7164a50b MW |
351 | * |
352 | * This function is somewhat careful only to read from actual regular files, | |
353 | * though (if the filesystem object identified by NAME is a symlink, say) it | |
354 | * might open a device node or other exotic thing without reading it. This | |
355 | * is likely harmless, since we're running as an unprivileged user anyway. | |
c3794524 MW |
356 | */ |
357 | extern int open_policy_file(struct policy_file */*pf*/, const char */*name*/, | |
17272ab8 MW |
358 | const char */*what*/, const struct query */*q*/, |
359 | unsigned /*f*/); | |
360 | #define OPF_NOENTOK 1u /* Don't complain if file missing */ | |
9da480be | 361 | |
c3794524 MW |
362 | /* Read a policy rule from the file, storing it in PF->p. Return one of the |
363 | * T_* codes. | |
364 | */ | |
365 | extern int read_policy_file(struct policy_file */*pf*/); | |
366 | ||
367 | /* Close a policy file. It doesn't matter whether the file was completely | |
368 | * read. | |
369 | */ | |
370 | extern void close_policy_file(struct policy_file */*pf*/); | |
9da480be | 371 | |
c3794524 MW |
372 | /* Load a policy file, writing a vector of records into PV. If the policy |
373 | * file has errors, then leave PV unchanged and return nonzero. | |
374 | */ | |
375 | extern int load_policy_file(const char */*file*/, policy_v */*pv*/); | |
9da480be MW |
376 | |
377 | /*----- That's all, folks -------------------------------------------------*/ | |
378 | ||
379 | #ifdef __cplusplus | |
380 | } | |
381 | #endif | |
382 | ||
383 | #endif |