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