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"
45 #include "sockaddr-util.h"
48 * Magic values for sec_conn->handle
50 #define H_TAKEN -1 /* sec_conn->tok was already read */
51 #define H_EOF -2 /* this connection has been shut down */
54 * This is a queue of open connections
56 struct connq_s connq = {
57 TAILQ_HEAD_INITIALIZER(connq.tailq), 0
59 static int newhandle = 1;
60 static int newevent = 1;
65 static void recvpkt_callback(void *, void *, ssize_t);
66 static void stream_read_callback(void *);
67 static void stream_read_sync_callback(void *);
69 static void sec_tcp_conn_read_cancel(struct tcp_conn *);
70 static void sec_tcp_conn_read_callback(void *);
74 * Authenticate a stream
75 * Nothing needed for sec. The connection is authenticated by secd
82 (void)s; /* Quiet unused parameter warning */
87 * Returns the stream id for this stream. This is just the local
94 struct sec_stream *rs = s;
102 * Setup to handle new incoming connections
106 const security_driver_t *driver,
107 char *(*conf_fn)(char *, void *),
110 void (*fn)(security_handle_t *, pkt_t *),
115 rc = sec_tcp_conn_get("unknown",0);
120 rc->conf_fn = conf_fn;
122 sec_tcp_conn_read(rc);
126 * frees a handle allocated by the above
132 struct sec_handle *rh = inst;
136 auth_debug(1, _("sec: closing handle to %s\n"), rh->hostname);
138 if (rh->rs != NULL) {
139 /* This may be null if we get here on an error */
140 stream_recvpkt_cancel(rh);
141 security_stream_close(&rh->rs->secstr);
143 /* keep us from getting here again */
144 rh->sech.driver = NULL;
145 amfree(rh->hostname);
150 * Called when a sec connection is finished connecting and is ready
151 * to be authenticated.
154 sec_connect_callback(
157 struct sec_handle *rh = cookie;
159 event_release(rh->rs->ev_read);
160 rh->rs->ev_read = NULL;
161 event_release(rh->ev_timeout);
162 rh->ev_timeout = NULL;
164 (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);
168 * Called if a connection times out before completion.
174 struct sec_handle *rh = cookie;
176 event_release(rh->rs->ev_read);
177 rh->rs->ev_read = NULL;
178 event_release(rh->ev_timeout);
179 rh->ev_timeout = NULL;
181 (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);
185 sec_close_connection_none(
206 struct sec_handle *rh = cookie;
213 auth_debug(1, _("sec: stream_sendpkt: enter\n"));
215 if (rh->rc->prefix_packet)
216 s = rh->rc->prefix_packet(rh, pkt);
219 len = strlen(pkt->body) + strlen(s) + 2;
221 buf[0] = (char)pkt->type;
222 strncpy(&buf[1], s, len - 1);
223 strncpy(&buf[1 + strlen(s)], pkt->body, (len - strlen(s) - 1));
228 _("sec: stream_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),
229 pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);
231 if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {
232 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
240 * Set up to receive a packet asyncronously, and call back when
246 void (*fn)(void *, pkt_t *, security_status_t),
250 struct sec_handle *rh = cookie;
254 auth_debug(1, _("sec: recvpkt registered for %s\n"), rh->hostname);
257 * Reset any pending timeout on this handle
259 if (rh->ev_timeout != NULL)
260 event_release(rh->ev_timeout);
263 * Negative timeouts mean no timeout
266 rh->ev_timeout = NULL;
268 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
269 stream_recvpkt_timeout, rh);
273 security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);
277 * This is called when a handle times out before receiving a packet.
280 stream_recvpkt_timeout(
283 struct sec_handle *rh = cookie;
287 auth_debug(1, _("sec: recvpkt timeout for %s\n"), 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, _("sec: cancelling recvpkt for %s\n"), rh->hostname);
306 security_stream_read_cancel(&rh->rs->secstr);
307 if (rh->ev_timeout != NULL) {
308 event_release(rh->ev_timeout);
309 rh->ev_timeout = NULL;
314 * Write a chunk of data to a stream. Blocks until completion.
322 struct sec_stream *rs = s;
325 assert(rs->rc != NULL);
327 auth_debug(1, _("sec: stream_write: writing %zu bytes to %s:%d %d\n"),
328 size, rs->rc->hostname, rs->handle,
331 if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg,
333 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
340 * Submit a request to read some data. Calls back with the given
341 * function and arg when completed.
346 void (*fn)(void *, void *, ssize_t),
349 struct sec_stream *rs = s;
354 * Only one read request can be active per stream.
356 if (rs->ev_read == NULL) {
357 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
358 stream_read_callback, rs);
359 sec_tcp_conn_read(rs->rc);
366 * Write a chunk of data to a stream. Blocks until completion.
369 tcpm_stream_read_sync(
373 struct sec_stream *rs = s;
378 * Only one read request can be active per stream.
380 if (rs->ev_read != NULL) {
383 rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,
384 stream_read_sync_callback, rs);
385 sec_tcp_conn_read(rs->rc);
386 event_wait(rs->ev_read);
388 return (rs->rc->pktlen);
392 * Cancel a previous stream read request. It's ok if we didn't have a read
396 tcpm_stream_read_cancel(
399 struct sec_stream *rs = s;
403 if (rs->ev_read != NULL) {
404 event_release(rs->ev_read);
406 sec_tcp_conn_read_cancel(rs->rc);
411 * Transmits a chunk of data over a rsh_handle, adding
412 * the necessary headers to allow the remote end to decode it.
431 assert(SIZEOF(netlength) == 4);
433 auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n",
437 * 32 bit length (network byte order)
438 * 32 bit handle (network byte order)
441 netlength = htonl(len);
442 iov[0].iov_base = (void *)&netlength;
443 iov[0].iov_len = SIZEOF(netlength);
445 nethandle = htonl((guint32)handle);
446 iov[1].iov_base = (void *)&nethandle;
447 iov[1].iov_len = SIZEOF(nethandle);
449 encbuf = (char *)buf;
456 if (rc->driver->data_encrypt == NULL) {
457 iov[2].iov_base = (void *)buf;
458 iov[2].iov_len = len;
460 /* (the extra (void *) cast is to quiet type-punning warnings) */
461 rc->driver->data_encrypt(rc, (void *)buf, len, (void **)(void *)&encbuf, &encsize);
462 iov[2].iov_base = (void *)encbuf;
463 iov[2].iov_len = encsize;
464 netlength = htonl(encsize);
469 rval = net_writev(fd, iov, nb_iov);
470 if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) {
476 *errmsg = newvstrallocf(*errmsg, _("write error to: %s"),
485 * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed
486 * return 0 on EOF: *handle = handle && *size = 0 if stream closed
487 * return size : *handle = handle && *size = size for data read
500 unsigned int netint[2];
502 assert(SIZEOF(netint) == 8);
504 switch (net_read(fd, &netint, SIZEOF(netint), timeout)) {
507 *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno));
508 auth_debug(1, _("tcpm_recv_token: A return(-1)\n"));
513 *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
514 auth_debug(1, _("tcpm_recv_token: A return(0)\n"));
520 *size = (ssize_t)ntohl(netint[0]);
521 *handle = (int)ntohl(netint[1]);
522 /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */
523 if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) {
524 if (isprint((int)(*size ) & 0xFF) &&
525 isprint((int)(*size >> 8 ) & 0xFF) &&
526 isprint((int)(*size >> 16) & 0xFF) &&
527 isprint((int)(*size >> 24) & 0xFF) &&
528 isprint((*handle ) & 0xFF) &&
529 isprint((*handle >> 8 ) & 0xFF) &&
530 isprint((*handle >> 16) & 0xFF) &&
531 isprint((*handle >> 24) & 0xFF)) {
534 s[0] = ((int)(*size) >> 24) & 0xFF;
535 s[1] = ((int)(*size) >> 16) & 0xFF;
536 s[2] = ((int)(*size) >> 8) & 0xFF;
537 s[3] = ((int)(*size) ) & 0xFF;
538 s[4] = (*handle >> 24) & 0xFF;
539 s[5] = (*handle >> 16) & 0xFF;
540 s[6] = (*handle >> 8 ) & 0xFF;
541 s[7] = (*handle ) & 0xFF;
543 while(i<100 && isprint((int)s[i]) && s[i] != '\n') {
544 switch(net_read(fd, &s[i], 1, 0)) {
545 case -1: s[i] = '\0'; break;
546 case 0: s[i] = '\0'; break;
548 dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' ';
553 *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size: %s"), s);
554 dbprintf(_("tcpm_recv_token: invalid size %s\n"), s);
556 *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size"));
557 dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size);
563 *buf = alloc((size_t)*size);
566 auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle);
567 *errmsg = newvstrallocf(*errmsg, _("EOF"));
570 switch (net_read(fd, *buf, (size_t)*size, timeout)) {
573 *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno));
574 auth_debug(1, _("tcpm_recv_token: B return(-1)\n"));
578 *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));
579 auth_debug(1, _("tcpm_recv_token: B return(0)\n"));
585 auth_debug(1, _("tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle);
587 if (*size > 0 && rc->driver->data_decrypt != NULL) {
590 rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize);
591 if (*buf != (char *)decbuf) {
593 *buf = (char *)decbuf;
602 tcpm_close_connection(
606 struct sec_handle *rh = h;
610 if (rh && rh->rc && rh->rc->toclose == 0) {
612 sec_tcp_conn_put(rh->rc);
619 * Accept an incoming connection on a stream_server socket
620 * Nothing needed for tcpma.
626 (void)s; /* Quiet unused parameter warning */
632 * Return a connected stream. For sec, this means setup a stream
633 * with the supplied handle.
640 struct sec_handle *rh = h;
641 struct sec_stream *rs;
646 security_seterror(&rh->sech,
647 _("%d: invalid security stream id"), id);
651 rs = alloc(SIZEOF(*rs));
652 security_streaminit(&rs->secstr, rh->sech.driver);
655 rs->closed_by_me = 0;
656 rs->closed_by_network = 0;
662 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
663 rs->rc->driver = rh->sech.driver;
667 auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id);
673 * Create the server end of a stream. For sec, this means setup a stream
674 * object and allocate a new handle for it.
680 struct sec_handle *rh = h;
681 struct sec_stream *rs;
685 rs = alloc(SIZEOF(*rs));
686 security_streaminit(&rs->secstr, rh->sech.driver);
687 rs->closed_by_me = 0;
688 rs->closed_by_network = 0;
694 rs->rc = sec_tcp_conn_get(rh->hostname, 0);
695 rs->rc->driver = rh->sech.driver;
699 * Stream should already be setup!
701 if (rs->rc->read < 0) {
702 sec_tcp_conn_put(rs->rc);
704 security_seterror(&rh->sech, _("lost connection to %s"), rh->hostname);
707 assert(strcmp(rh->hostname, rs->rc->hostname) == 0);
709 * so as not to conflict with the amanda server's handle numbers,
710 * we start at 500000 and work down
712 rs->handle = 500000 - newhandle++;
714 auth_debug(1, _("sec: stream_server: created stream %d\n"), rs->handle);
719 * Close and unallocate resources for a stream.
725 struct sec_stream *rs = s;
730 auth_debug(1, _("sec: tcpma_stream_close: closing stream %d\n"), rs->handle);
732 if(rs->closed_by_network == 0 && rs->rc->write != -1)
733 tcpm_stream_write(rs, &buf, 0);
734 security_stream_read_cancel(&rs->secstr);
735 if(rs->closed_by_network == 0)
736 sec_tcp_conn_put(rs->rc);
741 * Create the server end of a stream. For bsdudp, this means setup a tcp
742 * socket for receiving a connection.
748 struct sec_stream *rs = NULL;
749 struct sec_handle *rh = h;
753 rs = alloc(SIZEOF(*rs));
754 security_streaminit(&rs->secstr, rh->sech.driver);
755 rs->closed_by_me = 0;
756 rs->closed_by_network = 0;
759 rs->handle = 500000 - newhandle++;
761 rs->socket = 0; /* the socket is already opened */
764 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
765 rh->rc->driver = rh->sech.driver;
767 rs->socket = stream_server(SU_GET_FAMILY(&rh->udp->peer), &rs->port,
768 STREAM_BUFSIZE, STREAM_BUFSIZE, 0);
769 if (rs->socket < 0) {
770 security_seterror(&rh->sech,
771 _("can't create server stream: %s"), strerror(errno));
775 rh->rc->read = rs->socket;
776 rh->rc->write = rs->socket;
777 rs->handle = (int)rs->port;
785 * Accepts a new connection on unconnected streams. Assumes it is ok to
792 struct sec_stream *bs = s;
795 assert(bs->socket != -1);
798 if (bs->socket > 0) {
799 bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE);
801 security_stream_seterror(&bs->secstr,
802 _("can't accept new stream connection: %s"),
806 bs->rc->read = bs->fd;
807 bs->rc->write = bs->fd;
813 * Return a connected stream
820 struct sec_stream *rs = NULL;
821 struct sec_handle *rh = h;
825 rs = alloc(SIZEOF(*rs));
826 security_streaminit(&rs->secstr, rh->sech.driver);
829 rs->closed_by_me = 0;
830 rs->closed_by_network = 0;
836 rh->rc = sec_tcp_conn_get(rh->hostname, 1);
837 rh->rc->driver = rh->sech.driver;
839 rh->rc->read = stream_client(rh->hostname, (in_port_t)id,
840 STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0);
841 if (rh->rc->read < 0) {
842 security_seterror(&rh->sech,
843 _("can't connect stream to %s port %d: %s"),
844 rh->hostname, id, strerror(errno));
848 rh->rc->write = rh->rc->read;
850 rs->socket = -1; /* we're a client */
861 struct sec_stream *rs = s;
865 if (fullwrite(rs->fd, buf, size) < 0) {
866 security_stream_seterror(&rs->secstr,
867 _("write error on stream %d: %s"), rs->port, strerror(errno));
878 struct sec_handle *rh = h;
882 if (pkt->type != P_REQ)
885 if ((pwd = getpwuid(getuid())) == NULL) {
886 security_seterror(&rh->sech,
887 _("can't get login name for my uid %ld"),
891 buf = alloc(16+strlen(pwd->pw_name));
892 strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name)));
893 strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14));
894 buf[14 + strlen(pwd->pw_name)] = '\n';
895 buf[15 + strlen(pwd->pw_name)] = '\0';
902 * Check the security of a received packet. Returns negative on security
903 * violation, or returns 0 if ok. Removes the security info from the pkt_t.
906 bsd_recv_security_ok(
907 struct sec_handle * rh,
910 char *tok, *security, *body, *result;
911 char *service = NULL, *serviceX, *serviceY;
918 * Now, find the SECURITY line in the body, and parse it out
921 if (strncmp_const(pkt->body, "SECURITY ") == 0) {
922 security = pkt->body;
924 while(*security != '\n' && len < pkt->size) {
928 if(*security == '\n') {
931 security_line = stralloc(pkt->body);
932 security = pkt->body + strlen("SECURITY ");
935 security_line = NULL;
940 security_line = NULL;
945 * Now, find the SERVICE line in the body, and parse it out
949 if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) {
950 serviceX = stralloc(s);
951 serviceY = strtok(serviceX, "\n");
953 service = stralloc(serviceY);
958 * We need to do different things depending on which type of packet
964 * Request packets must come from a reserved port
966 port = SU_GET_PORT(&rh->peer);
967 if (port >= IPPORT_RESERVED) {
968 security_seterror(&rh->sech,
969 _("host %s: port %u not secure"), rh->hostname,
972 amfree(security_line);
977 security_seterror(&rh->sech,
978 _("packet as no SERVICE line"));
979 amfree(security_line);
984 * Request packets contain a remote username. We need to check
985 * that we allow it in.
987 * They will look like:
988 * SECURITY USER [username]
991 /* there must be some security info */
992 if (security == NULL) {
993 security_seterror(&rh->sech,
994 _("no bsd SECURITY for P_REQ"));
999 /* second word must be USER */
1000 if ((tok = strtok(security, " ")) == NULL) {
1001 security_seterror(&rh->sech,
1002 _("SECURITY line: %s"), security_line);
1004 amfree(security_line);
1005 return (-1); /* default errmsg */
1007 if (strcmp(tok, "USER") != 0) {
1008 security_seterror(&rh->sech,
1009 _("REQ SECURITY line parse error, expecting USER, got %s"), tok);
1011 amfree(security_line);
1015 /* the third word is the username */
1016 if ((tok = strtok(NULL, "")) == NULL) {
1017 security_seterror(&rh->sech,
1018 _("SECURITY line: %s"), security_line);
1019 amfree(security_line);
1020 return (-1); /* default errmsg */
1022 if ((result = check_user(rh, tok, service)) != NULL) {
1023 security_seterror(&rh->sech, "%s", result);
1026 amfree(security_line);
1030 /* we're good to go */
1036 amfree(security_line);
1039 * If there is security info at the front of the packet, we need to
1040 * shift the rest of the data up and nuke it.
1042 if (body != pkt->body)
1043 memmove(pkt->body, body, strlen(body) + 1);
1048 * Transmit a packet. Add security information first.
1055 struct sec_handle *rh = cookie;
1059 assert(pkt != NULL);
1061 auth_debug(1, _("udpbsd_sendpkt: enter\n"));
1063 * Initialize this datagram, and add the header
1065 dgram_zero(&rh->udp->dgram);
1066 dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt));
1069 * Add the security info. This depends on which kind of packet we're
1072 switch (pkt->type) {
1075 * Requests get sent with our username in the body
1077 if ((pwd = getpwuid(geteuid())) == NULL) {
1078 security_seterror(&rh->sech,
1079 _("can't get login name for my uid %ld"), (long)getuid());
1082 dgram_cat(&rh->udp->dgram, _("SECURITY USER %s\n"), pwd->pw_name);
1090 * Add the body, and send it
1092 dgram_cat(&rh->udp->dgram, pkt->body);
1095 _("sec: udpbsd_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),
1096 pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);
1098 if (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) {
1099 security_seterror(&rh->sech,
1100 _("send %s to %s failed: %s"), pkt_type2str(pkt->type),
1101 rh->hostname, strerror(errno));
1111 struct sec_handle *rh = cookie;
1113 if (rh->proto_handle == NULL) {
1117 auth_debug(1, _("udp: close handle '%s'\n"), rh->proto_handle);
1119 udp_recvpkt_cancel(rh);
1121 rh->next->prev = rh->prev;
1124 rh->udp->bh_last = rh->prev;
1127 rh->prev->next = rh->next;
1130 rh->udp->bh_first = rh->next;
1133 amfree(rh->proto_handle);
1134 amfree(rh->hostname);
1139 * Set up to receive a packet asynchronously, and call back when it has
1145 void (*fn)(void *, pkt_t *, security_status_t),
1149 struct sec_handle *rh = cookie;
1151 auth_debug(1, _("udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n"),
1152 cookie, fn, arg, timeout);
1158 * Subsequent recvpkt calls override previous ones
1160 if (rh->ev_read == NULL) {
1161 udp_addref(rh->udp, &udp_netfd_read_callback);
1162 rh->ev_read = event_register(rh->event_id, EV_WAIT,
1163 udp_recvpkt_callback, rh);
1165 if (rh->ev_timeout != NULL)
1166 event_release(rh->ev_timeout);
1168 rh->ev_timeout = NULL;
1170 rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,
1171 udp_recvpkt_timeout, rh);
1172 rh->fn.recvpkt = fn;
1177 * Remove a async receive request on this handle from the queue.
1178 * If it is the last one to be removed, then remove the event
1179 * handler for our network fd
1185 struct sec_handle *rh = cookie;
1189 if (rh->ev_read != NULL) {
1190 udp_delref(rh->udp);
1191 event_release(rh->ev_read);
1195 if (rh->ev_timeout != NULL) {
1196 event_release(rh->ev_timeout);
1197 rh->ev_timeout = NULL;
1202 * This is called when a handle is woken up because data read off of the
1206 udp_recvpkt_callback(
1209 struct sec_handle *rh = cookie;
1210 void (*fn)(void *, pkt_t *, security_status_t);
1213 auth_debug(1, _("udp: receive handle '%s' netfd '%s'\n"),
1214 rh->proto_handle, rh->udp->handle);
1217 /* if it doesn't correspond to this handle, something is wrong */
1218 assert(strcmp(rh->proto_handle, rh->udp->handle) == 0);
1220 /* if it didn't come from the same host/port, forget it */
1221 if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) {
1222 amfree(rh->udp->handle);
1223 dbprintf(_("not from same host\n"));
1224 dump_sockaddr(&rh->peer);
1225 dump_sockaddr(&rh->udp->peer);
1230 * We need to cancel the recvpkt request before calling the callback
1231 * because the callback may reschedule us.
1233 fn = rh->fn.recvpkt;
1235 udp_recvpkt_cancel(rh);
1238 * Check the security of the packet. If it is bad, then pass NULL
1239 * to the packet handling function instead of a packet.
1241 if (rh->udp->recv_security_ok &&
1242 rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) {
1243 (*fn)(arg, NULL, S_ERROR);
1245 (*fn)(arg, &rh->udp->pkt, S_OK);
1250 * This is called when a handle times out before receiving a packet.
1253 udp_recvpkt_timeout(
1256 struct sec_handle *rh = cookie;
1257 void (*fn)(void *, pkt_t *, security_status_t);
1262 assert(rh->ev_timeout != NULL);
1263 fn = rh->fn.recvpkt;
1265 udp_recvpkt_cancel(rh);
1266 (*fn)(arg, NULL, S_TIMEOUT);
1270 * Given a hostname and a port, setup a udp_handle
1275 struct sec_handle * rh,
1277 sockaddr_union *addr,
1283 * Save the hostname and port info
1285 auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"),
1286 (unsigned int)ntohs(port), handle, sequence);
1287 assert(addr != NULL);
1289 rh->hostname = stralloc(hostname);
1290 copy_sockaddr(&rh->peer, addr);
1291 SU_SET_PORT(&rh->peer, port);
1294 rh->prev = udp->bh_last;
1296 rh->prev->next = rh;
1298 if (!udp->bh_first) {
1304 rh->sequence = sequence;
1305 rh->event_id = (event_id_t)newevent++;
1306 amfree(rh->proto_handle);
1307 rh->proto_handle = stralloc(handle);
1308 rh->fn.connect = NULL;
1311 rh->ev_timeout = NULL;
1313 auth_debug(1, _("udp: adding handle '%s'\n"), rh->proto_handle);
1320 * Callback for received packets. This is the function bsd_recvpkt
1321 * registers with the event handler. It is called when the event handler
1322 * realizes that data is waiting to be read on the network socket.
1325 udp_netfd_read_callback(
1328 struct udp_handle *udp = cookie;
1329 struct sec_handle *rh;
1331 char hostname[NI_MAXHOST];
1333 char *errmsg = NULL;
1336 auth_debug(1, _("udp_netfd_read_callback(cookie=%p)\n"), cookie);
1337 assert(udp != NULL);
1339 #ifndef TEST /* { */
1341 * Receive the packet.
1343 dgram_zero(&udp->dgram);
1344 if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)
1346 #endif /* !TEST */ /* } */
1351 if (str2pkthdr(udp) < 0)
1355 * If there are events waiting on this handle, we're done
1358 while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||
1359 rh->sequence != udp->sequence ||
1360 cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) {
1363 if (rh && event_wakeup(rh->event_id) > 0)
1367 * If we didn't find a handle, then check for a new incoming packet.
1368 * If no accept handler was setup, then just return.
1370 if (udp->accept_fn == NULL) {
1371 dbprintf(_("Receive packet from unknown source"));
1375 rh = alloc(SIZEOF(*rh));
1376 rh->proto_handle=NULL;
1379 security_handleinit(&rh->sech, udp->driver);
1381 result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer),
1382 hostname, sizeof(hostname), NULL, 0, 0);
1384 dbprintf("getnameinfo failed: %s\n",
1385 gai_strerror(result));
1386 security_seterror(&rh->sech, "getnameinfo failed: %s",
1387 gai_strerror(result));
1390 if (check_name_give_sockaddr(hostname,
1391 (struct sockaddr *)&udp->peer, &errmsg) < 0) {
1392 security_seterror(&rh->sech, "%s",errmsg);
1398 port = SU_GET_PORT(&udp->peer);
1399 a = udp_inithandle(udp, rh,
1406 auth_debug(1, _("bsd: closeX handle '%s'\n"), rh->proto_handle);
1412 * Check the security of the packet. If it is bad, then pass NULL
1413 * to the accept function instead of a packet.
1415 if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)
1416 (*udp->accept_fn)(&rh->sech, NULL);
1418 (*udp->accept_fn)(&rh->sech, &udp->pkt);
1422 * Locate an existing connection to the given host, or create a new,
1423 * unconnected entry if none exists. The caller is expected to check
1424 * for the lack of a connection (rc->read == -1) and set one up.
1428 const char *hostname,
1431 struct tcp_conn *rc;
1433 auth_debug(1, _("sec_tcp_conn_get: %s\n"), hostname);
1435 if (want_new == 0) {
1436 for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {
1437 if (strcasecmp(hostname, rc->hostname) == 0)
1444 _("sec_tcp_conn_get: exists, refcnt to %s is now %d\n"),
1445 rc->hostname, rc->refcnt);
1450 auth_debug(1, _("sec_tcp_conn_get: creating new handle\n"));
1452 * We can't be creating a new handle if we are the client
1454 rc = alloc(SIZEOF(*rc));
1455 rc->read = rc->write = -1;
1461 strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);
1462 rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';
1467 rc->accept_fn = NULL;
1468 rc->recv_security_ok = NULL;
1469 rc->prefix_packet = NULL;
1478 * Delete a reference to a connection, and close it if it is the last
1483 struct tcp_conn * rc)
1487 assert(rc->refcnt > 0);
1489 auth_debug(1, _("sec_tcp_conn_put: decrementing refcnt for %s to %d\n"),
1490 rc->hostname, rc->refcnt);
1491 if (rc->refcnt > 0) {
1494 auth_debug(1, _("sec_tcp_conn_put: closing connection to %s\n"), rc->hostname);
1497 if (rc->write != -1)
1499 if (rc->pid != -1) {
1500 waitpid(rc->pid, &status, WNOHANG);
1502 if (rc->ev_read != NULL)
1503 event_release(rc->ev_read);
1504 if (rc->errmsg != NULL)
1509 amfree(rc); /* someone might still use it */
1510 /* eg. in sec_tcp_conn_read_callback if */
1511 /* event_wakeup call us. */
1515 * Turn on read events for a conn. Or, increase a ev_read_refcnt if we are
1516 * already receiving read events.
1520 struct tcp_conn * rc)
1522 assert (rc != NULL);
1524 if (rc->ev_read != NULL) {
1525 rc->ev_read_refcnt++;
1527 _("sec: conn_read: incremented ev_read_refcnt to %d for %s\n"),
1528 rc->ev_read_refcnt, rc->hostname);
1531 auth_debug(1, _("sec: conn_read registering event handler for %s\n"),
1533 rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,
1534 sec_tcp_conn_read_callback, rc);
1535 rc->ev_read_refcnt = 1;
1539 sec_tcp_conn_read_cancel(
1540 struct tcp_conn * rc)
1543 --rc->ev_read_refcnt;
1545 _("sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n"),
1546 rc->ev_read_refcnt, rc->hostname);
1547 if (rc->ev_read_refcnt > 0) {
1551 _("sec: conn_read_cancel: releasing event handler for %s\n"),
1553 event_release(rc->ev_read);
1558 * This is called when a handle is woken up because data read off of the
1568 struct sec_handle *rh = cookie;
1572 auth_debug(1, _("sec: recvpkt_callback: %zd\n"), bufsize);
1574 * We need to cancel the recvpkt request before calling
1575 * the callback because the callback may reschedule us.
1577 stream_recvpkt_cancel(rh);
1581 security_seterror(&rh->sech,
1582 _("EOF on read from %s"), rh->hostname);
1583 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1586 security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));
1587 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1593 parse_pkt(&pkt, buf, (size_t)bufsize);
1595 _("sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n"),
1596 pkt_type2str(pkt.type), pkt.type,
1597 rh->hostname, pkt.body);
1598 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1599 (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);
1601 (*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);
1606 * Callback for tcpm_stream_read_sync
1609 stream_read_sync_callback(
1612 struct sec_stream *rs = s;
1615 auth_debug(1, _("sec: stream_read_callback_sync: handle %d\n"), rs->handle);
1618 * Make sure this was for us. If it was, then blow away the handle
1619 * so it doesn't get claimed twice. Otherwise, leave it alone.
1621 * If the handle is EOF, pass that up to our callback.
1623 if (rs->rc->handle == rs->handle) {
1624 auth_debug(1, _("sec: stream_read_callback_sync: it was for us\n"));
1625 rs->rc->handle = H_TAKEN;
1626 } else if (rs->rc->handle != H_EOF) {
1627 auth_debug(1, _("sec: stream_read_callback_sync: not for us\n"));
1632 * Remove the event first, and then call the callback.
1633 * We remove it first because we don't want to get in their
1634 * way if they reschedule it.
1636 tcpm_stream_read_cancel(rs);
1638 if (rs->rc->pktlen <= 0) {
1639 auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), 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 _("sec: stream_read_callback_sync: read %zd bytes from %s:%d\n"),
1648 rs->rc->pktlen, rs->rc->hostname, rs->handle);
1652 * Callback for tcpm_stream_read
1655 stream_read_callback(
1658 struct sec_stream *rs = arg;
1661 auth_debug(1, _("sec: stream_read_callback: handle %d\n"), rs->handle);
1664 * Make sure this was for us. If it was, then blow away the handle
1665 * so it doesn't get claimed twice. Otherwise, leave it alone.
1667 * If the handle is EOF, pass that up to our callback.
1669 if (rs->rc->handle == rs->handle) {
1670 auth_debug(1, _("sec: stream_read_callback: it was for us\n"));
1671 rs->rc->handle = H_TAKEN;
1672 } else if (rs->rc->handle != H_EOF) {
1673 auth_debug(1, _("sec: stream_read_callback: not for us\n"));
1678 * Remove the event first, and then call the callback.
1679 * We remove it first because we don't want to get in their
1680 * way if they reschedule it.
1682 tcpm_stream_read_cancel(rs);
1684 if (rs->rc->pktlen <= 0) {
1685 auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg);
1686 security_stream_seterror(&rs->secstr, rs->rc->errmsg);
1687 if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
1688 sec_tcp_conn_put(rs->rc);
1689 rs->closed_by_network = 1;
1690 (*rs->fn)(rs->arg, NULL, rs->rc->pktlen);
1693 auth_debug(1, _("sec: stream_read_callback: read %zd bytes from %s:%d\n"),
1694 rs->rc->pktlen, rs->rc->hostname, rs->handle);
1695 (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);
1696 auth_debug(1, _("sec: after callback stream_read_callback\n"));
1700 * The callback for the netfd for the event handler
1701 * Determines if this packet is for this security handle,
1702 * and does the real callback if so.
1705 sec_tcp_conn_read_callback(
1708 struct tcp_conn * rc = cookie;
1709 struct sec_handle * rh;
1714 assert(cookie != NULL);
1716 auth_debug(1, _("sec: conn_read_callback\n"));
1718 /* Read the data off the wire. If we get errors, shut down. */
1719 rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt,
1721 auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"),
1723 if (rval < 0 || rc->handle == H_EOF) {
1726 revent = event_wakeup((event_id_t)rc);
1727 auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"),
1729 /* delete our 'accept' reference */
1730 if (rc->accept_fn != NULL) {
1731 if(rc->refcnt != 1) {
1732 dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"),
1736 rc->accept_fn = NULL;
1737 sec_tcp_conn_put(rc);
1744 revent = event_wakeup((event_id_t)rc);
1746 _("sec: conn_read_callback: event_wakeup return %d\n"), revent);
1750 /* If there are events waiting on this handle, we're done */
1752 revent = event_wakeup((event_id_t)rc);
1753 auth_debug(1, _("sec: conn_read_callback: event_wakeup return %zd\n"), rval);
1755 if (rc->handle == H_TAKEN || rc->pktlen == 0) {
1756 if(rc->refcnt == 0) amfree(rc);
1760 assert(rc->refcnt > 0);
1762 /* If there is no accept fn registered, then drop the packet */
1763 if (rc->accept_fn == NULL)
1766 rh = alloc(SIZEOF(*rh));
1767 security_handleinit(&rh->sech, rc->driver);
1768 rh->hostname = stralloc(rc->hostname);
1769 rh->ev_timeout = NULL;
1771 rh->peer = rc->peer;
1772 rh->rs = tcpma_stream_client(rh, rc->handle);
1774 auth_debug(1, _("sec: new connection\n"));
1776 parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);
1777 auth_debug(1, _("sec: calling accept_fn\n"));
1778 if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)
1779 (*rc->accept_fn)(&rh->sech, NULL);
1781 (*rc->accept_fn)(&rh->sech, &pkt);
1791 const unsigned char *bufp = buf;
1793 auth_debug(1, _("sec: parse_pkt: parsing buffer of %zu bytes\n"), bufsize);
1795 pkt->type = (pktype_t)*bufp++;
1798 pkt->packet_size = bufsize+1;
1799 pkt->body = alloc(pkt->packet_size);
1801 pkt->body[0] = '\0';
1803 memcpy(pkt->body, bufp, bufsize);
1804 pkt->body[pkt->packet_size - 1] = '\0';
1806 pkt->size = strlen(pkt->body);
1808 auth_debug(1, _("sec: parse_pkt: %s (%d): \"%s\"\n"), pkt_type2str(pkt->type),
1809 pkt->type, pkt->body);
1813 * Convert a packet header into a string
1817 const struct sec_handle * rh,
1820 static char retbuf[256];
1823 assert(pkt != NULL);
1825 g_snprintf(retbuf, SIZEOF(retbuf), _("Amanda %d.%d %s HANDLE %s SEQ %d\n"),
1826 VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),
1827 rh->proto_handle, rh->sequence);
1829 auth_debug(1, _("bsd: pkthdr2str handle '%s'\n"), rh->proto_handle);
1831 /* check for truncation. If only we had asprintf()... */
1832 assert(retbuf[strlen(retbuf) - 1] == '\n');
1838 * Parses out the header line in 'str' into the pkt and handle
1839 * Returns negative on parse error.
1851 assert(udp->dgram.cur != NULL);
1852 str = stralloc(udp->dgram.cur);
1854 /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */
1856 /* Read in "Amanda" */
1857 if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)
1860 /* nothing is done with the major/minor numbers currently */
1861 if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)
1864 /* Read in the packet type */
1865 if ((tok = strtok(NULL, " ")) == NULL)
1868 pkt_init_empty(pkt, pkt_str2type(tok));
1869 if (pkt->type == (pktype_t)-1)
1872 /* Read in "HANDLE" */
1873 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)
1876 /* parse the handle */
1877 if ((tok = strtok(NULL, " ")) == NULL)
1879 amfree(udp->handle);
1880 udp->handle = stralloc(tok);
1883 if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)
1886 /* parse the sequence number */
1887 if ((tok = strtok(NULL, "\n")) == NULL)
1889 udp->sequence = atoi(tok);
1891 /* Save the body, if any */
1892 if ((tok = strtok(NULL, "")) != NULL)
1893 pkt_cat(pkt, "%s", tok);
1899 #if 0 /* XXX we have no way of passing this back up */
1900 security_seterror(&rh->sech,
1901 "parse error in packet header : '%s'", origstr);
1909 struct sec_handle * rh,
1910 const char * remoteuser,
1911 const char * service)
1915 char *result = NULL;
1916 char *localuser = NULL;
1918 /* lookup our local user name */
1919 if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {
1920 return vstrallocf(_("getpwnam(%s) failed."), CLIENT_LOGIN);
1924 * Make a copy of the user name in case getpw* is called by
1925 * any of the lower level routines.
1927 localuser = stralloc(pwd->pw_name);
1929 #ifndef USE_AMANDAHOSTS
1930 r = check_user_ruserok(rh->hostname, pwd, remoteuser);
1932 r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service);
1935 result = vstrallocf(
1936 _("user %s from %s is not allowed to execute the service %s: %s"),
1937 remoteuser, rh->hostname, service, r);
1945 * See if a remote user is allowed in. This version uses ruserok()
1948 * Returns NULL on success, or error message on error.
1953 struct passwd * pwd,
1954 const char * remoteuser)
1965 uid_t myuid = getuid();
1968 * note that some versions of ruserok (eg SunOS 3.2) look in
1969 * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to
1970 * chdir ourselves. Sigh.
1972 * And, believe it or not, some ruserok()'s try an initgroup just
1973 * for the hell of it. Since we probably aren't root at this point
1974 * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"
1975 * into our stderr output even though the initgroup failure is not a
1976 * problem and is expected. Thanks a lot. Not.
1978 if (pipe(fd) != 0) {
1979 return stralloc2(_("pipe() fails: "), strerror(errno));
1981 if ((ruserok_pid = fork()) < 0) {
1982 return stralloc2(_("fork() fails: "), strerror(errno));
1983 } else if (ruserok_pid == 0) {
1987 fError = fdopen(fd[1], "w");
1989 error(_("Can't fdopen: %s"), strerror(errno));
1992 /* pamper braindead ruserok's */
1993 if (chdir(pwd->pw_dir) != 0) {
1994 g_fprintf(fError, _("chdir(%s) failed: %s"),
1995 pwd->pw_dir, strerror(errno));
2000 if (debug_auth >= 9) {
2001 char *dir = stralloc(pwd->pw_dir);
2003 auth_debug(9, _("bsd: calling ruserok(%s, %d, %s, %s)\n"), host,
2004 ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name);
2006 auth_debug(9, _("bsd: because you are running as root, "));
2007 auth_debug(9, _("/etc/hosts.equiv will not be used\n"));
2009 show_stat_info("/etc/hosts.equiv", NULL);
2011 show_stat_info(dir, "/.rhosts");
2015 saved_stderr = dup(2);
2017 if (open("/dev/null", O_RDWR) == -1) {
2018 auth_debug(1, _("Could not open /dev/null: %s\n"), strerror(errno));
2021 ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);
2028 (void)dup2(saved_stderr,2);
2029 close(saved_stderr);
2033 fError = fdopen(fd[0], "r");
2035 error(_("Can't fdopen: %s"), strerror(errno));
2040 while ((es = agets(fError)) != NULL) {
2045 if (result == NULL) {
2046 result = stralloc("");
2048 strappend(result, ": ");
2050 strappend(result, es);
2055 pid = wait(&exitcode);
2056 while (pid != ruserok_pid) {
2057 if ((pid == (pid_t) -1) && (errno != EINTR)) {
2059 return vstrallocf(_("ruserok wait failed: %s"), strerror(errno));
2061 pid = wait(&exitcode);
2063 if (!WIFEXITED(exitcode) || WEXITSTATUS(exitcode) != 0) {
2065 result = str_exit_status("ruserok child", exitcode);
2074 * Check to see if a user is allowed in. This version uses .amandahosts
2075 * Returns an error message on failure, or NULL on success.
2078 check_user_amandahosts(
2080 sockaddr_union *addr,
2081 struct passwd * pwd,
2082 const char * remoteuser,
2083 const char * service)
2087 const char *fileuser;
2089 char *result = NULL;
2095 char *aservice = NULL;
2097 char ipstr[INET6_ADDRSTRLEN];
2099 char ipstr[INET_ADDRSTRLEN];
2102 auth_debug(1, _("check_user_amandahosts(host=%s, pwd=%p, "
2103 "remoteuser=%s, service=%s)\n"),
2104 host, pwd, remoteuser, service);
2106 ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
2107 if (debug_auth >= 9) {
2108 show_stat_info(ptmp, "");;
2110 if ((fp = fopen(ptmp, "r")) == NULL) {
2111 result = vstrallocf(_("cannot open %s: %s"), ptmp, strerror(errno));
2117 * Make sure the file is owned by the Amanda user and does not
2118 * have any group/other access allowed.
2120 if (fstat(fileno(fp), &sbuf) != 0) {
2121 result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));
2124 if (sbuf.st_uid != pwd->pw_uid) {
2125 result = vstrallocf(_("%s: owned by id %ld, should be %ld"),
2126 ptmp, (long)sbuf.st_uid, (long)pwd->pw_uid);
2129 if ((sbuf.st_mode & 077) != 0) {
2130 result = vstrallocf(_("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);
2135 * Now, scan the file for the host/user/service.
2138 while ((line = agets(fp)) != NULL) {
2144 auth_debug(9, _("bsd: processing line: <%s>\n"), line);
2145 /* get the host out of the file */
2146 if ((filehost = strtok(line, " \t")) == NULL) {
2151 /* get the username. If no user specified, then use the local user */
2152 if ((fileuser = strtok(NULL, " \t")) == NULL) {
2153 fileuser = pwd->pw_name;
2156 hostmatch = (strcasecmp(filehost, host) == 0);
2157 /* ok if addr=127.0.0.1 and
2158 * either localhost or localhost.domain is in .amandahost */
2160 (strcasecmp(filehost, "localhost")== 0 ||
2161 strcasecmp(filehost, "localhost.localdomain")== 0)) {
2163 if (SU_GET_FAMILY(addr) == (sa_family_t)AF_INET6)
2164 inet_ntop(AF_INET6, &addr->sin6.sin6_addr,
2165 ipstr, sizeof(ipstr));
2168 inet_ntop(AF_INET, &addr->sin.sin_addr,
2169 ipstr, sizeof(ipstr));
2170 if (strcmp(ipstr, "127.0.0.1") == 0 ||
2171 strcmp(ipstr, "::1") == 0)
2174 usermatch = (strcasecmp(fileuser, remoteuser) == 0);
2175 auth_debug(9, _("bsd: comparing \"%s\" with\n"), filehost);
2176 auth_debug(9, _("bsd: \"%s\" (%s)\n"), host,
2177 hostmatch ? _("match") : _("no match"));
2178 auth_debug(9, _("bsd: and \"%s\" with\n"), fileuser);
2179 auth_debug(9, _("bsd: \"%s\" (%s)\n"), remoteuser,
2180 usermatch ? _("match") : _("no match"));
2182 if (!hostmatch || !usermatch) {
2194 /* get the services. If no service specified, then use
2195 * noop/selfcheck/sendsize/sendbackup
2197 aservice = strtok(NULL, " \t,");
2199 if (strcmp(service,"noop") == 0 ||
2200 strcmp(service,"selfcheck") == 0 ||
2201 strcmp(service,"sendsize") == 0 ||
2202 strcmp(service,"sendbackup") == 0) {
2215 if (strcmp(aservice,service) == 0) {
2219 if (strcmp(aservice, "amdump") == 0 &&
2220 (strcmp(service, "noop") == 0 ||
2221 strcmp(service, "selfcheck") == 0 ||
2222 strcmp(service, "sendsize") == 0 ||
2223 strcmp(service, "sendbackup") == 0)) {
2227 } while((aservice = strtok(NULL, " \t,")) != NULL);
2229 if (aservice && strcmp(aservice, service) == 0) {
2238 if (strcmp(service, "amindexd") == 0 ||
2239 strcmp(service, "amidxtaped") == 0) {
2240 result = vstrallocf(_("Please add the line \"%s %s amindexd amidxtaped\" to %s on the client"), host, remoteuser, ptmp);
2241 } else if (strcmp(service, "amdump") == 0 ||
2242 strcmp(service, "noop") == 0 ||
2243 strcmp(service, "selfcheck") == 0 ||
2244 strcmp(service, "sendsize") == 0 ||
2245 strcmp(service, "sendbackup") == 0) {
2246 result = vstrallocf(_("Please add the line \"%s %s amdump\" to %s on the client"), host, remoteuser, ptmp);
2248 result = vstrallocf(_("%s: invalid service %s"), ptmp, service);
2260 /* return 1 on success, 0 on failure */
2263 sockaddr_union *addr,
2265 unsigned long cksum,
2268 char * remotehost = NULL, *remoteuser = NULL;
2269 char * bad_bsd = NULL;
2270 struct passwd * pwptr;
2275 char hostname[NI_MAXHOST];
2279 (void)cksum; /* Quiet unused parameter warning */
2282 _("check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n"),
2283 addr, str, cksum, errstr);
2284 dump_sockaddr(addr);
2288 /* what host is making the request? */
2289 if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr),
2290 hostname, NI_MAXHOST, NULL, 0, 0)) != 0) {
2291 dbprintf(_("getnameinfo failed: %s\n"),
2292 gai_strerror(result));
2293 *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ",
2294 "getnameinfo failed: ", gai_strerror(result),
2298 remotehost = stralloc(hostname);
2299 if( check_name_give_sockaddr(hostname,
2300 (struct sockaddr *)addr, errstr) < 0) {
2306 /* next, make sure the remote port is a "reserved" one */
2307 port = SU_GET_PORT(addr);
2308 if (port >= IPPORT_RESERVED) {
2309 *errstr = vstrallocf(_("[host %s: port %u not secure]"),
2310 remotehost, (unsigned int)port);
2315 /* extract the remote user name from the message */
2320 bad_bsd = vstrallocf(_("[host %s: bad bsd security line]"), remotehost);
2322 if (strncmp_const_skip(s - 1, "USER ", s, ch) != 0) {
2329 skip_whitespace(s, ch);
2337 skip_non_whitespace(s, ch);
2339 remoteuser = stralloc(fp);
2343 /* lookup our local user name */
2346 if ((pwptr = getpwuid(myuid)) == NULL)
2347 error(_("error [getpwuid(%d) fails]"), (int)myuid);
2349 auth_debug(1, _("bsd security: remote host %s user %s local user %s\n"),
2350 remotehost, remoteuser, pwptr->pw_name);
2352 #ifndef USE_AMANDAHOSTS
2353 s = check_user_ruserok(remotehost, pwptr, remoteuser);
2355 s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL);
2359 *errstr = vstrallocf(_("[access as %s not allowed from %s@%s: %s]"),
2360 pwptr->pw_name, remoteuser, remotehost, s);
2365 return *errstr == NULL;
2369 * Writes out the entire iovec
2377 ssize_t delta, n, total;
2379 assert(iov != NULL);
2382 while (iovcnt > 0) {
2386 n = writev(fd, iov, iovcnt);
2390 auth_debug(1, _("net_writev got EINTR\n"));
2398 * Iterate through each iov. Figure out what we still need
2401 for (; n > 0; iovcnt--, iov++) {
2402 /* 'delta' is the bytes written from this iovec */
2403 delta = ((size_t)n < (size_t)iov->iov_len) ? n : (ssize_t)iov->iov_len;
2404 /* subtract from the total num bytes written */
2407 /* subtract from this iovec */
2408 iov->iov_len -= delta;
2409 iov->iov_base = (char *)iov->iov_base + delta;
2410 /* if this iovec isn't empty, run the writev again */
2411 if (iov->iov_len > 0)
2420 * Like read(), but waits until the entire buffer has been filled.
2429 char *buf = vbuf; /* ptr arith */
2431 size_t size = origsize;
2433 auth_debug(1, _("net_read: begin %zu\n"), origsize);
2436 auth_debug(1, _("net_read: while %zu\n"), size);
2437 nread = net_read_fillbuf(fd, timeout, buf, size);
2439 auth_debug(1, _("db: net_read: end return(-1)\n"));
2443 auth_debug(1, _("net_read: end return(0)\n"));
2449 auth_debug(1, _("net_read: end %zu\n"), origsize);
2450 return ((ssize_t)origsize);
2454 * net_read likes to do a lot of little reads. Buffer it.
2463 SELECT_ARG_TYPE readfds;
2467 auth_debug(1, _("net_read_fillbuf: begin\n"));
2469 FD_SET(fd, &readfds);
2470 tv.tv_sec = timeout;
2472 switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {
2477 auth_debug(1, _("net_read_fillbuf: case -1\n"));
2480 auth_debug(1, _("net_read_fillbuf: case 1\n"));
2481 assert(FD_ISSET(fd, &readfds));
2484 auth_debug(1, _("net_read_fillbuf: case default\n"));
2488 nread = read(fd, buf, size);
2491 auth_debug(1, _("net_read_fillbuf: end %zd\n"), nread);
2497 * Display stat() information about a file.
2505 char *name = vstralloc(a, b, NULL);
2507 struct passwd *pwptr G_GNUC_UNUSED;
2508 struct passwd pw G_GNUC_UNUSED;
2510 struct group *grptr G_GNUC_UNUSED;
2511 struct group gr G_GNUC_UNUSED;
2513 int buflen G_GNUC_UNUSED;
2514 char *buf G_GNUC_UNUSED;
2516 if (stat(name, &sbuf) != 0) {
2517 auth_debug(1, _("bsd: cannot stat %s: %s\n"), name, strerror(errno));
2522 #ifdef _SC_GETPW_R_SIZE_MAX
2523 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
2529 buf = malloc(buflen);
2531 #ifdef HAVE_GETPWUID_R
2532 if (getpwuid_r(sbuf.st_uid, &pw, buf, buflen, &pwptr) == 0 &&
2534 owner = stralloc(pwptr->pw_name);
2538 owner = alloc(NUM_STR_SIZE + 1);
2539 g_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);
2541 #ifdef HAVE_GETGRGID_R
2542 if (getgrgid_r(sbuf.st_gid, &gr, buf, buflen, &grptr) == 0 &&
2544 group = stralloc(grptr->gr_name);
2548 group = alloc(NUM_STR_SIZE + 1);
2549 g_snprintf(group, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);
2552 auth_debug(1, _("bsd: processing file: %s\n"), name);
2553 auth_debug(1, _("bsd: owner=%s group=%s mode=%03o\n"),
2555 (int) (sbuf.st_mode & 0777));
2563 check_name_give_sockaddr(
2564 const char *hostname,
2565 struct sockaddr *addr,
2569 struct addrinfo *res = NULL, *res1;
2572 result = resolve_hostname(hostname, 0, &res, &canonname);
2574 dbprintf(_("check_name_give_sockaddr: resolve_hostname('%s'): %s\n"), hostname, gai_strerror(result));
2575 *errstr = newvstrallocf(*errstr,
2576 _("check_name_give_sockaddr: resolve_hostname('%s'): %s"),
2577 hostname, gai_strerror(result));
2580 if (canonname == NULL) {
2581 dbprintf(_("resolve_hostname('%s') did not return a canonical name\n"), hostname);
2582 *errstr = newvstrallocf(*errstr,
2583 _("check_name_give_sockaddr: resolve_hostname('%s') did not return a canonical name"),
2588 if (strncasecmp(hostname, canonname, strlen(hostname)) != 0) {
2589 dbprintf(_("%s doesn't resolve to itself, it resolves to %s\n"),
2590 hostname, canonname);
2591 *errstr = newvstrallocf(*errstr,
2592 _("%s doesn't resolve to itself, it resolves to %s"),
2593 hostname, canonname);
2597 for(res1=res; res1 != NULL; res1 = res1->ai_next) {
2598 if (cmp_sockaddr((sockaddr_union *)res1->ai_addr, (sockaddr_union *)addr, 1) == 0) {
2605 dbprintf(_("%s doesn't resolve to %s"),
2606 hostname, str_sockaddr((sockaddr_union *)addr));
2607 *errstr = newvstrallocf(*errstr,
2608 "%s doesn't resolve to %s",
2609 hostname, str_sockaddr((sockaddr_union *)addr));
2611 if (res) freeaddrinfo(res);