Imported Upstream version 2.6.0p1
[debian/amanda] / common-src / security-util.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1999 University of Maryland
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26
27 /*
28  * $Id: security-util.c,v 1.25 2006/07/22 12:04:47 martinea Exp $
29  *
30  * sec-security.c - security and transport over sec or a sec-like command.
31  *
32  * XXX still need to check for initial keyword on connect so we can skip
33  * over shell garbage and other stuff that sec might want to spew out.
34  */
35
36 #include "amanda.h"
37 #include "util.h"
38 #include "event.h"
39 #include "packet.h"
40 #include "queue.h"
41 #include "security.h"
42 #include "security-util.h"
43 #include "stream.h"
44 #include "version.h"
45 #include "sockaddr-util.h"
46
47 /*
48  * Magic values for sec_conn->handle
49  */
50 #define H_TAKEN -1              /* sec_conn->tok was already read */
51 #define H_EOF   -2              /* this connection has been shut down */
52
53 /*
54  * This is a queue of open connections
55  */
56 struct connq_s connq = {
57     TAILQ_HEAD_INITIALIZER(connq.tailq), 0
58 };
59 static int newhandle = 1;
60 static int newevent = 1;
61
62 /*
63  * Local functions
64  */
65 static void recvpkt_callback(void *, void *, ssize_t);
66 static void stream_read_callback(void *);
67 static void stream_read_sync_callback(void *);
68
69 static void sec_tcp_conn_read_cancel(struct tcp_conn *);
70 static void sec_tcp_conn_read_callback(void *);
71
72
73 /*
74  * Authenticate a stream
75  * Nothing needed for sec.  The connection is authenticated by secd
76  * on startup.
77  */
78 int
79 sec_stream_auth(
80     void *      s)
81 {
82     (void)s;    /* Quiet unused parameter warning */
83     return (0);
84 }
85
86 /*
87  * Returns the stream id for this stream.  This is just the local
88  * port.
89  */
90 int
91 sec_stream_id(
92     void *      s)
93 {
94     struct sec_stream *rs = s;
95
96     assert(rs != NULL);
97
98     return (rs->handle);
99 }
100
101 /*
102  * Setup to handle new incoming connections
103  */
104 void
105 sec_accept(
106     const security_driver_t *driver,
107     char       *(*conf_fn)(char *, void *),
108     int         in,
109     int         out,
110     void        (*fn)(security_handle_t *, pkt_t *),
111     void       *datap)
112 {
113     struct tcp_conn *rc;
114
115     rc = sec_tcp_conn_get("unknown",0);
116     rc->read = in;
117     rc->write = out;
118     rc->accept_fn = fn;
119     rc->driver = driver;
120     rc->conf_fn = conf_fn;
121     rc->datap = datap;
122     sec_tcp_conn_read(rc);
123 }
124
125 /*
126  * frees a handle allocated by the above
127  */
128 void
129 sec_close(
130     void *      inst)
131 {
132     struct sec_handle *rh = inst;
133
134     assert(rh != NULL);
135
136     auth_debug(1, _("sec: closing handle to %s\n"), rh->hostname);
137
138     if (rh->rs != NULL) {
139         /* This may be null if we get here on an error */
140         stream_recvpkt_cancel(rh);
141         security_stream_close(&rh->rs->secstr);
142     }
143     /* keep us from getting here again */
144     rh->sech.driver = NULL;
145     amfree(rh->hostname);
146     amfree(rh);
147 }
148
149 /*
150  * Called when a sec connection is finished connecting and is ready
151  * to be authenticated.
152  */
153 void
154 sec_connect_callback(
155     void *      cookie)
156 {
157     struct sec_handle *rh = cookie;
158
159     event_release(rh->rs->ev_read);
160     rh->rs->ev_read = NULL;
161     event_release(rh->ev_timeout);
162     rh->ev_timeout = NULL;
163
164     (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
165 }
166
167 /*
168  * Called if a connection times out before completion.
169  */
170 void
171 sec_connect_timeout(
172     void *      cookie)
173 {
174     struct sec_handle *rh = cookie;
175
176     event_release(rh->rs->ev_read);
177     rh->rs->ev_read = NULL;
178     event_release(rh->ev_timeout);
179     rh->ev_timeout = NULL;
180
181     (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
182 }
183
184 void
185 sec_close_connection_none(
186     void *h,
187     char *hostname)
188 {
189     h = h;
190     hostname = hostname;
191
192     return;
193 }
194
195
196
197 /*
198  * Transmit a packet.
199  */
200 ssize_t
201 stream_sendpkt(
202     void *      cookie,
203     pkt_t *     pkt)
204 {
205     char *buf;
206     struct sec_handle *rh = cookie;
207     size_t len;
208     char *s;
209
210     assert(rh != NULL);
211     assert(pkt != NULL);
212
213     auth_debug(1, _("sec: stream_sendpkt: enter\n"));
214
215     if (rh->rc->prefix_packet)
216         s = rh->rc->prefix_packet(rh, pkt);
217     else
218         s = "";
219     len = strlen(pkt->body) + strlen(s) + 2;
220     buf = alloc(len);
221     buf[0] = (char)pkt->type;
222     strncpy(&buf[1], s, len - 1);
223     strncpy(&buf[1 + strlen(s)], pkt->body, (len - strlen(s) - 1));
224     if (strlen(s) > 0)
225         amfree(s);
226
227     auth_debug(1,
228      _("sec: stream_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),
229       pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);
230
231     if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {
232         security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
233         return (-1);
234     }
235     amfree(buf);
236     return (0);
237 }
238
239 /*
240  * Set up to receive a packet asyncronously, and call back when
241  * it has been read.
242  */
243 void
244 stream_recvpkt(
245     void *      cookie,
246     void        (*fn)(void *, pkt_t *, security_status_t),
247     void *      arg,
248     int         timeout)
249 {
250     struct sec_handle *rh = cookie;
251
252     assert(rh != NULL);
253
254     auth_debug(1, _("sec: recvpkt registered for %s\n"), rh->hostname);
255
256     /*
257      * Reset any pending timeout on this handle
258      */
259     if (rh->ev_timeout != NULL)
260         event_release(rh->ev_timeout);
261
262     /*
263      * Negative timeouts mean no timeout
264      */
265     if (timeout < 0) {
266         rh->ev_timeout = NULL;
267     } else {
268         rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
269                 stream_recvpkt_timeout, rh);
270     }
271     rh->fn.recvpkt = fn;
272     rh->arg = arg;
273     security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);
274 }
275
276 /*
277  * This is called when a handle times out before receiving a packet.
278  */
279 void
280 stream_recvpkt_timeout(
281     void *      cookie)
282 {
283     struct sec_handle *rh = cookie;
284
285     assert(rh != NULL);
286
287     auth_debug(1, _("sec: recvpkt timeout for %s\n"), rh->hostname);
288
289     stream_recvpkt_cancel(rh);
290     (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
291 }
292
293 /*
294  * Remove a async receive request from the queue
295  */
296 void
297 stream_recvpkt_cancel(
298     void *      cookie)
299 {
300     struct sec_handle *rh = cookie;
301
302     auth_debug(1, _("sec: cancelling recvpkt for %s\n"), rh->hostname);
303
304     assert(rh != NULL);
305
306     security_stream_read_cancel(&rh->rs->secstr);
307     if (rh->ev_timeout != NULL) {
308         event_release(rh->ev_timeout);
309         rh->ev_timeout = NULL;
310     }
311 }
312
313 /*
314  * Write a chunk of data to a stream.  Blocks until completion.
315  */
316 int
317 tcpm_stream_write(
318     void *      s,
319     const void *buf,
320     size_t      size)
321 {
322     struct sec_stream *rs = s;
323
324     assert(rs != NULL);
325     assert(rs->rc != NULL);
326
327     auth_debug(1, _("sec: stream_write: writing %zu bytes to %s:%d %d\n"),
328                    size, rs->rc->hostname, rs->handle,
329                    rs->rc->write);
330
331     if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg,
332                              buf, size)) {
333         security_stream_seterror(&rs->secstr, rs->rc->errmsg);
334         return (-1);
335     }
336     return (0);
337 }
338
339 /*
340  * Submit a request to read some data.  Calls back with the given
341  * function and arg when completed.
342  */
343 void
344 tcpm_stream_read(
345     void *      s,
346     void        (*fn)(void *, void *, ssize_t),
347     void *      arg)
348 {
349     struct sec_stream *rs = s;
350
351     assert(rs != NULL);
352
353     /*
354      * Only one read request can be active per stream.
355      */
356     if (rs->ev_read == NULL) {
357         rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
358             stream_read_callback, rs);
359         sec_tcp_conn_read(rs->rc);
360     }
361     rs->fn = fn;
362     rs->arg = arg;
363 }
364
365 /*
366  * Write a chunk of data to a stream.  Blocks until completion.
367  */
368 ssize_t
369 tcpm_stream_read_sync(
370     void *      s,
371     void **     buf)
372 {
373     struct sec_stream *rs = s;
374
375     assert(rs != NULL);
376
377     /*
378      * Only one read request can be active per stream.
379      */
380     if (rs->ev_read != NULL) {
381         return -1;
382     }
383     rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
384         stream_read_sync_callback, rs);
385     sec_tcp_conn_read(rs->rc);
386     event_wait(rs->ev_read);
387     *buf = rs->rc->pkt;
388     return (rs->rc->pktlen);
389 }
390
391 /*
392  * Cancel a previous stream read request.  It's ok if we didn't have a read
393  * scheduled.
394  */
395 void
396 tcpm_stream_read_cancel(
397     void *      s)
398 {
399     struct sec_stream *rs = s;
400
401     assert(rs != NULL);
402
403     if (rs->ev_read != NULL) {
404         event_release(rs->ev_read);
405         rs->ev_read = NULL;
406         sec_tcp_conn_read_cancel(rs->rc);
407     }
408 }
409
410 /*
411  * Transmits a chunk of data over a rsh_handle, adding
412  * the necessary headers to allow the remote end to decode it.
413  */
414 ssize_t
415 tcpm_send_token(
416     struct tcp_conn *rc,
417     int         fd,
418     int         handle,
419     char **     errmsg,
420     const void *buf,
421     size_t      len)
422 {
423     guint32             nethandle;
424     guint32             netlength;
425     struct iovec        iov[3];
426     int                 nb_iov = 3;
427     int                 rval;
428     char                *encbuf;
429     ssize_t             encsize;
430
431     assert(SIZEOF(netlength) == 4);
432
433     auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n",
434           len, handle);
435     /*
436      * Format is:
437      *   32 bit length (network byte order)
438      *   32 bit handle (network byte order)
439      *   data
440      */
441     netlength = htonl(len);
442     iov[0].iov_base = (void *)&netlength;
443     iov[0].iov_len = SIZEOF(netlength);
444
445     nethandle = htonl((guint32)handle);
446     iov[1].iov_base = (void *)&nethandle;
447     iov[1].iov_len = SIZEOF(nethandle);
448
449     encbuf = (char *)buf;
450     encsize = len;
451
452     if(len == 0) {
453         nb_iov = 2;
454     }
455     else {
456         if (rc->driver->data_encrypt == NULL) {
457             iov[2].iov_base = (void *)buf;
458             iov[2].iov_len = len;
459         } else {
460             /* (the extra (void *) cast is to quiet type-punning warnings) */
461             rc->driver->data_encrypt(rc, (void *)buf, len, (void **)(void *)&encbuf, &encsize);
462             iov[2].iov_base = (void *)encbuf;
463             iov[2].iov_len = encsize;
464             netlength = htonl(encsize);
465         }
466         nb_iov = 3;
467     }
468
469     rval = net_writev(fd, iov, nb_iov);
470     if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) {
471         amfree(encbuf);
472     }
473
474     if (rval < 0) {
475         if (errmsg)
476             *errmsg = newvstrallocf(*errmsg, _("write error to: %s"),
477                                    strerror(errno));
478         return (-1);
479     }
480     return (0);
481 }
482
483 /*
484  *  return -1 on error
485  *  return  0 on EOF:   *handle = H_EOF  && *size = 0    if socket closed
486  *  return  0 on EOF:   *handle = handle && *size = 0    if stream closed
487  *  return size     :   *handle = handle && *size = size for data read
488  */
489
490 ssize_t
491 tcpm_recv_token(
492     struct tcp_conn    *rc,
493     int         fd,
494     int *       handle,
495     char **     errmsg,
496     char **     buf,
497     ssize_t *   size,
498     int         timeout)
499 {
500     unsigned int netint[2];
501
502     assert(SIZEOF(netint) == 8);
503
504     switch (net_read(fd, &netint, SIZEOF(netint), timeout)) {
505     case -1:
506         if (errmsg)
507             *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno));
508         auth_debug(1, _("tcpm_recv_token: A return(-1)\n"));
509         return (-1);
510     case 0:
511         *size = 0;
512         *handle = H_EOF;
513         *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
514         auth_debug(1, _("tcpm_recv_token: A return(0)\n"));
515         return (0);
516     default:
517         break;
518     }
519
520     *size = (ssize_t)ntohl(netint[0]);
521     *handle = (int)ntohl(netint[1]);
522     /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */
523     if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) {
524         if (isprint((int)(*size        ) & 0xFF) &&
525             isprint((int)(*size   >> 8 ) & 0xFF) &&
526             isprint((int)(*size   >> 16) & 0xFF) &&
527             isprint((int)(*size   >> 24) & 0xFF) &&
528             isprint((*handle      ) & 0xFF) &&
529             isprint((*handle >> 8 ) & 0xFF) &&
530             isprint((*handle >> 16) & 0xFF) &&
531             isprint((*handle >> 24) & 0xFF)) {
532             char s[101];
533             int i;
534             s[0] = ((int)(*size)  >> 24) & 0xFF;
535             s[1] = ((int)(*size)  >> 16) & 0xFF;
536             s[2] = ((int)(*size)  >>  8) & 0xFF;
537             s[3] = ((int)(*size)       ) & 0xFF;
538             s[4] = (*handle >> 24) & 0xFF;
539             s[5] = (*handle >> 16) & 0xFF;
540             s[6] = (*handle >> 8 ) & 0xFF;
541             s[7] = (*handle      ) & 0xFF;
542             i = 8; s[i] = ' ';
543             while(i<100 && isprint((int)s[i]) && s[i] != '\n') {
544                 switch(net_read(fd, &s[i], 1, 0)) {
545                 case -1: s[i] = '\0'; break;
546                 case  0: s[i] = '\0'; break;
547                 default:
548                          dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' ';
549                          break;
550                 }
551             }
552             s[i] = '\0';
553             *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size: %s"), s);
554             dbprintf(_("tcpm_recv_token: invalid size %s\n"), s);
555         } else {
556             *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size"));
557             dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size);
558         }
559         *size = -1;
560         return -1;
561     }
562     amfree(*buf);
563     *buf = alloc((size_t)*size);
564
565     if(*size == 0) {
566         auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle);
567         *errmsg = newvstrallocf(*errmsg, _("EOF"));
568         return 0;
569     }
570     switch (net_read(fd, *buf, (size_t)*size, timeout)) {
571     case -1:
572         if (errmsg)
573             *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno));
574         auth_debug(1, _("tcpm_recv_token: B return(-1)\n"));
575         return (-1);
576     case 0:
577         *size = 0;
578         *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
579         auth_debug(1, _("tcpm_recv_token: B return(0)\n"));
580         return (0);
581     default:
582         break;
583     }
584
585     auth_debug(1, _("tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle);
586
587     if (*size > 0 && rc->driver->data_decrypt != NULL) {
588         void *decbuf;
589         ssize_t decsize;
590         rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize);
591         if (*buf != (char *)decbuf) {
592             amfree(*buf);
593             *buf = (char *)decbuf;
594         }
595         *size = decsize;
596     }
597
598     return((*size));
599 }
600
601 void
602 tcpm_close_connection(
603     void *h,
604     char *hostname)
605 {
606     struct sec_handle *rh = h;
607
608     (void)hostname;
609
610     if (rh && rh->rc && rh->rc->toclose == 0) {
611         rh->rc->toclose = 1;
612         sec_tcp_conn_put(rh->rc);
613     }
614 }
615
616
617
618 /*
619  * Accept an incoming connection on a stream_server socket
620  * Nothing needed for tcpma.
621  */
622 int
623 tcpma_stream_accept(
624     void *      s)
625 {
626     (void)s;    /* Quiet unused parameter warning */
627
628     return (0);
629 }
630
631 /*
632  * Return a connected stream.  For sec, this means setup a stream
633  * with the supplied handle.
634  */
635 void *
636 tcpma_stream_client(
637     void *      h,
638     int         id)
639 {
640     struct sec_handle *rh = h;
641     struct sec_stream *rs;
642
643     assert(rh != NULL);
644
645     if (id <= 0) {
646         security_seterror(&rh->sech,
647             _("%d: invalid security stream id"), id);
648         return (NULL);
649     }
650
651     rs = alloc(SIZEOF(*rs));
652     security_streaminit(&rs->secstr, rh->sech.driver);
653     rs->handle = id;
654     rs->ev_read = NULL;
655     rs->closed_by_me = 0;
656     rs->closed_by_network = 0;
657     if (rh->rc) {
658         rs->rc = rh->rc;
659         rh->rc->refcnt++;
660     }
661     else {
662         rs->rc = sec_tcp_conn_get(rh->hostname, 0);
663         rs->rc->driver = rh->sech.driver;
664         rh->rc = rs->rc;
665     }
666
667     auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id);
668
669     return (rs);
670 }
671
672 /*
673  * Create the server end of a stream.  For sec, this means setup a stream
674  * object and allocate a new handle for it.
675  */
676 void *
677 tcpma_stream_server(
678     void *      h)
679 {
680     struct sec_handle *rh = h;
681     struct sec_stream *rs;
682
683     assert(rh != NULL);
684
685     rs = alloc(SIZEOF(*rs));
686     security_streaminit(&rs->secstr, rh->sech.driver);
687     rs->closed_by_me = 0;
688     rs->closed_by_network = 0;
689     if (rh->rc) {
690         rs->rc = rh->rc;
691         rs->rc->refcnt++;
692     }
693     else {
694         rs->rc = sec_tcp_conn_get(rh->hostname, 0);
695         rs->rc->driver = rh->sech.driver;
696         rh->rc = rs->rc;
697     }
698     /*
699      * Stream should already be setup!
700      */
701     if (rs->rc->read < 0) {
702         sec_tcp_conn_put(rs->rc);
703         amfree(rs);
704         security_seterror(&rh->sech, _("lost connection to %s"), rh->hostname);
705         return (NULL);
706     }
707     assert(strcmp(rh->hostname, rs->rc->hostname) == 0);
708     /*
709      * so as not to conflict with the amanda server's handle numbers,
710      * we start at 500000 and work down
711      */
712     rs->handle = 500000 - newhandle++;
713     rs->ev_read = NULL;
714     auth_debug(1, _("sec: stream_server: created stream %d\n"), rs->handle);
715     return (rs);
716 }
717
718 /*
719  * Close and unallocate resources for a stream.
720  */
721 void
722 tcpma_stream_close(
723     void *      s)
724 {
725     struct sec_stream *rs = s;
726     char buf = 0;
727
728     assert(rs != NULL);
729
730     auth_debug(1, _("sec: tcpma_stream_close: closing stream %d\n"), rs->handle);
731
732     if(rs->closed_by_network == 0 && rs->rc->write != -1)
733         tcpm_stream_write(rs, &buf, 0);
734     security_stream_read_cancel(&rs->secstr);
735     if(rs->closed_by_network == 0)
736         sec_tcp_conn_put(rs->rc);
737     amfree(rs);
738 }
739
740 /*
741  * Create the server end of a stream.  For bsdudp, this means setup a tcp
742  * socket for receiving a connection.
743  */
744 void *
745 tcp1_stream_server(
746     void *      h)
747 {
748     struct sec_stream *rs = NULL;
749     struct sec_handle *rh = h;
750
751     assert(rh != NULL);
752
753     rs = alloc(SIZEOF(*rs));
754     security_streaminit(&rs->secstr, rh->sech.driver);
755     rs->closed_by_me = 0;
756     rs->closed_by_network = 0;
757     if (rh->rc) {
758         rs->rc = rh->rc;
759         rs->handle = 500000 - newhandle++;
760         rs->rc->refcnt++;
761         rs->socket = 0;         /* the socket is already opened */
762     }
763     else {
764         rh->rc = sec_tcp_conn_get(rh->hostname, 1);
765         rh->rc->driver = rh->sech.driver;
766         rs->rc = rh->rc;
767         rs->socket = stream_server(rh->udp->peer.ss_family, &rs->port,
768                                    STREAM_BUFSIZE, STREAM_BUFSIZE, 0);
769         if (rs->socket < 0) {
770             security_seterror(&rh->sech,
771                             _("can't create server stream: %s"), strerror(errno));
772             amfree(rs);
773             return (NULL);
774         }
775         rh->rc->read = rs->socket;
776         rh->rc->write = rs->socket;
777         rs->handle = (int)rs->port;
778     }
779     rs->fd = -1;
780     rs->ev_read = NULL;
781     return (rs);
782 }
783
784 /*
785  * Accepts a new connection on unconnected streams.  Assumes it is ok to
786  * block on accept()
787  */
788 int
789 tcp1_stream_accept(
790     void *      s)
791 {
792     struct sec_stream *bs = s;
793
794     assert(bs != NULL);
795     assert(bs->socket != -1);
796     assert(bs->fd < 0);
797
798     if (bs->socket > 0) {
799         bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE);
800         if (bs->fd < 0) {
801             security_stream_seterror(&bs->secstr,
802                                      _("can't accept new stream connection: %s"),
803                                      strerror(errno));
804             return (-1);
805         }
806         bs->rc->read = bs->fd;
807         bs->rc->write = bs->fd;
808     }
809     return (0);
810 }
811
812 /*
813  * Return a connected stream
814  */
815 void *
816 tcp1_stream_client(
817     void *      h,
818     int         id)
819 {
820     struct sec_stream *rs = NULL;
821     struct sec_handle *rh = h;
822
823     assert(rh != NULL);
824
825     rs = alloc(SIZEOF(*rs));
826     security_streaminit(&rs->secstr, rh->sech.driver);
827     rs->handle = id;
828     rs->ev_read = NULL;
829     rs->closed_by_me = 0;
830     rs->closed_by_network = 0;
831     if (rh->rc) {
832         rs->rc = rh->rc;
833         rh->rc->refcnt++;
834     }
835     else {
836         rh->rc = sec_tcp_conn_get(rh->hostname, 1);
837         rh->rc->driver = rh->sech.driver;
838         rs->rc = rh->rc;
839         rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
840                         STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
841         if (rh->rc->read < 0) {
842             security_seterror(&rh->sech,
843                               _("can't connect stream to %s port %d: %s"),
844                                rh->hostname, id, strerror(errno));
845             amfree(rs);
846             return (NULL);
847         }
848         rh->rc->write = rh->rc->read;
849     }
850     rs->socket = -1;    /* we're a client */
851     rh->rs = rs;
852     return (rs);
853 }
854
855 int
856 tcp_stream_write(
857     void *      s,
858     const void *buf,
859     size_t      size)
860 {
861     struct sec_stream *rs = s;
862
863     assert(rs != NULL);
864
865     if (fullwrite(rs->fd, buf, size) < 0) {
866         security_stream_seterror(&rs->secstr,
867             _("write error on stream %d: %s"), rs->port, strerror(errno));
868         return (-1);
869     }
870     return (0);
871 }
872
873 char *
874 bsd_prefix_packet(
875     void *      h,
876     pkt_t *     pkt)
877 {
878     struct sec_handle *rh = h;
879     struct passwd *pwd;
880     char *buf;
881
882     if (pkt->type != P_REQ)
883         return "";
884
885     if ((pwd = getpwuid(getuid())) == NULL) {
886         security_seterror(&rh->sech,
887                           _("can't get login name for my uid %ld"),
888                           (long)getuid());
889         return(NULL);
890     }
891     buf = alloc(16+strlen(pwd->pw_name));
892     strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name)));
893     strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14));
894     buf[14 + strlen(pwd->pw_name)] = '\n';
895     buf[15 + strlen(pwd->pw_name)] = '\0';
896
897     return (buf);
898 }
899
900
901 /*
902  * Check the security of a received packet.  Returns negative on security
903  * violation, or returns 0 if ok.  Removes the security info from the pkt_t.
904  */
905 int
906 bsd_recv_security_ok(
907     struct sec_handle * rh,
908     pkt_t *             pkt)
909 {
910     char *tok, *security, *body, *result;
911     char *service = NULL, *serviceX, *serviceY;
912     char *security_line;
913     char *s, ch;
914     size_t len;
915     in_port_t port;
916
917     /*
918      * Now, find the SECURITY line in the body, and parse it out
919      * into an argv.
920      */
921     if (strncmp_const(pkt->body, "SECURITY ") == 0) {
922         security = pkt->body;
923         len = 0;
924         while(*security != '\n' && len < pkt->size) {
925             security++;
926             len++;
927         }
928         if(*security == '\n') {
929             body = security+1;
930             *security = '\0';
931             security_line = stralloc(pkt->body);
932             security = pkt->body + strlen("SECURITY ");
933         } else {
934             body = pkt->body;
935             security_line = NULL;
936             security = NULL;
937         }
938     } else {
939         body = pkt->body;
940         security_line = NULL;
941         security = NULL;
942     }
943
944     /*
945      * Now, find the SERVICE line in the body, and parse it out
946      * into an argv.
947      */
948     s = body;
949     if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) {
950         serviceX = stralloc(s);
951         serviceY = strtok(serviceX, "\n");
952         if (serviceY)
953             service  = stralloc(serviceY);
954         amfree(serviceX);
955     }
956
957     /*
958      * We need to do different things depending on which type of packet
959      * this is.
960      */
961     switch (pkt->type) {
962     case P_REQ:
963         /*
964          * Request packets must come from a reserved port
965          */
966     port = SS_GET_PORT(&rh->peer);
967         if (port >= IPPORT_RESERVED) {
968             security_seterror(&rh->sech,
969                 _("host %s: port %u not secure"), rh->hostname,
970                 (unsigned int)port);
971             amfree(service);
972             amfree(security_line);
973             return (-1);
974         }
975
976         if (!service) {
977             security_seterror(&rh->sech,
978                               _("packet as no SERVICE line"));
979             amfree(security_line);
980             return (-1);
981         }
982
983         /*
984          * Request packets contain a remote username.  We need to check
985          * that we allow it in.
986          *
987          * They will look like:
988          *      SECURITY USER [username]
989          */
990
991         /* there must be some security info */
992         if (security == NULL) {
993             security_seterror(&rh->sech,
994                 _("no bsd SECURITY for P_REQ"));
995             amfree(service);
996             return (-1);
997         }
998
999         /* second word must be USER */
1000         if ((tok = strtok(security, " ")) == NULL) {
1001             security_seterror(&rh->sech,
1002                 _("SECURITY line: %s"), security_line);
1003             amfree(service);
1004             amfree(security_line);
1005             return (-1);        /* default errmsg */
1006         }
1007         if (strcmp(tok, "USER") != 0) {
1008             security_seterror(&rh->sech,
1009                 _("REQ SECURITY line parse error, expecting USER, got %s"), tok);
1010             amfree(service);
1011             amfree(security_line);
1012             return (-1);
1013         }
1014
1015         /* the third word is the username */
1016         if ((tok = strtok(NULL, "")) == NULL) {
1017             security_seterror(&rh->sech,
1018                 _("SECURITY line: %s"), security_line);
1019             amfree(security_line);
1020             return (-1);        /* default errmsg */
1021         }
1022         if ((result = check_user(rh, tok, service)) != NULL) {
1023             security_seterror(&rh->sech, "%s", result);
1024             amfree(service);
1025             amfree(result);
1026             amfree(security_line);
1027             return (-1);
1028         }
1029
1030         /* we're good to go */
1031         break;
1032     default:
1033         break;
1034     }
1035     amfree(service);
1036     amfree(security_line);
1037
1038     /*
1039      * If there is security info at the front of the packet, we need to
1040      * shift the rest of the data up and nuke it.
1041      */
1042     if (body != pkt->body)
1043         memmove(pkt->body, body, strlen(body) + 1);
1044     return (0);
1045 }
1046
1047 /*
1048  * Transmit a packet.  Add security information first.
1049  */
1050 ssize_t
1051 udpbsd_sendpkt(
1052     void *      cookie,
1053     pkt_t *     pkt)
1054 {
1055     struct sec_handle *rh = cookie;
1056     struct passwd *pwd;
1057
1058     assert(rh != NULL);
1059     assert(pkt != NULL);
1060
1061     auth_debug(1, _("udpbsd_sendpkt: enter\n"));
1062     /*
1063      * Initialize this datagram, and add the header
1064      */
1065     dgram_zero(&rh->udp->dgram);
1066     dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt));
1067
1068     /*
1069      * Add the security info.  This depends on which kind of packet we're
1070      * sending.
1071      */
1072     switch (pkt->type) {
1073     case P_REQ:
1074         /*
1075          * Requests get sent with our username in the body
1076          */
1077         if ((pwd = getpwuid(geteuid())) == NULL) {
1078             security_seterror(&rh->sech,
1079                 _("can't get login name for my uid %ld"), (long)getuid());
1080             return (-1);
1081         }
1082         dgram_cat(&rh->udp->dgram, _("SECURITY USER %s\n"), pwd->pw_name);
1083         break;
1084
1085     default:
1086         break;
1087     }
1088
1089     /*
1090      * Add the body, and send it
1091      */
1092     dgram_cat(&rh->udp->dgram, pkt->body);
1093
1094     auth_debug(1,
1095      _("sec: udpbsd_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),
1096       pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);
1097
1098     if (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) {
1099         security_seterror(&rh->sech,
1100             _("send %s to %s failed: %s"), pkt_type2str(pkt->type),
1101             rh->hostname, strerror(errno));
1102         return (-1);
1103     }
1104     return (0);
1105 }
1106
1107 void
1108 udp_close(
1109     void *      cookie)
1110 {
1111     struct sec_handle *rh = cookie;
1112
1113     if (rh->proto_handle == NULL) {
1114         return;
1115     }
1116
1117     auth_debug(1, _("udp: close handle '%s'\n"), rh->proto_handle);
1118
1119     udp_recvpkt_cancel(rh);
1120     if (rh->next) {
1121         rh->next->prev = rh->prev;
1122     }
1123     else {
1124         rh->udp->bh_last = rh->prev;
1125     }
1126     if (rh->prev) {
1127         rh->prev->next = rh->next;
1128     }
1129     else {
1130         rh->udp->bh_first = rh->next;
1131     }
1132
1133     amfree(rh->proto_handle);
1134     amfree(rh->hostname);
1135     amfree(rh);
1136 }
1137
1138 /*
1139  * Set up to receive a packet asynchronously, and call back when it has
1140  * been read.
1141  */
1142 void
1143 udp_recvpkt(
1144     void *      cookie,
1145     void        (*fn)(void *, pkt_t *, security_status_t),
1146     void *      arg,
1147     int         timeout)
1148 {
1149     struct sec_handle *rh = cookie;
1150
1151     auth_debug(1, _("udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n"),
1152                    cookie, fn, arg, timeout);
1153     assert(rh != NULL);
1154     assert(fn != NULL);
1155
1156
1157     /*
1158      * Subsequent recvpkt calls override previous ones
1159      */
1160     if (rh->ev_read == NULL) {
1161         udp_addref(rh->udp, &udp_netfd_read_callback);
1162         rh->ev_read = event_register(rh->event_id, EV_WAIT,
1163             udp_recvpkt_callback, rh);
1164     }
1165     if (rh->ev_timeout != NULL)
1166         event_release(rh->ev_timeout);
1167     if (timeout < 0)
1168         rh->ev_timeout = NULL;
1169     else
1170         rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
1171                                         udp_recvpkt_timeout, rh);
1172     rh->fn.recvpkt = fn;
1173     rh->arg = arg;
1174 }
1175
1176 /*
1177  * Remove a async receive request on this handle from the queue.
1178  * If it is the last one to be removed, then remove the event
1179  * handler for our network fd
1180  */
1181 void
1182 udp_recvpkt_cancel(
1183     void *      cookie)
1184 {
1185     struct sec_handle *rh = cookie;
1186
1187     assert(rh != NULL);
1188
1189     if (rh->ev_read != NULL) {
1190         udp_delref(rh->udp);
1191         event_release(rh->ev_read);
1192         rh->ev_read = NULL;
1193     }
1194
1195     if (rh->ev_timeout != NULL) {
1196         event_release(rh->ev_timeout);
1197         rh->ev_timeout = NULL;
1198     }
1199 }
1200
1201 /*
1202  * This is called when a handle is woken up because data read off of the
1203  * net is for it.
1204  */
1205 void
1206 udp_recvpkt_callback(
1207     void *      cookie)
1208 {
1209     struct sec_handle *rh = cookie;
1210     void (*fn)(void *, pkt_t *, security_status_t);
1211     void *arg;
1212
1213     auth_debug(1, _("udp: receive handle '%s' netfd '%s'\n"),
1214                    rh->proto_handle, rh->udp->handle);
1215     assert(rh != NULL);
1216
1217     /* if it doesn't correspond to this handle, something is wrong */
1218     assert(strcmp(rh->proto_handle, rh->udp->handle) == 0);
1219
1220     /* if it didn't come from the same host/port, forget it */
1221     if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) {
1222         amfree(rh->udp->handle);
1223         dbprintf(_("not from same host\n"));
1224         dump_sockaddr(&rh->peer);
1225         dump_sockaddr(&rh->udp->peer);
1226         return;
1227     }
1228
1229     /*
1230      * We need to cancel the recvpkt request before calling the callback
1231      * because the callback may reschedule us.
1232      */
1233     fn = rh->fn.recvpkt;
1234     arg = rh->arg;
1235     udp_recvpkt_cancel(rh);
1236
1237     /*
1238      * Check the security of the packet.  If it is bad, then pass NULL
1239      * to the packet handling function instead of a packet.
1240      */
1241     if (rh->udp->recv_security_ok &&
1242         rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) {
1243         (*fn)(arg, NULL, S_ERROR);
1244     } else {
1245         (*fn)(arg, &rh->udp->pkt, S_OK);
1246     }
1247 }
1248
1249 /*
1250  * This is called when a handle times out before receiving a packet.
1251  */
1252 void
1253 udp_recvpkt_timeout(
1254     void *      cookie)
1255 {
1256     struct sec_handle *rh = cookie;
1257     void (*fn)(void *, pkt_t *, security_status_t);
1258     void *arg;
1259
1260     assert(rh != NULL);
1261
1262     assert(rh->ev_timeout != NULL);
1263     fn = rh->fn.recvpkt;
1264     arg = rh->arg;
1265     udp_recvpkt_cancel(rh);
1266     (*fn)(arg, NULL, S_TIMEOUT);
1267 }
1268
1269 /*
1270  * Given a hostname and a port, setup a udp_handle
1271  */
1272 int
1273 udp_inithandle(
1274     udp_handle_t *      udp,
1275     struct sec_handle * rh,
1276     char *              hostname,
1277     struct sockaddr_storage *addr,
1278     in_port_t           port,
1279     char *              handle,
1280     int                 sequence)
1281 {
1282     /*
1283      * Save the hostname and port info
1284      */
1285     auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"),
1286                    (unsigned int)ntohs(port), handle, sequence);
1287     assert(addr != NULL);
1288
1289     rh->hostname = stralloc(hostname);
1290     copy_sockaddr(&rh->peer, addr);
1291     SS_SET_PORT(&rh->peer, port);
1292
1293
1294     rh->prev = udp->bh_last;
1295     if (udp->bh_last) {
1296         rh->prev->next = rh;
1297     }
1298     if (!udp->bh_first) {
1299         udp->bh_first = rh;
1300     }
1301     rh->next = NULL;
1302     udp->bh_last = rh;
1303
1304     rh->sequence = sequence;
1305     rh->event_id = (event_id_t)newevent++;
1306     amfree(rh->proto_handle);
1307     rh->proto_handle = stralloc(handle);
1308     rh->fn.connect = NULL;
1309     rh->arg = NULL;
1310     rh->ev_read = NULL;
1311     rh->ev_timeout = NULL;
1312
1313     auth_debug(1, _("udp: adding handle '%s'\n"), rh->proto_handle);
1314
1315     return(0);
1316 }
1317
1318
1319 /*
1320  * Callback for received packets.  This is the function bsd_recvpkt
1321  * registers with the event handler.  It is called when the event handler
1322  * realizes that data is waiting to be read on the network socket.
1323  */
1324 void
1325 udp_netfd_read_callback(
1326     void *      cookie)
1327 {
1328     struct udp_handle *udp = cookie;
1329     struct sec_handle *rh;
1330     int a;
1331     char hostname[NI_MAXHOST];
1332     in_port_t port;
1333     char *errmsg = NULL;
1334     int result;
1335
1336     auth_debug(1, _("udp_netfd_read_callback(cookie=%p)\n"), cookie);
1337     assert(udp != NULL);
1338     
1339 #ifndef TEST                                                    /* { */
1340     /*
1341      * Receive the packet.
1342      */
1343     dgram_zero(&udp->dgram);
1344     if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)
1345         return;
1346 #endif /* !TEST */                                              /* } */
1347
1348     /*
1349      * Parse the packet.
1350      */
1351     if (str2pkthdr(udp) < 0)
1352         return;
1353
1354     /*
1355      * If there are events waiting on this handle, we're done
1356      */
1357     rh = udp->bh_first;
1358     while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||
1359                          rh->sequence != udp->sequence ||
1360                          cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) {
1361         rh = rh->next;
1362     }
1363     if (rh && event_wakeup(rh->event_id) > 0)
1364         return;
1365
1366     /*
1367      * If we didn't find a handle, then check for a new incoming packet.
1368      * If no accept handler was setup, then just return.
1369      */
1370     if (udp->accept_fn == NULL) {
1371         dbprintf(_("Receive packet from unknown source"));
1372         return;
1373     }
1374
1375     rh = alloc(SIZEOF(*rh));
1376     rh->proto_handle=NULL;
1377     rh->udp = udp;
1378     rh->rc = NULL;
1379     security_handleinit(&rh->sech, udp->driver);
1380
1381     result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer),
1382                          hostname, sizeof(hostname), NULL, 0, 0);
1383     if (result != 0) {
1384         dbprintf("getnameinfo failed: %s\n",
1385                   gai_strerror(result));
1386         security_seterror(&rh->sech, "getnameinfo failed: %s",
1387                           gai_strerror(result));
1388         return;
1389     }
1390     if (check_name_give_sockaddr(hostname,
1391                                  (struct sockaddr *)&udp->peer, &errmsg) < 0) {
1392         security_seterror(&rh->sech, "%s",errmsg);
1393         amfree(errmsg);
1394         amfree(rh);
1395         return;
1396     }
1397
1398     port = SS_GET_PORT(&udp->peer);
1399     a = udp_inithandle(udp, rh,
1400                    hostname,
1401                    &udp->peer,
1402                    port,
1403                    udp->handle,
1404                    udp->sequence);
1405     if (a < 0) {
1406         auth_debug(1, _("bsd: closeX handle '%s'\n"), rh->proto_handle);
1407
1408         amfree(rh);
1409         return;
1410     }
1411     /*
1412      * Check the security of the packet.  If it is bad, then pass NULL
1413      * to the accept function instead of a packet.
1414      */
1415     if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)
1416         (*udp->accept_fn)(&rh->sech, NULL);
1417     else
1418         (*udp->accept_fn)(&rh->sech, &udp->pkt);
1419 }
1420
1421 /*
1422  * Locate an existing connection to the given host, or create a new,
1423  * unconnected entry if none exists.  The caller is expected to check
1424  * for the lack of a connection (rc->read == -1) and set one up.
1425  */
1426 struct tcp_conn *
1427 sec_tcp_conn_get(
1428     const char *hostname,
1429     int         want_new)
1430 {
1431     struct tcp_conn *rc;
1432
1433     auth_debug(1, _("sec_tcp_conn_get: %s\n"), hostname);
1434
1435     if (want_new == 0) {
1436         for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
1437             if (strcasecmp(hostname, rc->hostname) == 0)
1438                 break;
1439         }
1440
1441         if (rc != NULL) {
1442             rc->refcnt++;
1443             auth_debug(1,
1444                       _("sec_tcp_conn_get: exists, refcnt to %s is now %d\n"),
1445                        rc->hostname, rc->refcnt);
1446             return (rc);
1447         }
1448     }
1449
1450     auth_debug(1, _("sec_tcp_conn_get: creating new handle\n"));
1451     /*
1452      * We can't be creating a new handle if we are the client
1453      */
1454     rc = alloc(SIZEOF(*rc));
1455     rc->read = rc->write = -1;
1456     rc->driver = NULL;
1457     rc->pid = -1;
1458     rc->ev_read = NULL;
1459     rc->toclose = 0;
1460     rc->donotclose = 0;
1461     strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);
1462     rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';
1463     rc->errmsg = NULL;
1464     rc->refcnt = 1;
1465     rc->handle = -1;
1466     rc->pkt = NULL;
1467     rc->accept_fn = NULL;
1468     rc->recv_security_ok = NULL;
1469     rc->prefix_packet = NULL;
1470     rc->auth = 0;
1471     rc->conf_fn = NULL;
1472     rc->datap = NULL;
1473     connq_append(rc);
1474     return (rc);
1475 }
1476
1477 /*
1478  * Delete a reference to a connection, and close it if it is the last
1479  * reference.
1480  */
1481 void
1482 sec_tcp_conn_put(
1483     struct tcp_conn *   rc)
1484 {
1485     amwait_t status;
1486
1487     assert(rc->refcnt > 0);
1488     --rc->refcnt;
1489     auth_debug(1, _("sec_tcp_conn_put: decrementing refcnt for %s to %d\n"),
1490                    rc->hostname, rc->refcnt);
1491     if (rc->refcnt > 0) {
1492         return;
1493     }
1494     auth_debug(1, _("sec_tcp_conn_put: closing connection to %s\n"), rc->hostname);
1495     if (rc->read != -1)
1496         aclose(rc->read);
1497     if (rc->write != -1)
1498         aclose(rc->write);
1499     if (rc->pid != -1) {
1500         waitpid(rc->pid, &status, WNOHANG);
1501     }
1502     if (rc->ev_read != NULL)
1503         event_release(rc->ev_read);
1504     if (rc->errmsg != NULL)
1505         amfree(rc->errmsg);
1506     connq_remove(rc);
1507     amfree(rc->pkt);
1508     if(!rc->donotclose)
1509         amfree(rc); /* someone might still use it           */
1510                     /* eg. in sec_tcp_conn_read_callback if */
1511                     /*     event_wakeup call us.            */
1512 }
1513
1514 /*
1515  * Turn on read events for a conn.  Or, increase a ev_read_refcnt if we are
1516  * already receiving read events.
1517  */
1518 void
1519 sec_tcp_conn_read(
1520     struct tcp_conn *   rc)
1521 {
1522     assert (rc != NULL);
1523
1524     if (rc->ev_read != NULL) {
1525         rc->ev_read_refcnt++;
1526         auth_debug(1,
1527               _("sec: conn_read: incremented ev_read_refcnt to %d for %s\n"),
1528                rc->ev_read_refcnt, rc->hostname);
1529         return;
1530     }
1531     auth_debug(1, _("sec: conn_read registering event handler for %s\n"),
1532                    rc->hostname);
1533     rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,
1534                 sec_tcp_conn_read_callback, rc);
1535     rc->ev_read_refcnt = 1;
1536 }
1537
1538 static void
1539 sec_tcp_conn_read_cancel(
1540     struct tcp_conn *   rc)
1541 {
1542
1543     --rc->ev_read_refcnt;
1544     auth_debug(1,
1545        _("sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n"),
1546         rc->ev_read_refcnt, rc->hostname);
1547     if (rc->ev_read_refcnt > 0) {
1548         return;
1549     }
1550     auth_debug(1,
1551                 _("sec: conn_read_cancel: releasing event handler for %s\n"),
1552                  rc->hostname);
1553     event_release(rc->ev_read);
1554     rc->ev_read = NULL;
1555 }
1556
1557 /*
1558  * This is called when a handle is woken up because data read off of the
1559  * net is for it.
1560  */
1561 static void
1562 recvpkt_callback(
1563     void *      cookie,
1564     void *      buf,
1565     ssize_t     bufsize)
1566 {
1567     pkt_t pkt;
1568     struct sec_handle *rh = cookie;
1569
1570     assert(rh != NULL);
1571
1572     auth_debug(1, _("sec: recvpkt_callback: %zd\n"), bufsize);
1573     /*
1574      * We need to cancel the recvpkt request before calling
1575      * the callback because the callback may reschedule us.
1576      */
1577     stream_recvpkt_cancel(rh);
1578
1579     switch (bufsize) {
1580     case 0:
1581         security_seterror(&rh->sech,
1582             _("EOF on read from %s"), rh->hostname);
1583         (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1584         return;
1585     case -1:
1586         security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
1587         (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1588         return;
1589     default:
1590         break;
1591     }
1592
1593     parse_pkt(&pkt, buf, (size_t)bufsize);
1594     auth_debug(1,
1595           _("sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n"),
1596            pkt_type2str(pkt.type), pkt.type,
1597            rh->hostname, pkt.body);
1598     if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1599         (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1600     else
1601         (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
1602     amfree(pkt.body);
1603 }
1604
1605 /*
1606  * Callback for tcpm_stream_read_sync
1607  */
1608 static void
1609 stream_read_sync_callback(
1610     void *      s)
1611 {
1612     struct sec_stream *rs = s;
1613     assert(rs != NULL);
1614
1615     auth_debug(1, _("sec: stream_read_callback_sync: handle %d\n"), rs->handle);
1616
1617     /*
1618      * Make sure this was for us.  If it was, then blow away the handle
1619      * so it doesn't get claimed twice.  Otherwise, leave it alone.
1620      *
1621      * If the handle is EOF, pass that up to our callback.
1622      */
1623     if (rs->rc->handle == rs->handle) {
1624         auth_debug(1, _("sec: stream_read_callback_sync: it was for us\n"));
1625         rs->rc->handle = H_TAKEN;
1626     } else if (rs->rc->handle != H_EOF) {
1627         auth_debug(1, _("sec: stream_read_callback_sync: not for us\n"));
1628         return;
1629     }
1630
1631     /*
1632      * Remove the event first, and then call the callback.
1633      * We remove it first because we don't want to get in their
1634      * way if they reschedule it.
1635      */
1636     tcpm_stream_read_cancel(rs);
1637
1638     if (rs->rc->pktlen <= 0) {
1639         auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), rs->rc->errmsg);
1640         security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1641         if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1642             sec_tcp_conn_put(rs->rc);
1643         rs->closed_by_network = 1;
1644         return;
1645     }
1646     auth_debug(1,
1647             _("sec: stream_read_callback_sync: read %zd bytes from %s:%d\n"),
1648             rs->rc->pktlen, rs->rc->hostname, rs->handle);
1649 }
1650
1651 /*
1652  * Callback for tcpm_stream_read
1653  */
1654 static void
1655 stream_read_callback(
1656     void *      arg)
1657 {
1658     struct sec_stream *rs = arg;
1659     assert(rs != NULL);
1660
1661     auth_debug(1, _("sec: stream_read_callback: handle %d\n"), rs->handle);
1662
1663     /*
1664      * Make sure this was for us.  If it was, then blow away the handle
1665      * so it doesn't get claimed twice.  Otherwise, leave it alone.
1666      *
1667      * If the handle is EOF, pass that up to our callback.
1668      */
1669     if (rs->rc->handle == rs->handle) {
1670         auth_debug(1, _("sec: stream_read_callback: it was for us\n"));
1671         rs->rc->handle = H_TAKEN;
1672     } else if (rs->rc->handle != H_EOF) {
1673         auth_debug(1, _("sec: stream_read_callback: not for us\n"));
1674         return;
1675     }
1676
1677     /*
1678      * Remove the event first, and then call the callback.
1679      * We remove it first because we don't want to get in their
1680      * way if they reschedule it.
1681      */
1682     tcpm_stream_read_cancel(rs);
1683
1684     if (rs->rc->pktlen <= 0) {
1685         auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg);
1686         security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1687         if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1688             sec_tcp_conn_put(rs->rc);
1689         rs->closed_by_network = 1;
1690         (*rs->fn)(rs->arg, NULL, rs->rc->pktlen);
1691         return;
1692     }
1693     auth_debug(1, _("sec: stream_read_callback: read %zd bytes from %s:%d\n"),
1694                    rs->rc->pktlen, rs->rc->hostname, rs->handle);
1695     (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
1696     auth_debug(1, _("sec: after callback stream_read_callback\n"));
1697 }
1698
1699 /*
1700  * The callback for the netfd for the event handler
1701  * Determines if this packet is for this security handle,
1702  * and does the real callback if so.
1703  */
1704 static void
1705 sec_tcp_conn_read_callback(
1706     void *      cookie)
1707 {
1708     struct tcp_conn *   rc = cookie;
1709     struct sec_handle * rh;
1710     pkt_t               pkt;
1711     ssize_t             rval;
1712     int                 revent;
1713
1714     assert(cookie != NULL);
1715
1716     auth_debug(1, _("sec: conn_read_callback\n"));
1717
1718     /* Read the data off the wire.  If we get errors, shut down. */
1719     rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt,
1720                                 &rc->pktlen, 60);
1721     auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"),
1722                    rval);
1723     if (rval < 0 || rc->handle == H_EOF) {
1724         rc->pktlen = rval;
1725         rc->handle = H_EOF;
1726         revent = event_wakeup((event_id_t)rc);
1727         auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"),
1728                        revent);
1729         /* delete our 'accept' reference */
1730         if (rc->accept_fn != NULL) {
1731             if(rc->refcnt != 1) {
1732                 dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"),
1733                           rc->refcnt);
1734                 rc->refcnt=1;
1735             }
1736             rc->accept_fn = NULL;
1737             sec_tcp_conn_put(rc);
1738         }
1739         return;
1740     }
1741
1742     if(rval == 0) {
1743         rc->pktlen = 0;
1744         revent = event_wakeup((event_id_t)rc);
1745         auth_debug(1,
1746                    _("sec: conn_read_callback: event_wakeup return %d\n"), revent);
1747         return;
1748     }
1749
1750     /* If there are events waiting on this handle, we're done */
1751     rc->donotclose = 1;
1752     revent = event_wakeup((event_id_t)rc);
1753     auth_debug(1, _("sec: conn_read_callback: event_wakeup return %zd\n"), rval);
1754     rc->donotclose = 0;
1755     if (rc->handle == H_TAKEN || rc->pktlen == 0) {
1756         if(rc->refcnt == 0) amfree(rc);
1757         return;
1758     }
1759
1760     assert(rc->refcnt > 0);
1761
1762     /* If there is no accept fn registered, then drop the packet */
1763     if (rc->accept_fn == NULL)
1764         return;
1765
1766     rh = alloc(SIZEOF(*rh));
1767     security_handleinit(&rh->sech, rc->driver);
1768     rh->hostname = stralloc(rc->hostname);
1769     rh->ev_timeout = NULL;
1770     rh->rc = rc;
1771     rh->peer = rc->peer;
1772     rh->rs = tcpma_stream_client(rh, rc->handle);
1773
1774     auth_debug(1, _("sec: new connection\n"));
1775     pkt.body = NULL;
1776     parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);
1777     auth_debug(1, _("sec: calling accept_fn\n"));
1778     if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1779         (*rc->accept_fn)(&rh->sech, NULL);
1780     else
1781         (*rc->accept_fn)(&rh->sech, &pkt);
1782     amfree(pkt.body);
1783 }
1784
1785 void
1786 parse_pkt(
1787     pkt_t *     pkt,
1788     const void *buf,
1789     size_t      bufsize)
1790 {
1791     const unsigned char *bufp = buf;
1792
1793     auth_debug(1, _("sec: parse_pkt: parsing buffer of %zu bytes\n"), bufsize);
1794
1795     pkt->type = (pktype_t)*bufp++;
1796     bufsize--;
1797
1798     pkt->packet_size = bufsize+1;
1799     pkt->body = alloc(pkt->packet_size);
1800     if (bufsize == 0) {
1801         pkt->body[0] = '\0';
1802     } else {
1803         memcpy(pkt->body, bufp, bufsize);
1804         pkt->body[pkt->packet_size - 1] = '\0';
1805     }
1806     pkt->size = strlen(pkt->body);
1807
1808     auth_debug(1, _("sec: parse_pkt: %s (%d): \"%s\"\n"), pkt_type2str(pkt->type),
1809                    pkt->type, pkt->body);
1810 }
1811
1812 /*
1813  * Convert a packet header into a string
1814  */
1815 const char *
1816 pkthdr2str(
1817     const struct sec_handle *   rh,
1818     const pkt_t *               pkt)
1819 {
1820     static char retbuf[256];
1821
1822     assert(rh != NULL);
1823     assert(pkt != NULL);
1824
1825     g_snprintf(retbuf, SIZEOF(retbuf), _("Amanda %d.%d %s HANDLE %s SEQ %d\n"),
1826         VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
1827         rh->proto_handle, rh->sequence);
1828
1829     auth_debug(1, _("bsd: pkthdr2str handle '%s'\n"), rh->proto_handle);
1830
1831     /* check for truncation.  If only we had asprintf()... */
1832     assert(retbuf[strlen(retbuf) - 1] == '\n');
1833
1834     return (retbuf);
1835 }
1836
1837 /*
1838  * Parses out the header line in 'str' into the pkt and handle
1839  * Returns negative on parse error.
1840  */
1841 int
1842 str2pkthdr(
1843     udp_handle_t *      udp)
1844 {
1845     char *str;
1846     const char *tok;
1847     pkt_t *pkt;
1848
1849     pkt = &udp->pkt;
1850
1851     assert(udp->dgram.cur != NULL);
1852     str = stralloc(udp->dgram.cur);
1853
1854     /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
1855
1856     /* Read in "Amanda" */
1857     if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
1858         goto parse_error;
1859
1860     /* nothing is done with the major/minor numbers currently */
1861     if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
1862         goto parse_error;
1863
1864     /* Read in the packet type */
1865     if ((tok = strtok(NULL, " ")) == NULL)
1866         goto parse_error;
1867     amfree(pkt->body);
1868     pkt_init_empty(pkt, pkt_str2type(tok));
1869     if (pkt->type == (pktype_t)-1)    
1870         goto parse_error;
1871
1872     /* Read in "HANDLE" */
1873     if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
1874         goto parse_error;
1875
1876     /* parse the handle */
1877     if ((tok = strtok(NULL, " ")) == NULL)
1878         goto parse_error;
1879     amfree(udp->handle);
1880     udp->handle = stralloc(tok);
1881
1882     /* Read in "SEQ" */
1883     if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)   
1884         goto parse_error;
1885
1886     /* parse the sequence number */   
1887     if ((tok = strtok(NULL, "\n")) == NULL)
1888         goto parse_error;
1889     udp->sequence = atoi(tok);
1890
1891     /* Save the body, if any */       
1892     if ((tok = strtok(NULL, "")) != NULL)
1893         pkt_cat(pkt, "%s", tok);
1894
1895     amfree(str);
1896     return (0);
1897
1898 parse_error:
1899 #if 0 /* XXX we have no way of passing this back up */
1900     security_seterror(&rh->sech,
1901         "parse error in packet header : '%s'", origstr);
1902 #endif
1903     amfree(str);
1904     return (-1);
1905 }
1906
1907 char *
1908 check_user(
1909     struct sec_handle * rh,
1910     const char *        remoteuser,
1911     const char *        service)
1912 {
1913     struct passwd *pwd;
1914     char *r;
1915     char *result = NULL;
1916     char *localuser = NULL;
1917
1918     /* lookup our local user name */
1919     if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
1920         return vstrallocf(_("getpwnam(%s) failed."), CLIENT_LOGIN);
1921     }
1922
1923     /*
1924      * Make a copy of the user name in case getpw* is called by
1925      * any of the lower level routines.
1926      */
1927     localuser = stralloc(pwd->pw_name);
1928
1929 #ifndef USE_AMANDAHOSTS
1930     r = check_user_ruserok(rh->hostname, pwd, remoteuser);
1931 #else
1932     r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service);
1933 #endif
1934     if (r != NULL) {
1935         result = vstrallocf(
1936                 _("user %s from %s is not allowed to execute the service %s: %s"),
1937                 remoteuser, rh->hostname, service, r);
1938         amfree(r);
1939     }
1940     amfree(localuser);
1941     return result;
1942 }
1943
1944 /*
1945  * See if a remote user is allowed in.  This version uses ruserok()
1946  * and friends.
1947  *
1948  * Returns NULL on success, or error message on error.
1949  */
1950 char *
1951 check_user_ruserok(
1952     const char *        host,
1953     struct passwd *     pwd,
1954     const char *        remoteuser)
1955 {
1956     int saved_stderr;
1957     int fd[2];
1958     FILE *fError;
1959     amwait_t exitcode;
1960     pid_t ruserok_pid;
1961     pid_t pid;
1962     char *es;
1963     char *result;
1964     int ok;
1965     uid_t myuid = getuid();
1966
1967     /*
1968      * note that some versions of ruserok (eg SunOS 3.2) look in
1969      * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
1970      * chdir ourselves.  Sigh.
1971      *
1972      * And, believe it or not, some ruserok()'s try an initgroup just
1973      * for the hell of it.  Since we probably aren't root at this point
1974      * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
1975      * into our stderr output even though the initgroup failure is not a
1976      * problem and is expected.  Thanks a lot.  Not.
1977      */
1978     if (pipe(fd) != 0) {
1979         return stralloc2(_("pipe() fails: "), strerror(errno));
1980     }
1981     if ((ruserok_pid = fork()) < 0) {
1982         return stralloc2(_("fork() fails: "), strerror(errno));
1983     } else if (ruserok_pid == 0) {
1984         int ec;
1985
1986         close(fd[0]);
1987         fError = fdopen(fd[1], "w");
1988         if (!fError) {
1989             error(_("Can't fdopen: %s"), strerror(errno));
1990             /*NOTREACHED*/
1991         }
1992         /* pamper braindead ruserok's */
1993         if (chdir(pwd->pw_dir) != 0) {
1994             g_fprintf(fError, _("chdir(%s) failed: %s"),
1995                     pwd->pw_dir, strerror(errno));
1996             fclose(fError);
1997             exit(1);
1998         }
1999
2000         if (debug_auth >= 9) {
2001             char *dir = stralloc(pwd->pw_dir);
2002
2003             auth_debug(9, _("bsd: calling ruserok(%s, %d, %s, %s)\n"), host,
2004                            ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name);
2005             if (myuid == 0) {
2006                 auth_debug(9, _("bsd: because you are running as root, "));
2007                 auth_debug(9, _("/etc/hosts.equiv will not be used\n"));
2008             } else {
2009                 show_stat_info("/etc/hosts.equiv", NULL);
2010             }
2011             show_stat_info(dir, "/.rhosts");
2012             amfree(dir);
2013         }
2014
2015         saved_stderr = dup(2);
2016         close(2);
2017         if (open("/dev/null", O_RDWR) == -1) {
2018             auth_debug(1, _("Could not open /dev/null: %s\n"), strerror(errno));
2019             ec = 1;
2020         } else {
2021             ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
2022             if (ok < 0) {
2023                 ec = 1;
2024             } else {
2025                 ec = 0;
2026             }
2027         }
2028         (void)dup2(saved_stderr,2);
2029         close(saved_stderr);
2030         exit(ec);
2031     }
2032     close(fd[1]);
2033     fError = fdopen(fd[0], "r");
2034     if (!fError) {
2035         error(_("Can't fdopen: %s"), strerror(errno));
2036         /*NOTREACHED*/
2037     }
2038
2039     result = NULL;
2040     while ((es = agets(fError)) != NULL) {
2041         if (*es == 0) {
2042             amfree(es);
2043             continue;
2044         }
2045         if (result == NULL) {
2046             result = stralloc("");
2047         } else {
2048             strappend(result, ": ");
2049         }
2050         strappend(result, es);
2051         amfree(es);
2052     }
2053     close(fd[0]);
2054
2055     pid = wait(&exitcode);
2056     while (pid != ruserok_pid) {
2057         if ((pid == (pid_t) -1) && (errno != EINTR)) {
2058             amfree(result);
2059             return vstrallocf(_("ruserok wait failed: %s"), strerror(errno));
2060         }
2061         pid = wait(&exitcode);
2062     }
2063     if (!WIFEXITED(exitcode) || WEXITSTATUS(exitcode) != 0) {
2064         amfree(result);
2065         result = str_exit_status("ruserok child", exitcode);
2066     } else {
2067         amfree(result);
2068     }
2069
2070     return result;
2071 }
2072
2073 /*
2074  * Check to see if a user is allowed in.  This version uses .amandahosts
2075  * Returns an error message on failure, or NULL on success.
2076  */
2077 char *
2078 check_user_amandahosts(
2079     const char *        host,
2080     struct sockaddr_storage *addr,
2081     struct passwd *     pwd,
2082     const char *        remoteuser,
2083     const char *        service)
2084 {
2085     char *line = NULL;
2086     char *filehost;
2087     const char *fileuser;
2088     char *ptmp = NULL;
2089     char *result = NULL;
2090     FILE *fp = NULL;
2091     int found;
2092     struct stat sbuf;
2093     int hostmatch;
2094     int usermatch;
2095     char *aservice = NULL;
2096 #ifdef WORKING_IPV6
2097     char ipstr[INET6_ADDRSTRLEN];
2098 #else
2099     char ipstr[INET_ADDRSTRLEN];
2100 #endif
2101
2102     auth_debug(1, _("check_user_amandahosts(host=%s, pwd=%p, "
2103                    "remoteuser=%s, service=%s)\n"),
2104                    host, pwd, remoteuser, service);
2105
2106     ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
2107     if (debug_auth >= 9) {
2108         show_stat_info(ptmp, "");;
2109     }
2110     if ((fp = fopen(ptmp, "r")) == NULL) {
2111         result = vstrallocf(_("cannot open %s: %s"), ptmp, strerror(errno));
2112         amfree(ptmp);
2113         return result;
2114     }
2115
2116     /*
2117      * Make sure the file is owned by the Amanda user and does not
2118      * have any group/other access allowed.
2119      */
2120     if (fstat(fileno(fp), &sbuf) != 0) {
2121         result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));
2122         goto common_exit;
2123     }
2124     if (sbuf.st_uid != pwd->pw_uid) {
2125         result = vstrallocf(_("%s: owned by id %ld, should be %ld"),
2126                         ptmp, (long)sbuf.st_uid, (long)pwd->pw_uid);
2127         goto common_exit;
2128     }
2129     if ((sbuf.st_mode & 077) != 0) {
2130         result = vstrallocf(_("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);
2131         goto common_exit;
2132     }
2133
2134     /*
2135      * Now, scan the file for the host/user/service.
2136      */
2137     found = 0;
2138     while ((line = agets(fp)) != NULL) {
2139         if (*line == 0) {
2140             amfree(line);
2141             continue;
2142         }
2143
2144         auth_debug(9, _("bsd: processing line: <%s>\n"), line);
2145         /* get the host out of the file */
2146         if ((filehost = strtok(line, " \t")) == NULL) {
2147             amfree(line);
2148             continue;
2149         }
2150
2151         /* get the username.  If no user specified, then use the local user */
2152         if ((fileuser = strtok(NULL, " \t")) == NULL) {
2153             fileuser = pwd->pw_name;
2154         }
2155
2156         hostmatch = (strcasecmp(filehost, host) == 0);
2157         /*  ok if addr=127.0.0.1 and
2158          *  either localhost or localhost.domain is in .amandahost */
2159         if (!hostmatch  &&
2160             (strcasecmp(filehost, "localhost")== 0 ||
2161              strcasecmp(filehost, "localhost.localdomain")== 0)) {
2162 #ifdef WORKING_IPV6
2163             if (addr->ss_family == (sa_family_t)AF_INET6)
2164                 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr,
2165                           ipstr, sizeof(ipstr));
2166             else
2167 #endif
2168                 inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr,
2169                           ipstr, sizeof(ipstr));
2170             if (strcmp(ipstr, "127.0.0.1") == 0 ||
2171                 strcmp(ipstr, "::1") == 0)
2172                 hostmatch = 1;
2173         }
2174         usermatch = (strcasecmp(fileuser, remoteuser) == 0);
2175         auth_debug(9, _("bsd: comparing \"%s\" with\n"), filehost);
2176         auth_debug(9, _("bsd:           \"%s\" (%s)\n"), host,
2177                        hostmatch ? _("match") : _("no match"));
2178         auth_debug(9, _("bsd:       and \"%s\" with\n"), fileuser);
2179         auth_debug(9, _("bsd:           \"%s\" (%s)\n"), remoteuser,
2180                        usermatch ? _("match") : _("no match"));
2181         /* compare */
2182         if (!hostmatch || !usermatch) {
2183             amfree(line);
2184             continue;
2185         }
2186
2187         if (!service) {
2188             /* success */
2189             amfree(line);
2190             found = 1;
2191             break;
2192         }
2193
2194         /* get the services.  If no service specified, then use
2195          * noop/selfcheck/sendsize/sendbackup
2196          */
2197         aservice = strtok(NULL, " \t,");
2198         if (!aservice) {
2199             if (strcmp(service,"noop") == 0 ||
2200                strcmp(service,"selfcheck") == 0 ||
2201                strcmp(service,"sendsize") == 0 ||
2202                strcmp(service,"sendbackup") == 0) {
2203                 /* success */
2204                 found = 1;
2205                 amfree(line);
2206                 break;
2207             }
2208             else {
2209                 amfree(line);
2210                 break;
2211             }
2212         }
2213
2214         do {
2215             if (strcmp(aservice,service) == 0) {
2216                 found = 1;
2217                 break;
2218             }
2219             if (strcmp(aservice, "amdump") == 0 && 
2220                (strcmp(service, "noop") == 0 ||
2221                 strcmp(service, "selfcheck") == 0 ||
2222                 strcmp(service, "sendsize") == 0 ||
2223                 strcmp(service, "sendbackup") == 0)) {
2224                 found = 1;
2225                 break;
2226             }
2227         } while((aservice = strtok(NULL, " \t,")) != NULL);
2228
2229         if (aservice && strcmp(aservice, service) == 0) {
2230             /* success */
2231             found = 1;
2232             amfree(line);
2233             break;
2234         }
2235         amfree(line);
2236     }
2237     if (! found) {
2238         if (strcmp(service, "amindexd") == 0 ||
2239             strcmp(service, "amidxtaped") == 0) {
2240             result = vstrallocf(_("Please add the line \"%s %s amindexd amidxtaped\" to %s on the client"), host, remoteuser, ptmp);
2241         } else if (strcmp(service, "amdump") == 0 ||
2242                    strcmp(service, "noop") == 0 ||
2243                    strcmp(service, "selfcheck") == 0 ||
2244                    strcmp(service, "sendsize") == 0 ||
2245                    strcmp(service, "sendbackup") == 0) {
2246             result = vstrallocf(_("Please add the line \"%s %s amdump\" to %s on the client"), host, remoteuser, ptmp);
2247         } else {
2248             result = vstrallocf(_("%s: invalid service %s"), ptmp, service);
2249         }
2250     }
2251
2252 common_exit:
2253
2254     afclose(fp);
2255     amfree(ptmp);
2256
2257     return result;
2258 }
2259
2260 /* return 1 on success, 0 on failure */
2261 int
2262 check_security(
2263     struct sockaddr_storage *addr,
2264     char *              str,
2265     unsigned long       cksum,
2266     char **             errstr)
2267 {
2268     char *              remotehost = NULL, *remoteuser = NULL;
2269     char *              bad_bsd = NULL;
2270     struct passwd *     pwptr;
2271     uid_t               myuid;
2272     char *              s;
2273     char *              fp;
2274     int                 ch;
2275     char                hostname[NI_MAXHOST];
2276     in_port_t           port;
2277     int                 result;
2278
2279     (void)cksum;        /* Quiet unused parameter warning */
2280
2281     auth_debug(1,
2282                _("check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n"),
2283                 addr, str, cksum, errstr);
2284     dump_sockaddr(addr);
2285
2286     *errstr = NULL;
2287
2288     /* what host is making the request? */
2289     if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr),
2290                               hostname, NI_MAXHOST, NULL, 0, 0)) != 0) {
2291         dbprintf(_("getnameinfo failed: %s\n"),
2292                   gai_strerror(result));
2293         *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ",
2294                             "getnameinfo failed: ", gai_strerror(result),
2295                             "]", NULL);
2296         return 0;
2297     }
2298     remotehost = stralloc(hostname);
2299     if( check_name_give_sockaddr(hostname,
2300                                  (struct sockaddr *)addr, errstr) < 0) {
2301         amfree(remotehost);
2302         return 0;
2303     }
2304
2305
2306     /* next, make sure the remote port is a "reserved" one */
2307     port = SS_GET_PORT(addr);
2308     if (port >= IPPORT_RESERVED) {
2309         *errstr = vstrallocf(_("[host %s: port %u not secure]"),
2310                         remotehost, (unsigned int)port);
2311         amfree(remotehost);
2312         return 0;
2313     }
2314
2315     /* extract the remote user name from the message */
2316
2317     s = str;
2318     ch = *s++;
2319
2320     bad_bsd = vstrallocf(_("[host %s: bad bsd security line]"), remotehost);
2321
2322     if (strncmp_const_skip(s - 1, "USER ", s, ch) != 0) {
2323         *errstr = bad_bsd;
2324         bad_bsd = NULL;
2325         amfree(remotehost);
2326         return 0;
2327     }
2328
2329     skip_whitespace(s, ch);
2330     if (ch == '\0') {
2331         *errstr = bad_bsd;
2332         bad_bsd = NULL;
2333         amfree(remotehost);
2334         return 0;
2335     }
2336     fp = s - 1;
2337     skip_non_whitespace(s, ch);
2338     s[-1] = '\0';
2339     remoteuser = stralloc(fp);
2340     s[-1] = (char)ch;
2341     amfree(bad_bsd);
2342
2343     /* lookup our local user name */
2344
2345     myuid = getuid();
2346     if ((pwptr = getpwuid(myuid)) == NULL)
2347         error(_("error [getpwuid(%d) fails]"), (int)myuid);
2348
2349     auth_debug(1, _("bsd security: remote host %s user %s local user %s\n"),
2350                    remotehost, remoteuser, pwptr->pw_name);
2351
2352 #ifndef USE_AMANDAHOSTS
2353     s = check_user_ruserok(remotehost, pwptr, remoteuser);
2354 #else
2355     s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL);
2356 #endif
2357
2358     if (s != NULL) {
2359         *errstr = vstrallocf(_("[access as %s not allowed from %s@%s: %s]"),
2360                             pwptr->pw_name, remoteuser, remotehost, s);
2361     }
2362     amfree(s);
2363     amfree(remotehost);
2364     amfree(remoteuser);
2365     return *errstr == NULL;
2366 }
2367
2368 /*
2369  * Writes out the entire iovec
2370  */
2371 ssize_t
2372 net_writev(
2373     int                 fd,
2374     struct iovec *      iov,
2375     int                 iovcnt)
2376 {
2377     ssize_t delta, n, total;
2378
2379     assert(iov != NULL);
2380
2381     total = 0;
2382     while (iovcnt > 0) {
2383         /*
2384          * Write the iovec
2385          */
2386         n = writev(fd, iov, iovcnt);
2387         if (n < 0) {
2388             if (errno != EINTR)
2389                 return (-1);
2390             auth_debug(1, _("net_writev got EINTR\n"));
2391         }
2392         else if (n == 0) {
2393             errno = EIO;
2394             return (-1);
2395         } else {
2396             total += n;
2397             /*
2398              * Iterate through each iov.  Figure out what we still need
2399              * to write out.
2400              */
2401             for (; n > 0; iovcnt--, iov++) {
2402                 /* 'delta' is the bytes written from this iovec */
2403                 delta = ((size_t)n < (size_t)iov->iov_len) ? n : (ssize_t)iov->iov_len;
2404                 /* subtract from the total num bytes written */
2405                 n -= delta;
2406                 assert(n >= 0);
2407                 /* subtract from this iovec */
2408                 iov->iov_len -= delta;
2409                 iov->iov_base = (char *)iov->iov_base + delta;
2410                 /* if this iovec isn't empty, run the writev again */
2411                 if (iov->iov_len > 0)
2412                     break;
2413             }
2414         }
2415     }
2416     return (total);
2417 }
2418
2419 /*
2420  * Like read(), but waits until the entire buffer has been filled.
2421  */
2422 ssize_t
2423 net_read(
2424     int         fd,
2425     void *      vbuf,
2426     size_t      origsize,
2427     int         timeout)
2428 {
2429     char *buf = vbuf;   /* ptr arith */
2430     ssize_t nread;
2431     size_t size = origsize;
2432
2433     auth_debug(1, _("net_read: begin %zu\n"), origsize);
2434
2435     while (size > 0) {
2436         auth_debug(1, _("net_read: while %zu\n"), size);
2437         nread = net_read_fillbuf(fd, timeout, buf, size);
2438         if (nread < 0) {
2439             auth_debug(1, _("db: net_read: end return(-1)\n"));
2440             return (-1);
2441         }
2442         if (nread == 0) {
2443             auth_debug(1, _("net_read: end return(0)\n"));
2444             return (0);
2445         }
2446         buf += nread;
2447         size -= nread;
2448     }
2449     auth_debug(1, _("net_read: end %zu\n"), origsize);
2450     return ((ssize_t)origsize);
2451 }
2452
2453 /*
2454  * net_read likes to do a lot of little reads.  Buffer it.
2455  */
2456 ssize_t
2457 net_read_fillbuf(
2458     int         fd,
2459     int         timeout,
2460     void *      buf,
2461     size_t      size)
2462 {
2463     SELECT_ARG_TYPE readfds;
2464     struct timeval tv;
2465     ssize_t nread;
2466
2467     auth_debug(1, _("net_read_fillbuf: begin\n"));
2468     FD_ZERO(&readfds);
2469     FD_SET(fd, &readfds);
2470     tv.tv_sec = timeout;
2471     tv.tv_usec = 0;
2472     switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
2473     case 0:
2474         errno = ETIMEDOUT;
2475         /* FALLTHROUGH */
2476     case -1:
2477         auth_debug(1, _("net_read_fillbuf: case -1\n"));
2478         return (-1);
2479     case 1:
2480         auth_debug(1, _("net_read_fillbuf: case 1\n"));
2481         assert(FD_ISSET(fd, &readfds));
2482         break;
2483     default:
2484         auth_debug(1, _("net_read_fillbuf: case default\n"));
2485         assert(0);
2486         break;
2487     }
2488     nread = read(fd, buf, size);
2489     if (nread < 0)
2490         return (-1);
2491     auth_debug(1, _("net_read_fillbuf: end %zd\n"), nread);
2492     return (nread);
2493 }
2494
2495
2496 /*
2497  * Display stat() information about a file.
2498  */
2499
2500 void
2501 show_stat_info(
2502     char *      a,
2503     char *      b)
2504 {
2505     char *name = vstralloc(a, b, NULL);
2506     struct stat sbuf;
2507     struct passwd *pwptr;
2508     struct passwd pw;
2509     char *owner;
2510     struct group *grptr;
2511     struct group gr;
2512     char *group;
2513     int buflen;
2514     char *buf;
2515
2516     if (stat(name, &sbuf) != 0) {
2517         auth_debug(1, _("bsd: cannot stat %s: %s\n"), name, strerror(errno));
2518         amfree(name);
2519         return;
2520     }
2521
2522 #ifdef _SC_GETPW_R_SIZE_MAX
2523     buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
2524     if (buflen == -1)
2525         buflen = 1024;
2526 #else
2527     buflen = 1024;
2528 #endif
2529     buf = malloc(buflen);
2530
2531     if (getpwuid_r(sbuf.st_uid, &pw, buf, buflen, &pwptr) != 0 ||
2532         pwptr == NULL) {
2533         owner = alloc(NUM_STR_SIZE + 1);
2534         g_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
2535     } else {
2536         owner = stralloc(pwptr->pw_name);
2537     }
2538     if (getgrgid_r(sbuf.st_gid, &gr, buf, buflen, &grptr) != 0 ||
2539         grptr == NULL) {
2540         group = alloc(NUM_STR_SIZE + 1);
2541         g_snprintf(group, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
2542     } else {
2543         group = stralloc(grptr->gr_name);
2544     }
2545     auth_debug(1, _("bsd: processing file: %s\n"), name);
2546     auth_debug(1, _("bsd:                  owner=%s group=%s mode=%03o\n"),
2547                    owner, group,
2548                    (int) (sbuf.st_mode & 0777));
2549     amfree(name);
2550     amfree(owner);
2551     amfree(group);
2552     amfree(buf);
2553 }
2554
2555 int
2556 check_name_give_sockaddr(
2557     const char *hostname,
2558     struct sockaddr *addr,
2559     char **errstr)
2560 {
2561     int result;
2562     struct addrinfo *res = NULL, *res1;
2563     char *canonname;
2564
2565     result = resolve_hostname(hostname, 0, &res, &canonname);
2566     if (result != 0) {
2567         dbprintf(_("check_name_give_sockaddr: resolve_hostname('%s'): %s\n"), hostname, gai_strerror(result));
2568         *errstr = newvstrallocf(*errstr,
2569                                _("check_name_give_sockaddr: resolve_hostname('%s'): %s"),
2570                                hostname, gai_strerror(result));
2571         goto error;
2572     }
2573     if (canonname == NULL) {
2574         dbprintf(_("resolve_hostname('%s') did not return a canonical name\n"), hostname);
2575         *errstr = newvstrallocf(*errstr,
2576                 _("check_name_give_sockaddr: resolve_hostname('%s') did not return a canonical name"),
2577                 hostname);
2578         goto error;
2579     }
2580
2581     if (strncasecmp(hostname, canonname, strlen(hostname)) != 0) {
2582         dbprintf(_("%s doesn't resolve to itself, it resolves to %s\n"),
2583                        hostname, canonname);
2584         *errstr = newvstrallocf(*errstr,
2585                                _("%s doesn't resolve to itself, it resolves to %s"),
2586                                hostname, canonname);
2587         goto error;
2588     }
2589
2590     for(res1=res; res1 != NULL; res1 = res1->ai_next) {
2591         if (cmp_sockaddr((struct sockaddr_storage *)res1->ai_addr, (struct sockaddr_storage *)addr, 1) == 0) {
2592             freeaddrinfo(res);
2593             amfree(canonname);
2594             return 0;
2595         }
2596     }
2597
2598     dbprintf(_("%s doesn't resolve to %s"),
2599             hostname, str_sockaddr((struct sockaddr_storage *)addr));
2600     *errstr = newvstrallocf(*errstr,
2601                            "%s doesn't resolve to %s",
2602                            hostname, str_sockaddr((struct sockaddr_storage *)addr));
2603 error:
2604     if (res) freeaddrinfo(res);
2605     amfree(canonname);
2606     return -1;
2607 }