2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1999 University of Maryland
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.
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.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
28 * $Id: security-util.c,v 1.25 2006/07/22 12:04:47 martinea Exp $
30 * sec-security.c - security and transport over sec or a sec-like command.
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.
41 #include "security-util.h"
43 #include "sockaddr-util.h"
46 * This is a queue of open connections
49 static int newhandle = 1;
50 static int newevent = 1;
55 static void recvpkt_callback(void *, void *, ssize_t);
56 static void stream_read_callback(void *);
57 static void stream_read_sync_callback(void *);
59 static void sec_tcp_conn_read_cancel(struct tcp_conn *);
60 static void sec_tcp_conn_read_callback(void *);
64 * Authenticate a stream
65 * Nothing needed for sec. The connection is authenticated by secd
72 (void)s; /* Quiet unused parameter warning */
77 * Returns the stream id for this stream. This is just the local
84 struct sec_stream *rs = s;
92 * Setup to handle new incoming connections
96 const security_driver_t *driver,
97 char *(*conf_fn)(char *, void *),
100 void (*fn)(security_handle_t *, pkt_t *),
105 rc = sec_tcp_conn_get("",0); /* no hostname yet */
110 rc->conf_fn = conf_fn;
112 sec_tcp_conn_read(rc);
116 * frees a handle allocated by the above
122 struct sec_handle *rh = inst;
126 auth_debug(1, _("sec: closing handle to %s\n"), rh->hostname);
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);
133 /* keep us from getting here again */
134 rh->sech.driver = NULL;
135 amfree(rh->hostname);
140 * Called when a sec connection is finished connecting and is ready
141 * to be authenticated.
144 sec_connect_callback(
147 struct sec_handle *rh = cookie;
149 event_release(rh->rs->ev_read);
150 rh->rs->ev_read = NULL;
151 event_release(rh->ev_timeout);
152 rh->ev_timeout = NULL;
154 (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
158 * Called if a connection times out before completion.
164 struct sec_handle *rh = cookie;
166 event_release(rh->rs->ev_read);
167 rh->rs->ev_read = NULL;
168 event_release(rh->ev_timeout);
169 rh->ev_timeout = NULL;
171 (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
175 sec_close_connection_none(
196 struct sec_handle *rh = cookie;
203 auth_debug(1, _("sec: stream_sendpkt: enter\n"));
205 if (rh->rc->prefix_packet)
206 s = rh->rc->prefix_packet(rh, pkt);
209 len = strlen(pkt->body) + strlen(s) + 2;
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));
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);
221 if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {
222 security_seterror(&rh->sech, "%s", security_stream_geterror(&rh->rs->secstr));
231 * Set up to receive a packet asyncronously, and call back when
237 void (*fn)(void *, pkt_t *, security_status_t),
241 struct sec_handle *rh = cookie;
245 auth_debug(1, _("sec: recvpkt registered for %s\n"), rh->hostname);
248 * Reset any pending timeout on this handle
250 if (rh->ev_timeout != NULL)
251 event_release(rh->ev_timeout);
254 * Negative timeouts mean no timeout
257 rh->ev_timeout = NULL;
259 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
260 stream_recvpkt_timeout, rh);
264 security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);
268 * This is called when a handle times out before receiving a packet.
271 stream_recvpkt_timeout(
274 struct sec_handle *rh = cookie;
278 auth_debug(1, _("sec: recvpkt timeout for %s\n"), rh->hostname);
280 stream_recvpkt_cancel(rh);
281 (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
285 * Remove a async receive request from the queue
288 stream_recvpkt_cancel(
291 struct sec_handle *rh = cookie;
293 auth_debug(1, _("sec: cancelling recvpkt for %s\n"), rh->hostname);
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;
305 * Write a chunk of data to a stream. Blocks until completion.
313 struct sec_stream *rs = s;
316 assert(rs->rc != NULL);
318 auth_debug(1, _("sec: stream_write: writing %zu bytes to %s:%d %d\n"),
319 size, rs->rc->hostname, rs->handle,
322 if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg,
324 security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg);
331 * Submit a request to read some data. Calls back with the given
332 * function and arg when completed.
337 void (*fn)(void *, void *, ssize_t),
340 struct sec_stream *rs = s;
345 * Only one read request can be active per stream.
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);
356 /* buffer for tcpm_stream_read_sync function */
357 static ssize_t sync_pktlen;
358 static void *sync_pkt;
361 * Write a chunk of data to a stream. Blocks until completion.
364 tcpm_stream_read_sync(
368 struct sec_stream *rs = s;
373 * Only one read request can be active per stream.
375 if (rs->ev_read != 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 */
386 return (sync_pktlen);
390 * Cancel a previous stream read request. It's ok if we didn't have a read
394 tcpm_stream_read_cancel(
397 struct sec_stream *rs = s;
401 if (rs->ev_read != NULL) {
402 event_release(rs->ev_read);
404 sec_tcp_conn_read_cancel(rs->rc);
409 * Transmits a chunk of data over a rsh_handle, adding
410 * the necessary headers to allow the remote end to decode it.
431 assert(SIZEOF(netlength) == 4);
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;
439 auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n",
443 * 32 bit length (network byte order)
444 * 32 bit handle (network byte order)
447 netlength = htonl(len);
448 iov[0].iov_base = (void *)&netlength;
449 iov[0].iov_len = SIZEOF(netlength);
451 nethandle = htonl((guint32)handle);
452 iov[1].iov_base = (void *)&nethandle;
453 iov[1].iov_len = SIZEOF(nethandle);
455 encbuf = (char *)buf;
462 if (rc->driver->data_encrypt == NULL) {
463 iov[2].iov_base = (void *)buf;
464 iov[2].iov_len = len;
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);
475 rval = full_writev(fd, iov, nb_iov);
477 if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) {
483 *errmsg = newvstrallocf(*errmsg, _("write error to: %s"),
484 strerror(save_errno));
491 * return -2 for incomplete packet
493 * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed
494 * return 0 on EOF: *handle = handle && *size = 0 if stream closed
495 * return size : *handle = handle && *size = size for data read
509 assert(SIZEOF(rc->netint) == 8);
510 if (rc->size_header_read < (ssize_t)SIZEOF(rc->netint)) {
511 rval = read(fd, ((char *)&rc->netint) + rc->size_header_read,
512 SIZEOF(rc->netint) - rc->size_header_read);
515 *errmsg = newvstrallocf(*errmsg, _("recv error: %s"),
517 auth_debug(1, _("tcpm_recv_token: A return(-1)\n"));
519 } else if (rval == 0) {
522 *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
523 auth_debug(1, _("tcpm_recv_token: A return(0)\n"));
525 } else if (rval < (ssize_t)SIZEOF(rc->netint) - rc->size_header_read) {
526 rc->size_header_read += rval;
529 rc->size_header_read += rval;
531 *size = (ssize_t)ntohl(rc->netint[0]);
532 *handle = (int)ntohl(rc->netint[1]);
534 rc->size_buffer_read = 0;
536 /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */
537 if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) {
538 if (isprint((int)(*size ) & 0xFF) &&
539 isprint((int)(*size >> 8 ) & 0xFF) &&
540 isprint((int)(*size >> 16) & 0xFF) &&
541 isprint((int)(*size >> 24) & 0xFF) &&
542 isprint((*handle ) & 0xFF) &&
543 isprint((*handle >> 8 ) & 0xFF) &&
544 isprint((*handle >> 16) & 0xFF) &&
545 isprint((*handle >> 24) & 0xFF)) {
549 s[0] = ((int)(*size) >> 24) & 0xFF;
550 s[1] = ((int)(*size) >> 16) & 0xFF;
551 s[2] = ((int)(*size) >> 8) & 0xFF;
552 s[3] = ((int)(*size) ) & 0xFF;
553 s[4] = (*handle >> 24) & 0xFF;
554 s[5] = (*handle >> 16) & 0xFF;
555 s[6] = (*handle >> 8 ) & 0xFF;
556 s[7] = (*handle ) & 0xFF;
558 while(i<200 && isprint((int)s[i]) && s[i] != '\n') {
559 switch(net_read(fd, &s[i], 1, 0)) {
560 case -1: s[i] = '\0'; break;
561 case 0: s[i] = '\0'; break;
563 dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' ';
568 s1 = quote_string(s);
569 *errmsg = newvstrallocf(*errmsg,
570 _("tcpm_recv_token: invalid size: %s"), s1);
571 dbprintf(_("tcpm_recv_token: invalid size %s\n"), s1);
574 *errmsg = newvstrallocf(*errmsg,
575 _("tcpm_recv_token: invalid size"));
576 dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size);
581 rc->buffer = alloc((size_t)*size);
584 auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle);
585 *errmsg = newvstrallocf(*errmsg, _("EOF"));
586 rc->size_header_read = 0;
591 *size = (ssize_t)ntohl(rc->netint[0]);
592 *handle = (int)ntohl(rc->netint[1]);
594 rval = read(fd, rc->buffer + rc->size_buffer_read,
595 (size_t)*size - rc->size_buffer_read);
598 *errmsg = newvstrallocf(*errmsg, _("recv error: %s"),
600 auth_debug(1, _("tcpm_recv_token: B return(-1)\n"));
602 } else if (rval == 0) {
604 *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
605 auth_debug(1, _("tcpm_recv_token: B return(0)\n"));
607 } else if (rval < (ssize_t)*size - rc->size_buffer_read) {
608 rc->size_buffer_read += rval;
611 rc->size_buffer_read += rval;
614 rc->size_header_read = 0;
615 rc->size_buffer_read = 0;
618 auth_debug(1, _("tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle);
620 if (*size > 0 && rc->driver->data_decrypt != NULL) {
623 rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize);
624 if (*buf != (char *)decbuf) {
626 *buf = (char *)decbuf;
635 tcpm_close_connection(
639 struct sec_handle *rh = h;
643 if (rh && rh->rc && rh->rc->read >= 0 && rh->rc->toclose == 0) {
645 sec_tcp_conn_put(rh->rc);
652 * Accept an incoming connection on a stream_server socket
653 * Nothing needed for tcpma.
659 (void)s; /* Quiet unused parameter warning */
665 * Return a connected stream. For sec, this means setup a stream
666 * with the supplied handle.
673 struct sec_handle *rh = h;
674 struct sec_stream *rs;
679 security_seterror(&rh->sech,
680 _("%d: invalid security stream id"), id);
684 rs = g_new0(struct sec_stream, 1);
685 security_streaminit(&rs->secstr, rh->sech.driver);
688 rs->closed_by_me = 0;
689 rs->closed_by_network = 0;
695 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
696 rs->rc->driver = rh->sech.driver;
700 auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id);
706 * Create the server end of a stream. For sec, this means setup a stream
707 * object and allocate a new handle for it.
713 struct sec_handle *rh = h;
714 struct sec_stream *rs;
718 rs = g_new0(struct sec_stream, 1);
719 security_streaminit(&rs->secstr, rh->sech.driver);
720 rs->closed_by_me = 0;
721 rs->closed_by_network = 0;
727 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
728 rs->rc->driver = rh->sech.driver;
732 * Stream should already be setup!
734 if (rs->rc->read < 0) {
735 sec_tcp_conn_put(rs->rc);
737 security_seterror(&rh->sech, _("lost connection to %s"), rh->hostname);
740 assert(strcmp(rh->hostname, rs->rc->hostname) == 0);
742 * so as not to conflict with the amanda server's handle numbers,
743 * we start at 500000 and work down
745 rs->handle = 500000 - newhandle++;
747 auth_debug(1, _("sec: stream_server: created stream %d\n"), rs->handle);
752 * Close and unallocate resources for a stream.
758 struct sec_stream *rs = s;
763 auth_debug(1, _("sec: tcpma_stream_close: closing stream %d\n"), rs->handle);
765 if(rs->closed_by_network == 0 && rs->rc->write != -1)
766 tcpm_stream_write(rs, &buf, 0);
767 security_stream_read_cancel(&rs->secstr);
768 if(rs->closed_by_network == 0)
769 sec_tcp_conn_put(rs->rc);
770 amfree(((security_stream_t *)rs)->error);
775 * Create the server end of a stream. For bsdudp, this means setup a tcp
776 * socket for receiving a connection.
782 struct sec_stream *rs = NULL;
783 struct sec_handle *rh = h;
787 rs = g_new0(struct sec_stream, 1);
788 security_streaminit(&rs->secstr, rh->sech.driver);
789 rs->closed_by_me = 0;
790 rs->closed_by_network = 0;
793 rs->handle = 500000 - newhandle++;
795 rs->socket = 0; /* the socket is already opened */
798 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
799 rh->rc->driver = rh->sech.driver;
801 rs->socket = stream_server(SU_GET_FAMILY(&rh->udp->peer), &rs->port,
802 STREAM_BUFSIZE, STREAM_BUFSIZE, 0);
803 if (rs->socket < 0) {
804 security_seterror(&rh->sech,
805 _("can't create server stream: %s"), strerror(errno));
809 rh->rc->read = rs->socket;
810 rh->rc->write = rs->socket;
811 rs->handle = (int)rs->port;
819 * Accepts a new connection on unconnected streams. Assumes it is ok to
826 struct sec_stream *bs = s;
829 assert(bs->socket != -1);
832 if (bs->socket > 0) {
833 bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE);
835 security_stream_seterror(&bs->secstr,
836 _("can't accept new stream connection: %s"),
840 bs->rc->read = bs->fd;
841 bs->rc->write = bs->fd;
847 * Return a connected stream
854 struct sec_stream *rs = NULL;
855 struct sec_handle *rh = h;
859 rs = g_new0(struct sec_stream, 1);
860 security_streaminit(&rs->secstr, rh->sech.driver);
863 rs->closed_by_me = 0;
864 rs->closed_by_network = 0;
870 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
871 rh->rc->driver = rh->sech.driver;
873 rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
874 STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
875 if (rh->rc->read < 0) {
876 security_seterror(&rh->sech,
877 _("can't connect stream to %s port %d: %s"),
878 rh->hostname, id, strerror(errno));
882 rh->rc->write = rh->rc->read;
884 rs->socket = -1; /* we're a client */
895 struct sec_stream *rs = s;
900 logtime = time(NULL);
901 if (rs && rs->rc && logtime > rs->rc->logstamp + 10) {
902 g_debug("tcp_stream_write: data is still flowing");
903 rs->rc->logstamp = logtime;
906 if (full_write(rs->fd, buf, size) < size) {
907 security_stream_seterror(&rs->secstr,
908 _("write error on stream %d: %s"), rs->port, strerror(errno));
919 struct sec_handle *rh = h;
923 if (pkt->type != P_REQ)
926 if ((pwd = getpwuid(geteuid())) == NULL) {
927 security_seterror(&rh->sech,
928 _("can't get login name for my uid %ld"),
932 buf = alloc(16+strlen(pwd->pw_name));
933 strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name)));
934 strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14));
935 buf[14 + strlen(pwd->pw_name)] = '\n';
936 buf[15 + strlen(pwd->pw_name)] = '\0';
943 * Check the security of a received packet. Returns negative on security
944 * violation, or returns 0 if ok. Removes the security info from the pkt_t.
947 bsd_recv_security_ok(
948 struct sec_handle * rh,
951 char *tok, *security, *body, *result;
952 char *service = NULL, *serviceX, *serviceY;
959 * Now, find the SECURITY line in the body, and parse it out
962 if (strncmp_const(pkt->body, "SECURITY ") == 0) {
963 security = pkt->body;
965 while(*security != '\n' && len < pkt->size) {
969 if(*security == '\n') {
972 security_line = stralloc(pkt->body);
973 security = pkt->body + strlen("SECURITY ");
976 security_line = NULL;
981 security_line = NULL;
986 * Now, find the SERVICE line in the body, and parse it out
990 if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) {
992 serviceX = stralloc(s);
993 serviceY = strtok(serviceX, "\n");
995 service = stralloc(serviceY);
1000 * We need to do different things depending on which type of packet
1003 switch (pkt->type) {
1006 * Request packets must come from a reserved port
1008 port = SU_GET_PORT(&rh->peer);
1009 if (port >= IPPORT_RESERVED) {
1010 security_seterror(&rh->sech,
1011 _("host %s: port %u not secure"), rh->hostname,
1012 (unsigned int)port);
1014 amfree(security_line);
1019 security_seterror(&rh->sech,
1020 _("packet as no SERVICE line"));
1021 amfree(security_line);
1026 * Request packets contain a remote username. We need to check
1027 * that we allow it in.
1029 * They will look like:
1030 * SECURITY USER [username]
1033 /* there must be some security info */
1034 if (security == NULL) {
1035 security_seterror(&rh->sech,
1036 _("no bsd SECURITY for P_REQ"));
1041 /* second word must be USER */
1042 if ((tok = strtok(security, " ")) == NULL) {
1043 security_seterror(&rh->sech,
1044 _("SECURITY line: %s"), security_line);
1046 amfree(security_line);
1047 return (-1); /* default errmsg */
1049 if (strcmp(tok, "USER") != 0) {
1050 security_seterror(&rh->sech,
1051 _("REQ SECURITY line parse error, expecting USER, got %s"), tok);
1053 amfree(security_line);
1057 /* the third word is the username */
1058 if ((tok = strtok(NULL, "")) == NULL) {
1059 security_seterror(&rh->sech,
1060 _("SECURITY line: %s"), security_line);
1062 amfree(security_line);
1063 return (-1); /* default errmsg */
1065 if ((result = check_user(rh, tok, service)) != NULL) {
1066 security_seterror(&rh->sech, "%s", result);
1069 amfree(security_line);
1073 /* we're good to go */
1079 amfree(security_line);
1082 * If there is security info at the front of the packet, we need to
1083 * shift the rest of the data up and nuke it.
1085 if (body != pkt->body)
1086 memmove(pkt->body, body, strlen(body) + 1);
1091 * Transmit a packet. Add security information first.
1098 struct sec_handle *rh = cookie;
1102 assert(pkt != NULL);
1104 auth_debug(1, _("udpbsd_sendpkt: enter\n"));
1106 * Initialize this datagram, and add the header
1108 dgram_zero(&rh->udp->dgram);
1109 dgram_cat(&rh->udp->dgram, "%s", pkthdr2str(rh, pkt));
1112 * Add the security info. This depends on which kind of packet we're
1115 switch (pkt->type) {
1118 * Requests get sent with our username in the body
1120 if ((pwd = getpwuid(geteuid())) == NULL) {
1121 security_seterror(&rh->sech,
1122 _("can't get login name for my uid %ld"), (long)getuid());
1125 dgram_cat(&rh->udp->dgram, _("SECURITY USER %s\n"), pwd->pw_name);
1133 * Add the body, and send it
1135 dgram_cat(&rh->udp->dgram, "%s", pkt->body);
1138 _("sec: udpbsd_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),
1139 pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);
1141 if (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) {
1142 security_seterror(&rh->sech,
1143 _("send %s to %s failed: %s"), pkt_type2str(pkt->type),
1144 rh->hostname, strerror(errno));
1154 struct sec_handle *rh = cookie;
1156 if (rh->proto_handle == NULL) {
1160 auth_debug(1, _("udp: close handle '%s'\n"), rh->proto_handle);
1162 udp_recvpkt_cancel(rh);
1164 rh->next->prev = rh->prev;
1167 rh->udp->bh_last = rh->prev;
1170 rh->prev->next = rh->next;
1173 rh->udp->bh_first = rh->next;
1176 amfree(rh->proto_handle);
1177 amfree(rh->hostname);
1182 * Set up to receive a packet asynchronously, and call back when it has
1188 void (*fn)(void *, pkt_t *, security_status_t),
1192 struct sec_handle *rh = cookie;
1194 auth_debug(1, _("udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n"),
1195 cookie, fn, arg, timeout);
1201 * Subsequent recvpkt calls override previous ones
1203 if (rh->ev_read == NULL) {
1204 udp_addref(rh->udp, &udp_netfd_read_callback);
1205 rh->ev_read = event_register(rh->event_id, EV_WAIT,
1206 udp_recvpkt_callback, rh);
1208 if (rh->ev_timeout != NULL)
1209 event_release(rh->ev_timeout);
1211 rh->ev_timeout = NULL;
1213 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
1214 udp_recvpkt_timeout, rh);
1215 rh->fn.recvpkt = fn;
1220 * Remove a async receive request on this handle from the queue.
1221 * If it is the last one to be removed, then remove the event
1222 * handler for our network fd
1228 struct sec_handle *rh = cookie;
1232 if (rh->ev_read != NULL) {
1233 udp_delref(rh->udp);
1234 event_release(rh->ev_read);
1238 if (rh->ev_timeout != NULL) {
1239 event_release(rh->ev_timeout);
1240 rh->ev_timeout = NULL;
1245 * This is called when a handle is woken up because data read off of the
1249 udp_recvpkt_callback(
1252 struct sec_handle *rh = cookie;
1253 void (*fn)(void *, pkt_t *, security_status_t);
1256 auth_debug(1, _("udp: receive handle '%s' netfd '%s'\n"),
1257 rh->proto_handle, rh->udp->handle);
1260 /* if it doesn't correspond to this handle, something is wrong */
1261 assert(strcmp(rh->proto_handle, rh->udp->handle) == 0);
1263 /* if it didn't come from the same host/port, forget it */
1264 if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) {
1265 amfree(rh->udp->handle);
1266 dbprintf(_("not from same host\n"));
1267 dump_sockaddr(&rh->peer);
1268 dump_sockaddr(&rh->udp->peer);
1273 * We need to cancel the recvpkt request before calling the callback
1274 * because the callback may reschedule us.
1276 fn = rh->fn.recvpkt;
1278 udp_recvpkt_cancel(rh);
1281 * Check the security of the packet. If it is bad, then pass NULL
1282 * to the packet handling function instead of a packet.
1284 if (rh->udp->recv_security_ok &&
1285 rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) {
1286 (*fn)(arg, NULL, S_ERROR);
1288 (*fn)(arg, &rh->udp->pkt, S_OK);
1293 * This is called when a handle times out before receiving a packet.
1296 udp_recvpkt_timeout(
1299 struct sec_handle *rh = cookie;
1300 void (*fn)(void *, pkt_t *, security_status_t);
1305 assert(rh->ev_timeout != NULL);
1306 fn = rh->fn.recvpkt;
1308 udp_recvpkt_cancel(rh);
1309 (*fn)(arg, NULL, S_TIMEOUT);
1313 * Given a hostname and a port, setup a udp_handle
1318 struct sec_handle * rh,
1320 sockaddr_union *addr,
1326 * Save the hostname and port info
1328 auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"),
1329 (unsigned int)ntohs(port), handle, sequence);
1330 assert(addr != NULL);
1332 rh->hostname = stralloc(hostname);
1333 copy_sockaddr(&rh->peer, addr);
1334 SU_SET_PORT(&rh->peer, port);
1337 rh->prev = udp->bh_last;
1339 rh->prev->next = rh;
1341 if (!udp->bh_first) {
1347 rh->sequence = sequence;
1348 rh->event_id = (event_id_t)newevent++;
1349 amfree(rh->proto_handle);
1350 rh->proto_handle = stralloc(handle);
1351 rh->fn.connect = NULL;
1354 rh->ev_timeout = NULL;
1356 auth_debug(1, _("udp: adding handle '%s'\n"), rh->proto_handle);
1363 * Callback for received packets. This is the function bsd_recvpkt
1364 * registers with the event handler. It is called when the event handler
1365 * realizes that data is waiting to be read on the network socket.
1368 udp_netfd_read_callback(
1371 struct udp_handle *udp = cookie;
1372 struct sec_handle *rh;
1374 char hostname[NI_MAXHOST];
1376 char *errmsg = NULL;
1379 auth_debug(1, _("udp_netfd_read_callback(cookie=%p)\n"), cookie);
1380 assert(udp != NULL);
1382 #ifndef TEST /* { */
1384 * Receive the packet.
1386 dgram_zero(&udp->dgram);
1387 if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)
1389 #endif /* !TEST */ /* } */
1394 if (str2pkthdr(udp) < 0)
1398 * If there are events waiting on this handle, we're done
1401 while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||
1402 rh->sequence != udp->sequence ||
1403 cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) {
1406 if (rh && event_wakeup(rh->event_id) > 0)
1410 * If we didn't find a handle, then check for a new incoming packet.
1411 * If no accept handler was setup, then just return.
1413 if (udp->accept_fn == NULL) {
1414 dbprintf(_("Receive packet from unknown source"));
1418 rh = g_new0(struct sec_handle, 1);
1419 rh->proto_handle=NULL;
1422 security_handleinit(&rh->sech, udp->driver);
1424 result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer),
1425 hostname, sizeof(hostname), NULL, 0, 0);
1427 dbprintf("getnameinfo failed: %s\n",
1428 gai_strerror(result));
1429 security_seterror(&rh->sech, "getnameinfo failed: %s",
1430 gai_strerror(result));
1433 if (check_name_give_sockaddr(hostname,
1434 (struct sockaddr *)&udp->peer, &errmsg) < 0) {
1435 security_seterror(&rh->sech, "%s",errmsg);
1441 port = SU_GET_PORT(&udp->peer);
1442 a = udp_inithandle(udp, rh,
1449 auth_debug(1, _("bsd: closeX handle '%s'\n"), rh->proto_handle);
1455 * Check the security of the packet. If it is bad, then pass NULL
1456 * to the accept function instead of a packet.
1458 if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)
1459 (*udp->accept_fn)(&rh->sech, NULL);
1461 (*udp->accept_fn)(&rh->sech, &udp->pkt);
1465 * Locate an existing connection to the given host, or create a new,
1466 * unconnected entry if none exists. The caller is expected to check
1467 * for the lack of a connection (rc->read == -1) and set one up.
1471 const char *hostname,
1475 struct tcp_conn *rc = NULL;
1477 auth_debug(1, _("sec_tcp_conn_get: %s\n"), hostname);
1479 if (want_new == 0) {
1480 for (iter = connq; iter != NULL; iter = iter->next) {
1481 rc = (struct tcp_conn *)iter->data;
1482 if (strcasecmp(hostname, rc->hostname) == 0)
1489 _("sec_tcp_conn_get: exists, refcnt to %s is now %d\n"),
1490 rc->hostname, rc->refcnt);
1495 auth_debug(1, _("sec_tcp_conn_get: creating new handle\n"));
1497 * We can't be creating a new handle if we are the client
1499 rc = g_new0(struct tcp_conn, 1);
1500 rc->read = rc->write = -1;
1506 strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);
1507 rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';
1512 rc->accept_fn = NULL;
1513 rc->recv_security_ok = NULL;
1514 rc->prefix_packet = NULL;
1518 rc->event_id = newevent++;
1519 connq = g_slist_append(connq, rc);
1524 * Delete a reference to a connection, and close it if it is the last
1529 struct tcp_conn * rc)
1533 assert(rc->refcnt > 0);
1535 auth_debug(1, _("sec_tcp_conn_put: decrementing refcnt for %s to %d\n"),
1536 rc->hostname, rc->refcnt);
1537 if (rc->refcnt > 0) {
1540 auth_debug(1, _("sec_tcp_conn_put: closing connection to %s\n"), rc->hostname);
1543 if (rc->write != -1)
1545 if (rc->pid != -1) {
1546 waitpid(rc->pid, &status, WNOHANG);
1548 if (rc->ev_read != NULL)
1549 event_release(rc->ev_read);
1550 if (rc->errmsg != NULL)
1552 connq = g_slist_remove(connq, rc);
1554 if(!rc->donotclose) {
1556 /* a memory leak occurs, but freeing it lead to memory
1557 * corruption because it can still be used.
1558 * We need to find a good place to free 'rc'.
1564 * Turn on read events for a conn. Or, increase a ev_read_refcnt if we are
1565 * already receiving read events.
1569 struct tcp_conn * rc)
1571 assert (rc != NULL);
1573 if (rc->ev_read != NULL) {
1574 rc->ev_read_refcnt++;
1576 _("sec: conn_read: incremented ev_read_refcnt to %d for %s\n"),
1577 rc->ev_read_refcnt, rc->hostname);
1580 auth_debug(1, _("sec: conn_read registering event handler for %s\n"),
1582 rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,
1583 sec_tcp_conn_read_callback, rc);
1584 rc->ev_read_refcnt = 1;
1588 sec_tcp_conn_read_cancel(
1589 struct tcp_conn * rc)
1592 --rc->ev_read_refcnt;
1594 _("sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n"),
1595 rc->ev_read_refcnt, rc->hostname);
1596 if (rc->ev_read_refcnt > 0) {
1600 _("sec: conn_read_cancel: releasing event handler for %s\n"),
1602 event_release(rc->ev_read);
1607 * This is called when a handle is woken up because data read off of the
1617 struct sec_handle *rh = cookie;
1621 auth_debug(1, _("sec: recvpkt_callback: %zd\n"), bufsize);
1623 * We need to cancel the recvpkt request before calling
1624 * the callback because the callback may reschedule us.
1626 stream_recvpkt_cancel(rh);
1630 security_seterror(&rh->sech,
1631 _("EOF on read from %s"), rh->hostname);
1632 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1635 security_seterror(&rh->sech, "%s", security_stream_geterror(&rh->rs->secstr));
1636 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1642 parse_pkt(&pkt, buf, (size_t)bufsize);
1644 _("sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n"),
1645 pkt_type2str(pkt.type), pkt.type,
1646 rh->hostname, pkt.body);
1647 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1648 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1650 (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
1655 * Callback for tcpm_stream_read_sync
1658 stream_read_sync_callback(
1661 struct sec_stream *rs = s;
1664 auth_debug(1, _("sec: stream_read_callback_sync: handle %d\n"), rs->handle);
1667 * Make sure this was for us. If it was, then blow away the handle
1668 * so it doesn't get claimed twice. Otherwise, leave it alone.
1670 * If the handle is EOF, pass that up to our callback.
1672 if (rs->rc->handle == rs->handle) {
1673 auth_debug(1, _("sec: stream_read_callback_sync: it was for us\n"));
1674 rs->rc->handle = H_TAKEN;
1675 } else if (rs->rc->handle != H_EOF) {
1676 auth_debug(1, _("sec: stream_read_callback_sync: not for us\n"));
1681 * Remove the event first, and then call the callback.
1682 * We remove it first because we don't want to get in their
1683 * way if they reschedule it.
1685 tcpm_stream_read_cancel(rs);
1687 sync_pktlen = rs->rc->pktlen;
1688 sync_pkt = malloc(sync_pktlen);
1689 memcpy(sync_pkt, rs->rc->pkt, sync_pktlen);
1691 if (rs->rc->pktlen <= 0) {
1692 auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), rs->rc->errmsg);
1693 security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg);
1694 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1695 sec_tcp_conn_put(rs->rc);
1696 rs->closed_by_network = 1;
1700 _("sec: stream_read_callback_sync: read %zd bytes from %s:%d\n"),
1701 rs->rc->pktlen, rs->rc->hostname, rs->handle);
1705 * Callback for tcpm_stream_read
1708 stream_read_callback(
1711 struct sec_stream *rs = arg;
1716 logtime = time(NULL);
1717 if (rs && rs->rc && logtime > rs->rc->logstamp + 10) {
1718 g_debug("stream_read_callback: data is still flowing");
1719 rs->rc->logstamp = logtime;
1721 auth_debug(1, _("sec: stream_read_callback: handle %d\n"), rs->handle);
1724 * Make sure this was for us. If it was, then blow away the handle
1725 * so it doesn't get claimed twice. Otherwise, leave it alone.
1727 * If the handle is EOF, pass that up to our callback.
1729 if (rs->rc->handle == rs->handle) {
1730 auth_debug(1, _("sec: stream_read_callback: it was for us\n"));
1731 rs->rc->handle = H_TAKEN;
1732 } else if (rs->rc->handle != H_EOF) {
1733 auth_debug(1, _("sec: stream_read_callback: not for us\n"));
1738 * Remove the event first, and then call the callback.
1739 * We remove it first because we don't want to get in their
1740 * way if they reschedule it.
1742 tcpm_stream_read_cancel(rs);
1744 if (rs->rc->pktlen <= 0) {
1745 auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg);
1746 security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg);
1747 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1748 sec_tcp_conn_put(rs->rc);
1749 rs->closed_by_network = 1;
1750 (*rs->fn)(rs->arg, NULL, rs->rc->pktlen);
1753 auth_debug(1, _("sec: stream_read_callback: read %zd bytes from %s:%d\n"),
1754 rs->rc->pktlen, rs->rc->hostname, rs->handle);
1755 (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
1756 auth_debug(1, _("sec: after callback stream_read_callback\n"));
1760 * The callback for the netfd for the event handler
1761 * Determines if this packet is for this security handle,
1762 * and does the real callback if so.
1765 sec_tcp_conn_read_callback(
1768 struct tcp_conn * rc = cookie;
1769 struct sec_handle * rh;
1774 assert(cookie != NULL);
1776 auth_debug(1, _("sec: conn_read_callback\n"));
1778 /* Read the data off the wire. If we get errors, shut down. */
1779 rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt,
1781 auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"),
1788 if (rval < 0 || rc->handle == H_EOF) {
1791 revent = event_wakeup((event_id_t)rc->event_id);
1792 auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"),
1794 /* delete our 'accept' reference */
1795 if (rc->accept_fn != NULL) {
1796 if(rc->refcnt != 1) {
1797 dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"),
1801 rc->accept_fn = NULL;
1802 sec_tcp_conn_put(rc);
1809 revent = event_wakeup((event_id_t)rc->event_id);
1811 _("sec: conn_read_callback: event_wakeup return %d\n"), revent);
1815 /* If there are events waiting on this handle, we're done */
1817 revent = event_wakeup((event_id_t)rc->event_id);
1818 auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"), revent);
1820 if (rc->handle == H_TAKEN || rc->pktlen == 0) {
1821 if(rc->refcnt == 0) amfree(rc);
1825 assert(rc->refcnt > 0);
1827 /* If there is no accept fn registered, then drop the packet */
1828 if (rc->accept_fn == NULL) {
1830 _("sec: conn_read_callback: %zd bytes for handle %d went unclaimed!"),
1831 rc->pktlen, rc->handle);
1835 rh = g_new0(struct sec_handle, 1);
1836 security_handleinit(&rh->sech, rc->driver);
1837 rh->hostname = stralloc(rc->hostname);
1838 rh->ev_timeout = NULL;
1840 rh->peer = rc->peer;
1841 rh->rs = tcpma_stream_client(rh, rc->handle);
1843 auth_debug(1, _("sec: new connection\n"));
1845 parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);
1846 auth_debug(1, _("sec: calling accept_fn\n"));
1847 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1848 (*rc->accept_fn)(&rh->sech, NULL);
1850 (*rc->accept_fn)(&rh->sech, &pkt);
1860 const unsigned char *bufp = buf;
1862 auth_debug(1, _("sec: parse_pkt: parsing buffer of %zu bytes\n"), bufsize);
1864 pkt->type = (pktype_t)*bufp++;
1867 pkt->packet_size = bufsize+1;
1868 pkt->body = alloc(pkt->packet_size);
1870 pkt->body[0] = '\0';
1872 memcpy(pkt->body, bufp, bufsize);
1873 pkt->body[pkt->packet_size - 1] = '\0';
1875 pkt->size = strlen(pkt->body);
1877 auth_debug(1, _("sec: parse_pkt: %s (%d): \"%s\"\n"), pkt_type2str(pkt->type),
1878 pkt->type, pkt->body);
1882 * Convert a packet header into a string
1886 const struct sec_handle * rh,
1889 static char retbuf[256];
1892 assert(pkt != NULL);
1894 g_snprintf(retbuf, SIZEOF(retbuf), _("Amanda %d.%d %s HANDLE %s SEQ %d\n"),
1895 VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
1896 rh->proto_handle, rh->sequence);
1898 auth_debug(1, _("bsd: pkthdr2str handle '%s'\n"), rh->proto_handle);
1900 /* check for truncation. If only we had asprintf()... */
1901 assert(retbuf[strlen(retbuf) - 1] == '\n');
1907 * Parses out the header line in 'str' into the pkt and handle
1908 * Returns negative on parse error.
1920 assert(udp->dgram.cur != NULL);
1921 str = stralloc(udp->dgram.cur);
1923 /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
1925 /* Read in "Amanda" */
1926 if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
1929 /* nothing is done with the major/minor numbers currently */
1930 if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
1933 /* Read in the packet type */
1934 if ((tok = strtok(NULL, " ")) == NULL)
1937 pkt_init_empty(pkt, pkt_str2type(tok));
1938 if (pkt->type == (pktype_t)-1)
1941 /* Read in "HANDLE" */
1942 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
1945 /* parse the handle */
1946 if ((tok = strtok(NULL, " ")) == NULL)
1948 amfree(udp->handle);
1949 udp->handle = stralloc(tok);
1952 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)
1955 /* parse the sequence number */
1956 if ((tok = strtok(NULL, "\n")) == NULL)
1958 udp->sequence = atoi(tok);
1960 /* Save the body, if any */
1961 if ((tok = strtok(NULL, "")) != NULL)
1962 pkt_cat(pkt, "%s", tok);
1968 #if 0 /* XXX we have no way of passing this back up */
1969 security_seterror(&rh->sech,
1970 "parse error in packet header : '%s'", origstr);
1978 struct sec_handle * rh,
1979 const char * remoteuser,
1980 const char * service)
1984 char *result = NULL;
1985 char *localuser = NULL;
1987 /* lookup our local user name */
1988 if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
1989 return vstrallocf(_("getpwnam(%s) failed."), CLIENT_LOGIN);
1993 * Make a copy of the user name in case getpw* is called by
1994 * any of the lower level routines.
1996 localuser = stralloc(pwd->pw_name);
1998 #ifndef USE_AMANDAHOSTS
1999 r = check_user_ruserok(rh->hostname, pwd, remoteuser);
2001 r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service);
2004 result = vstrallocf(
2005 _("user %s from %s is not allowed to execute the service %s: %s"),
2006 remoteuser, rh->hostname, service, r);
2014 * See if a remote user is allowed in. This version uses ruserok()
2017 * Returns NULL on success, or error message on error.
2022 struct passwd * pwd,
2023 const char * remoteuser)
2034 uid_t myuid = getuid();
2037 * note that some versions of ruserok (eg SunOS 3.2) look in
2038 * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
2039 * chdir ourselves. Sigh.
2041 * And, believe it or not, some ruserok()'s try an initgroup just
2042 * for the hell of it. Since we probably aren't root at this point
2043 * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
2044 * into our stderr output even though the initgroup failure is not a
2045 * problem and is expected. Thanks a lot. Not.
2047 if (pipe(fd) != 0) {
2048 return stralloc2(_("pipe() fails: "), strerror(errno));
2050 if ((ruserok_pid = fork()) < 0) {
2051 return stralloc2(_("fork() fails: "), strerror(errno));
2052 } else if (ruserok_pid == 0) {
2056 fError = fdopen(fd[1], "w");
2058 error(_("Can't fdopen: %s"), strerror(errno));
2061 /* pamper braindead ruserok's */
2062 if (chdir(pwd->pw_dir) != 0) {
2063 g_fprintf(fError, _("chdir(%s) failed: %s"),
2064 pwd->pw_dir, strerror(errno));
2069 if (debug_auth >= 9) {
2070 char *dir = stralloc(pwd->pw_dir);
2072 auth_debug(9, _("bsd: calling ruserok(%s, %d, %s, %s)\n"), host,
2073 ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name);
2075 auth_debug(9, _("bsd: because you are running as root, "));
2076 auth_debug(9, _("/etc/hosts.equiv will not be used\n"));
2078 show_stat_info("/etc/hosts.equiv", NULL);
2080 show_stat_info(dir, "/.rhosts");
2084 saved_stderr = dup(2);
2086 if (open("/dev/null", O_RDWR) == -1) {
2087 auth_debug(1, _("Could not open /dev/null: %s\n"), strerror(errno));
2090 ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
2097 (void)dup2(saved_stderr,2);
2098 close(saved_stderr);
2102 fError = fdopen(fd[0], "r");
2104 error(_("Can't fdopen: %s"), strerror(errno));
2109 while ((es = agets(fError)) != NULL) {
2114 if (result == NULL) {
2115 result = stralloc("");
2117 strappend(result, ": ");
2119 strappend(result, es);
2124 pid = wait(&exitcode);
2125 while (pid != ruserok_pid) {
2126 if ((pid == (pid_t) -1) && (errno != EINTR)) {
2128 return vstrallocf(_("ruserok wait failed: %s"), strerror(errno));
2130 pid = wait(&exitcode);
2132 if (!WIFEXITED(exitcode) || WEXITSTATUS(exitcode) != 0) {
2134 result = str_exit_status("ruserok child", exitcode);
2143 * Check to see if a user is allowed in. This version uses .amandahosts
2144 * Returns an error message on failure, or NULL on success.
2147 check_user_amandahosts(
2149 sockaddr_union *addr,
2150 struct passwd * pwd,
2151 const char * remoteuser,
2152 const char * service)
2156 const char *fileuser;
2158 char *result = NULL;
2164 char *aservice = NULL;
2166 char ipstr[INET6_ADDRSTRLEN];
2168 char ipstr[INET_ADDRSTRLEN];
2171 auth_debug(1, _("check_user_amandahosts(host=%s, pwd=%p, "
2172 "remoteuser=%s, service=%s)\n"),
2173 host, pwd, remoteuser, service);
2175 ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
2176 if (debug_auth >= 9) {
2177 show_stat_info(ptmp, "");;
2179 if ((fp = fopen(ptmp, "r")) == NULL) {
2180 result = vstrallocf(_("cannot open %s: %s"), ptmp, strerror(errno));
2186 * Make sure the file is owned by the Amanda user and does not
2187 * have any group/other access allowed.
2189 if (fstat(fileno(fp), &sbuf) != 0) {
2190 result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));
2193 if (sbuf.st_uid != pwd->pw_uid) {
2194 result = vstrallocf(_("%s: owned by id %ld, should be %ld"),
2195 ptmp, (long)sbuf.st_uid, (long)pwd->pw_uid);
2198 if ((sbuf.st_mode & 077) != 0) {
2199 result = vstrallocf(_("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);
2204 * Now, scan the file for the host/user/service.
2207 while ((line = agets(fp)) != NULL) {
2213 auth_debug(9, _("bsd: processing line: <%s>\n"), line);
2214 /* get the host out of the file */
2215 if ((filehost = strtok(line, " \t")) == NULL) {
2220 /* get the username. If no user specified, then use the local user */
2221 if ((fileuser = strtok(NULL, " \t")) == NULL) {
2222 fileuser = pwd->pw_name;
2225 hostmatch = (strcasecmp(filehost, host) == 0);
2226 /* ok if addr=127.0.0.1 and
2227 * either localhost or localhost.domain is in .amandahost */
2229 (strcasecmp(filehost, "localhost")== 0 ||
2230 strcasecmp(filehost, "localhost.localdomain")== 0)) {
2232 if (SU_GET_FAMILY(addr) == (sa_family_t)AF_INET6)
2233 inet_ntop(AF_INET6, &addr->sin6.sin6_addr,
2234 ipstr, sizeof(ipstr));
2237 inet_ntop(AF_INET, &addr->sin.sin_addr,
2238 ipstr, sizeof(ipstr));
2239 if (strcmp(ipstr, "127.0.0.1") == 0 ||
2240 strcmp(ipstr, "::1") == 0)
2243 usermatch = (strcasecmp(fileuser, remoteuser) == 0);
2244 auth_debug(9, _("bsd: comparing \"%s\" with\n"), filehost);
2245 auth_debug(9, _("bsd: \"%s\" (%s)\n"), host,
2246 hostmatch ? _("match") : _("no match"));
2247 auth_debug(9, _("bsd: and \"%s\" with\n"), fileuser);
2248 auth_debug(9, _("bsd: \"%s\" (%s)\n"), remoteuser,
2249 usermatch ? _("match") : _("no match"));
2251 if (!hostmatch || !usermatch) {
2263 /* get the services. If no service specified, then use
2264 * noop/selfcheck/sendsize/sendbackup
2266 aservice = strtok(NULL, " \t,");
2268 if (strcmp(service,"noop") == 0 ||
2269 strcmp(service,"selfcheck") == 0 ||
2270 strcmp(service,"sendsize") == 0 ||
2271 strcmp(service,"sendbackup") == 0) {
2284 if (strcmp(aservice,service) == 0) {
2288 if (strcmp(aservice, "amdump") == 0 &&
2289 (strcmp(service, "noop") == 0 ||
2290 strcmp(service, "selfcheck") == 0 ||
2291 strcmp(service, "sendsize") == 0 ||
2292 strcmp(service, "sendbackup") == 0)) {
2296 } while((aservice = strtok(NULL, " \t,")) != NULL);
2298 if (aservice && strcmp(aservice, service) == 0) {
2307 if (strcmp(service, "amindexd") == 0 ||
2308 strcmp(service, "amidxtaped") == 0) {
2309 result = vstrallocf(_("Please add the line \"%s %s amindexd amidxtaped\" to %s on the server"), host, remoteuser, ptmp);
2310 } else if (strcmp(service, "amdump") == 0 ||
2311 strcmp(service, "noop") == 0 ||
2312 strcmp(service, "selfcheck") == 0 ||
2313 strcmp(service, "sendsize") == 0 ||
2314 strcmp(service, "sendbackup") == 0) {
2315 result = vstrallocf(_("Please add the line \"%s %s amdump\" to %s on the client"), host, remoteuser, ptmp);
2317 result = vstrallocf(_("%s: invalid service %s"), ptmp, service);
2329 /* return 1 on success, 0 on failure */
2332 sockaddr_union *addr,
2334 unsigned long cksum,
2337 char * remotehost = NULL, *remoteuser = NULL;
2338 char * bad_bsd = NULL;
2339 struct passwd * pwptr;
2344 char hostname[NI_MAXHOST];
2348 (void)cksum; /* Quiet unused parameter warning */
2351 _("check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n"),
2352 addr, str, cksum, errstr);
2353 dump_sockaddr(addr);
2357 /* what host is making the request? */
2358 if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr),
2359 hostname, NI_MAXHOST, NULL, 0, 0)) != 0) {
2360 dbprintf(_("getnameinfo failed: %s\n"),
2361 gai_strerror(result));
2362 *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ",
2363 "getnameinfo failed: ", gai_strerror(result),
2367 remotehost = stralloc(hostname);
2368 if( check_name_give_sockaddr(hostname,
2369 (struct sockaddr *)addr, errstr) < 0) {
2375 /* next, make sure the remote port is a "reserved" one */
2376 port = SU_GET_PORT(addr);
2377 if (port >= IPPORT_RESERVED) {
2378 *errstr = vstrallocf(_("[host %s: port %u not secure]"),
2379 remotehost, (unsigned int)port);
2384 /* extract the remote user name from the message */
2389 bad_bsd = vstrallocf(_("[host %s: bad bsd security line]"), remotehost);
2391 if (strncmp_const_skip(s - 1, "USER ", s, ch) != 0) {
2398 skip_whitespace(s, ch);
2406 skip_non_whitespace(s, ch);
2408 remoteuser = stralloc(fp);
2412 /* lookup our local user name */
2415 if ((pwptr = getpwuid(myuid)) == NULL)
2416 error(_("error [getpwuid(%d) fails]"), (int)myuid);
2418 auth_debug(1, _("bsd security: remote host %s user %s local user %s\n"),
2419 remotehost, remoteuser, pwptr->pw_name);
2421 #ifndef USE_AMANDAHOSTS
2422 s = check_user_ruserok(remotehost, pwptr, remoteuser);
2424 s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL);
2428 *errstr = vstrallocf(_("[access as %s not allowed from %s@%s: %s]"),
2429 pwptr->pw_name, remoteuser, remotehost, s);
2434 return *errstr == NULL;
2438 * Like read(), but waits until the entire buffer has been filled.
2447 char *buf = vbuf; /* ptr arith */
2449 size_t size = origsize;
2451 auth_debug(1, _("net_read: begin %zu\n"), origsize);
2454 auth_debug(1, _("net_read: while %zu\n"), size);
2455 nread = net_read_fillbuf(fd, timeout, buf, size);
2457 auth_debug(1, _("db: net_read: end return(-1)\n"));
2461 auth_debug(1, _("net_read: end return(0)\n"));
2467 auth_debug(1, _("net_read: end %zu\n"), origsize);
2468 return ((ssize_t)origsize);
2472 * net_read likes to do a lot of little reads. Buffer it.
2481 SELECT_ARG_TYPE readfds;
2485 auth_debug(1, _("net_read_fillbuf: begin\n"));
2487 FD_SET(fd, &readfds);
2488 tv.tv_sec = timeout;
2490 switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
2495 auth_debug(1, _("net_read_fillbuf: case -1\n"));
2498 auth_debug(1, _("net_read_fillbuf: case 1\n"));
2499 assert(FD_ISSET(fd, &readfds));
2502 auth_debug(1, _("net_read_fillbuf: case default\n"));
2506 nread = read(fd, buf, size);
2509 auth_debug(1, _("net_read_fillbuf: end %zd\n"), nread);
2515 * Display stat() information about a file.
2523 char *name = vstralloc(a, b, NULL);
2525 struct passwd *pwptr G_GNUC_UNUSED;
2526 struct passwd pw G_GNUC_UNUSED;
2528 struct group *grptr G_GNUC_UNUSED;
2529 struct group gr G_GNUC_UNUSED;
2531 int buflen G_GNUC_UNUSED;
2532 char *buf G_GNUC_UNUSED;
2534 if (stat(name, &sbuf) != 0) {
2535 auth_debug(1, _("bsd: cannot stat %s: %s\n"), name, strerror(errno));
2540 #ifdef _SC_GETPW_R_SIZE_MAX
2541 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
2547 buf = malloc(buflen);
2549 #ifdef HAVE_GETPWUID_R
2550 if (getpwuid_r(sbuf.st_uid, &pw, buf, buflen, &pwptr) == 0 &&
2552 owner = stralloc(pwptr->pw_name);
2556 owner = alloc(NUM_STR_SIZE + 1);
2557 g_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
2559 #ifdef HAVE_GETGRGID_R
2560 if (getgrgid_r(sbuf.st_gid, &gr, buf, buflen, &grptr) == 0 &&
2562 group = stralloc(grptr->gr_name);
2566 group = alloc(NUM_STR_SIZE + 1);
2567 g_snprintf(group, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
2570 auth_debug(1, _("bsd: processing file: %s\n"), name);
2571 auth_debug(1, _("bsd: owner=%s group=%s mode=%03o\n"),
2573 (int) (sbuf.st_mode & 0777));
2581 check_name_give_sockaddr(
2582 const char *hostname,
2583 struct sockaddr *addr,
2587 struct addrinfo *res = NULL, *res1;
2590 result = resolve_hostname(hostname, 0, &res, &canonname);
2592 dbprintf(_("check_name_give_sockaddr: resolve_hostname('%s'): %s\n"), hostname, gai_strerror(result));
2593 *errstr = newvstrallocf(*errstr,
2594 _("check_name_give_sockaddr: resolve_hostname('%s'): %s"),
2595 hostname, gai_strerror(result));
2598 if (canonname == NULL) {
2599 dbprintf(_("resolve_hostname('%s') did not return a canonical name\n"), hostname);
2600 *errstr = newvstrallocf(*errstr,
2601 _("check_name_give_sockaddr: resolve_hostname('%s') did not return a canonical name"),
2606 if (strncasecmp(hostname, canonname, strlen(hostname)) != 0) {
2607 dbprintf(_("%s doesn't resolve to itself, it resolves to %s\n"),
2608 hostname, canonname);
2609 *errstr = newvstrallocf(*errstr,
2610 _("%s doesn't resolve to itself, it resolves to %s"),
2611 hostname, canonname);
2615 for(res1=res; res1 != NULL; res1 = res1->ai_next) {
2616 if (cmp_sockaddr((sockaddr_union *)res1->ai_addr, (sockaddr_union *)addr, 1) == 0) {
2623 g_debug("%s doesn't resolve to %s",
2624 hostname, str_sockaddr((sockaddr_union *)addr));
2625 *errstr = newvstrallocf(*errstr,
2626 "%s doesn't resolve to %s",
2627 hostname, str_sockaddr((sockaddr_union *)addr));
2629 if (res) freeaddrinfo(res);
2635 find_port_for_service(
2641 int all_numeric = 1;
2643 for (s=service; *s != '\0'; s++) {
2644 if (!isdigit((int)*s)) {
2649 if (all_numeric == 1) {
2650 port = atoi(service);
2654 if ((sp = getservbyname(service, proto)) == NULL) {
2657 port = (in_port_t)(ntohs((in_port_t)sp->s_port));
2665 sec_get_authenticated_peer_name_gethostname(
2666 security_handle_t *hdl G_GNUC_UNUSED)
2668 char *server_hostname;
2669 server_hostname = malloc(1024);
2670 if (gethostname(server_hostname, 1024) == 0) {
2671 server_hostname[1023] = '\0';
2672 return server_hostname;
2674 amfree(server_hostname);
2675 return strdup("localhost");
2679 sec_get_authenticated_peer_name_hostname(
2680 security_handle_t *hdl)
2682 char *hostname = ((struct sec_handle *)hdl)->hostname;
2685 return strdup(hostname);