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.
42 #include "security-util.h"
47 * Magic values for sec_conn->handle
49 #define H_TAKEN -1 /* sec_conn->tok was already read */
50 #define H_EOF -2 /* this connection has been shut down */
53 * This is a queue of open connections
55 struct connq_s connq = {
56 TAILQ_HEAD_INITIALIZER(connq.tailq), 0
58 static int newhandle = 1;
59 static int newevent = 1;
64 static void recvpkt_callback(void *, void *, ssize_t);
65 static void stream_read_callback(void *);
66 static void stream_read_sync_callback(void *);
68 static void sec_tcp_conn_read_cancel(struct tcp_conn *);
69 static void sec_tcp_conn_read_callback(void *);
73 * Authenticate a stream
74 * Nothing needed for sec. The connection is authenticated by secd
81 (void)s; /* Quiet unused parameter warning */
86 * Returns the stream id for this stream. This is just the local
93 struct sec_stream *rs = s;
101 * Setup to handle new incoming connections
105 const security_driver_t *driver,
108 void (*fn)(security_handle_t *, pkt_t *))
112 rc = sec_tcp_conn_get("unknown",0);
117 sec_tcp_conn_read(rc);
121 * frees a handle allocated by the above
127 struct sec_handle *rh = inst;
131 auth_debug(1, ("%s: sec: closing handle to %s\n", debug_prefix_time(NULL),
134 if (rh->rs != NULL) {
135 /* This may be null if we get here on an error */
136 stream_recvpkt_cancel(rh);
137 security_stream_close(&rh->rs->secstr);
139 /* keep us from getting here again */
140 rh->sech.driver = NULL;
141 amfree(rh->hostname);
146 * Called when a sec connection is finished connecting and is ready
147 * to be authenticated.
150 sec_connect_callback(
153 struct sec_handle *rh = cookie;
155 event_release(rh->rs->ev_read);
156 rh->rs->ev_read = NULL;
157 event_release(rh->ev_timeout);
158 rh->ev_timeout = NULL;
160 (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
164 * Called if a connection times out before completion.
170 struct sec_handle *rh = cookie;
172 event_release(rh->rs->ev_read);
173 rh->rs->ev_read = NULL;
174 event_release(rh->ev_timeout);
175 rh->ev_timeout = NULL;
177 (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
181 sec_close_connection_none(
202 struct sec_handle *rh = cookie;
209 auth_debug(1, ("%s: sec: stream_sendpkt: enter\n",
210 debug_prefix_time(NULL)));
212 if (rh->rc->prefix_packet)
213 s = rh->rc->prefix_packet(rh, pkt);
216 len = strlen(pkt->body) + strlen(s) + 2;
218 buf[0] = (char)pkt->type;
219 strncpy(&buf[1], s, len - 1);
220 strncpy(&buf[1 + strlen(s)], pkt->body, (len - strlen(s) - 1));
225 ("%s: sec: stream_sendpkt: %s (%d) pkt_t (len " SIZE_T_FMT ") contains:\n\n\"%s\"\n\n",
226 debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type,
227 strlen(pkt->body), pkt->body));
229 if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {
230 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
238 * Set up to receive a packet asyncronously, and call back when
244 void (*fn)(void *, pkt_t *, security_status_t),
248 struct sec_handle *rh = cookie;
252 auth_debug(1, ("%s: sec: recvpkt registered for %s\n",
253 debug_prefix_time(NULL), rh->hostname));
256 * Reset any pending timeout on this handle
258 if (rh->ev_timeout != NULL)
259 event_release(rh->ev_timeout);
262 * Negative timeouts mean no timeout
265 rh->ev_timeout = NULL;
267 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
268 stream_recvpkt_timeout, rh);
272 security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);
276 * This is called when a handle times out before receiving a packet.
279 stream_recvpkt_timeout(
282 struct sec_handle *rh = cookie;
286 auth_debug(1, ("%s: sec: recvpkt timeout for %s\n",
287 debug_prefix_time(NULL), rh->hostname));
289 stream_recvpkt_cancel(rh);
290 (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
294 * Remove a async receive request from the queue
297 stream_recvpkt_cancel(
300 struct sec_handle *rh = cookie;
302 auth_debug(1, ("%s: sec: cancelling recvpkt for %s\n",
303 debug_prefix_time(NULL), rh->hostname));
307 security_stream_read_cancel(&rh->rs->secstr);
308 if (rh->ev_timeout != NULL) {
309 event_release(rh->ev_timeout);
310 rh->ev_timeout = NULL;
315 * Write a chunk of data to a stream. Blocks until completion.
323 struct sec_stream *rs = s;
326 assert(rs->rc != NULL);
328 auth_debug(1, ("%s: sec: stream_write: writing " SIZE_T_FMT " bytes to %s:%d %d\n",
329 debug_prefix_time(NULL), size, rs->rc->hostname, rs->handle,
332 if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg,
334 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
341 * Submit a request to read some data. Calls back with the given
342 * function and arg when completed.
347 void (*fn)(void *, void *, ssize_t),
350 struct sec_stream *rs = s;
355 * Only one read request can be active per stream.
357 if (rs->ev_read == NULL) {
358 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
359 stream_read_callback, rs);
360 sec_tcp_conn_read(rs->rc);
367 * Write a chunk of data to a stream. Blocks until completion.
370 tcpm_stream_read_sync(
374 struct sec_stream *rs = s;
379 * Only one read request can be active per stream.
381 if (rs->ev_read != NULL) {
384 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
385 stream_read_sync_callback, rs);
386 sec_tcp_conn_read(rs->rc);
387 event_wait(rs->ev_read);
389 return (rs->rc->pktlen);
393 * Cancel a previous stream read request. It's ok if we didn't have a read
397 tcpm_stream_read_cancel(
400 struct sec_stream *rs = s;
404 if (rs->ev_read != NULL) {
405 event_release(rs->ev_read);
407 sec_tcp_conn_read_cancel(rs->rc);
412 * Transmits a chunk of data over a rsh_handle, adding
413 * the necessary headers to allow the remote end to decode it.
432 assert(SIZEOF(netlength) == 4);
434 auth_debug(1, ("%s: tcpm_send_token: write %zd bytes to handle %d\n",
435 debug_prefix_time(NULL), len, handle));
438 * 32 bit length (network byte order)
439 * 32 bit handle (network byte order)
442 netlength = htonl(len);
443 iov[0].iov_base = (void *)&netlength;
444 iov[0].iov_len = SIZEOF(netlength);
446 nethandle = htonl((uint32_t)handle);
447 iov[1].iov_base = (void *)&nethandle;
448 iov[1].iov_len = SIZEOF(nethandle);
450 encbuf = (char *)buf;
457 if (rc->driver->data_encrypt == NULL) {
458 iov[2].iov_base = (void *)buf;
459 iov[2].iov_len = len;
461 /* (the extra (void *) cast is to quiet type-punning warnings) */
462 rc->driver->data_encrypt(rc, (void *)buf, len, (void **)(void *)&encbuf, &encsize);
463 iov[2].iov_base = (void *)encbuf;
464 iov[2].iov_len = encsize;
465 netlength = htonl(encsize);
470 rval = net_writev(fd, iov, nb_iov);
471 if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) {
477 *errmsg = newvstralloc(*errmsg, "write error to ",
478 ": ", strerror(errno), NULL);
486 * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed
487 * return 0 on EOF: *handle = handle && *size = 0 if stream closed
488 * return size : *handle = handle && *size = size for data read
501 unsigned int netint[2];
503 assert(SIZEOF(netint) == 8);
505 switch (net_read(fd, &netint, SIZEOF(netint), timeout)) {
508 *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno),
510 auth_debug(1, ("%s: tcpm_recv_token: A return(-1)\n",
511 debug_prefix_time(NULL)));
516 *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL);
517 auth_debug(1, ("%s: tcpm_recv_token: A return(0)\n",
518 debug_prefix_time(NULL)));
524 *size = (ssize_t)ntohl(netint[0]);
525 *handle = (int)ntohl(netint[1]);
526 /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */
527 if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) {
528 if (isprint((int)(*size ) & 0xFF) &&
529 isprint((int)(*size >> 8 ) & 0xFF) &&
530 isprint((int)(*size >> 16) & 0xFF) &&
531 isprint((int)(*size >> 24) & 0xFF) &&
532 isprint((*handle ) & 0xFF) &&
533 isprint((*handle >> 8 ) & 0xFF) &&
534 isprint((*handle >> 16) & 0xFF) &&
535 isprint((*handle >> 24) & 0xFF)) {
538 s[0] = ((int)(*size) >> 24) & 0xFF;
539 s[1] = ((int)(*size) >> 16) & 0xFF;
540 s[2] = ((int)(*size) >> 8) & 0xFF;
541 s[3] = ((int)(*size) ) & 0xFF;
542 s[4] = (*handle >> 24) & 0xFF;
543 s[5] = (*handle >> 16) & 0xFF;
544 s[6] = (*handle >> 8 ) & 0xFF;
545 s[7] = (*handle ) & 0xFF;
547 while(i<100 && isprint(s[i]) && s[i] != '\n') {
548 switch(net_read(fd, &s[i], 1, 0)) {
549 case -1: s[i] = '\0'; break;
550 case 0: s[i] = '\0'; break;
551 default: dbprintf(("read: %c\n", s[i])); i++; s[i]=' ';break;
555 *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size: ",
557 dbprintf(("%s: tcpm_recv_token: invalid size: %s\n",
558 debug_prefix_time(NULL), s));
560 *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size",
562 dbprintf(("%s: tcpm_recv_token: invalid size " SSIZE_T_FMT "\n",
563 debug_prefix_time(NULL), *size));
569 *buf = alloc((size_t)*size);
572 auth_debug(1, ("%s: tcpm_recv_token: read EOF from %d\n",
573 debug_prefix_time(NULL), *handle));
574 *errmsg = newvstralloc(*errmsg, "EOF",
578 switch (net_read(fd, *buf, (size_t)*size, timeout)) {
581 *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno),
583 auth_debug(1, ("%s: tcpm_recv_token: B return(-1)\n",
584 debug_prefix_time(NULL)));
588 *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL);
589 auth_debug(1, ("%s: tcpm_recv_token: B return(0)\n",
590 debug_prefix_time(NULL)));
596 auth_debug(1, ("%s: tcpm_recv_token: read " SSIZE_T_FMT " bytes from %d\n",
597 debug_prefix_time(NULL), *size, *handle));
599 if (*size > 0 && rc->driver->data_decrypt != NULL) {
602 /* (the extra (void *) cast is to quiet type-punning warnings) */
603 rc->driver->data_decrypt(rc, *buf, *size, (void **)(void *)&decbuf, &decsize);
604 if (*buf != decbuf) {
615 tcpm_close_connection(
619 struct sec_handle *rh = h;
623 if (rh && rh->rc && rh->rc->toclose == 0) {
625 sec_tcp_conn_put(rh->rc);
632 * Accept an incoming connection on a stream_server socket
633 * Nothing needed for tcpma.
639 (void)s; /* Quiet unused parameter warning */
645 * Return a connected stream. For sec, this means setup a stream
646 * with the supplied handle.
653 struct sec_handle *rh = h;
654 struct sec_stream *rs;
659 security_seterror(&rh->sech,
660 "%d: invalid security stream id", id);
664 rs = alloc(SIZEOF(*rs));
665 security_streaminit(&rs->secstr, rh->sech.driver);
668 rs->closed_by_me = 0;
669 rs->closed_by_network = 0;
675 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
676 rs->rc->driver = rh->sech.driver;
680 auth_debug(1, ("%s: sec: stream_client: connected to stream %d\n",
681 debug_prefix_time(NULL), id));
687 * Create the server end of a stream. For sec, this means setup a stream
688 * object and allocate a new handle for it.
694 struct sec_handle *rh = h;
695 struct sec_stream *rs;
699 rs = alloc(SIZEOF(*rs));
700 security_streaminit(&rs->secstr, rh->sech.driver);
701 rs->closed_by_me = 0;
702 rs->closed_by_network = 0;
708 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
709 rs->rc->driver = rh->sech.driver;
713 * Stream should already be setup!
715 if (rs->rc->read < 0) {
716 sec_tcp_conn_put(rs->rc);
718 security_seterror(&rh->sech, "lost connection to %s", rh->hostname);
721 assert(strcmp(rh->hostname, rs->rc->hostname) == 0);
723 * so as not to conflict with the amanda server's handle numbers,
724 * we start at 500000 and work down
726 rs->handle = 500000 - newhandle++;
728 auth_debug(1, ("%s: sec: stream_server: created stream %d\n",
729 debug_prefix_time(NULL), rs->handle));
734 * Close and unallocate resources for a stream.
740 struct sec_stream *rs = s;
745 auth_debug(1, ("%s: sec: tcpma_stream_close: closing stream %d\n",
746 debug_prefix_time(NULL), rs->handle));
748 if(rs->closed_by_network == 0 && rs->rc->write != -1)
749 tcpm_stream_write(rs, &buf, 0);
750 security_stream_read_cancel(&rs->secstr);
751 if(rs->closed_by_network == 0)
752 sec_tcp_conn_put(rs->rc);
757 * Create the server end of a stream. For bsdudp, this means setup a tcp
758 * socket for receiving a connection.
764 struct sec_stream *rs = NULL;
765 struct sec_handle *rh = h;
769 rs = alloc(SIZEOF(*rs));
770 security_streaminit(&rs->secstr, rh->sech.driver);
771 rs->closed_by_me = 0;
772 rs->closed_by_network = 0;
775 rs->handle = 500000 - newhandle++;
777 rs->socket = 0; /* the socket is already opened */
780 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
781 rh->rc->driver = rh->sech.driver;
783 rs->socket = stream_server(&rs->port, STREAM_BUFSIZE,
785 if (rs->socket < 0) {
786 security_seterror(&rh->sech,
787 "can't create server stream: %s", strerror(errno));
791 rh->rc->read = rs->socket;
792 rh->rc->write = rs->socket;
793 rs->handle = (int)rs->port;
801 * Accepts a new connection on unconnected streams. Assumes it is ok to
808 struct sec_stream *bs = s;
811 assert(bs->socket != -1);
814 if (bs->socket > 0) {
815 bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE);
817 security_stream_seterror(&bs->secstr,
818 "can't accept new stream connection: %s",
822 bs->rc->read = bs->fd;
823 bs->rc->write = bs->fd;
829 * Return a connected stream
836 struct sec_stream *rs = NULL;
837 struct sec_handle *rh = h;
841 rs = alloc(SIZEOF(*rs));
842 security_streaminit(&rs->secstr, rh->sech.driver);
845 rs->closed_by_me = 0;
846 rs->closed_by_network = 0;
852 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
853 rh->rc->driver = rh->sech.driver;
855 rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
856 STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
857 if (rh->rc->read < 0) {
858 security_seterror(&rh->sech,
859 "can't connect stream to %s port %d: %s",
860 rh->hostname, id, strerror(errno));
864 rh->rc->write = rh->rc->read;
866 rs->socket = -1; /* we're a client */
877 struct sec_stream *rs = s;
881 if (fullwrite(rs->fd, buf, size) < 0) {
882 security_stream_seterror(&rs->secstr,
883 "write error on stream %d: %s", rs->port, strerror(errno));
894 struct sec_handle *rh = h;
898 if (pkt->type != P_REQ)
901 if ((pwd = getpwuid(getuid())) == NULL) {
902 security_seterror(&rh->sech,
903 "can't get login name for my uid %ld",
907 buf = alloc(16+strlen(pwd->pw_name));
908 strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name)));
909 strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14));
910 buf[14 + strlen(pwd->pw_name)] = '\n';
911 buf[15 + strlen(pwd->pw_name)] = '\0';
918 * Check the security of a received packet. Returns negative on security
919 * violation, or returns 0 if ok. Removes the security info from the pkt_t.
922 bsd_recv_security_ok(
923 struct sec_handle * rh,
926 char *tok, *security, *body, *result;
927 char *service = NULL, *serviceX, *serviceY;
934 * Now, find the SECURITY line in the body, and parse it out
937 if (strncmp_const(pkt->body, "SECURITY ") == 0) {
938 security = pkt->body;
940 while(*security != '\n' && len < pkt->size) {
944 if(*security == '\n') {
947 security_line = stralloc(pkt->body);
948 security = pkt->body + strlen("SECURITY ");
951 security_line = NULL;
956 security_line = NULL;
961 * Now, find the SERVICE line in the body, and parse it out
965 if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) {
966 serviceX = stralloc(s);
967 serviceY = strtok(serviceX, "\n");
969 service = stralloc(serviceY);
974 * We need to do different things depending on which type of packet
980 * Request packets must come from a reserved port
982 port = SS_GET_PORT(&rh->peer);
983 if (port >= IPPORT_RESERVED) {
984 security_seterror(&rh->sech,
985 "host %s: port %u not secure", rh->hostname,
988 amfree(security_line);
993 security_seterror(&rh->sech,
994 "packet as no SERVICE line");
995 amfree(security_line);
1000 * Request packets contain a remote username. We need to check
1001 * that we allow it in.
1003 * They will look like:
1004 * SECURITY USER [username]
1007 /* there must be some security info */
1008 if (security == NULL) {
1009 security_seterror(&rh->sech,
1010 "no bsd SECURITY for P_REQ");
1015 /* second word must be USER */
1016 if ((tok = strtok(security, " ")) == NULL) {
1017 security_seterror(&rh->sech,
1018 "SECURITY line: %s", security_line);
1020 amfree(security_line);
1021 return (-1); /* default errmsg */
1023 if (strcmp(tok, "USER") != 0) {
1024 security_seterror(&rh->sech,
1025 "REQ SECURITY line parse error, expecting USER, got %s", tok);
1027 amfree(security_line);
1031 /* the third word is the username */
1032 if ((tok = strtok(NULL, "")) == NULL) {
1033 security_seterror(&rh->sech,
1034 "SECURITY line: %s", security_line);
1035 amfree(security_line);
1036 return (-1); /* default errmsg */
1038 if ((result = check_user(rh, tok, service)) != NULL) {
1039 security_seterror(&rh->sech, "%s", result);
1042 amfree(security_line);
1046 /* we're good to go */
1052 amfree(security_line);
1055 * If there is security info at the front of the packet, we need to
1056 * shift the rest of the data up and nuke it.
1058 if (body != pkt->body)
1059 memmove(pkt->body, body, strlen(body) + 1);
1064 * Transmit a packet. Add security information first.
1071 struct sec_handle *rh = cookie;
1075 assert(pkt != NULL);
1077 auth_debug(1, ("%s: udpbsd_sendpkt: enter\n", get_pname()));
1079 * Initialize this datagram, and add the header
1081 dgram_zero(&rh->udp->dgram);
1082 dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt));
1085 * Add the security info. This depends on which kind of packet we're
1088 switch (pkt->type) {
1091 * Requests get sent with our username in the body
1093 if ((pwd = getpwuid(geteuid())) == NULL) {
1094 security_seterror(&rh->sech,
1095 "can't get login name for my uid %ld", (long)getuid());
1098 dgram_cat(&rh->udp->dgram, "SECURITY USER %s\n", pwd->pw_name);
1106 * Add the body, and send it
1108 dgram_cat(&rh->udp->dgram, pkt->body);
1111 ("%s: sec: udpbsd_sendpkt: %s (%d) pkt_t (len " SIZE_T_FMT ") contains:\n\n\"%s\"\n\n",
1112 debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type,
1113 strlen(pkt->body), pkt->body));
1115 if (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) {
1116 security_seterror(&rh->sech,
1117 "send %s to %s failed: %s", pkt_type2str(pkt->type),
1118 rh->hostname, strerror(errno));
1128 struct sec_handle *rh = cookie;
1130 if (rh->proto_handle == NULL) {
1134 auth_debug(1, ("%s: udp: close handle '%s'\n",
1135 debug_prefix_time(NULL), rh->proto_handle));
1137 udp_recvpkt_cancel(rh);
1139 rh->next->prev = rh->prev;
1142 rh->udp->bh_last = rh->prev;
1145 rh->prev->next = rh->next;
1148 rh->udp->bh_first = rh->next;
1151 amfree(rh->proto_handle);
1152 amfree(rh->hostname);
1157 * Set up to receive a packet asynchronously, and call back when it has
1163 void (*fn)(void *, pkt_t *, security_status_t),
1167 struct sec_handle *rh = cookie;
1169 auth_debug(1, ("%s: udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n",
1170 debug_prefix_time(NULL), cookie, fn, arg, timeout));
1176 * Subsequent recvpkt calls override previous ones
1178 if (rh->ev_read == NULL) {
1179 udp_addref(rh->udp, &udp_netfd_read_callback);
1180 rh->ev_read = event_register(rh->event_id, EV_WAIT,
1181 udp_recvpkt_callback, rh);
1183 if (rh->ev_timeout != NULL)
1184 event_release(rh->ev_timeout);
1186 rh->ev_timeout = NULL;
1188 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
1189 udp_recvpkt_timeout, rh);
1190 rh->fn.recvpkt = fn;
1195 * Remove a async receive request on this handle from the queue.
1196 * If it is the last one to be removed, then remove the event
1197 * handler for our network fd
1203 struct sec_handle *rh = cookie;
1207 if (rh->ev_read != NULL) {
1208 udp_delref(rh->udp);
1209 event_release(rh->ev_read);
1213 if (rh->ev_timeout != NULL) {
1214 event_release(rh->ev_timeout);
1215 rh->ev_timeout = NULL;
1220 * This is called when a handle is woken up because data read off of the
1224 udp_recvpkt_callback(
1227 struct sec_handle *rh = cookie;
1228 void (*fn)(void *, pkt_t *, security_status_t);
1231 auth_debug(1, ("%s: udp: receive handle '%s' netfd '%s'\n",
1232 debug_prefix_time(NULL), rh->proto_handle, rh->udp->handle));
1235 /* if it doesn't correspond to this handle, something is wrong */
1236 assert(strcmp(rh->proto_handle, rh->udp->handle) == 0);
1238 /* if it didn't come from the same host/port, forget it */
1239 if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) {
1240 amfree(rh->udp->handle);
1241 dbprintf(("not form same host\n"));
1242 dump_sockaddr(&rh->peer);
1243 dump_sockaddr(&rh->udp->peer);
1248 * We need to cancel the recvpkt request before calling the callback
1249 * because the callback may reschedule us.
1251 fn = rh->fn.recvpkt;
1253 udp_recvpkt_cancel(rh);
1256 * Check the security of the packet. If it is bad, then pass NULL
1257 * to the packet handling function instead of a packet.
1259 if (rh->udp->recv_security_ok &&
1260 rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) {
1261 (*fn)(arg, NULL, S_ERROR);
1263 (*fn)(arg, &rh->udp->pkt, S_OK);
1268 * This is called when a handle times out before receiving a packet.
1271 udp_recvpkt_timeout(
1274 struct sec_handle *rh = cookie;
1275 void (*fn)(void *, pkt_t *, security_status_t);
1280 assert(rh->ev_timeout != NULL);
1281 fn = rh->fn.recvpkt;
1283 udp_recvpkt_cancel(rh);
1284 (*fn)(arg, NULL, S_TIMEOUT);
1288 * Given a hostname and a port, setup a udp_handle
1293 struct sec_handle * rh,
1295 struct sockaddr_storage *addr,
1301 * Save the hostname and port info
1303 auth_debug(1, ("%s: udp_inithandle port %u handle %s sequence %d\n",
1304 debug_prefix_time(NULL), (unsigned int)ntohs(port),
1306 assert(addr != NULL);
1308 rh->hostname = stralloc(hostname);
1309 memcpy(&rh->peer, addr, SIZEOF(rh->peer));
1310 SS_SET_PORT(&rh->peer, port);
1312 rh->prev = udp->bh_last;
1314 rh->prev->next = rh;
1316 if (!udp->bh_first) {
1322 rh->sequence = sequence;
1323 rh->event_id = (event_id_t)newevent++;
1324 amfree(rh->proto_handle);
1325 rh->proto_handle = stralloc(handle);
1326 rh->fn.connect = NULL;
1329 rh->ev_timeout = NULL;
1331 auth_debug(1, ("%s: udp: adding handle '%s'\n",
1332 debug_prefix_time(NULL), rh->proto_handle));
1339 * Callback for received packets. This is the function bsd_recvpkt
1340 * registers with the event handler. It is called when the event handler
1341 * realizes that data is waiting to be read on the network socket.
1344 udp_netfd_read_callback(
1347 struct udp_handle *udp = cookie;
1348 struct sec_handle *rh;
1350 char hostname[NI_MAXHOST];
1352 char *errmsg = NULL;
1355 auth_debug(1, ("%s: udp_netfd_read_callback(cookie=%p)\n",
1356 debug_prefix_time(NULL), cookie));
1357 assert(udp != NULL);
1359 #ifndef TEST /* { */
1361 * Receive the packet.
1363 dgram_zero(&udp->dgram);
1364 if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)
1366 #endif /* !TEST */ /* } */
1371 if (str2pkthdr(udp) < 0)
1375 * If there are events waiting on this handle, we're done
1378 while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||
1379 rh->sequence != udp->sequence ||
1380 cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) {
1383 if (rh && event_wakeup(rh->event_id) > 0)
1387 * If we didn't find a handle, then check for a new incoming packet.
1388 * If no accept handler was setup, then just return.
1390 if (udp->accept_fn == NULL) {
1391 dbprintf(("%s: Receive packet from unknown source", debug_prefix_time(NULL)));
1395 rh = alloc(SIZEOF(*rh));
1396 rh->proto_handle=NULL;
1399 security_handleinit(&rh->sech, udp->driver);
1401 result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer),
1402 hostname, sizeof(hostname), NULL, 0, 0);
1404 dbprintf(("%s: getnameinfo failed: %s\n",
1405 debug_prefix_time(NULL), gai_strerror(result)));
1406 security_seterror(&rh->sech, "getnameinfo failed: %s",
1407 gai_strerror(result));
1410 if (check_name_give_sockaddr(hostname,
1411 (struct sockaddr *)&udp->peer, &errmsg) < 0) {
1412 security_seterror(&rh->sech, "%s",errmsg);
1418 port = SS_GET_PORT(&udp->peer);
1419 a = udp_inithandle(udp, rh,
1426 auth_debug(1, ("%s: bsd: closeX handle '%s'\n",
1427 debug_prefix_time(NULL), rh->proto_handle));
1433 * Check the security of the packet. If it is bad, then pass NULL
1434 * to the accept function instead of a packet.
1436 if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)
1437 (*udp->accept_fn)(&rh->sech, NULL);
1439 (*udp->accept_fn)(&rh->sech, &udp->pkt);
1443 * Locate an existing connection to the given host, or create a new,
1444 * unconnected entry if none exists. The caller is expected to check
1445 * for the lack of a connection (rc->read == -1) and set one up.
1449 const char *hostname,
1452 struct tcp_conn *rc;
1454 auth_debug(1, ("%s: sec_tcp_conn_get: %s\n",
1455 debug_prefix_time(NULL), hostname));
1457 if (want_new == 0) {
1458 for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
1459 if (strcasecmp(hostname, rc->hostname) == 0)
1466 ("%s: sec_tcp_conn_get: exists, refcnt to %s is now %d\n",
1467 debug_prefix_time(NULL),
1468 rc->hostname, rc->refcnt));
1473 auth_debug(1, ("%s: sec_tcp_conn_get: creating new handle\n",
1474 debug_prefix_time(NULL)));
1476 * We can't be creating a new handle if we are the client
1478 rc = alloc(SIZEOF(*rc));
1479 rc->read = rc->write = -1;
1485 strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);
1486 rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';
1491 rc->accept_fn = NULL;
1492 rc->recv_security_ok = NULL;
1493 rc->prefix_packet = NULL;
1500 * Delete a reference to a connection, and close it if it is the last
1505 struct tcp_conn * rc)
1509 assert(rc->refcnt > 0);
1511 auth_debug(1, ("%s: sec_tcp_conn_put: decrementing refcnt for %s to %d\n",
1512 debug_prefix_time(NULL),
1513 rc->hostname, rc->refcnt));
1514 if (rc->refcnt > 0) {
1517 auth_debug(1, ("%s: sec_tcp_conn_put: closing connection to %s\n",
1518 debug_prefix_time(NULL), rc->hostname));
1521 if (rc->write != -1)
1523 if (rc->pid != -1) {
1524 waitpid(rc->pid, &status, WNOHANG);
1526 if (rc->ev_read != NULL)
1527 event_release(rc->ev_read);
1528 if (rc->errmsg != NULL)
1533 amfree(rc); /* someone might still use it */
1534 /* eg. in sec_tcp_conn_read_callback if */
1535 /* event_wakeup call us. */
1539 * Turn on read events for a conn. Or, increase a ev_read_refcnt if we are
1540 * already receiving read events.
1544 struct tcp_conn * rc)
1546 assert (rc != NULL);
1548 if (rc->ev_read != NULL) {
1549 rc->ev_read_refcnt++;
1551 ("%s: sec: conn_read: incremented ev_read_refcnt to %d for %s\n",
1552 debug_prefix_time(NULL), rc->ev_read_refcnt, rc->hostname));
1555 auth_debug(1, ("%s: sec: conn_read registering event handler for %s\n",
1556 debug_prefix_time(NULL), rc->hostname));
1557 rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,
1558 sec_tcp_conn_read_callback, rc);
1559 rc->ev_read_refcnt = 1;
1563 sec_tcp_conn_read_cancel(
1564 struct tcp_conn * rc)
1567 --rc->ev_read_refcnt;
1569 ("%s: sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n",
1570 debug_prefix_time(NULL),
1571 rc->ev_read_refcnt, rc->hostname));
1572 if (rc->ev_read_refcnt > 0) {
1576 ("%s: sec: conn_read_cancel: releasing event handler for %s\n",
1577 debug_prefix_time(NULL), rc->hostname));
1578 event_release(rc->ev_read);
1583 * This is called when a handle is woken up because data read off of the
1593 struct sec_handle *rh = cookie;
1597 auth_debug(1, ("%s: sec: recvpkt_callback: " SSIZE_T_FMT "\n",
1598 debug_prefix_time(NULL), bufsize));
1600 * We need to cancel the recvpkt request before calling
1601 * the callback because the callback may reschedule us.
1603 stream_recvpkt_cancel(rh);
1607 security_seterror(&rh->sech,
1608 "EOF on read from %s", rh->hostname);
1609 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1612 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
1613 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1619 parse_pkt(&pkt, buf, (size_t)bufsize);
1621 ("%s: sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n",
1622 debug_prefix_time(NULL), pkt_type2str(pkt.type), pkt.type,
1623 rh->hostname, pkt.body));
1624 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1625 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1627 (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
1632 * Callback for tcpm_stream_read_sync
1635 stream_read_sync_callback(
1638 struct sec_stream *rs = s;
1641 auth_debug(1, ("%s: sec: stream_read_callback_sync: handle %d\n",
1642 debug_prefix_time(NULL), rs->handle));
1645 * Make sure this was for us. If it was, then blow away the handle
1646 * so it doesn't get claimed twice. Otherwise, leave it alone.
1648 * If the handle is EOF, pass that up to our callback.
1650 if (rs->rc->handle == rs->handle) {
1651 auth_debug(1, ("%s: sec: stream_read_callback_sync: it was for us\n",
1652 debug_prefix_time(NULL)));
1653 rs->rc->handle = H_TAKEN;
1654 } else if (rs->rc->handle != H_EOF) {
1655 auth_debug(1, ("%s: sec: stream_read_callback_sync: not for us\n",
1656 debug_prefix_time(NULL)));
1661 * Remove the event first, and then call the callback.
1662 * We remove it first because we don't want to get in their
1663 * way if they reschedule it.
1665 tcpm_stream_read_cancel(rs);
1667 if (rs->rc->pktlen <= 0) {
1668 auth_debug(1, ("%s: sec: stream_read_sync_callback: %s\n",
1669 debug_prefix_time(NULL), rs->rc->errmsg));
1670 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1671 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1672 sec_tcp_conn_put(rs->rc);
1673 rs->closed_by_network = 1;
1677 ("%s: sec: stream_read_callback_sync: read " SSIZE_T_FMT " bytes from %s:%d\n",
1678 debug_prefix_time(NULL),
1679 rs->rc->pktlen, rs->rc->hostname, rs->handle));
1683 * Callback for tcpm_stream_read
1686 stream_read_callback(
1689 struct sec_stream *rs = arg;
1692 auth_debug(1, ("%s: sec: stream_read_callback: handle %d\n",
1693 debug_prefix_time(NULL), rs->handle));
1696 * Make sure this was for us. If it was, then blow away the handle
1697 * so it doesn't get claimed twice. Otherwise, leave it alone.
1699 * If the handle is EOF, pass that up to our callback.
1701 if (rs->rc->handle == rs->handle) {
1702 auth_debug(1, ("%s: sec: stream_read_callback: it was for us\n",
1703 debug_prefix_time(NULL)));
1704 rs->rc->handle = H_TAKEN;
1705 } else if (rs->rc->handle != H_EOF) {
1706 auth_debug(1, ("%s: sec: stream_read_callback: not for us\n",
1707 debug_prefix_time(NULL)));
1712 * Remove the event first, and then call the callback.
1713 * We remove it first because we don't want to get in their
1714 * way if they reschedule it.
1716 tcpm_stream_read_cancel(rs);
1718 if (rs->rc->pktlen <= 0) {
1719 auth_debug(1, ("%s: sec: stream_read_callback: %s\n",
1720 debug_prefix_time(NULL), rs->rc->errmsg));
1721 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1722 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1723 sec_tcp_conn_put(rs->rc);
1724 rs->closed_by_network = 1;
1725 (*rs->fn)(rs->arg, NULL, rs->rc->pktlen);
1728 auth_debug(1, ("%s: sec: stream_read_callback: read " SSIZE_T_FMT " bytes from %s:%d\n",
1729 debug_prefix_time(NULL),
1730 rs->rc->pktlen, rs->rc->hostname, rs->handle));
1731 (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
1732 auth_debug(1, ("%s: sec: after callback stream_read_callback\n",
1733 debug_prefix_time(NULL)));
1737 * The callback for the netfd for the event handler
1738 * Determines if this packet is for this security handle,
1739 * and does the real callback if so.
1742 sec_tcp_conn_read_callback(
1745 struct tcp_conn * rc = cookie;
1746 struct sec_handle * rh;
1751 assert(cookie != NULL);
1753 auth_debug(1, ("%s: sec: conn_read_callback\n", debug_prefix_time(NULL)));
1755 /* Read the data off the wire. If we get errors, shut down. */
1756 rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt,
1758 auth_debug(1, ("%s: sec: conn_read_callback: tcpm_recv_token returned " SSIZE_T_FMT "\n",
1759 debug_prefix_time(NULL), rval));
1760 if (rval < 0 || rc->handle == H_EOF) {
1763 revent = event_wakeup((event_id_t)rc);
1764 auth_debug(1, ("%s: sec: conn_read_callback: event_wakeup return %d\n",
1765 debug_prefix_time(NULL), revent));
1766 /* delete our 'accept' reference */
1767 if (rc->accept_fn != NULL) {
1768 if(rc->refcnt != 1) {
1769 dbprintf(("STRANGE, rc->refcnt should be 1, it is %d\n",
1773 rc->accept_fn = NULL;
1774 sec_tcp_conn_put(rc);
1781 revent = event_wakeup((event_id_t)rc);
1783 ("%s: 0 sec: conn_read_callback: event_wakeup return %d\n",
1784 debug_prefix_time(NULL), revent));
1788 /* If there are events waiting on this handle, we're done */
1790 revent = event_wakeup((event_id_t)rc);
1791 auth_debug(1, ("%s: sec: conn_read_callback: event_wakeup return " SSIZE_T_FMT "\n",
1792 debug_prefix_time(NULL), rval));
1794 if (rc->handle == H_TAKEN || rc->pktlen == 0) {
1795 if(rc->refcnt == 0) amfree(rc);
1799 assert(rc->refcnt > 0);
1801 /* If there is no accept fn registered, then drop the packet */
1802 if (rc->accept_fn == NULL)
1805 rh = alloc(SIZEOF(*rh));
1806 security_handleinit(&rh->sech, rc->driver);
1807 rh->hostname = stralloc(rc->hostname);
1808 rh->ev_timeout = NULL;
1810 rh->peer = rc->peer;
1811 rh->rs = tcpma_stream_client(rh, rc->handle);
1813 auth_debug(1, ("%s: sec: new connection\n", debug_prefix_time(NULL)));
1815 parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);
1816 auth_debug(1, ("%s: sec: calling accept_fn\n", debug_prefix_time(NULL)));
1817 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1818 (*rc->accept_fn)(&rh->sech, NULL);
1820 (*rc->accept_fn)(&rh->sech, &pkt);
1830 const unsigned char *bufp = buf;
1832 auth_debug(1, ("%s: sec: parse_pkt: parsing buffer of " SSIZE_T_FMT " bytes\n",
1833 debug_prefix_time(NULL), bufsize));
1835 pkt->type = (pktype_t)*bufp++;
1838 pkt->packet_size = bufsize+1;
1839 pkt->body = alloc(pkt->packet_size);
1841 pkt->body[0] = '\0';
1843 memcpy(pkt->body, bufp, bufsize);
1844 pkt->body[pkt->packet_size - 1] = '\0';
1846 pkt->size = strlen(pkt->body);
1848 auth_debug(1, ("%s: sec: parse_pkt: %s (%d): \"%s\"\n",
1849 debug_prefix_time(NULL), pkt_type2str(pkt->type),
1850 pkt->type, pkt->body));
1854 * Convert a packet header into a string
1858 const struct sec_handle * rh,
1861 static char retbuf[256];
1864 assert(pkt != NULL);
1866 snprintf(retbuf, SIZEOF(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n",
1867 VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
1868 rh->proto_handle, rh->sequence);
1870 auth_debug(1, ("%s: bsd: pkthdr2str handle '%s'\n",
1871 debug_prefix_time(NULL), rh->proto_handle));
1873 /* check for truncation. If only we had asprintf()... */
1874 assert(retbuf[strlen(retbuf) - 1] == '\n');
1880 * Parses out the header line in 'str' into the pkt and handle
1881 * Returns negative on parse error.
1893 assert(udp->dgram.cur != NULL);
1894 str = stralloc(udp->dgram.cur);
1896 /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
1898 /* Read in "Amanda" */
1899 if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
1902 /* nothing is done with the major/minor numbers currently */
1903 if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
1906 /* Read in the packet type */
1907 if ((tok = strtok(NULL, " ")) == NULL)
1910 pkt_init_empty(pkt, pkt_str2type(tok));
1911 if (pkt->type == (pktype_t)-1)
1914 /* Read in "HANDLE" */
1915 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
1918 /* parse the handle */
1919 if ((tok = strtok(NULL, " ")) == NULL)
1921 amfree(udp->handle);
1922 udp->handle = stralloc(tok);
1925 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)
1928 /* parse the sequence number */
1929 if ((tok = strtok(NULL, "\n")) == NULL)
1931 udp->sequence = atoi(tok);
1933 /* Save the body, if any */
1934 if ((tok = strtok(NULL, "")) != NULL)
1935 pkt_cat(pkt, "%s", tok);
1941 #if 0 /* XXX we have no way of passing this back up */
1942 security_seterror(&rh->sech,
1943 "parse error in packet header : '%s'", origstr);
1951 struct sec_handle * rh,
1952 const char * remoteuser,
1953 const char * service)
1957 char *result = NULL;
1958 char *localuser = NULL;
1960 /* lookup our local user name */
1961 if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
1962 return vstralloc("getpwnam(", CLIENT_LOGIN, ") fails", NULL);
1966 * Make a copy of the user name in case getpw* is called by
1967 * any of the lower level routines.
1969 localuser = stralloc(pwd->pw_name);
1971 #ifndef USE_AMANDAHOSTS
1972 r = check_user_ruserok(rh->hostname, pwd, remoteuser);
1974 r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service);
1977 result = vstralloc("user ", remoteuser, " from ", rh->hostname,
1978 " is not allowed to execute the service ",
1979 service, ": ", r, NULL);
1987 * See if a remote user is allowed in. This version uses ruserok()
1990 * Returns 0 on success, or negative on error.
1995 struct passwd * pwd,
1996 const char * remoteuser)
2007 char number[NUM_STR_SIZE];
2008 uid_t myuid = getuid();
2011 * note that some versions of ruserok (eg SunOS 3.2) look in
2012 * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
2013 * chdir ourselves. Sigh.
2015 * And, believe it or not, some ruserok()'s try an initgroup just
2016 * for the hell of it. Since we probably aren't root at this point
2017 * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
2018 * into our stderr output even though the initgroup failure is not a
2019 * problem and is expected. Thanks a lot. Not.
2021 if (pipe(fd) != 0) {
2022 return stralloc2("pipe() fails: ", strerror(errno));
2024 if ((ruserok_pid = fork()) < 0) {
2025 return stralloc2("fork() fails: ", strerror(errno));
2026 } else if (ruserok_pid == 0) {
2030 fError = fdopen(fd[1], "w");
2032 error("Can't fdopen: %s", strerror(errno));
2035 /* pamper braindead ruserok's */
2036 if (chdir(pwd->pw_dir) != 0) {
2037 fprintf(fError, "chdir(%s) failed: %s",
2038 pwd->pw_dir, strerror(errno));
2043 if (debug_auth >= 9) {
2044 char *dir = stralloc(pwd->pw_dir);
2046 auth_debug(9, ("%s: bsd: calling ruserok(%s, %d, %s, %s)\n",
2047 debug_prefix_time(NULL), host,
2048 ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name));
2050 auth_debug(9, ("%s: bsd: because you are running as root, ",
2051 debug_prefix_time(NULL)));
2052 auth_debug(9, ("/etc/hosts.equiv will not be used\n"));
2054 show_stat_info("/etc/hosts.equiv", NULL);
2056 show_stat_info(dir, "/.rhosts");
2060 saved_stderr = dup(2);
2062 if (open("/dev/null", O_RDWR) == -1) {
2063 auth_debug(1, ("%s: Could not open /dev/null: %s\n",
2064 debug_prefix_time(NULL), strerror(errno)));
2067 ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
2074 (void)dup2(saved_stderr,2);
2075 close(saved_stderr);
2079 fError = fdopen(fd[0], "r");
2081 error("Can't fdopen: %s", strerror(errno));
2086 while ((es = agets(fError)) != NULL) {
2091 if (result == NULL) {
2092 result = stralloc("");
2094 strappend(result, ": ");
2096 strappend(result, es);
2101 pid = wait(&exitcode);
2102 while (pid != ruserok_pid) {
2103 if ((pid == (pid_t) -1) && (errno != EINTR)) {
2105 return stralloc2("ruserok wait failed: %s", strerror(errno));
2107 pid = wait(&exitcode);
2109 if (WIFSIGNALED(exitcode)) {
2111 snprintf(number, SIZEOF(number), "%d", WTERMSIG(exitcode));
2112 return stralloc2("ruserok child got signal ", number);
2114 if (WEXITSTATUS(exitcode) == 0) {
2116 } else if (result == NULL) {
2117 result = stralloc("ruserok failed");
2124 * Check to see if a user is allowed in. This version uses .amandahosts
2125 * Returns -1 on failure, or 0 on success.
2128 check_user_amandahosts(
2130 struct sockaddr_storage *addr,
2131 struct passwd * pwd,
2132 const char * remoteuser,
2133 const char * service)
2137 const char *fileuser;
2139 char *result = NULL;
2143 char n1[NUM_STR_SIZE];
2144 char n2[NUM_STR_SIZE];
2147 char *aservice = NULL;
2149 char ipstr[INET6_ADDRSTRLEN];
2151 char ipstr[INET_ADDRSTRLEN];
2154 auth_debug(1, ("check_user_amandahosts(host=%s, pwd=%p, "
2155 "remoteuser=%s, service=%s)\n",
2156 host, pwd, remoteuser, service));
2158 ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
2159 if (debug_auth >= 9) {
2160 show_stat_info(ptmp, "");;
2162 if ((fp = fopen(ptmp, "r")) == NULL) {
2163 result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL);
2169 * Make sure the file is owned by the Amanda user and does not
2170 * have any group/other access allowed.
2172 if (fstat(fileno(fp), &sbuf) != 0) {
2173 result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL);
2176 if (sbuf.st_uid != pwd->pw_uid) {
2177 snprintf(n1, SIZEOF(n1), "%ld", (long)sbuf.st_uid);
2178 snprintf(n2, SIZEOF(n2), "%ld", (long)pwd->pw_uid);
2179 result = vstralloc(ptmp, ": ",
2185 if ((sbuf.st_mode & 077) != 0) {
2186 result = stralloc2(ptmp,
2187 ": incorrect permissions; file must be accessible only by its owner");
2192 * Now, scan the file for the host/user/service.
2195 while ((line = agets(fp)) != NULL) {
2201 auth_debug(9, ("%s: bsd: processing line: <%s>\n",
2202 debug_prefix_time(NULL), line));
2203 /* get the host out of the file */
2204 if ((filehost = strtok(line, " \t")) == NULL) {
2209 /* get the username. If no user specified, then use the local user */
2210 if ((fileuser = strtok(NULL, " \t")) == NULL) {
2211 fileuser = pwd->pw_name;
2214 hostmatch = (strcasecmp(filehost, host) == 0);
2215 /* ok if addr=127.0.0.1 and
2216 * either localhost or localhost.domain is in .amandahost */
2218 (strcasecmp(filehost, "localhost")== 0 ||
2219 strcasecmp(filehost, "localhost.localdomain")== 0)) {
2221 if (addr->ss_family == (sa_family_t)AF_INET6)
2222 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr,
2223 ipstr, sizeof(ipstr));
2226 inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr,
2227 ipstr, sizeof(ipstr));
2228 if (strcmp(ipstr, "127.0.0.1") == 0 ||
2229 strcmp(ipstr, "::1") == 0)
2232 usermatch = (strcasecmp(fileuser, remoteuser) == 0);
2233 auth_debug(9, ("%s: bsd: comparing \"%s\" with\n",
2234 debug_prefix_time(NULL), filehost));
2235 auth_debug(9, ("%s: bsd: \"%s\" (%s)\n", host,
2236 debug_prefix_time(NULL), hostmatch ? "match" : "no match"));
2237 auth_debug(9, ("%s: bsd: and \"%s\" with\n",
2238 fileuser, debug_prefix_time(NULL)));
2239 auth_debug(9, ("%s: bsd: \"%s\" (%s)\n", remoteuser,
2240 debug_prefix_time(NULL), usermatch ? "match" : "no match"));
2242 if (!hostmatch || !usermatch) {
2254 /* get the services. If no service specified, then use
2255 * noop/selfcheck/sendsize/sendbackup
2257 aservice = strtok(NULL, " \t,");
2259 if (strcmp(service,"noop") == 0 ||
2260 strcmp(service,"selfcheck") == 0 ||
2261 strcmp(service,"sendsize") == 0 ||
2262 strcmp(service,"sendbackup") == 0) {
2275 if (strcmp(aservice,service) == 0) {
2279 if (strcmp(aservice, "amdump") == 0 &&
2280 (strcmp(service, "noop") == 0 ||
2281 strcmp(service, "selfcheck") == 0 ||
2282 strcmp(service, "sendsize") == 0 ||
2283 strcmp(service, "sendbackup") == 0)) {
2287 } while((aservice = strtok(NULL, " \t,")) != NULL);
2289 if (aservice && strcmp(aservice, service) == 0) {
2298 if (strcmp(service, "amindexd") == 0 ||
2299 strcmp(service, "amidxtaped") == 0) {
2300 result = vstralloc("Please add \"amindexd amidxtaped\" to "
2301 "the line in ", ptmp, " on the client", NULL);
2302 } else if (strcmp(service, "amdump") == 0 ||
2303 strcmp(service, "noop") == 0 ||
2304 strcmp(service, "selfcheck") == 0 ||
2305 strcmp(service, "sendsize") == 0 ||
2306 strcmp(service, "sendbackup") == 0) {
2307 result = vstralloc("Please add \"amdump\" to the line in ",
2308 ptmp, " on the client", NULL);
2310 result = vstralloc(ptmp, ": ",
2311 "invalid service ", service, NULL);
2323 /* return 1 on success, 0 on failure */
2326 struct sockaddr_storage *addr,
2328 unsigned long cksum,
2331 char * remotehost = NULL, *remoteuser = NULL;
2332 char * bad_bsd = NULL;
2333 struct passwd * pwptr;
2338 char hostname[NI_MAXHOST];
2342 (void)cksum; /* Quiet unused parameter warning */
2345 ("%s: check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n",
2346 debug_prefix_time(NULL), addr, str, cksum, errstr));
2347 dump_sockaddr(addr);
2351 /* what host is making the request? */
2352 if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr),
2353 hostname, NI_MAXHOST, NULL, 0, 0) != 0)) {
2354 dbprintf(("%s: getnameinfo failed: %s\n",
2355 debug_prefix_time(NULL), gai_strerror(result)));
2356 *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ",
2357 "getnameinfo failed: ", gai_strerror(result),
2361 remotehost = stralloc(hostname);
2362 if( check_name_give_sockaddr(hostname,
2363 (struct sockaddr *)addr, errstr) < 0) {
2368 /* next, make sure the remote port is a "reserved" one */
2369 port = SS_GET_PORT(addr);
2370 if (port >= IPPORT_RESERVED) {
2371 char number[NUM_STR_SIZE];
2373 snprintf(number, SIZEOF(number), "%u", (unsigned int)port);
2374 *errstr = vstralloc("[",
2375 "host ", remotehost, ": ",
2376 "port ", number, " not secure",
2382 /* extract the remote user name from the message */
2387 bad_bsd = vstralloc("[",
2388 "host ", remotehost, ": ",
2389 "bad bsd security line",
2392 if (strncmp_const_skip(s - 1, "USER ", s, ch) != 0) {
2399 skip_whitespace(s, ch);
2407 skip_non_whitespace(s, ch);
2409 remoteuser = stralloc(fp);
2413 /* lookup our local user name */
2416 if ((pwptr = getpwuid(myuid)) == NULL)
2417 error("error [getpwuid(%d) fails]", myuid);
2419 auth_debug(1, ("%s: bsd security: remote host %s user %s local user %s\n",
2420 debug_prefix_time(NULL), remotehost, remoteuser, pwptr->pw_name));
2422 #ifndef USE_AMANDAHOSTS
2423 s = check_user_ruserok(remotehost, pwptr, remoteuser);
2425 s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL);
2429 *errstr = vstralloc("[",
2430 "access as ", pwptr->pw_name, " not allowed",
2431 " from ", remoteuser, "@", remotehost,
2432 ": ", s, "]", NULL);
2437 return *errstr == NULL;
2441 * Writes out the entire iovec
2449 ssize_t delta, n, total;
2451 assert(iov != NULL);
2454 while (iovcnt > 0) {
2458 n = writev(fd, iov, iovcnt);
2462 auth_debug(1, ("%s: net_writev got EINTR\n",
2463 debug_prefix_time(NULL)));
2471 * Iterate through each iov. Figure out what we still need
2474 for (; n > 0; iovcnt--, iov++) {
2475 /* 'delta' is the bytes written from this iovec */
2476 delta = ((size_t)n < iov->iov_len) ? n : (ssize_t)iov->iov_len;
2477 /* subtract from the total num bytes written */
2480 /* subtract from this iovec */
2481 iov->iov_len -= delta;
2482 iov->iov_base = (char *)iov->iov_base + delta;
2483 /* if this iovec isn't empty, run the writev again */
2484 if (iov->iov_len > 0)
2493 * Like read(), but waits until the entire buffer has been filled.
2502 char *buf = vbuf; /* ptr arith */
2504 size_t size = origsize;
2506 auth_debug(1, ("%s: net_read: begin " SIZE_T_FMT "\n",
2507 debug_prefix_time(NULL), origsize));
2510 auth_debug(1, ("%s: net_read: while " SIZE_T_FMT "\n",
2511 debug_prefix_time(NULL), size));
2512 nread = net_read_fillbuf(fd, timeout, buf, size);
2514 auth_debug(1, ("%s: db: net_read: end return(-1)\n",
2515 debug_prefix_time(NULL)));
2519 auth_debug(1, ("%s: net_read: end return(0)\n",
2520 debug_prefix_time(NULL)));
2526 auth_debug(1, ("%s: net_read: end " SIZE_T_FMT "\n",
2527 debug_prefix_time(NULL), origsize));
2528 return ((ssize_t)origsize);
2532 * net_read likes to do a lot of little reads. Buffer it.
2541 SELECT_ARG_TYPE readfds;
2545 auth_debug(1, ("%s: net_read_fillbuf: begin\n", debug_prefix_time(NULL)));
2547 FD_SET(fd, &readfds);
2548 tv.tv_sec = timeout;
2550 switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
2555 auth_debug(1, ("%s: net_read_fillbuf: case -1\n",
2556 debug_prefix_time(NULL)));
2559 auth_debug(1, ("%s: net_read_fillbuf: case 1\n",
2560 debug_prefix_time(NULL)));
2561 assert(FD_ISSET(fd, &readfds));
2564 auth_debug(1, ("%s: net_read_fillbuf: case default\n",
2565 debug_prefix_time(NULL)));
2569 nread = read(fd, buf, size);
2572 auth_debug(1, ("%s: net_read_fillbuf: end " SSIZE_T_FMT "\n",
2573 debug_prefix_time(NULL), nread));
2579 * Display stat() information about a file.
2587 char *name = vstralloc(a, b, NULL);
2589 struct passwd *pwptr;
2591 struct group *grptr;
2594 if (stat(name, &sbuf) != 0) {
2595 auth_debug(1, ("%s: bsd: cannot stat %s: %s\n",
2596 debug_prefix_time(NULL), name, strerror(errno)));
2600 if ((pwptr = getpwuid(sbuf.st_uid)) == NULL) {
2601 owner = alloc(NUM_STR_SIZE + 1);
2602 snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
2604 owner = stralloc(pwptr->pw_name);
2606 if ((grptr = getgrgid(sbuf.st_gid)) == NULL) {
2607 group = alloc(NUM_STR_SIZE + 1);
2608 snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
2610 group = stralloc(grptr->gr_name);
2612 auth_debug(1, ("%s: bsd: processing file: %s\n", debug_prefix_time(NULL), name));
2613 auth_debug(1, ("%s: bsd: owner=%s group=%s mode=%03o\n",
2614 debug_prefix_time(NULL), owner, group,
2615 (int) (sbuf.st_mode & 0777)));
2622 check_name_give_sockaddr(
2623 const char *hostname,
2624 struct sockaddr *addr,
2627 struct addrinfo *res = NULL, *res1;
2628 struct addrinfo hints;
2632 if ((addr)->sa_family == AF_INET6)
2633 hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL;
2636 hints.ai_flags = AI_CANONNAME;
2637 hints.ai_family = addr->sa_family;
2638 hints.ai_socktype = 0;
2639 hints.ai_protocol = 0;
2640 hints.ai_addrlen = 0;
2641 hints.ai_addr = NULL;
2642 hints.ai_canonname = NULL;
2643 hints.ai_next = NULL;
2644 result = getaddrinfo(hostname, NULL, &hints, &res);
2646 dbprintf(("check_name_give_sockaddr: getaddrinfo(%s): %s\n", hostname, gai_strerror(result)));
2647 *errstr = newvstralloc(*errstr,
2648 " getaddrinfo(", hostname, "): ",
2649 gai_strerror(result), NULL);
2652 if (res->ai_canonname == NULL) {
2653 dbprintf(("getaddrinfo(%s) did not return a canonical name\n", hostname));
2654 *errstr = newvstralloc(*errstr,
2655 " getaddrinfo(", hostname, ") did not return a canonical name", NULL);
2659 if (strncasecmp(hostname, res->ai_canonname, strlen(hostname)) != 0) {
2660 auth_debug(1, ("%s: %s doesn't resolve to itself, it resolves to %s\n",
2661 debug_prefix_time(NULL),
2662 hostname, res->ai_canonname));
2663 *errstr = newvstralloc(*errstr, hostname,
2664 _(" doesn't resolve to itself, it resolves to "),
2665 res->ai_canonname, NULL);
2669 for(res1=res; res1 != NULL; res1 = res1->ai_next) {
2670 if (res1->ai_addr->sa_family == addr->sa_family) {
2671 if (cmp_sockaddr((struct sockaddr_storage *)res1->ai_addr, (struct sockaddr_storage *)addr, 1) == 0) {
2678 *errstr = newvstralloc(*errstr,
2679 str_sockaddr((struct sockaddr_storage *)addr),
2680 " doesn't resolve to ",
2688 check_addrinfo_give_name(
2689 struct addrinfo *res,
2690 const char *hostname,
2693 if (strncasecmp(hostname, res->ai_canonname, strlen(hostname)) != 0) {
2694 dbprintf(("%s: %s doesn't resolve to itself, it resolv to %s\n",
2695 debug_prefix_time(NULL),
2696 hostname, res->ai_canonname));
2697 *errstr = newvstralloc(*errstr, hostname,
2698 " doesn't resolve to itself, it resolv to ",
2699 res->ai_canonname, NULL);
2706 /* Try resolving the hostname, just to catch any potential
2707 * problems down the road. This is used from most security_connect
2708 * methods, many of which also want the canonical name. Returns
2712 try_resolving_hostname(
2713 const char *hostname,
2716 struct addrinfo hints;
2717 struct addrinfo *gaires;
2721 hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL;
2722 hints.ai_family = AF_UNSPEC;
2724 hints.ai_flags = AI_CANONNAME;
2725 hints.ai_family = AF_INET;
2727 hints.ai_socktype = 0;
2728 hints.ai_protocol = 0;
2729 hints.ai_addrlen = 0;
2730 hints.ai_addr = NULL;
2731 hints.ai_canonname = NULL;
2732 hints.ai_next = NULL;
2733 if ((res = getaddrinfo(hostname, NULL, &hints, &gaires)) != 0) {
2736 if (canonname && gaires && gaires->ai_canonname)
2737 *canonname = stralloc(gaires->ai_canonname);
2738 if (gaires) freeaddrinfo(gaires);