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