chiark / gitweb /
linux.c, yaid.c: Correct policy application for proxied queries.
[yaid] / yaid.c
1 /* -*-c-*-
2  *
3  * Main daemon
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 /*----- Header files ------------------------------------------------------*/
28
29 #include "yaid.h"
30
31 /*----- Data structures ---------------------------------------------------*/
32
33 /* A write buffer is the gadget which keeps track of our output and writes
34  * portions of it out as and when connections are ready for it.
35  */
36 #define WRBUFSZ 1024
37 struct writebuf {
38   size_t o;                             /* Offset of remaining data */
39   size_t n;                             /* Length of remaining data */
40   sel_file wr;                          /* Write selector */
41   void (*func)(int /*err*/, void *);    /* Function to call on completion */
42   void *p;                              /* Context for `func' */
43   unsigned char buf[WRBUFSZ];           /* Output buffer */
44 };
45
46 /* Structure for a listening socket.  There's one of these for each address
47  * family we're looking after.
48  */
49 struct listen {
50   const struct addrops *ao;             /* Address family operations */
51   sel_file f;                           /* Watch for incoming connections */
52 };
53
54 /* The main structure for a client. */
55 struct client {
56   int fd;                               /* The connection to the client */
57   selbuf b;                             /* Accumulate lines of input */
58   union addr raddr;                     /* Remote address */
59   struct query q;                       /* The clients query and our reply */
60   struct sel_timer t;                   /* Timeout for idle or doomed conn */
61   struct listen *l;                     /* Back to the listener (and ops) */
62   struct writebuf wb;                   /* Write buffer for our reply */
63   struct proxy *px;                     /* Proxy if conn goes via NAT */
64 };
65
66 /* A proxy connection. */
67 struct proxy {
68   int fd;                               /* Connection; -1 if in progress */
69   struct client *c;                     /* Back to the client */
70   conn cn;                              /* Nonblocking connection */
71   selbuf b;                             /* Accumulate the response line */
72   struct writebuf wb;                   /* Write buffer for query */
73   char nat[ADDRLEN];                    /* Server address, as text */
74 };
75
76 /*----- Static variables --------------------------------------------------*/
77
78 static sel_state sel;                   /* I/O multiplexer state */
79
80 static const char *pidfile = 0;         /* Where to write daemon's pid */
81
82 static const char *policyfile = POLICYFILE; /* Filename for global policy */
83 static const struct policy default_policy = POLICY_INIT(A_NAME);
84 static policy_v policy = DA_INIT;       /* Vector of global policy rules */
85 static fwatch polfw;                    /* Watch policy file for changes */
86
87 static unsigned char tokenbuf[4096];    /* Random-ish data for tokens */
88 static size_t tokenptr = sizeof(tokenbuf); /* Current read position */
89 static int randfd;                      /* File descriptor for random data */
90
91 static unsigned flags = 0;              /* Various interesting flags */
92 #define F_SYSLOG 1u                     /*   Use syslog for logging */
93 #define F_RUNNING 2u                    /*   Running properly now */
94
95 /*----- Ident protocol parsing --------------------------------------------*/
96
97 /* Advance *PP over whitespace characters. */
98 static void skipws(const char **pp)
99   { while (isspace((unsigned char )**pp)) (*pp)++; }
100
101 /* Copy a token of no more than N bytes starting at *PP into Q, advancing *PP
102  * over it.
103  */
104 static int idtoken(const char **pp, char *q, size_t n)
105 {
106   const char *p = *pp;
107
108   skipws(&p);
109   n--;
110   for (;;) {
111     if (*p == ':' || *p <= 32 || *p >= 127) break;
112     if (!n) return (-1);
113     *q++ = *p++;
114     n--;
115   }
116   *q++ = 0;
117   *pp = p;
118   return (0);
119 }
120
121 /* Read an unsigned decimal number from *PP, and store it in *II.  Check that
122  * it's between MIN and MAX, and advance *PP over it.  Return zero for
123  * success, or nonzero if something goes wrong.
124  */
125 static int unum(const char **pp, unsigned *ii, unsigned min, unsigned max)
126 {
127   char *q;
128   unsigned long i;
129   int e;
130
131   skipws(pp);
132   if (!isdigit((unsigned char)**pp)) return (-1);
133   e = errno; errno = 0;
134   i = strtoul(*pp, &q, 10);
135   if (errno) return (-1);
136   *pp = q;
137   errno = e;
138   if (i < min || i > max) return (-1);
139   *ii = i;
140   return (0);
141 }
142
143 /*----- Asynchronous writing ----------------------------------------------*/
144
145 /* Callback for actually writing stuff from a `writebuf'. */
146 static void write_out(int fd, unsigned mode, void *p)
147 {
148   ssize_t n;
149   struct writebuf *wb = p;
150
151   /* Try to write something. */
152   if ((n = write(fd, wb->buf + wb->o, wb->n)) < 0) {
153     if (errno == EAGAIN || errno == EWOULDBLOCK) return;
154     wb->n = 0;
155     sel_rmfile(&wb->wr);
156     wb->func(errno, wb->p);
157   }
158   wb->o += n;
159   wb->n -= n;
160
161   /* If there's nothing left then restore the buffer to its empty state. */
162   if (!wb->n) {
163     wb->o = 0;
164     sel_rmfile(&wb->wr);
165     wb->func(0, wb->p);
166   }
167 }
168
169 /* Queue N bytes starting at P to be written. */
170 static int queue_write(struct writebuf *wb, const void *p, size_t n)
171 {
172   /* Maybe there's nothing to actually do. */
173   if (!n) return (0);
174
175   /* Make sure it'll fit. */
176   if (wb->n - wb->o + n > WRBUFSZ) return (-1);
177
178   /* If there's anything there already, then make sure it's at the start of
179    * the available space.
180    */
181   if (wb->o) {
182     memmove(wb->buf, wb->buf + wb->o, wb->n);
183     wb->o = 0;
184   }
185
186   /* If there's nothing currently there, then we're not requesting write
187    * notifications, so set that up, and force an initial wake-up.
188    */
189   if (!wb->n) {
190     sel_addfile(&wb->wr);
191     sel_force(&wb->wr);
192   }
193
194   /* Copy the new material over. */
195   memcpy(wb->buf + wb->n, p, n);
196   wb->n += n;
197
198   /* Done. */
199   return (0);
200 }
201
202 /* Release resources allocated to WB. */
203 static void free_writebuf(struct writebuf *wb)
204   { if (wb->n) sel_rmfile(&wb->wr); }
205
206 /* Initialize a writebuf in *WB, writing to file descriptor FD.  On
207  * completion, call FUNC, passing it P and an error indicator: either 0 for
208  * success or an `errno' value on failure.
209  */
210 static void init_writebuf(struct writebuf *wb,
211                           int fd, void (*func)(int, void *), void *p)
212 {
213   sel_initfile(&sel, &wb->wr, fd, SEL_WRITE, write_out, wb);
214   wb->func = func;
215   wb->p = p;
216   wb->n = wb->o = 0;
217 }
218
219 /*----- General utilities -------------------------------------------------*/
220
221 /* Format and log MSG somewhere sensible, at the syslog(3) priority PRIO.
222  * Prefix it with a description of the query Q, if non-null.
223  */
224 void logmsg(const struct query *q, int prio, const char *msg, ...)
225 {
226   va_list ap;
227   dstr d = DSTR_INIT;
228   time_t t;
229   struct tm *tm;
230   char buf[64];
231
232   va_start(ap, msg);
233   if (q) {
234     dputsock(&d, q->ao, &q->s[L]);
235     dstr_puts(&d, " <-> ");
236     dputsock(&d, q->ao, &q->s[R]);
237     dstr_puts(&d, ": ");
238   }
239   dstr_vputf(&d, msg, &ap);
240   va_end(ap);
241
242   if (!(flags & F_RUNNING))
243     moan("%s", d.buf);
244   else if (flags & F_SYSLOG)
245     syslog(prio, "%s", d.buf);
246   else {
247     t = time(0);
248     tm = localtime(&t);
249     strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", tm);
250     fprintf(stderr, "%s %s: %s\n", buf, QUIS, d.buf);
251   }
252
253   dstr_destroy(&d);
254 }
255
256 /* Fix up a socket FD so that it won't bite us.  Returns zero on success, or
257  * nonzero on error.
258  */
259 static int fix_up_socket(int fd, const char *what)
260 {
261   int yes = 1;
262
263   if (fdflags(fd, O_NONBLOCK, O_NONBLOCK, 0, 0)) {
264     logmsg(0, LOG_ERR, "failed to set %s connection nonblocking: %s",
265            what, strerror(errno));
266     return (-1);
267   }
268
269   if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &yes, sizeof(yes))) {
270     logmsg(0, LOG_ERR,
271            "failed to disable `out-of-band' data on %s connection: %s",
272            what, strerror(errno));
273     return (-1);
274   }
275
276   return (0);
277 }
278
279 /*----- Client output functions -------------------------------------------*/
280
281 static void disconnect_client(struct client *c);
282
283 /* Notification that output has been written.  If successful, re-enable the
284  * input buffer and prepare for another query.
285  */
286 static void done_client_write(int err, void *p)
287 {
288   struct client *c = p;
289
290   if (!err)
291     selbuf_enable(&c->b);
292   else {
293     logmsg(&c->q, LOG_ERR, "failed to send reply: %s", strerror(err));
294     disconnect_client(c);
295   }
296 }
297
298 /* Format the message FMT and queue it to be sent to the client.  Client
299  * input will be disabled until the write completes.
300  */
301 static void write_to_client(struct client *c, const char *fmt, ...)
302 {
303   va_list ap;
304   char buf[WRBUFSZ];
305   ssize_t n;
306
307   va_start(ap, fmt);
308   n = vsnprintf(buf, sizeof(buf), fmt, ap);
309   if (n < 0) {
310     logmsg(&c->q, LOG_ERR, "failed to format output: %s", strerror(errno));
311     disconnect_client(c);
312     return;
313   } else if (n > sizeof(buf)) {
314     logmsg(&c->q, LOG_ERR, "output too long for client send buffer");
315     disconnect_client(c);
316     return;
317   }
318
319   selbuf_disable(&c->b);
320   if (queue_write(&c->wb, buf, n)) {
321     logmsg(&c->q, LOG_ERR, "write buffer overflow");
322     disconnect_client(c);
323   }
324 }
325
326 /* Format a reply to the client, with the form LPORT:RPORT:TY:TOK0[:TOK1].
327  * Typically, TY will be `ERROR' or `USERID'.  In the former case, TOK0 will
328  * be the error token and TOK1 will be null; in the latter case, TOK0 will be
329  * the operating system and TOK1 the user name.
330  */
331 static void reply(struct client *c, const char *ty,
332                   const char *tok0, const char *tok1)
333 {
334   write_to_client(c, "%u,%u:%s:%s%s%s\r\n",
335                   c->q.s[L].port, c->q.s[R].port, ty,
336                   tok0, tok1 ? ":" : "", tok1 ? tok1 : "");
337 }
338
339 /* Mapping from error codes to their protocol tokens. */
340 const char *const errtok[] = {
341 #define DEFTOK(err, tok) tok,
342   ERROR(DEFTOK)
343 #undef DEFTOK
344 };
345
346 /* Report an error with code ERR to the client. */
347 static void reply_error(struct client *c, unsigned err)
348 {
349   assert(err < E_LIMIT);
350   reply(c, "ERROR", errtok[err], 0);
351 }
352
353 /*----- NAT proxy functions -----------------------------------------------*/
354
355 /* Cancel the proxy operation PX, closing the connection and releasing
356  * resources.  This is used for both normal and unexpected closures.
357  */
358 static void cancel_proxy(struct proxy *px)
359 {
360   if (px->fd == -1)
361     conn_kill(&px->cn);
362   else {
363     close(px->fd);
364     selbuf_destroy(&px->b);
365     free_writebuf(&px->wb);
366   }
367   selbuf_enable(&px->c->b);
368   px->c->px = 0;
369   xfree(px);
370 }
371
372 /* Notification that a line (presumably a reply) has been received from the
373  * server.  We should check it, log it, and propagate the answer back.
374  * Whatever happens, this proxy operation is now complete.
375  */
376 static void proxy_line(char *line, size_t sz, void *p)
377 {
378   struct proxy *px = p;
379   char buf[1024];
380   const char *q = line;
381   unsigned lp, rp;
382
383   /* Trim trailing space. */
384   while (sz && isspace((unsigned char)line[sz - 1])) sz--;
385
386   /* Parse the port numbers.  These should match the request. */
387   if (unum(&q, &lp, 1, 65535)) goto syntax;
388   skipws(&q); if (*q != ',') goto syntax; q++;
389   if (unum(&q, &rp, 1, 65535)) goto syntax;
390   skipws(&q); if (*q != ':') goto syntax; q++;
391   if (lp != px->c->q.u.nat.port || rp != px->c->q.s[R].port) goto syntax;
392
393   /* Find out what kind of reply this is. */
394   if (idtoken(&q, buf, sizeof(buf))) goto syntax;
395   skipws(&q); if (*q != ':') goto syntax; q++;
396
397   if (strcmp(buf, "ERROR") == 0) {
398
399     /* Report the error without interpreting it.  It might be meaningful to
400      * the client.
401      */
402     skipws(&q);
403     logmsg(&px->c->q, LOG_ERR, "proxy error from %s: %s", px->nat, q);
404     reply(px->c, "ERROR", q, 0);
405
406   } else if (strcmp(buf, "USERID") == 0) {
407
408     /* Parse out the operating system and user name, and pass them on. */
409     if (idtoken(&q, buf, sizeof(buf))) goto syntax;
410     skipws(&q); if (*q != ':') goto syntax; q++;
411     skipws(&q);
412     logmsg(&px->c->q, LOG_ERR, "user `%s'; proxy = %s, os = %s",
413            q, px->nat, buf);
414     reply(px->c, "USERID", buf, q);
415
416   } else
417     goto syntax;
418   goto done;
419
420 syntax:
421   /* We didn't understand the message from the client. */
422   logmsg(&px->c->q, LOG_ERR, "failed to parse response from %s", px->nat);
423   reply_error(px->c, E_UNKNOWN);
424 done:
425   /* All finished, no matter what. */
426   cancel_proxy(px);
427 }
428
429 /* Notification that we have written the query to the server.  Await a
430  * response if successful.
431  */
432 static void done_proxy_write(int err, void *p)
433 {
434   struct proxy *px = p;
435
436   if (err) {
437     logmsg(&px->c->q, LOG_ERR, "failed to proxy query to %s: %s",
438            px->nat, strerror(errno));
439     reply_error(px->c, E_UNKNOWN);
440     cancel_proxy(px);
441     return;
442   }
443   selbuf_enable(&px->b);
444 }
445
446 /* Notification that the connection to the server is either established or
447  * failed.  In the former case, queue the right query.
448  */
449 static void proxy_connected(int fd, void *p)
450 {
451   struct proxy *px = p;
452   char buf[16];
453   int n;
454
455   /* If the connection failed then report the problem and give up. */
456   if (fd < 0) {
457     logmsg(&px->c->q, LOG_ERR,
458            "failed to make %s proxy connection to %s: %s",
459            px->c->l->ao->name, px->nat, strerror(errno));
460     reply_error(px->c, E_UNKNOWN);
461     cancel_proxy(px);
462     return;
463   }
464
465   /* We're now ready to go, so set things up. */
466   px->fd = fd;
467   selbuf_init(&px->b, &sel, fd, proxy_line, px);
468   selbuf_setsize(&px->b, 1024);
469   selbuf_disable(&px->b);
470   init_writebuf(&px->wb, fd, done_proxy_write, px);
471
472   /* Write the query.  This buffer is large enough because we've already
473    * range-checked the remote the port number and the local one came from the
474    * kernel, which we trust not to do anything stupid.
475    */
476   n = sprintf(buf, "%u,%u\r\n", px->c->q.u.nat.port, px->c->q.s[R].port);
477   queue_write(&px->wb, buf, n);
478 }
479
480 /* Proxy the query through to a client machine for which we're providing NAT
481  * disservice.
482  */
483 static void proxy_query(struct client *c)
484 {
485   struct socket s;
486   struct sockaddr_storage ss;
487   size_t ssz;
488   struct proxy *px;
489   int fd;
490
491   /* Allocate the context structure for the NAT. */
492   px = xmalloc(sizeof(*px));
493
494   /* We'll use the client host's address in lots of log messages, so we may
495    * as well format it once and use it over and over.
496    */
497   inet_ntop(c->q.ao->af, &c->q.u.nat.addr, px->nat, sizeof(px->nat));
498
499   /* Create the socket for the connection. */
500   if ((fd = socket(c->q.ao->af, SOCK_STREAM, 0)) < 0) {
501     logmsg(&c->q, LOG_ERR, "failed to make %s socket for proxy: %s",
502            c->l->ao->name, strerror(errno));
503     goto err_0;
504   }
505   if (fix_up_socket(fd, "proxy")) goto err_1;
506
507   /* Set up the connection to the client host.  The connection interface is a
508    * bit broken: if the connection completes immediately, then the callback
509    * function is called synchronously, and that might decide to shut
510    * everything down.  So we must have fully initialized our context before
511    * calling `conn_init', and mustn't touch it again afterwards -- since the
512    * block may have been freed.
513    */
514   s = c->q.u.nat;
515   s.port = 113;
516   c->l->ao->socket_to_sockaddr(&s, &ss, &ssz);
517   selbuf_disable(&c->b);
518   c->px = px; px->c = c;
519   px->fd = -1;
520   if (conn_init(&px->cn, &sel, fd, (struct sockaddr *)&ss, ssz,
521                 proxy_connected, px)) {
522     logmsg(&c->q, LOG_ERR, "failed to make %s proxy connection to %s: %s",
523            c->l->ao->name, px->nat, strerror(errno));
524     goto err_2;
525   }
526
527   /* All ready to go. */
528   return;
529
530   /* Tidy up after various kinds of failures. */
531 err_2:
532   selbuf_enable(&c->b);
533 err_1:
534   close(px->fd);
535 err_0:
536   xfree(px);
537   reply_error(c, E_UNKNOWN);
538 }
539
540 /*----- Client connection functions ---------------------------------------*/
541
542 /* Disconnect a client, freeing up any associated resources. */
543 static void disconnect_client(struct client *c)
544 {
545   close(c->fd);
546   selbuf_destroy(&c->b);
547   sel_rmtimer(&c->t);
548   free_writebuf(&c->wb);
549   if (c->px) cancel_proxy(c->px);
550   xfree(c);
551 }
552
553 /* Time out a client because it's been idle for too long. */
554 static void timeout_client(struct timeval *tv, void *p)
555 {
556   struct client *c = p;
557   logmsg(&c->q, LOG_NOTICE, "timing out idle or stuck client");
558   sel_addtimer(&sel, &c->t, tv, timeout_client, 0);
559   disconnect_client(c);
560 }
561
562 /* Reset the client idle timer, as a result of activity.  Set EXISTP if
563  * there is an existing timer which needs to be removed.
564  */
565 static void reset_client_timer(struct client *c, int existp)
566 {
567   struct timeval tv;
568
569   gettimeofday(&tv, 0);
570   tv.tv_sec += 30;
571   if (existp) sel_rmtimer(&c->t);
572   sel_addtimer(&sel, &c->t, &tv, timeout_client, c);
573 }
574
575 /* Write a pseudorandom token into the buffer at P, which must have space for
576  * at least TOKENSZ bytes.
577  */
578 #define TOKENRANDSZ 8
579 #define TOKENSZ ((4*TOKENRANDSZ + 5)/3)
580 static void user_token(char *p)
581 {
582   unsigned a = 0;
583   unsigned b = 0;
584   int i;
585   static const char tokmap[64] =
586     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-";
587
588   /* If there's not enough pseudorandom stuff lying around, then read more
589    * from the kernel.
590    */
591   if (tokenptr + TOKENRANDSZ >= sizeof(tokenbuf)) {
592     if (read(randfd, tokenbuf, sizeof(tokenbuf)) < sizeof(tokenbuf))
593       die(1, "unexpected short read or error from `/dev/urandom'");
594     tokenptr = 0;
595   }
596
597   /* Now encode the bytes using a slightly tweaked base-64 encoding.  Read
598    * bytes into the accumulator and write out characters while there's
599    * enough material.
600    */
601   for (i = 0; i < TOKENRANDSZ; i++) {
602     a = (a << 8) | tokenbuf[tokenptr++]; b += 8;
603     while (b >= 6) {
604       b -= 6;
605       *p++ = tokmap[(a >> b) & 0x3f];
606     }
607   }
608
609   /* If there's anything left in the accumulator then flush it out. */
610   if (b)
611     *p++ = tokmap[(a << (6 - b)) & 0x3f];
612
613   /* Null-terminate the token. */
614   *p++ = 0;
615 }
616
617 /* Notification that a line has been received from the client.  Parse it,
618  * find out about the connection it's referring to, apply the relevant
619  * policy rules, and produce a response.  This is where almost everything
620  * interesting happens.
621  */
622 static void client_line(char *line, size_t len, void *p)
623 {
624   struct client *c = p;
625   const char *q;
626   struct passwd *pw = 0;
627   const struct policy *pol;
628   dstr d = DSTR_INIT;
629   struct policy upol = POLICY_INIT(A_LIMIT);
630   struct policy_file pf;
631   char buf[16];
632   int i;
633
634   /* If the connection has closed, then tidy stuff away. */
635   c->q.s[L].port = c->q.s[R].port = 0;
636   if (!line) {
637     disconnect_client(c);
638     return;
639   }
640
641   /* Client activity, so update the timer. */
642   reset_client_timer(c, 1);
643
644   /* See if the policy file has changed since we last looked.  If so, try to
645    * read the new version.
646    */
647   if (fwatch_update(&polfw, policyfile)) {
648     logmsg(0, LOG_INFO, "reload master policy file `%s'", policyfile);
649     load_policy_file(policyfile, &policy);
650   }
651
652   /* Read the local and remote port numbers into the query structure. */
653   q = line;
654   if (unum(&q, &c->q.s[L].port, 1, 65535)) goto bad;
655   skipws(&q); if (*q != ',') goto bad; q++;
656   if (unum(&q, &c->q.s[R].port, 1, 65535)) goto bad;
657   skipws(&q); if (*q) goto bad;
658
659   /* Identify the connection.  Act on the result. */
660   c->q.s[R].addr = c->raddr;
661   identify(&c->q);
662   switch (c->q.resp) {
663
664     case R_UID:
665       /* We found a user.  Track down the user's password entry, because
666        * we'll want that later.  Most of the processing for this case is
667        * below.
668        */
669       if ((pw = getpwuid(c->q.u.uid)) == 0) {
670         logmsg(&c->q, LOG_ERR, "no passwd entry for user %d", c->q.u.uid);
671         reply_error(c, E_NOUSER);
672         return;
673       }
674       break;
675
676     case R_NAT:
677       /* We've acted as a NAT for this connection.  Proxy the query through
678        * to the actal client host.
679        */
680       proxy_query(c);
681       return;
682
683     case R_ERROR:
684       /* We failed to identify the connection for some reason.  We should
685        * already have logged an error, so there's not much to do here.
686        */
687       reply_error(c, c->q.u.error);
688       return;
689
690     default:
691       /* Something happened that we don't understand. */
692       abort();
693   }
694
695   /* Search the table of policy rules to find a match. */
696   for (i = 0; i < DA_LEN(&policy); i++) {
697     pol = &DA(&policy)[i];
698     if (!match_policy(pol, &c->q)) continue;
699
700     /* If this is something simple, then apply the resulting policy rule. */
701     if (pol->act.act != A_USER) goto match;
702
703     /* The global policy has decided to let the user have a say, so we must
704      * parse the user file.
705      */
706     DRESET(&d);
707     dstr_putf(&d, "%s/.yaid.policy", pw->pw_dir);
708     if (open_policy_file(&pf, d.buf, "user policy file", &c->q))
709       continue;
710     while (!read_policy_file(&pf)) {
711
712       /* Give up after 100 lines.  If the user's policy is that complicated,
713        * something's gone very wrong.  Or there's too much commentary or
714        * something.
715        */
716       if (pf.lno > 100) {
717         logmsg(&c->q, LOG_ERR, "%s:%d: user policy file too long",
718                pf.name, pf.lno);
719         break;
720       }
721
722       /* If this isn't a match, go around for the next rule. */
723       if (!match_policy(&pf.p, &c->q)) continue;
724
725       /* Check that the user is allowed to request this action.  If not, see
726        * if there's a more acceptable action later on.
727        */
728       if (!(pol->act.u.user & (1 << pf.p.act.act))) {
729         logmsg(&c->q, LOG_ERR,
730                "%s:%d: user action forbidden by global policy",
731                pf.name, pf.lno);
732         continue;
733       }
734
735       /* We've found a match, so grab it, close the file, and say we're
736        * done.
737        */
738       upol = pf.p; pol = &upol;
739       init_policy(&pf.p);
740       close_policy_file(&pf);
741       DDESTROY(&d);
742       goto match;
743     }
744     close_policy_file(&pf);
745     DDESTROY(&d);
746   }
747
748   /* No match: apply the built-in default policy. */
749   pol = &default_policy;
750
751 match:
752   switch (pol->act.act) {
753
754     case A_NAME:
755       /* Report the actual user's name. */
756       logmsg(&c->q, LOG_INFO, "user `%s' (%d)", pw->pw_name, c->q.u.uid);
757       reply(c, "USERID", "UNIX", pw->pw_name);
758       break;
759
760     case A_TOKEN:
761       /* Report an arbitrary token which we can look up in our log file. */
762       user_token(buf);
763       logmsg(&c->q, LOG_INFO, "user `%s' (%d); token = %s",
764              pw->pw_name, c->q.u.uid, buf);
765       reply(c, "USERID", "OTHER", buf);
766       break;
767
768     case A_DENY:
769       /* Deny that there's anyone there at all. */
770       logmsg(&c->q, LOG_INFO, "user `%s' (%d); denying",
771              pw->pw_name, c->q.u.uid);
772       break;
773
774     case A_HIDE:
775       /* Report the user as being hidden. */
776       logmsg(&c->q, LOG_INFO, "user `%s' (%d); hiding",
777              pw->pw_name, c->q.u.uid);
778       reply_error(c, E_HIDDEN);
779       break;
780
781     case A_LIE:
782       /* Tell an egregious lie about who the user is. */
783       logmsg(&c->q, LOG_INFO, "user `%s' (%d); lie = `%s'",
784              pw->pw_name, c->q.u.uid, pol->act.u.lie);
785       reply(c, "USERID", "UNIX", pol->act.u.lie);
786       break;
787
788     default:
789       /* Something has gone very wrong. */
790       abort();
791   }
792
793   /* All done. */
794   free_policy(&upol);
795   return;
796
797 bad:
798   logmsg(&c->q, LOG_ERR, "failed to parse query from client");
799   disconnect_client(c);
800 }
801
802 /* Notification that a new client has connected.  Prepare to read a query. */
803 static void accept_client(int fd, unsigned mode, void *p)
804 {
805   struct listen *l = p;
806   struct client *c;
807   struct sockaddr_storage ssr, ssl;
808   size_t ssz = sizeof(ssr);
809   int sk;
810
811   /* Accept the new connection. */
812   if ((sk = accept(fd, (struct sockaddr *)&ssr, &ssz)) < 0) {
813     if (errno != EAGAIN && errno == EWOULDBLOCK) {
814       logmsg(0, LOG_ERR, "failed to accept incoming %s connection: %s",
815              l->ao->name, strerror(errno));
816     }
817     return;
818   }
819   if (fix_up_socket(sk, "incoming client")) { close(sk); return; }
820
821   /* Build a client block and fill it in. */
822   c = xmalloc(sizeof(*c));
823   c->l = l;
824   c->q.ao = l->ao;
825
826   /* Collect the local and remote addresses. */
827   l->ao->sockaddr_to_addr(&ssr, &c->raddr);
828   ssz = sizeof(ssl);
829   if (getsockname(sk, (struct sockaddr *)&ssl, &ssz)) {
830     logmsg(0, LOG_ERR,
831            "failed to read local address for incoming %s connection: %s",
832            l->ao->name, strerror(errno));
833     close(sk);
834     xfree(c);
835     return;
836   }
837   l->ao->sockaddr_to_addr(&ssl, &c->q.s[L].addr);
838   c->q.s[L].port = c->q.s[R].port = 0;
839
840   /* Set stuff up for reading the query and sending responses. */
841   selbuf_init(&c->b, &sel, sk, client_line, c);
842   selbuf_setsize(&c->b, 1024);
843   reset_client_timer(c, 0);
844   c->fd = sk;
845   c->px = 0;
846   init_writebuf(&c->wb, sk, done_client_write, c);
847 }
848
849 /*----- Main code ---------------------------------------------------------*/
850
851 /* Set up a listening socket for the address family described by AO,
852  * listening on PORT.
853  */
854 static int make_listening_socket(const struct addrops *ao, int port)
855 {
856   int fd;
857   int yes = 1;
858   struct socket s;
859   struct sockaddr_storage ss;
860   struct listen *l;
861   size_t ssz;
862
863   /* Make the socket. */
864   if ((fd = socket(ao->af, SOCK_STREAM, 0)) < 0) {
865     if (errno == EAFNOSUPPORT) return (-1);
866     die(1, "failed to create %s listening socket: %s",
867         ao->name, strerror(errno));
868   }
869
870   /* Build the appropriate local address. */
871   s.addr = *ao->any;
872   s.port = port;
873   ao->socket_to_sockaddr(&s, &ss, &ssz);
874
875   /* Perform any initialization specific to the address type. */
876   if (ao->init_listen_socket(fd)) {
877     die(1, "failed to initialize %s listening socket: %s",
878         ao->name, strerror(errno));
879   }
880
881   /* Bind to the address. */
882   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
883   if (bind(fd, (struct sockaddr *)&ss, ssz)) {
884     die(1, "failed to bind %s listening socket: %s",
885         ao->name, strerror(errno));
886   }
887
888   /* Avoid unpleasant race conditions. */
889   if (fdflags(fd, O_NONBLOCK, O_NONBLOCK, 0, 0)) {
890     die(1, "failed to set %s listening socket nonblocking: %s",
891         ao->name, strerror(errno));
892   }
893
894   /* Prepare to listen. */
895   if (listen(fd, 5))
896     die(1, "failed to listen for %s: %s", ao->name, strerror(errno));
897
898   /* Make a record of all of this. */
899   l = xmalloc(sizeof(*l));
900   l->ao = ao;
901   sel_initfile(&sel, &l->f, fd, SEL_READ, accept_client, l);
902   sel_addfile(&l->f);
903
904   /* Done. */
905   return (0);
906 }
907
908 /* Quit because of a fatal signal. */
909 static void quit(int sig, void *p)
910 {
911   const char *signame = p;
912
913   logmsg(0, LOG_NOTICE, "shutting down on %s", signame);
914   if (pidfile) unlink(pidfile);
915   exit(0);
916 }
917
918 /* Answer whether the string pointed to by P consists entirely of digits. */
919 static int numericp(const char *p)
920 {
921   while (*p)
922     if (!isdigit((unsigned char)*p++)) return (0);
923   return (1);
924 }
925
926 static void usage(FILE *fp)
927 {
928   pquis(fp, "Usage: $ [-Dl] [-G GROUP] [-U USER] [-P FILE] "
929         "[-c FILE] [-p PORT]\n");
930 }
931
932 static void version(FILE *fp)
933   { pquis(fp, "$, version " VERSION "\n"); }
934
935 static void help(FILE *fp)
936 {
937   version(fp); fputc('\n', fp);
938   usage(fp);
939   fputs("\n\
940 Yet Another Ident Daemon.  Really, the world doesn't need such a thing.\n\
941 It's just a shame none of the others do the right things.\n\
942 \n\
943 Options:\n\
944 \n\
945   -h, --help            Show this help message.\n\
946   -v, --version         Show the version number.\n\
947   -u, --usage           Show a very short usage summary.\n\
948 \n\
949   -D, --daemon          Become a daemon, running in the background.\n\
950   -G, --group=GROUP     Set group after initialization.\n\
951   -P, --pidfile=FILE    Write process id to FILE.\n\
952   -U, --user=USER       Set user after initialization.\n\
953   -c, --config=FILE     Read global policy from FILE.\n\
954   -l, --syslog          Write log messages using syslog(3).\n\
955   -p, --port=PORT       Listen for connections on this port.\n",
956         fp);
957 }
958
959 int main(int argc, char *argv[])
960 {
961   int port = 113;
962   uid_t u = -1;
963   gid_t g = -1;
964   struct passwd *pw = 0;
965   struct group *gr;
966   struct servent *s;
967   sig sigint, sigterm;
968   FILE *fp = 0;
969   int i;
970   unsigned f = 0;
971 #define f_bogus 1u
972 #define f_daemon 2u
973   const struct addrops *ao;
974   int any = 0;
975
976   ego(argv[0]);
977
978   /* Parse command-line options. */
979   for (;;) {
980     const struct option opts[] = {
981       { "help",         0,              0,      'h' },
982       { "version",      0,              0,      'v' },
983       { "usage",        0,              0,      'u' },
984       { "daemon",       0,              0,      'D' },
985       { "group",        OPTF_ARGREQ,    0,      'G' },
986       { "pidfile",      OPTF_ARGREQ,    0,      'P' },
987       { "user",         OPTF_ARGREQ,    0,      'U' },
988       { "config",       OPTF_ARGREQ,    0,      'c' },
989       { "syslog",       0,              0,      'l' },
990       { "port",         OPTF_ARGREQ,    0,      'p' },
991       { 0,              0,              0,      0 }
992     };
993
994     if ((i = mdwopt(argc, argv, "hvuDG:P:U:c:lp:", opts, 0, 0, 0)) < 0)
995       break;
996     switch (i) {
997       case 'h': help(stdout); exit(0);
998       case 'v': version(stdout); exit(0);
999       case 'u': usage(stdout); exit(0);
1000       case 'D': f |= f_daemon; break;
1001       case 'P': pidfile = optarg; break;
1002       case 'c': policyfile = optarg; break;
1003       case 'l': flags |= F_SYSLOG; break;
1004       case 'G':
1005         if (numericp(optarg))
1006           g = atoi(optarg);
1007         else if ((gr = getgrnam(optarg)) == 0)
1008           die(1, "unknown group `%s'", optarg);
1009         else
1010           g = gr->gr_gid;
1011         break;
1012       case 'U':
1013         if (numericp(optarg))
1014           u = atoi(optarg);
1015         else if ((pw = getpwnam(optarg)) == 0)
1016           die(1, "unknown user `%s'", optarg);
1017         else
1018           u = pw->pw_uid;
1019         break;
1020       case 'p':
1021         if (numericp(optarg))
1022           port = atoi(optarg);
1023         else if ((s = getservbyname(optarg, "tcp")) == 0)
1024           die(1, "unknown service name `%s'", optarg);
1025         else
1026           port = ntohs(s->s_port);
1027         break;
1028       default: f |= f_bogus; break;
1029     }
1030   }
1031   if (optind < argc) f |= f_bogus;
1032   if (f & f_bogus) { usage(stderr); exit(1); }
1033
1034   /* If a user has been requested, but no group, then find the user's primary
1035    * group.  If the user was given by name, then we already have a password
1036    * entry and should use that, in case two differently-named users have the
1037    * same uid but distinct gids.
1038    */
1039   if (u != -1 && g == -1) {
1040     if (!pw && (pw = getpwuid(u)) == 0) {
1041       die(1, "failed to find password entry for user %d: "
1042           "request group explicitly", u);
1043     }
1044     g = pw->pw_gid;
1045   }
1046
1047   /* Initialize system-specific machinery. */
1048   init_sys();
1049
1050   /* Load the global policy rules. */
1051   fwatch_init(&polfw, policyfile);
1052   if (load_policy_file(policyfile, &policy))
1053     exit(1);
1054
1055   /* Open the random data source. */
1056   if ((randfd = open("/dev/urandom", O_RDONLY)) < 0) {
1057     die(1, "failed to open `/dev/urandom' for reading: %s",
1058         strerror(errno));
1059   }
1060
1061   /* Set up the I/O event system. */
1062   sel_init(&sel);
1063
1064   /* Watch for some interesting signals. */
1065   sig_init(&sel);
1066   sig_add(&sigint, SIGINT, quit, "SIGINT");
1067   sig_add(&sigterm, SIGTERM, quit, "SIGTERM");
1068
1069   /* Listen for incoming connections. */
1070   for (ao = addroptab; ao->name; ao++)
1071     if (!make_listening_socket(ao, port)) any = 1;
1072   if (!any) die(1, "no IP protocols supported");
1073
1074   /* Open the pidfile now, in case it's somewhere we can't write. */
1075   if (pidfile && (fp = fopen(pidfile, "w")) == 0) {
1076     die(1, "failed to open pidfile `%s' for writing: %s",
1077         pidfile, strerror(errno));
1078   }
1079
1080   /* If we're meant to use syslog, then open the log. */
1081   if (flags & F_SYSLOG)
1082     openlog(QUIS, 0, LOG_DAEMON);
1083
1084   /* Drop privileges. */
1085   if ((g != -1 && (setegid(g) || setgid(g) ||
1086                    (getuid() == 0 && setgroups(1, &g)))) ||
1087       (u != -1 && setuid(u)))
1088     die(1, "failed to drop privileges: %s", strerror(errno));
1089
1090   /* Become a background process, if requested. */
1091   if ((f & f_daemon) && daemonize())
1092     die(1, "failed to become daemon: %s", strerror(errno));
1093
1094   /* Write the process id to the pidfile. */
1095   if (fp) {
1096     fprintf(fp, "%d\n", getpid());
1097     fclose(fp);
1098   }
1099
1100   /* And now we're going. */
1101   flags |= F_RUNNING;
1102
1103   /* Read events and process them. */
1104   for (;;) {
1105     if (sel_select(&sel) && errno != EINTR)
1106       die(1, "select failed: %s", strerror(errno));
1107   }
1108
1109   /* This just keeps the compiler happy. */
1110   return (0);
1111 }
1112
1113 /*----- That's all, folks -------------------------------------------------*/