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"
46 /* #define SEC_DEBUG */
47 #define SHOW_SECURITY_DETAIL
50 # define secprintf(x) dbprintf(x)
53 # define secprintf(x) (void)(x)
60 * Magic values for sec_conn->handle
62 #define H_TAKEN -1 /* sec_conn->tok was already read */
63 #define H_EOF -2 /* this connection has been shut down */
66 * This is a queue of open connections
68 struct connq_s connq = {
69 TAILQ_HEAD_INITIALIZER(connq.tailq), 0
71 static int newhandle = 1;
72 static int newevent = 1;
77 static void recvpkt_callback(void *, void *, ssize_t);
78 static void stream_read_callback(void *);
79 static void stream_read_sync_callback(void *);
81 static void sec_tcp_conn_read_cancel(struct tcp_conn *);
82 static void sec_tcp_conn_read_callback(void *);
86 * Authenticate a stream
87 * Nothing needed for sec. The connection is authenticated by secd
94 (void)s; /* Quiet unused parameter warning */
99 * Returns the stream id for this stream. This is just the local
106 struct sec_stream *rs = s;
114 * Setup to handle new incoming connections
118 const security_driver_t *driver,
121 void (*fn)(security_handle_t *, pkt_t *))
125 rc = sec_tcp_conn_get("unknown",0);
130 sec_tcp_conn_read(rc);
134 * frees a handle allocated by the above
140 struct sec_handle *rh = inst;
144 secprintf(("%s: sec: closing handle to %s\n", debug_prefix_time(NULL),
147 if (rh->rs != NULL) {
148 /* This may be null if we get here on an error */
149 stream_recvpkt_cancel(rh);
150 security_stream_close(&rh->rs->secstr);
152 /* keep us from getting here again */
153 rh->sech.driver = NULL;
154 amfree(rh->hostname);
159 * Called when a sec connection is finished connecting and is ready
160 * to be authenticated.
163 sec_connect_callback(
166 struct sec_handle *rh = cookie;
168 event_release(rh->rs->ev_read);
169 rh->rs->ev_read = NULL;
170 event_release(rh->ev_timeout);
171 rh->ev_timeout = NULL;
173 (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
177 * Called if a connection times out before completion.
183 struct sec_handle *rh = cookie;
185 event_release(rh->rs->ev_read);
186 rh->rs->ev_read = NULL;
187 event_release(rh->ev_timeout);
188 rh->ev_timeout = NULL;
190 (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
194 sec_close_connection_none(
215 struct sec_handle *rh = cookie;
222 secprintf(("%s: sec: stream_sendpkt: enter\n", debug_prefix_time(NULL)));
224 if (rh->rc->prefix_packet)
225 s = rh->rc->prefix_packet(rh, pkt);
228 len = strlen(pkt->body) + strlen(s) + 2;
230 buf[0] = (char)pkt->type;
231 strncpy(&buf[1], s, len - 1);
232 strncpy(&buf[1 + strlen(s)], pkt->body, (len - strlen(s) - 1));
237 "%s: sec: stream_sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n",
238 debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type,
239 strlen(pkt->body), pkt->body));
241 if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {
242 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
250 * Set up to receive a packet asyncronously, and call back when
256 void (*fn)(void *, pkt_t *, security_status_t),
260 struct sec_handle *rh = cookie;
264 secprintf(("%s: sec: recvpkt registered for %s\n",
265 debug_prefix_time(NULL), rh->hostname));
268 * Reset any pending timeout on this handle
270 if (rh->ev_timeout != NULL)
271 event_release(rh->ev_timeout);
274 * Negative timeouts mean no timeout
277 rh->ev_timeout = NULL;
279 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
280 stream_recvpkt_timeout, rh);
284 security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);
288 * This is called when a handle times out before receiving a packet.
291 stream_recvpkt_timeout(
294 struct sec_handle *rh = cookie;
298 secprintf(("%s: sec: recvpkt timeout for %s\n",
299 debug_prefix_time(NULL), rh->hostname));
301 stream_recvpkt_cancel(rh);
302 (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);
306 * Remove a async receive request from the queue
309 stream_recvpkt_cancel(
312 struct sec_handle *rh = cookie;
314 secprintf(("%s: sec: cancelling recvpkt for %s\n",
315 debug_prefix_time(NULL), rh->hostname));
319 security_stream_read_cancel(&rh->rs->secstr);
320 if (rh->ev_timeout != NULL) {
321 event_release(rh->ev_timeout);
322 rh->ev_timeout = NULL;
327 * Write a chunk of data to a stream. Blocks until completion.
335 struct sec_stream *rs = s;
338 assert(rs->rc != NULL);
340 secprintf(("%s: sec: stream_write: writing %d bytes to %s:%d %d\n",
341 debug_prefix_time(NULL), size, rs->rc->hostname, rs->handle,
344 if (tcpm_send_token(rs->rc->write, rs->handle, &rs->rc->errmsg,
346 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
353 * Submit a request to read some data. Calls back with the given
354 * function and arg when completed.
359 void (*fn)(void *, void *, ssize_t),
362 struct sec_stream *rs = s;
367 * Only one read request can be active per stream.
369 if (rs->ev_read == NULL) {
370 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
371 stream_read_callback, rs);
372 sec_tcp_conn_read(rs->rc);
379 * Write a chunk of data to a stream. Blocks until completion.
382 tcpm_stream_read_sync(
386 struct sec_stream *rs = s;
391 * Only one read request can be active per stream.
393 if (rs->ev_read != NULL) {
396 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
397 stream_read_sync_callback, rs);
398 sec_tcp_conn_read(rs->rc);
399 event_wait(rs->ev_read);
401 return (rs->rc->pktlen);
405 * Cancel a previous stream read request. It's ok if we didn't have a read
409 tcpm_stream_read_cancel(
412 struct sec_stream *rs = s;
416 if (rs->ev_read != NULL) {
417 event_release(rs->ev_read);
419 sec_tcp_conn_read_cancel(rs->rc);
424 * Transmits a chunk of data over a rsh_handle, adding
425 * the necessary headers to allow the remote end to decode it.
440 assert(SIZEOF(netlength) == 4);
444 * 32 bit length (network byte order)
445 * 32 bit handle (network byte order)
448 netlength = htonl(len);
449 iov[0].iov_base = (void *)&netlength;
450 iov[0].iov_len = SIZEOF(netlength);
452 nethandle = htonl((uint32_t)handle);
453 iov[1].iov_base = (void *)&nethandle;
454 iov[1].iov_len = SIZEOF(nethandle);
460 iov[2].iov_base = (void *)buf;
461 iov[2].iov_len = len;
465 if (net_writev(fd, iov, nb_iov) < 0) {
467 *errmsg = newvstralloc(*errmsg, "write error to ",
468 ": ", strerror(errno), NULL);
476 * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed
477 * return 0 on EOF: *handle = handle && *size = 0 if stream closed
478 * return size : *handle = handle && *size = size for data read
490 unsigned int netint[2];
492 assert(SIZEOF(netint) == 8);
494 switch (net_read(fd, &netint, SIZEOF(netint), timeout)) {
497 *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno),
499 secprintf(("%s: tcpm_recv_token: A return(-1)\n",
500 debug_prefix_time(NULL)));
505 *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL);
506 secprintf(("%s: tcpm_recv_token: A return(0)\n",
507 debug_prefix_time(NULL)));
513 *size = (ssize_t)ntohl(netint[0]);
514 if (*size > NETWORK_BLOCK_BYTES) {
515 *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size",
517 dbprintf(("%s: tcpm_recv_token: invalid size %d\n",
518 debug_prefix_time(NULL), *size));
523 *buf = alloc((size_t)*size);
524 *handle = (int)ntohl(netint[1]);
527 secprintf(("%s: tcpm_recv_token: read EOF from %d\n",
528 debug_prefix_time(NULL), *handle));
529 *errmsg = newvstralloc(*errmsg, "EOF",
533 switch (net_read(fd, *buf, (size_t)*size, timeout)) {
536 *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno),
538 secprintf(("%s: tcpm_recv_token: B return(-1)\n",
539 debug_prefix_time(NULL)));
543 *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL);
544 secprintf(("%s: tcpm_recv_token: B return(0)\n",
545 debug_prefix_time(NULL)));
551 secprintf(("%s: tcpm_recv_token: read %ld bytes from %d\n",
552 debug_prefix_time(NULL), *size, *handle));
557 tcpm_close_connection(
561 struct sec_handle *rh = h;
565 if(rh->rc->toclose == 0) {
567 sec_tcp_conn_put(rh->rc);
574 * Accept an incoming connection on a stream_server socket
575 * Nothing needed for tcpma.
581 (void)s; /* Quiet unused parameter warning */
587 * Return a connected stream. For sec, this means setup a stream
588 * with the supplied handle.
595 struct sec_handle *rh = h;
596 struct sec_stream *rs;
601 security_seterror(&rh->sech,
602 "%hd: invalid security stream id", id);
606 rs = alloc(SIZEOF(*rs));
607 security_streaminit(&rs->secstr, rh->sech.driver);
610 rs->closed_by_me = 0;
611 rs->closed_by_network = 0;
617 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
618 rs->rc->driver = rh->sech.driver;
622 secprintf(("%s: sec: stream_client: connected to stream %hd\n",
623 debug_prefix_time(NULL), id));
629 * Create the server end of a stream. For sec, this means setup a stream
630 * object and allocate a new handle for it.
636 struct sec_handle *rh = h;
637 struct sec_stream *rs;
641 rs = alloc(SIZEOF(*rs));
642 security_streaminit(&rs->secstr, rh->sech.driver);
643 rs->closed_by_me = 0;
644 rs->closed_by_network = 0;
650 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
651 rs->rc->driver = rh->sech.driver;
655 * Stream should already be setup!
657 if (rs->rc->read < 0) {
658 sec_tcp_conn_put(rs->rc);
660 security_seterror(&rh->sech, "lost connection to %s", rh->hostname);
663 assert(strcmp(rh->hostname, rs->rc->hostname) == 0);
664 //amfree(rh->hostname);
665 //rh->hostname = stralloc(rs->rc->hostname);
667 * so as not to conflict with the amanda server's handle numbers,
668 * we start at 500000 and work down
670 rs->handle = 500000 - newhandle++;
672 secprintf(("%s: sec: stream_server: created stream %d\n",
673 debug_prefix_time(NULL), rs->handle));
678 * Close and unallocate resources for a stream.
684 struct sec_stream *rs = s;
689 secprintf(("%s: sec: tcpma_stream_close: closing stream %d\n",
690 debug_prefix_time(NULL), rs->handle));
692 if(rs->closed_by_network == 0 && rs->rc->write != -1)
693 tcpm_stream_write(rs, &buf, 0);
694 security_stream_read_cancel(&rs->secstr);
695 if(rs->closed_by_network == 0)
696 sec_tcp_conn_put(rs->rc);
701 * Create the server end of a stream. For bsdudp, this means setup a tcp
702 * socket for receiving a connection.
708 struct sec_stream *rs = NULL;
709 struct sec_handle *rh = h;
713 rs = alloc(SIZEOF(*rs));
714 security_streaminit(&rs->secstr, rh->sech.driver);
715 rs->closed_by_me = 0;
716 rs->closed_by_network = 0;
719 rs->handle = 500000 - newhandle++;
721 rs->socket = 0; /* the socket is already opened */
724 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
725 rh->rc->driver = rh->sech.driver;
727 rs->socket = stream_server(&rs->port, STREAM_BUFSIZE,
729 if (rs->socket < 0) {
730 security_seterror(&rh->sech,
731 "can't create server stream: %s", strerror(errno));
735 rh->rc->read = rs->socket;
736 rh->rc->write = rs->socket;
737 rs->handle = (int)rs->port;
745 * Accepts a new connection on unconnected streams. Assumes it is ok to
752 struct sec_stream *bs = s;
755 assert(bs->socket != -1);
758 if (bs->socket > 0) {
759 bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE);
761 security_stream_seterror(&bs->secstr,
762 "can't accept new stream connection: %s",
766 bs->rc->read = bs->fd;
767 bs->rc->write = bs->fd;
773 * Return a connected stream
780 struct sec_stream *rs = NULL;
781 struct sec_handle *rh = h;
785 rs = alloc(SIZEOF(*rs));
786 security_streaminit(&rs->secstr, rh->sech.driver);
789 rs->closed_by_me = 0;
790 rs->closed_by_network = 0;
796 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
798 rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
799 STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
800 if (rh->rc->read < 0) {
801 security_seterror(&rh->sech,
802 "can't connect stream to %s port %d: %s",
803 rh->hostname, id, strerror(errno));
807 rh->rc->write = rh->rc->read;
809 rs->socket = -1; /* we're a client */
820 struct sec_stream *rs = s;
824 if (fullwrite(rs->fd, buf, size) < 0) {
825 security_stream_seterror(&rs->secstr,
826 "write error on stream %d: %s", rs->port, strerror(errno));
837 struct sec_handle *rh = h;
841 if (pkt->type != P_REQ)
844 if ((pwd = getpwuid(getuid())) == NULL) {
845 security_seterror(&rh->sech,
846 "can't get login name for my uid %ld",
850 buf = alloc(16+strlen(pwd->pw_name));
851 strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name)));
852 strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14));
853 buf[14 + strlen(pwd->pw_name)] = '\n';
854 buf[15 + strlen(pwd->pw_name)] = '\0';
861 * Check the security of a received packet. Returns negative on security
862 * violation, or returns 0 if ok. Removes the security info from the pkt_t.
865 bsd_recv_security_ok(
866 struct sec_handle * rh,
869 char *tok, *security, *body, *result;
870 char *service = NULL, *serviceX, *serviceY;
875 * Now, find the SECURITY line in the body, and parse it out
878 if (strncmp(pkt->body, "SECURITY ", SIZEOF("SECURITY ") - 1) == 0) {
879 security = pkt->body;
881 while(*security != '\n' && len < pkt->size) {
885 if(*security == '\n') {
888 security_line = stralloc(pkt->body);
889 security = pkt->body + strlen("SECURITY ");
892 security_line = NULL;
897 security_line = NULL;
902 * Now, find the SERVICE line in the body, and parse it out
905 if (strncmp(body, "SERVICE", SIZEOF("SERVICE") - 1) == 0) {
906 serviceX = stralloc(body + strlen("SERVICE "));
907 serviceY = strtok(serviceX, "\n");
909 service = stralloc(serviceY);
914 * We need to do different things depending on which type of packet
920 * Request packets must come from a reserved port
922 if (ntohs(rh->peer.sin_port) >= IPPORT_RESERVED) {
923 security_seterror(&rh->sech,
924 "host %s: port %d not secure", rh->hostname,
925 ntohs(rh->peer.sin_port));
927 amfree(security_line);
932 security_seterror(&rh->sech,
933 "packet as no SERVICE line");
934 amfree(security_line);
939 * Request packets contain a remote username. We need to check
940 * that we allow it in.
942 * They will look like:
943 * SECURITY USER [username]
946 /* there must be some security info */
947 if (security == NULL) {
948 security_seterror(&rh->sech,
949 "no bsd SECURITY for P_REQ");
954 /* second word must be USER */
955 if ((tok = strtok(security, " ")) == NULL) {
956 security_seterror(&rh->sech,
957 "SECURITY line: %s", security_line);
959 amfree(security_line);
960 return (-1); /* default errmsg */
962 if (strcmp(tok, "USER") != 0) {
963 security_seterror(&rh->sech,
964 "REQ SECURITY line parse error, expecting USER, got %s", tok);
966 amfree(security_line);
970 /* the third word is the username */
971 if ((tok = strtok(NULL, "")) == NULL) {
972 security_seterror(&rh->sech,
973 "SECURITY line: %s", security_line);
974 amfree(security_line);
975 return (-1); /* default errmsg */
977 if ((result = check_user(rh, tok, service)) != NULL) {
978 security_seterror(&rh->sech, "%s", result);
981 amfree(security_line);
985 /* we're good to go */
991 amfree(security_line);
994 * If there is security info at the front of the packet, we need to
995 * shift the rest of the data up and nuke it.
997 if (body != pkt->body)
998 memmove(pkt->body, body, strlen(body) + 1);
1003 * Transmit a packet. Add security information first.
1010 struct sec_handle *rh = cookie;
1014 assert(pkt != NULL);
1016 secprintf(("%s: udpbsd_sendpkt: enter\n", get_pname()));
1018 * Initialize this datagram, and add the header
1020 dgram_zero(&rh->udp->dgram);
1021 dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt));
1024 * Add the security info. This depends on which kind of packet we're
1027 switch (pkt->type) {
1030 * Requests get sent with our username in the body
1032 if ((pwd = getpwuid(geteuid())) == NULL) {
1033 security_seterror(&rh->sech,
1034 "can't get login name for my uid %ld", (long)getuid());
1037 dgram_cat(&rh->udp->dgram, "SECURITY USER %s\n", pwd->pw_name);
1045 * Add the body, and send it
1047 dgram_cat(&rh->udp->dgram, pkt->body);
1050 "%s: sec: udpbsd_sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n",
1051 debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type,
1052 strlen(pkt->body), pkt->body));
1054 if (dgram_send_addr(rh->peer, &rh->udp->dgram) != 0) {
1055 security_seterror(&rh->sech,
1056 "send %s to %s failed: %s", pkt_type2str(pkt->type),
1057 rh->hostname, strerror(errno));
1067 struct sec_handle *rh = cookie;
1069 if (rh->proto_handle == NULL) {
1073 secprintf(("%s: udp: close handle '%s'\n",
1074 debug_prefix_time(NULL), rh->proto_handle));
1076 udp_recvpkt_cancel(rh);
1078 rh->next->prev = rh->prev;
1081 rh->udp->bh_last = rh->prev;
1084 rh->prev->next = rh->next;
1087 rh->udp->bh_first = rh->next;
1090 amfree(rh->proto_handle);
1091 amfree(rh->hostname);
1096 * Set up to receive a packet asynchronously, and call back when it has
1102 void (*fn)(void *, pkt_t *, security_status_t),
1106 struct sec_handle *rh = cookie;
1108 secprintf(("%s: udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n",
1109 debug_prefix(NULL), cookie, fn, arg, timeout));
1115 * Subsequent recvpkt calls override previous ones
1117 if (rh->ev_read == NULL) {
1118 udp_addref(rh->udp, &udp_netfd_read_callback);
1119 rh->ev_read = event_register(rh->event_id, EV_WAIT,
1120 udp_recvpkt_callback, rh);
1122 if (rh->ev_timeout != NULL)
1123 event_release(rh->ev_timeout);
1125 rh->ev_timeout = NULL;
1127 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
1128 udp_recvpkt_timeout, rh);
1129 rh->fn.recvpkt = fn;
1134 * Remove a async receive request on this handle from the queue.
1135 * If it is the last one to be removed, then remove the event
1136 * handler for our network fd
1142 struct sec_handle *rh = cookie;
1146 if (rh->ev_read != NULL) {
1147 udp_delref(rh->udp);
1148 event_release(rh->ev_read);
1152 if (rh->ev_timeout != NULL) {
1153 event_release(rh->ev_timeout);
1154 rh->ev_timeout = NULL;
1159 * This is called when a handle is woken up because data read off of the
1163 udp_recvpkt_callback(
1166 struct sec_handle *rh = cookie;
1167 void (*fn)(void *, pkt_t *, security_status_t);
1170 secprintf(("%s: udp: receive handle '%s' netfd '%s'\n",
1171 debug_prefix_time(NULL), rh->proto_handle, rh->udp->handle));
1174 if (strcmp(rh->proto_handle, rh->udp->handle) != 0) assert(1);
1175 /* if it didn't come from the same host/port, forget it */
1176 if (memcmp(&rh->peer.sin_addr, &rh->udp->peer.sin_addr,
1177 SIZEOF(rh->udp->peer.sin_addr)) != 0 ||
1178 rh->peer.sin_port != rh->udp->peer.sin_port) {
1179 amfree(rh->udp->handle);
1180 //rh->udp->handle = NULL;
1185 * We need to cancel the recvpkt request before calling the callback
1186 * because the callback may reschedule us.
1188 fn = rh->fn.recvpkt;
1190 udp_recvpkt_cancel(rh);
1193 * Check the security of the packet. If it is bad, then pass NULL
1194 * to the packet handling function instead of a packet.
1196 if (rh->udp->recv_security_ok &&
1197 rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0)
1198 (*fn)(arg, NULL, S_ERROR);
1200 (*fn)(arg, &rh->udp->pkt, S_OK);
1204 * This is called when a handle times out before receiving a packet.
1207 udp_recvpkt_timeout(
1210 struct sec_handle *rh = cookie;
1211 void (*fn)(void *, pkt_t *, security_status_t);
1216 assert(rh->ev_timeout != NULL);
1217 fn = rh->fn.recvpkt;
1219 udp_recvpkt_cancel(rh);
1220 (*fn)(arg, NULL, S_TIMEOUT);
1224 * Given a hostname and a port, setup a udp_handle
1229 struct sec_handle * rh,
1230 struct hostent * he,
1238 * Save the hostname and port info
1240 secprintf(("%s: udp_inithandle port %hd handle %s sequence %d\n",
1241 debug_prefix_time(NULL), ntohs(port),
1245 rh->hostname = stralloc(he->h_name);
1246 memcpy(&rh->peer.sin_addr, he->h_addr, SIZEOF(rh->peer.sin_addr));
1247 rh->peer.sin_port = port;
1248 rh->peer.sin_family = (sa_family_t)AF_INET;
1251 * Do a forward lookup of the hostname. This is unnecessary if we
1252 * are initiating the connection, but is very serious if we are
1253 * receiving. We want to make sure the hostname
1254 * resolves back to the remote ip for security reasons.
1256 if ((he = gethostbyname(rh->hostname)) == NULL) {
1257 secprintf(("%s: udp: bb\n", debug_prefix_time(NULL)));
1258 security_seterror(&rh->sech,
1259 "%s: could not resolve hostname", rh->hostname);
1264 * Make sure the hostname matches. This should always work.
1266 if (strncasecmp(rh->hostname, he->h_name, strlen(rh->hostname)) != 0) {
1267 secprintf(("%s: udp: cc\n", debug_prefix_time(NULL)));
1268 security_seterror(&rh->sech,
1269 "%s: did not resolve to itself, it resolv to",
1270 rh->hostname, he->h_name);
1275 * Now look for a matching ip address.
1277 for (i = 0; he->h_addr_list[i] != NULL; i++) {
1278 if (memcmp(&rh->peer.sin_addr, he->h_addr_list[i],
1279 SIZEOF(struct in_addr)) == 0) {
1285 * If we didn't find it, try the aliases. This is a workaround for
1286 * Solaris if DNS goes over NIS.
1288 if (he->h_addr_list[i] == NULL) {
1289 const char *ipstr = inet_ntoa(rh->peer.sin_addr);
1290 for (i = 0; he->h_aliases[i] != NULL; i++) {
1291 if (strcmp(he->h_aliases[i], ipstr) == 0)
1295 * No aliases either. Failure. Someone is fooling with us or
1298 if (he->h_aliases[i] == NULL) {
1299 security_seterror(&rh->sech,
1300 "DNS check failed: no matching ip address for %s",
1306 rh->prev = udp->bh_last;
1308 rh->prev->next = rh;
1310 if (!udp->bh_first) {
1316 rh->sequence = sequence;
1317 rh->event_id = (event_id_t)newevent++;
1318 amfree(rh->proto_handle);
1319 rh->proto_handle = stralloc(handle);
1320 rh->fn.connect = NULL;
1323 rh->ev_timeout = NULL;
1325 secprintf(("%s: udp: adding handle '%s'\n",
1326 debug_prefix_time(NULL), rh->proto_handle));
1333 * Callback for received packets. This is the function bsd_recvpkt
1334 * registers with the event handler. It is called when the event handler
1335 * realizes that data is waiting to be read on the network socket.
1338 udp_netfd_read_callback(
1341 struct udp_handle *udp = cookie;
1342 struct sec_handle *rh;
1346 secprintf(("%s: udp_netfd_read_callback(cookie=%p)\n",
1347 debug_prefix(NULL), cookie));
1348 assert(udp != NULL);
1350 #ifndef TEST /* { */
1352 * Receive the packet.
1354 dgram_zero(&udp->dgram);
1355 if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)
1357 #endif /* !TEST */ /* } */
1362 if (str2pkthdr(udp) < 0)
1366 * If there are events waiting on this handle, we're done
1369 while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||
1370 rh->sequence != udp->sequence ||
1371 rh->peer.sin_addr.s_addr != udp->peer.sin_addr.s_addr ||
1372 rh->peer.sin_port != udp->peer.sin_port)) {
1375 if (rh && event_wakeup(rh->event_id) > 0)
1379 * If we didn't find a handle, then check for a new incoming packet.
1380 * If no accept handler was setup, then just return.
1382 if (udp->accept_fn == NULL)
1385 he = gethostbyaddr((void *)&udp->peer.sin_addr,
1386 (socklen_t)sizeof(udp->peer.sin_addr), AF_INET);
1389 rh = alloc(SIZEOF(*rh));
1390 rh->proto_handle=NULL;
1393 security_handleinit(&rh->sech, udp->driver);
1394 a = udp_inithandle(udp, rh,
1400 secprintf(("%s: bsd: closeX handle '%s'\n",
1401 debug_prefix_time(NULL), rh->proto_handle));
1407 * Check the security of the packet. If it is bad, then pass NULL
1408 * to the accept function instead of a packet.
1410 if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)
1411 (*udp->accept_fn)(&rh->sech, NULL);
1413 (*udp->accept_fn)(&rh->sech, &udp->pkt);
1417 * Locate an existing connection to the given host, or create a new,
1418 * unconnected entry if none exists. The caller is expected to check
1419 * for the lack of a connection (rc->read == -1) and set one up.
1423 const char *hostname,
1426 struct tcp_conn *rc;
1428 secprintf(("%s: sec_tcp_conn_get: %s\n", debug_prefix_time(NULL), hostname));
1430 if (want_new == 0) {
1431 for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
1432 if (strcasecmp(hostname, rc->hostname) == 0)
1438 secprintf(("%s: sec_tcp_conn_get: exists, refcnt to %s is now %d\n",
1439 debug_prefix_time(NULL),
1440 rc->hostname, rc->refcnt));
1445 secprintf(("%s: sec_tcp_conn_get: creating new handle\n",
1446 debug_prefix_time(NULL)));
1448 * We can't be creating a new handle if we are the client
1450 rc = alloc(SIZEOF(*rc));
1451 rc->read = rc->write = -1;
1457 strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);
1458 rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';
1463 rc->accept_fn = NULL;
1464 rc->recv_security_ok = NULL;
1465 rc->prefix_packet = NULL;
1471 * Delete a reference to a connection, and close it if it is the last
1476 struct tcp_conn * rc)
1480 assert(rc->refcnt > 0);
1482 secprintf(("%s: sec_tcp_conn_put: decrementing refcnt for %s to %d\n",
1483 debug_prefix_time(NULL),
1484 rc->hostname, rc->refcnt));
1485 if (rc->refcnt > 0) {
1488 secprintf(("%s: sec_tcp_conn_put: closing connection to %s\n",
1489 debug_prefix_time(NULL), rc->hostname));
1492 if (rc->write != -1)
1494 if (rc->pid != -1) {
1495 waitpid(rc->pid, &status, WNOHANG);
1497 if (rc->ev_read != NULL)
1498 event_release(rc->ev_read);
1499 if (rc->errmsg != NULL)
1504 amfree(rc); /* someone might still use it */
1505 /* eg. in sec_tcp_conn_read_callback if */
1506 /* event_wakeup call us. */
1510 * Turn on read events for a conn. Or, increase a ev_read_refcnt if we are
1511 * already receiving read events.
1515 struct tcp_conn * rc)
1517 assert (rc != NULL);
1519 if (rc->ev_read != NULL) {
1520 rc->ev_read_refcnt++;
1522 "%s: sec: conn_read: incremented ev_read_refcnt to %d for %s\n",
1523 debug_prefix_time(NULL), rc->ev_read_refcnt, rc->hostname));
1526 secprintf(("%s: sec: conn_read registering event handler for %s\n",
1527 debug_prefix_time(NULL), rc->hostname));
1528 rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,
1529 sec_tcp_conn_read_callback, rc);
1530 rc->ev_read_refcnt = 1;
1534 sec_tcp_conn_read_cancel(
1535 struct tcp_conn * rc)
1538 --rc->ev_read_refcnt;
1540 "%s: sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n",
1541 debug_prefix_time(NULL),
1542 rc->ev_read_refcnt, rc->hostname));
1543 if (rc->ev_read_refcnt > 0) {
1546 secprintf(("%s: sec: conn_read_cancel: releasing event handler for %s\n",
1547 debug_prefix_time(NULL), rc->hostname));
1548 event_release(rc->ev_read);
1553 * This is called when a handle is woken up because data read off of the
1563 struct sec_handle *rh = cookie;
1567 secprintf(("%s: sec: recvpkt_callback: %d\n",
1568 debug_prefix_time(NULL), bufsize));
1570 * We need to cancel the recvpkt request before calling
1571 * the callback because the callback may reschedule us.
1573 stream_recvpkt_cancel(rh);
1577 security_seterror(&rh->sech,
1578 "EOF on read from %s", rh->hostname);
1579 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1582 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
1583 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1589 parse_pkt(&pkt, buf, (size_t)bufsize);
1591 "%s: sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n",
1592 debug_prefix_time(NULL), pkt_type2str(pkt.type), pkt.type,
1593 rh->hostname, pkt.body));
1594 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1595 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1597 (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
1602 * Callback for tcpm_stream_read_sync
1605 stream_read_sync_callback(
1608 struct sec_stream *rs = s;
1611 secprintf(("%s: sec: stream_read_callback_sync: handle %d\n",
1612 debug_prefix_time(NULL), rs->handle));
1615 * Make sure this was for us. If it was, then blow away the handle
1616 * so it doesn't get claimed twice. Otherwise, leave it alone.
1618 * If the handle is EOF, pass that up to our callback.
1620 if (rs->rc->handle == rs->handle) {
1621 secprintf(("%s: sec: stream_read_callback_sync: it was for us\n",
1622 debug_prefix_time(NULL)));
1623 rs->rc->handle = H_TAKEN;
1624 } else if (rs->rc->handle != H_EOF) {
1625 secprintf(("%s: sec: stream_read_callback_sync: not for us\n",
1626 debug_prefix_time(NULL)));
1631 * Remove the event first, and then call the callback.
1632 * We remove it first because we don't want to get in their
1633 * way if they reschedule it.
1635 tcpm_stream_read_cancel(rs);
1637 if (rs->rc->pktlen <= 0) {
1638 secprintf(("%s: sec: stream_read_sync_callback: %s\n",
1639 debug_prefix_time(NULL), rs->rc->errmsg));
1640 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1641 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1642 sec_tcp_conn_put(rs->rc);
1643 rs->closed_by_network = 1;
1647 "%s: sec: stream_read_callback_sync: read %ld bytes from %s:%d\n",
1648 debug_prefix_time(NULL),
1649 rs->rc->pktlen, rs->rc->hostname, rs->handle));
1653 * Callback for tcpm_stream_read
1656 stream_read_callback(
1659 struct sec_stream *rs = arg;
1662 secprintf(("%s: sec: stream_read_callback: handle %d\n",
1663 debug_prefix_time(NULL), rs->handle));
1666 * Make sure this was for us. If it was, then blow away the handle
1667 * so it doesn't get claimed twice. Otherwise, leave it alone.
1669 * If the handle is EOF, pass that up to our callback.
1671 if (rs->rc->handle == rs->handle) {
1672 secprintf(("%s: sec: stream_read_callback: it was for us\n",
1673 debug_prefix_time(NULL)));
1674 rs->rc->handle = H_TAKEN;
1675 } else if (rs->rc->handle != H_EOF) {
1676 secprintf(("%s: sec: stream_read_callback: not for us\n",
1677 debug_prefix_time(NULL)));
1682 * Remove the event first, and then call the callback.
1683 * We remove it first because we don't want to get in their
1684 * way if they reschedule it.
1686 tcpm_stream_read_cancel(rs);
1688 if (rs->rc->pktlen <= 0) {
1689 secprintf(("%s: sec: stream_read_callback: %s\n",
1690 debug_prefix_time(NULL), rs->rc->errmsg));
1691 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1692 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1693 sec_tcp_conn_put(rs->rc);
1694 rs->closed_by_network = 1;
1695 (*rs->fn)(rs->arg, NULL, rs->rc->pktlen);
1698 secprintf(("%s: sec: stream_read_callback: read %ld bytes from %s:%d\n",
1699 debug_prefix_time(NULL),
1700 rs->rc->pktlen, rs->rc->hostname, rs->handle));
1701 (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
1702 secprintf(("%s: sec: after callback stream_read_callback\n",
1703 debug_prefix_time(NULL)));
1707 * The callback for the netfd for the event handler
1708 * Determines if this packet is for this security handle,
1709 * and does the real callback if so.
1712 sec_tcp_conn_read_callback(
1715 struct tcp_conn * rc = cookie;
1716 struct sec_handle * rh;
1721 assert(cookie != NULL);
1723 secprintf(("%s: sec: conn_read_callback\n", debug_prefix_time(NULL)));
1725 /* Read the data off the wire. If we get errors, shut down. */
1726 rval = tcpm_recv_token(rc->read, &rc->handle, &rc->errmsg, &rc->pkt,
1728 secprintf(("%s: sec: conn_read_callback: tcpm_recv_token returned %d\n",
1729 debug_prefix_time(NULL), rval));
1730 if (rval < 0 || rc->handle == H_EOF) {
1733 revent = event_wakeup((event_id_t)rc);
1734 secprintf(("%s: sec: conn_read_callback: event_wakeup return %d\n",
1735 debug_prefix_time(NULL), revent));
1736 /* delete our 'accept' reference */
1737 if (rc->accept_fn != NULL) {
1738 if(rc->refcnt != 1) {
1739 dbprintf(("STRANGE, rc->refcnt should be 1"));
1742 rc->accept_fn = NULL;
1743 sec_tcp_conn_put(rc);
1750 revent = event_wakeup((event_id_t)rc);
1751 secprintf(("%s: 0 sec: conn_read_callback: event_wakeup return %d\n",
1752 debug_prefix_time(NULL), revent));
1756 /* If there are events waiting on this handle, we're done */
1758 revent = event_wakeup((event_id_t)rc);
1759 secprintf(("%s: sec: conn_read_callback: event_wakeup return %d\n",
1760 debug_prefix_time(NULL), rval));
1762 if (rc->handle == H_TAKEN || rc->pktlen == 0) {
1763 if(rc->refcnt == 0) amfree(rc);
1767 assert(rc->refcnt > 0);
1769 /* If there is no accept fn registered, then drop the packet */
1770 if (rc->accept_fn == NULL)
1773 rh = alloc(SIZEOF(*rh));
1774 security_handleinit(&rh->sech, rc->driver);
1775 rh->hostname = stralloc(rc->hostname);
1776 rh->ev_timeout = NULL;
1778 rh->peer = rc->peer;
1779 rh->rs = tcpma_stream_client(rh, rc->handle);
1781 secprintf(("%s: sec: new connection\n", debug_prefix_time(NULL)));
1783 parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);
1784 secprintf(("%s: sec: calling accept_fn\n", debug_prefix_time(NULL)));
1785 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1786 (*rc->accept_fn)(&rh->sech, NULL);
1788 (*rc->accept_fn)(&rh->sech, &pkt);
1798 const unsigned char *bufp = buf;
1800 secprintf(("%s: sec: parse_pkt: parsing buffer of %d bytes\n",
1801 debug_prefix_time(NULL), bufsize));
1803 pkt->type = (pktype_t)*bufp++;
1806 pkt->packet_size = bufsize+1;
1807 pkt->body = alloc(pkt->packet_size);
1809 pkt->body[0] = '\0';
1811 memcpy(pkt->body, bufp, bufsize);
1812 pkt->body[pkt->packet_size - 1] = '\0';
1814 pkt->size = strlen(pkt->body);
1816 secprintf(("%s: sec: parse_pkt: %s (%d): \"%s\"\n",
1817 debug_prefix_time(NULL), pkt_type2str(pkt->type),
1818 pkt->type, pkt->body));
1822 * Convert a packet header into a string
1826 const struct sec_handle * rh,
1829 static char retbuf[256];
1832 assert(pkt != NULL);
1834 snprintf(retbuf, SIZEOF(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n",
1835 VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
1836 rh->proto_handle, rh->sequence);
1838 secprintf(("%s: bsd: pkthdr2str handle '%s'\n",
1839 debug_prefix_time(NULL), rh->proto_handle));
1841 /* check for truncation. If only we had asprintf()... */
1842 assert(retbuf[strlen(retbuf) - 1] == '\n');
1848 * Parses out the header line in 'str' into the pkt and handle
1849 * Returns negative on parse error.
1861 assert(udp->dgram.cur != NULL);
1862 str = stralloc(udp->dgram.cur);
1864 /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
1866 /* Read in "Amanda" */
1867 if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
1870 /* nothing is done with the major/minor numbers currently */
1871 if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
1874 /* Read in the packet type */
1875 if ((tok = strtok(NULL, " ")) == NULL)
1878 pkt_init(pkt, pkt_str2type(tok), "");
1879 if (pkt->type == (pktype_t)-1)
1882 /* Read in "HANDLE" */
1883 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
1886 /* parse the handle */
1887 if ((tok = strtok(NULL, " ")) == NULL)
1889 amfree(udp->handle);
1890 udp->handle = stralloc(tok);
1893 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)
1896 /* parse the sequence number */
1897 if ((tok = strtok(NULL, "\n")) == NULL)
1899 udp->sequence = atoi(tok);
1901 /* Save the body, if any */
1902 if ((tok = strtok(NULL, "")) != NULL)
1903 pkt_cat(pkt, "%s", tok);
1909 #if 0 /* XXX we have no way of passing this back up */
1910 security_seterror(&rh->sech,
1911 "parse error in packet header : '%s'", origstr);
1919 struct sec_handle * rh,
1920 const char * remoteuser,
1921 const char * service)
1925 char *result = NULL;
1926 char *localuser = NULL;
1928 /* lookup our local user name */
1929 if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
1930 return vstralloc("getpwnam(", CLIENT_LOGIN, ") fails", NULL);
1934 * Make a copy of the user name in case getpw* is called by
1935 * any of the lower level routines.
1937 localuser = stralloc(pwd->pw_name);
1939 #ifndef USE_AMANDAHOSTS
1940 r = check_user_ruserok(rh->hostname, pwd, remoteuser);
1942 r = check_user_amandahosts(rh->hostname, rh->peer.sin_addr, pwd, remoteuser, service);
1945 result = vstralloc("user ", remoteuser, " from ", rh->hostname,
1946 " is not allowed to execute the service ",
1947 service, ": ", r, NULL);
1955 * See if a remote user is allowed in. This version uses ruserok()
1958 * Returns 0 on success, or negative on error.
1963 struct passwd * pwd,
1964 const char * remoteuser)
1975 char number[NUM_STR_SIZE];
1976 uid_t myuid = getuid();
1979 * note that some versions of ruserok (eg SunOS 3.2) look in
1980 * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
1981 * chdir ourselves. Sigh.
1983 * And, believe it or not, some ruserok()'s try an initgroup just
1984 * for the hell of it. Since we probably aren't root at this point
1985 * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
1986 * into our stderr output even though the initgroup failure is not a
1987 * problem and is expected. Thanks a lot. Not.
1989 if (pipe(fd) != 0) {
1990 return stralloc2("pipe() fails: ", strerror(errno));
1992 if ((ruserok_pid = fork()) < 0) {
1993 return stralloc2("fork() fails: ", strerror(errno));
1994 } else if (ruserok_pid == 0) {
1998 fError = fdopen(fd[1], "w");
2000 error("Can't fdopen: %s", strerror(errno));
2003 /* pamper braindead ruserok's */
2004 if (chdir(pwd->pw_dir) != 0) {
2005 fprintf(fError, "chdir(%s) failed: %s",
2006 pwd->pw_dir, strerror(errno));
2011 #if defined(SHOW_SECURITY_DETAIL) /* { */
2013 char *dir = stralloc(pwd->pw_dir);
2015 secprintf(("%s: bsd: calling ruserok(%s, %d, %s, %s)\n",
2016 debug_prefix_time(NULL),
2017 host, ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name));
2019 secprintf(("%s: bsd: because you are running as root, ",
2020 debug_prefix(NULL)));
2021 secprintf(("/etc/hosts.equiv will not be used\n"));
2023 show_stat_info("/etc/hosts.equiv", NULL);
2025 show_stat_info(dir, "/.rhosts");
2030 saved_stderr = dup(2);
2032 if (open("/dev/null", O_RDWR) == -1) {
2033 secprintf(("%s: Could not open /dev/null: %s\n",
2034 debug_prefix(NULL), strerror(errno)));
2037 ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
2044 (void)dup2(saved_stderr,2);
2045 close(saved_stderr);
2049 fError = fdopen(fd[0], "r");
2051 error("Can't fdopen: %s", strerror(errno));
2056 while ((es = agets(fError)) != NULL) {
2061 if (result == NULL) {
2062 result = stralloc("");
2064 strappend(result, ": ");
2066 strappend(result, es);
2071 pid = wait(&exitcode);
2072 while (pid != ruserok_pid) {
2073 if ((pid == (pid_t) -1) && (errno != EINTR)) {
2075 return stralloc2("ruserok wait failed: %s", strerror(errno));
2077 pid = wait(&exitcode);
2079 if (WIFSIGNALED(exitcode)) {
2081 snprintf(number, SIZEOF(number), "%d", WTERMSIG(exitcode));
2082 return stralloc2("ruserok child got signal ", number);
2084 if (WEXITSTATUS(exitcode) == 0) {
2086 } else if (result == NULL) {
2087 result = stralloc("ruserok failed");
2094 * Check to see if a user is allowed in. This version uses .amandahosts
2095 * Returns -1 on failure, or 0 on success.
2098 check_user_amandahosts(
2100 struct in_addr addr,
2101 struct passwd * pwd,
2102 const char * remoteuser,
2103 const char * service)
2107 const char *fileuser;
2109 char *result = NULL;
2113 char n1[NUM_STR_SIZE];
2114 char n2[NUM_STR_SIZE];
2117 char *aservice = NULL;
2119 secprintf(("check_user_amandahosts(host=%s, pwd=%p, "
2120 "remoteuser=%s, service=%s)\n",
2121 host, pwd, remoteuser, service));
2123 ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
2124 #if defined(SHOW_SECURITY_DETAIL) /* { */
2125 show_stat_info(ptmp, "");;
2127 if ((fp = fopen(ptmp, "r")) == NULL) {
2128 result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL);
2134 * Make sure the file is owned by the Amanda user and does not
2135 * have any group/other access allowed.
2137 if (fstat(fileno(fp), &sbuf) != 0) {
2138 result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL);
2141 if (sbuf.st_uid != pwd->pw_uid) {
2142 snprintf(n1, SIZEOF(n1), "%ld", (long)sbuf.st_uid);
2143 snprintf(n2, SIZEOF(n2), "%ld", (long)pwd->pw_uid);
2144 result = vstralloc(ptmp, ": ",
2150 if ((sbuf.st_mode & 077) != 0) {
2151 result = stralloc2(ptmp,
2152 ": incorrect permissions; file must be accessible only by its owner");
2157 * Now, scan the file for the host/user/service.
2160 while ((line = agets(fp)) != NULL) {
2166 #if defined(SHOW_SECURITY_DETAIL) /* { */
2167 secprintf(("%s: bsd: processing line: <%s>\n", debug_prefix(NULL), line));
2169 /* get the host out of the file */
2170 if ((filehost = strtok(line, " \t")) == NULL) {
2175 /* get the username. If no user specified, then use the local user */
2176 if ((fileuser = strtok(NULL, " \t")) == NULL) {
2177 fileuser = pwd->pw_name;
2180 hostmatch = (strcasecmp(filehost, host) == 0);
2181 /* ok if addr=127.0.0.1 and
2182 * either localhost or localhost.domain is in .amandahost */
2184 if (strcmp(inet_ntoa(addr), "127.0.0.1")== 0 &&
2185 (strcasecmp(filehost, "localhost")== 0 ||
2186 strcasecmp(filehost, "localhost.localdomain")== 0))
2191 usermatch = (strcasecmp(fileuser, remoteuser) == 0);
2192 #if defined(SHOW_SECURITY_DETAIL) /* { */
2193 secprintf(("%s: bsd: comparing \"%s\" with\n", debug_prefix(NULL), filehost));
2194 secprintf(("%s: bsd: \"%s\" (%s)\n", host,
2195 debug_prefix(NULL), hostmatch ? "match" : "no match"));
2196 secprintf(("%s: bsd: and \"%s\" with\n", fileuser, debug_prefix(NULL)));
2197 secprintf(("%s: bsd: \"%s\" (%s)\n", remoteuser,
2198 debug_prefix(NULL), usermatch ? "match" : "no match"));
2201 if (!hostmatch || !usermatch) {
2213 /* get the services. If no service specified, then use
2214 * noop/selfcheck/sendsize/sendbackup
2216 aservice = strtok(NULL, " \t,");
2218 if (strcmp(service,"noop") == 0 ||
2219 strcmp(service,"selfcheck") == 0 ||
2220 strcmp(service,"sendsize") == 0 ||
2221 strcmp(service,"sendbackup") == 0) {
2234 if (strcmp(aservice,service) == 0) {
2238 if (strcmp(aservice, "amdump") == 0 &&
2239 (strcmp(service, "noop") == 0 ||
2240 strcmp(service, "selfcheck") == 0 ||
2241 strcmp(service, "sendsize") == 0 ||
2242 strcmp(service, "sendbackup") == 0)) {
2246 } while((aservice = strtok(NULL, " \t,")) != NULL);
2248 if (aservice && strcmp(aservice, service) == 0) {
2257 if (strcmp(service, "amindexd") == 0 ||
2258 strcmp(service, "amidxtaped") == 0) {
2259 result = vstralloc("Please add \"amindexd amidxtaped\" to "
2260 "the line in ", ptmp, NULL);
2261 } else if (strcmp(service, "amdump") == 0 ||
2262 strcmp(service, "noop") == 0 ||
2263 strcmp(service, "selfcheck") == 0 ||
2264 strcmp(service, "sendsize") == 0 ||
2265 strcmp(service, "sendbackup") == 0) {
2266 result = vstralloc("Please add \"amdump\" to the line in ",
2269 result = vstralloc(ptmp, ": ",
2270 "invalid service ", service, NULL);
2282 /* return 1 on success, 0 on failure */
2285 struct sockaddr_in *addr,
2287 unsigned long cksum,
2290 char * remotehost = NULL, *remoteuser = NULL;
2291 char * bad_bsd = NULL;
2292 struct hostent * hp;
2293 struct passwd * pwptr;
2301 (void)cksum; /* Quiet unused parameter warning */
2303 secprintf(("%s: check_security(addr=%p, str='%s', cksum=%ul, errstr=%p\n",
2304 debug_prefix(NULL), addr, str, cksum, errstr));
2305 dump_sockaddr(addr);
2309 /* what host is making the request? */
2311 hp = gethostbyaddr((char *)&addr->sin_addr, SIZEOF(addr->sin_addr),
2314 /* XXX include remote address in message */
2315 *errstr = vstralloc("[",
2316 "addr ", inet_ntoa(addr->sin_addr), ": ",
2317 "hostname lookup failed",
2321 remotehost = stralloc(hp->h_name);
2323 /* Now let's get the hostent for that hostname */
2324 hp = gethostbyname( remotehost );
2326 /* XXX include remote hostname in message */
2327 *errstr = vstralloc("[",
2328 "host ", remotehost, ": ",
2329 "hostname lookup failed",
2335 /* Verify that the hostnames match -- they should theoretically */
2336 if (strncasecmp( remotehost, hp->h_name, strlen(remotehost)+1 ) != 0 ) {
2337 *errstr = vstralloc("[",
2338 "hostnames do not match: ",
2339 remotehost, " ", hp->h_name,
2345 /* Now let's verify that the ip which gave us this hostname
2346 * is really an ip for this hostname; or is someone trying to
2347 * break in? (THIS IS THE CRUCIAL STEP)
2349 for (i = 0; hp->h_addr_list[i]; i++) {
2350 if (memcmp(hp->h_addr_list[i],
2351 (char *) &addr->sin_addr, SIZEOF(addr->sin_addr)) == 0)
2352 break; /* name is good, keep it */
2355 /* If we did not find it, your DNS is messed up or someone is trying
2356 * to pull a fast one on you. :(
2359 /* Check even the aliases list. Work around for Solaris if dns goes over NIS */
2361 if (!hp->h_addr_list[i] ) {
2362 for (j = 0; hp->h_aliases[j] !=0 ; j++) {
2363 if (strcmp(hp->h_aliases[j],inet_ntoa(addr->sin_addr)) == 0)
2364 break; /* name is good, keep it */
2366 if (!hp->h_aliases[j] ) {
2367 *errstr = vstralloc("[",
2368 "ip address ", inet_ntoa(addr->sin_addr),
2369 " is not in the ip list for ", remotehost,
2377 /* next, make sure the remote port is a "reserved" one */
2379 if (ntohs(addr->sin_port) >= IPPORT_RESERVED) {
2380 char number[NUM_STR_SIZE];
2382 snprintf(number, SIZEOF(number), "%hd", (short)ntohs(addr->sin_port));
2383 *errstr = vstralloc("[",
2384 "host ", remotehost, ": ",
2385 "port ", number, " not secure",
2391 /* extract the remote user name from the message */
2396 bad_bsd = vstralloc("[",
2397 "host ", remotehost, ": ",
2398 "bad bsd security line",
2402 if (strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) {
2412 skip_whitespace(s, ch);
2420 skip_non_whitespace(s, ch);
2422 remoteuser = stralloc(fp);
2426 /* lookup our local user name */
2429 if ((pwptr = getpwuid(myuid)) == NULL)
2430 error("error [getpwuid(%d) fails]", myuid);
2432 secprintf(("%s: bsd security: remote host %s user %s local user %s\n",
2433 debug_prefix(NULL), remotehost, remoteuser, pwptr->pw_name));
2435 #ifndef USE_AMANDAHOSTS
2436 s = check_user_ruserok(remotehost, pwptr, remoteuser);
2438 s = check_user_amandahosts(remotehost, addr->sin_addr, pwptr, remoteuser, NULL);
2442 *errstr = vstralloc("[",
2443 "access as ", pwptr->pw_name, " not allowed",
2444 " from ", remoteuser, "@", remotehost,
2445 ": ", s, "]", NULL);
2450 return *errstr == NULL;
2454 * Writes out the entire iovec
2462 ssize_t delta, n, total;
2464 assert(iov != NULL);
2467 while (iovcnt > 0) {
2471 n = writev(fd, iov, iovcnt);
2475 secprintf(("%s: net_writev got EINTR\n",
2476 debug_prefix(NULL)));
2484 * Iterate through each iov. Figure out what we still need
2487 for (; n > 0; iovcnt--, iov++) {
2488 /* 'delta' is the bytes written from this iovec */
2489 delta = ((size_t)n < iov->iov_len) ? n : (ssize_t)iov->iov_len;
2490 /* subtract from the total num bytes written */
2493 /* subtract from this iovec */
2494 iov->iov_len -= delta;
2495 iov->iov_base = (char *)iov->iov_base + delta;
2496 /* if this iovec isn't empty, run the writev again */
2497 if (iov->iov_len > 0)
2506 * Like read(), but waits until the entire buffer has been filled.
2515 char *buf = vbuf; /* ptr arith */
2517 size_t size = origsize;
2519 secprintf(("%s: net_read: begin %d\n", debug_prefix_time(NULL), origsize));
2522 secprintf(("%s: net_read: while %d\n",
2523 debug_prefix_time(NULL), size));
2524 nread = net_read_fillbuf(fd, timeout, buf, size);
2526 secprintf(("%s: db: net_read: end return(-1)\n",
2527 debug_prefix_time(NULL)));
2531 secprintf(("%s: net_read: end return(0)\n",
2532 debug_prefix_time(NULL)));
2538 secprintf(("%s: net_read: end %d\n",
2539 debug_prefix_time(NULL), origsize));
2540 return ((ssize_t)origsize);
2544 * net_read likes to do a lot of little reads. Buffer it.
2557 secprintf(("%s: net_read_fillbuf: begin\n", debug_prefix_time(NULL)));
2559 FD_SET(fd, &readfds);
2560 tv.tv_sec = timeout;
2562 switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
2567 secprintf(("%s: net_read_fillbuf: case -1\n",
2568 debug_prefix_time(NULL)));
2571 secprintf(("%s: net_read_fillbuf: case 1\n",
2572 debug_prefix_time(NULL)));
2573 assert(FD_ISSET(fd, &readfds));
2576 secprintf(("%s: net_read_fillbuf: case default\n",
2577 debug_prefix_time(NULL)));
2581 nread = read(fd, buf, size);
2584 secprintf(("%s: net_read_fillbuf: end %d\n",
2585 debug_prefix_time(NULL), nread));
2591 * Display stat() information about a file.
2599 char *name = vstralloc(a, b, NULL);
2601 struct passwd *pwptr;
2603 struct group *grptr;
2606 if (stat(name, &sbuf) != 0) {
2607 secprintf(("%s: bsd: cannot stat %s: %s\n",
2608 debug_prefix_time(NULL), name, strerror(errno)));
2612 if ((pwptr = getpwuid(sbuf.st_uid)) == NULL) {
2613 owner = alloc(NUM_STR_SIZE + 1);
2614 snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
2616 owner = stralloc(pwptr->pw_name);
2618 if ((grptr = getgrgid(sbuf.st_gid)) == NULL) {
2619 group = alloc(NUM_STR_SIZE + 1);
2620 snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
2622 group = stralloc(grptr->gr_name);
2624 secprintf(("%s: bsd: processing file: %s\n", debug_prefix(NULL), name));
2625 secprintf(("%s: bsd: owner=%s group=%s mode=%03o\n",
2626 debug_prefix(NULL), owner, group, (int) (sbuf.st_mode & 0777)));