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: local-security.c 6512 2007-05-24 17:00:24Z ian $
30 * local-security.c - security and transport over local or a local-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 local might want to spew out.
42 #include "security-util.h"
46 * Number of seconds amandad has to start up
48 #define CONNECT_TIMEOUT 20
53 static void local_connect(const char *, char *(*)(char *, void *),
54 void (*)(void *, security_handle_t *, security_status_t),
58 * This is our interface to the outside world.
60 const security_driver_t local_security_driver = {
64 sec_get_authenticated_peer_name_gethostname,
68 stream_recvpkt_cancel,
77 tcpm_stream_read_sync,
78 tcpm_stream_read_cancel,
79 tcpm_close_connection,
84 static int newhandle = 1;
89 static int runlocal(struct tcp_conn *, const char *, const char *);
93 * local version of a security handle allocator. Logically sets
94 * up a network "connection".
98 const char * hostname,
99 char * (*conf_fn)(char *, void *),
100 void (*fn)(void *, security_handle_t *, security_status_t),
104 struct sec_handle *rh;
105 char *amandad_path=NULL;
106 char *client_username=NULL;
107 char myhostname[MAX_HOSTNAME_LENGTH+1];
110 assert(hostname != NULL);
112 auth_debug(1, _("local: local_connect: %s\n"), hostname);
114 rh = g_new0(struct sec_handle, 1);
115 security_handleinit(&rh->sech, &local_security_driver);
118 rh->ev_timeout = NULL;
121 if (gethostname(myhostname, MAX_HOSTNAME_LENGTH) == -1) {
122 security_seterror(&rh->sech, _("gethostname failed"));
123 (*fn)(arg, &rh->sech, S_ERROR);
126 myhostname[SIZEOF(myhostname)-1] = '\0';
128 if (strcmp(hostname, myhostname) != 0 &&
129 match("^localhost(\\.localdomain)?$", hostname) == 0) {
130 security_seterror(&rh->sech,
131 _("%s: is not local"), hostname);
132 (*fn)(arg, &rh->sech, S_ERROR);
135 rh->hostname = stralloc(hostname);
136 rh->rs = tcpma_stream_client(rh, newhandle++);
141 amfree(rh->hostname);
142 rh->hostname = stralloc(rh->rs->rc->hostname);
145 * We need to open a new connection.
147 * XXX need to eventually limit number of outgoing connections here.
150 amandad_path = conf_fn("amandad_path", datap);
151 client_username = conf_fn("client_username", datap);
153 if(rh->rc->read == -1) {
154 if (runlocal(rh->rs->rc, amandad_path, client_username) < 0) {
155 security_seterror(&rh->sech, _("can't connect to %s: %s"),
156 hostname, rh->rs->rc->errmsg);
163 * The socket will be opened async so hosts that are down won't
164 * block everything. We need to register a write event
165 * so we will know when the socket comes alive.
167 * Overload rh->rs->ev_read to provide a write event handle.
168 * We also register a timeout.
172 rh->rs->ev_read = event_register((event_id_t)rh->rs->rc->write, EV_WRITEFD,
173 sec_connect_callback, rh);
174 rh->ev_timeout = event_register((event_id_t)CONNECT_TIMEOUT, EV_TIME,
175 sec_connect_timeout, rh);
180 (*fn)(arg, &rh->sech, S_ERROR);
181 amfree(rh->hostname);
185 * Forks a local to the host listed in rc->hostname
186 * Returns negative on error, with an errmsg in rc->errmsg.
190 struct tcp_conn * rc,
191 const char * amandad_path,
192 const char * client_username G_GNUC_UNUSED)
194 int rpipe[2], wpipe[2];
195 char *xamandad_path = (char *)amandad_path;
197 #ifndef SINGLE_USERID
198 struct passwd *pwd = NULL;
203 if (client_username && strlen(client_username) > 1) {
204 pwd = getpwnam(client_username);
206 dbprintf("User '%s' doesn't exist\n", client_username);
213 uid = get_client_uid();
214 gid = get_client_gid();
219 memset(rpipe, -1, SIZEOF(rpipe));
220 memset(wpipe, -1, SIZEOF(wpipe));
221 if (pipe(rpipe) < 0 || pipe(wpipe) < 0) {
222 rc->errmsg = newvstrallocf(rc->errmsg, _("pipe: %s"), strerror(errno));
226 switch (rc->pid = fork()) {
228 rc->errmsg = newvstrallocf(rc->errmsg, _("fork: %s"), strerror(errno));
241 rc->write = wpipe[1];
246 /* drop root privs for good */
249 if(!xamandad_path || strlen(xamandad_path) <= 1)
250 xamandad_path = vstralloc(amlibexecdir, "/", "amandad", NULL);
252 #ifndef SINGLE_USERID
253 if (client_username && *client_username != '\0') {
254 initgroups(client_username, gid);
256 initgroups(CLIENT_LOGIN, gid);
266 execlp(xamandad_path, xamandad_path,
267 "-auth=local", (char *)NULL);
268 error(_("error: couldn't exec %s: %s"), xamandad_path, strerror(errno));
270 /* should never go here, shut up compiler warning */