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