chiark / gitweb /
Properly log fatal errors encountered after program startup.
[yaid] / yaid.h
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
36 #include "config.h"
37
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>
46 #include <time.h>
47
48 #include <sys/types.h>
49 #include <sys/time.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52
53 #include <grp.h>
54 #include <pwd.h>
55
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 #include <netdb.h>
60
61 #include <syslog.h>
62
63 #include <mLib/bits.h>
64 #include <mLib/conn.h>
65 #include <mLib/daemonize.h>
66 #include <mLib/darray.h>
67 #include <mLib/dstr.h>
68 #include <mLib/fdflags.h>
69 #include <mLib/fwatch.h>
70 #include <mLib/macros.h>
71 #include <mLib/mdwopt.h>
72 #include <mLib/quis.h>
73 #include <mLib/report.h>
74 #include <mLib/sel.h>
75 #include <mLib/selbuf.h>
76 #include <mLib/sig.h>
77
78 /*----- Address family handling -------------------------------------------*/
79
80 /* The maximum length of an address formatted as a text string, including the
81  * terminating null byte.
82  */
83 #define ADDRLEN 64
84
85 /* A list of address types. */
86 #define ADDRTYPES(_)                                                    \
87   _(ipv4, IPV4)                                                         \
88   _(ipv6, IPV6)
89
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
94
95 /* A union of address types. */
96 union addr {
97 #define UMEMB(ty, TY) TYPE_##TY ty;
98   ADDRTYPES(UMEMB)
99 #undef UMEMB
100 };
101
102 /* A socket holds an address and a port number. */
103 struct socket {
104   union addr addr;                      /* The address */
105   unsigned port;                        /* The port, in /host/ byte order */
106 };
107
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  */
111 struct addrpat {
112   union addr addr;                      /* The base address */
113   unsigned len;                         /* The prefix length */
114 };
115
116 /* A port pattern matches a port if the port is within the stated (inclusive)
117  * bounds.
118  */
119 struct portpat {
120   unsigned lo, hi;
121 };
122
123 /* A socket pattern consists simply of an address pattern and a port pattern:
124  * it matches a socket componentwise.
125  */
126 struct sockpat {
127   struct addrpat addr;
128   struct portpat port;
129 };
130
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  */
135 struct addrops {
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
142   int (*addreq)(const union addr *, const union addr *);
143         /* Return nonzero if the two addresses are equal. */
144
145   int (*match_addrpat)(const struct addrpat *, const union addr *);
146         /* Return nonzero if the pattern matches the address. */
147
148   void (*socket_to_sockaddr)(const struct socket *s, void *, size_t *);
149         /* Convert a socket structure to a `struct sockaddr', and return the
150          * size of the latter.
151          */
152
153   void (*sockaddr_to_addr)(const void *, union addr *);
154         /* Extract the address from a `struct sockaddr'. */
155
156   int (*init_listen_socket)(int);
157         /* Perform any necessary extra operations on a socket which is going
158          * to be used to listen for incoming connections.
159          */
160 };
161
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  */
165 enum {
166 #define DEFADDR(ty, TY) ADDR_##TY,
167   ADDRTYPES(DEFADDR)
168 #undef DEFADDR
169   ADDR_LIMIT
170 };
171
172 /* The table of address operations, indexed by the ADDR_* constants defined
173  * just above.
174  */
175 extern const struct addrops addroptab[];
176
177 /* System-specific operations, provided by the system-specific code for its
178  * own purposes.
179  */
180 #define OPS_SYS(ty, TY)                                                 \
181   extern const struct addrops_sys addrops_sys_##ty;
182 ADDRTYPES(OPS_SYS)
183 #undef OPS_SYS
184
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. */
196 enum { L, R, NDIR };
197
198 /* Response types, and the data needed to represent any associated data.  A
199  * U_(MEMB, TYPE) constructs a union member; an N_ means no associated data.
200  */
201 #define RESPONSE(_)                                                     \
202   _(ERROR, U_(error, unsigned))                                         \
203   _(UID, U_(uid, uid_t))                                                \
204   _(NAT, U_(nat, struct socket))
205
206 enum {
207 #define DEFENUM(what, branch) R_##what,
208   RESPONSE(DEFENUM)
209 #undef DEFENUM
210   R_LIMIT
211 };
212
213 /* Protocol error tokens. */
214 #define ERROR(_)                                                        \
215   _(INVPORT, "INVALID-PORT")                                            \
216   _(NOUSER, "NO-USER")                                                  \
217   _(HIDDEN, "HIDDEN-USER")                                              \
218   _(UNKNOWN, "UNKNOWN-ERROR")
219
220 enum {
221 #define DEFENUM(err, tok) E_##err,
222   ERROR(DEFENUM)
223 #undef DEFENUM
224   E_LIMIT
225 };
226
227 extern const char *const errtok[];
228
229 /* The query structure keeps together the parameters to the client's query
230  * and our response to it.
231  */
232 struct query {
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 */
237 #define DEFBRANCH(WHAT, branch) branch
238 #define U_(memb, ty) ty memb;
239 #define N_
240     RESPONSE(DEFBRANCH)
241 #undef U_
242 #undef N_
243 #undef DEFBRANCH
244   } u;
245 } query;
246
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  */
252 extern void PRINTF_LIKE(3, 4)
253   logmsg(const struct query */*q*/, int /*prio*/, const char */*msg*/, ...);
254
255 /* Format and report MSG as a fatal error, and exit. */
256 extern void PRINTF_LIKE(1, 2) fatal(const char */*msg*/, ...);
257
258 /*----- System-specific connection identification code --------------------*/
259
260 /* Find out who is responsible for the connection described in the query Q.
261  * Write the answer to Q.  Errors are logged and reported via the query
262  * structure.
263  */
264 extern void identify(struct query */*q*/);
265
266 /* Fill the buffer at P with SZ random bytes.  The buffer will be moderately
267  * large: this is intended to be a low-level interface, not a general-purpose
268  * utility.
269  */
270 extern void fill_random(void */*p*/, size_t /*sz*/);
271
272 /* Initialize the system-specific code. */
273 extern void init_sys(void);
274
275 /*----- Policy management -------------------------------------------------*/
276
277 /* The possible policy actions and their names. */
278 #define ACTIONS(_)                                                      \
279   _(USER, "user")                                                       \
280   _(TOKEN, "token")                                                     \
281   _(NAME, "name")                                                       \
282   _(DENY, "deny")                                                       \
283   _(HIDE, "hide")                                                       \
284   _(LIE, "lie")
285
286 enum {
287 #define DEFENUM(tag, word) A_##tag,
288   ACTIONS(DEFENUM)
289 #undef DEFENUM
290   A_LIMIT
291 };
292
293 /* A policy action. */
294 struct action {
295   unsigned act;
296   union {
297     unsigned user;                      /* Bitmask of permitted actions */
298     char *lie;                          /* The user name to impersonate */
299   } u;
300 };
301
302 /* A user pattern matches a user if the uid is within the given bounds. */
303 struct userpat {
304   unsigned lo, hi;
305 };
306
307 /* A policy rule: if the query matches the pattern, then perform the
308  * action.
309  */
310 struct policy {
311   const struct addrops *ao;
312   struct sockpat sp[NDIR];
313   struct userpat up;
314   struct action act;
315 };
316 #define POLICY_INIT(a) { .act.act = a }
317 DA_DECL(policy_v, struct policy);
318
319 /* Initialize a policy structure.  In this state, it doesn't actually have
320  * any resources allocated (so can be simply discarded) but it's safe to free
321  * (using `free_policy').
322  */
323 extern void init_policy(struct policy */*p*/);
324
325 /* Free a policy structure, resetting it to its freshly-initialized state.
326  * This function is idempotent.
327  */
328 extern void free_policy(struct policy */*p*/);
329
330 /* Print a policy rule to standard output. */
331 extern void print_policy(const struct policy */*p*/);
332
333 /* Return true if the query matches the patterns in the policy rule. */
334 extern int match_policy(const struct policy */*p*/,
335                         const struct query */*q*/);
336
337 /*----- Parsing policy files ----------------------------------------------*/
338
339 /* Possible results from a parse. */
340 enum {
341   T_OK,                                 /* Successful: results returned */
342   T_EOL,                                /* End-of-line found immediately */
343   T_ERROR,                              /* Some kind of error occurred */
344   T_EOF                                 /* End-of-file found immediately */
345 };
346
347 /* A context for parsing a policy file. */
348 struct policy_file {
349   FILE *fp;                             /* The file to read from */
350   const struct query *q;                /* A query to use for logging */
351   const char *name;                     /* The name of the file */
352   const char *what;                     /* A description of the file */
353   int err;                              /* Have there been any errors? */
354   int lno;                              /* The current line number */
355   struct policy p;                      /* Parsed policy rule goes here */
356 };
357
358 /* Open a policy file by NAME.  The description WHAT and query Q are used for
359  * formatting error messages for the log.
360  *
361  * This function is somewhat careful only to read from actual regular files,
362  * though (if the filesystem object identified by NAME is a symlink, say) it
363  * might open a device node or other exotic thing without reading it.  This
364  * is likely harmless, since we're running as an unprivileged user anyway.
365  */
366 extern int open_policy_file(struct policy_file */*pf*/, const char */*name*/,
367                             const char */*what*/, const struct query */*q*/,
368                             unsigned /*f*/);
369 #define OPF_NOENTOK 1u                  /* Don't complain if file missing */
370
371 /* Read a policy rule from the file, storing it in PF->p.  Return one of the
372  * T_* codes.
373  */
374 extern int read_policy_file(struct policy_file */*pf*/);
375
376 /* Close a policy file.  It doesn't matter whether the file was completely
377  * read.
378  */
379 extern void close_policy_file(struct policy_file */*pf*/);
380
381 /* Load a policy file, writing a vector of records into PV.  If the policy
382  * file has errors, then leave PV unchanged and return nonzero.
383  */
384 extern int load_policy_file(const char */*file*/, policy_v */*pv*/);
385
386 /*----- That's all, folks -------------------------------------------------*/
387
388 #ifdef __cplusplus
389   }
390 #endif
391
392 #endif