usr/src/cmd/rad/mod/xport_unix/mod_xport_unix.c
changeset 862 f20f2afa6263
parent 861 98a84e2ccca6
child 863 83ff534df225
--- a/usr/src/cmd/rad/mod/xport_unix/mod_xport_unix.c	Fri May 18 01:37:59 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <bsm/adt_event.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <ucred.h>
-#include <zone.h>
-
-#include <rad/adr_stream.h>
-#include "rad_object.h"
-#include "rad_modapi.h"
-#include "rad_modapi_xport.h"
-#include "rad_connection.h"
-#include "rad_xport.h"
-
-#include "api_unix.h"
-
-static char *pam_service = "rad-unix";
-
-static boolean_t
-sockaddr_init(struct sockaddr_un *addr, const char *name)
-{
-	size_t namelen;
-	size_t addrlen;
-
-	(void) memset(addr, 0, sizeof (*addr));
-	addr->sun_family = AF_UNIX;
-
-	namelen = strlen(name);
-	addrlen = sizeof (addr->sun_path);
-
-	if (namelen >= addrlen)
-		return (B_FALSE);
-
-	(void) strlcpy(addr->sun_path, name, sizeof (addr->sun_path));
-	return (B_TRUE);
-}
-
-static int
-create_tmpdir(const char *name)
-{
-	int retval = 0;
-	struct stat st;
-	mode_t um;
-
-	int i = strncmp(name, RAD_TMPDIR "/", strlen(RAD_TMPDIR "/"));
-
-	if (i == 0) {	/* Default path specified */
-		if (stat(RAD_TMPDIR, &st) == 0) {
-			if (!S_ISDIR(st.st_mode)) {
-				rad_log(RL_ERROR, "file '%s' exists.",
-				    RAD_TMPDIR);
-				retval = -1;
-			}
-		} else if (errno == ENOENT) { /* Create it */
-			um = umask(0);
-			i = mkdir(RAD_TMPDIR, S_IRWXU | S_IRWXG | S_IRWXO);
-			(void) umask(um);
-			if (i != 0) {
-				rad_log(RL_ERROR, "error creating '%s': %s."
-				    RAD_TMPDIR, strerror(errno));
-				retval = -1;
-			}
-		} else {
-			rad_log(RL_ERROR, "error creating '%s': %s."
-			    RAD_TMPDIR, strerror(errno));
-			retval = -1;
-		}
-	}
-	return (retval);
-}
-
-static int
-listen_on_name(const char *name)
-{
-	int fd;
-	struct sockaddr_un addr;
-
-	if (create_tmpdir(name) != 0)
-		return (-1);
-
-	if (unlink(name) == -1 && errno != ENOENT) {
-		rad_log(RL_ERROR, "unlink of '%s' failed: %s", name,
-		    strerror(errno));
-		return (-1);
-	}
-
-	if (!sockaddr_init(&addr, name)) {
-		rad_log(RL_ERROR, "socket name '%s' too long", name);
-		return (-1);
-	}
-
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-		rad_log(RL_ERROR, "socket failed: %s", strerror(errno));
-		return (-1);
-	}
-
-	if (bind(fd, (struct sockaddr *)&addr, sizeof (addr)) == -1) {
-		rad_log(RL_ERROR, "bind to '%s' failed: %s", name,
-		    strerror(errno));
-		(void) close(fd);
-		return (-1);
-	}
-
-	if (listen(fd, 15) == -1) {
-		rad_log(RL_ERROR, "listen on '%s' failed: %s", name,
-		    strerror(errno));
-		return (-1);
-	}
-
-	return (fd);
-}
-
-/*
- * Determines if the ucred represents someone who is effectively us.
- */
-static boolean_t
-sent_by_joe(ucred_t *uc)
-{
-	const priv_set_t *theirprivs;
-	priv_set_t *myprivs = priv_allocset();
-	if (myprivs == NULL) {
-		rad_log(RL_ERROR, "failed to allocate privilege set");
-		return (B_FALSE);
-	}
-
-	/* Could handle this "gracefully", but it isn't supposed to fail */
-	if (getppriv(PRIV_PERMITTED, myprivs) == -1)
-		rad_log(RL_FATAL, "getppriv(PRIV_PERMITTED) failed: %s",
-		    strerror(errno));
-
-	if (uc == NULL ||
-	    ucred_geteuid(uc) != getuid() ||
-	    ucred_getzoneid(uc) != getzoneid() ||
-	    (theirprivs = ucred_getprivset(uc, PRIV_EFFECTIVE)) == NULL ||
-	    !priv_issubset(myprivs, theirprivs)) {
-		priv_freeset(myprivs);
-		rad_log(RL_WARN, "unprivileged client (uid=%d) "
-		    "attempted connection to control port", ucred_geteuid(uc));
-		return (B_FALSE);
-	}
-
-	priv_freeset(myprivs);
-	return (B_TRUE);
-}
-
-static void
-unix_run(void *arg)
-{
-	radmod_connection_t *conn = arg;
-	rad_proto_handle(conn);
-	rad_conn_free(conn);
-}
-
-static rad_moderr_t
-unix_listen(rad_thread_t *arg)
-{
-	data_t *data = rad_thread_arg(arg);
-	int fd;
-	data_t *d, *path = struct_get(data, "path");
-	d = struct_get(data, "proto");
-	const char *protostr = d != NULL ? data_to_string(d) : "rad";
-	d = struct_get(data, "control");
-	boolean_t control = d != NULL ? data_to_boolean(d) : B_FALSE;
-	d = struct_get(data, "peercred");
-	boolean_t peercred = d != NULL ? data_to_boolean(d) : B_TRUE;
-	d = struct_get(data, "pam_service");
-	if (d != NULL) {
-		pam_service = (char *)data_to_string(d);
-	}
-
-	rad_protocol_t *proto = rad_proto_find(protostr);
-	if (proto == NULL) {
-		rad_log(RL_ERROR, "Unable to find protocol \"%s\".", protostr);
-		return (rm_config);
-	}
-
-	if ((fd = listen_on_name(data_to_string(path))) < 0) {
-		rad_log(RL_ERROR, "Error starting AF_UNIX server: %s",
-		    strerror(errno));
-		return (rm_system);
-	}
-
-	rad_thread_ack(arg, rm_ok);
-	for (;;) {
-		int afd;
-
-		rad_log(RL_DEBUG, "Waiting for connection.\n");
-		if ((afd = accept(fd, 0, 0)) == -1) {
-			rad_log(RL_WARN, "Error in accept(): %s\n",
-			    strerror(errno));
-			continue;
-		}
-		rad_log(RL_DEBUG, "Connection accepted.\n");
-
-		/* subject allocation failure and missing ucred are conflated */
-		rad_subject_t *subject = peercred ?
-		    rad_subject_create_fd(afd, pam_service) : NULL;
-
-		if (control) {
-			if (subject == NULL) {
-				(void) close(afd);
-				continue;
-			}
-
-			if (!sent_by_joe(subject->rs_ucred)) {
-				rad_subject_unref(subject);
-				(void) close(afd);
-				continue;
-			}
-			rad_log(RL_DEBUG,
-			    "accepting connection on control port");
-			subject->rs_control = B_TRUE;
-		}
-
-		adr_stream_t *stream = adr_stream_create_fd(afd);
-		if (stream == NULL)
-			continue;
-
-		radmod_connection_t *conn = rad_conn_create_fd(afd, B_TRUE);
-		if (conn == NULL) {
-			adr_stream_close(stream);
-			adr_stream_free(stream);
-			rad_log(RL_WARN, "failed to allocate connection");
-			continue;
-		}
-		conn->rm_conn_xport = stream;
-		conn->rm_conn_proto_ops = proto;
-		conn->rm_conn_pam_service = pam_service;
-
-		if (subject != NULL &&
-		    !rad_conn_setsubject(conn, subject)) {
-			rad_conn_close(conn);
-			rad_conn_free(conn);
-			rad_log(RL_WARN, "failed to set connection subject");
-			continue;
-		}
-
-		if (rad_thread_create_async(unix_run, conn) != rm_ok) {
-			rad_conn_close(conn);
-			rad_conn_free(conn);
-		}
-	}
-}
-
-static rad_moderr_t
-starter(data_t *data)
-{
-	data_t *path = struct_get(data, "path");
-
-	if (path == NULL) {
-		rad_log(RL_ERROR, "Unix domain socket requires path\n");
-		return (rm_config);
-	}
-
-	return (rad_thread_create(unix_listen, data));
-}
-
-static rad_modinfo_t modinfo = {
-	"xport_unix", "unix domain socket transport module",
-};
-
-int
-_rad_init(void *handle)
-{
-	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
-		return (-1);
-
-	rad_xport_register("unix", &t__unix, starter);
-	return (0);
-}