xref: /illumos-gate/usr/src/cmd/vntsd/auth.c (revision bbf21555)
128b1e50eSSriharsha Basavapatna /*
228b1e50eSSriharsha Basavapatna  * CDDL HEADER START
328b1e50eSSriharsha Basavapatna  *
428b1e50eSSriharsha Basavapatna  * The contents of this file are subject to the terms of the
528b1e50eSSriharsha Basavapatna  * Common Development and Distribution License (the "License").
628b1e50eSSriharsha Basavapatna  * You may not use this file except in compliance with the License.
728b1e50eSSriharsha Basavapatna  *
828b1e50eSSriharsha Basavapatna  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
928b1e50eSSriharsha Basavapatna  * or http://www.opensolaris.org/os/licensing.
1028b1e50eSSriharsha Basavapatna  * See the License for the specific language governing permissions
1128b1e50eSSriharsha Basavapatna  * and limitations under the License.
1228b1e50eSSriharsha Basavapatna  *
1328b1e50eSSriharsha Basavapatna  * When distributing Covered Code, include this CDDL HEADER in each
1428b1e50eSSriharsha Basavapatna  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1528b1e50eSSriharsha Basavapatna  * If applicable, add the following below this CDDL HEADER, with the
1628b1e50eSSriharsha Basavapatna  * fields enclosed by brackets "[]" replaced with your own identifying
1728b1e50eSSriharsha Basavapatna  * information: Portions Copyright [yyyy] [name of copyright owner]
1828b1e50eSSriharsha Basavapatna  *
1928b1e50eSSriharsha Basavapatna  * CDDL HEADER END
2028b1e50eSSriharsha Basavapatna  */
2128b1e50eSSriharsha Basavapatna 
2228b1e50eSSriharsha Basavapatna /*
2328b1e50eSSriharsha Basavapatna  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2428b1e50eSSriharsha Basavapatna  * Use is subject to license terms.
2528b1e50eSSriharsha Basavapatna  */
2628b1e50eSSriharsha Basavapatna 
2728b1e50eSSriharsha Basavapatna /*
2828b1e50eSSriharsha Basavapatna  * Authorization checking:
2928b1e50eSSriharsha Basavapatna  *
3028b1e50eSSriharsha Basavapatna  * These functions check 'vntsd' authorization to access guest consoles.
3128b1e50eSSriharsha Basavapatna  * The mechanism used is Solaris authorizations. The local client (telnet)
3228b1e50eSSriharsha Basavapatna  * process requesting the connection to a console is verified to have the
3328b1e50eSSriharsha Basavapatna  * required authorization.
3428b1e50eSSriharsha Basavapatna  *
3528b1e50eSSriharsha Basavapatna  * Authorizations available are to access the console of any/all guests or to
3628b1e50eSSriharsha Basavapatna  * access the consoles of a specific console group. A client connecting to the
3728b1e50eSSriharsha Basavapatna  * console through telnet must have the appropriate authorization from file
3828b1e50eSSriharsha Basavapatna  * /etc/security/auth_attr.
3928b1e50eSSriharsha Basavapatna  *
4028b1e50eSSriharsha Basavapatna  * The all-consoles authorization is added during vntsd installation:
4128b1e50eSSriharsha Basavapatna  * solaris.vntsd.consoles:::Access All LDoms Guest Consoles::
4228b1e50eSSriharsha Basavapatna  *
4328b1e50eSSriharsha Basavapatna  * Example of a specific console group authorization based on the name of the
4428b1e50eSSriharsha Basavapatna  * console group (added manually by a user with 'vntsd.grant' authorization,
4528b1e50eSSriharsha Basavapatna  * such as 'root'); the group name in this example is "ldg1" :
4628b1e50eSSriharsha Basavapatna  * solaris.vntsd.console-ldg1:::Access Specific LDoms Guest Console::
4728b1e50eSSriharsha Basavapatna  *
48*bbf21555SRichard Lowe  * Specific users are authorized with usermod(8). To add an authorization
4928b1e50eSSriharsha Basavapatna  * (to /etc/user_attr) type a command similar to this (when user NOT
5028b1e50eSSriharsha Basavapatna  * logged in):
5128b1e50eSSriharsha Basavapatna  *
5228b1e50eSSriharsha Basavapatna  *    To authorize a user 'user1' to access all guest consoles:
5328b1e50eSSriharsha Basavapatna  *    # usermod -A solaris.vntsd.consoles user1
5428b1e50eSSriharsha Basavapatna  *
5528b1e50eSSriharsha Basavapatna  */
5628b1e50eSSriharsha Basavapatna 
5728b1e50eSSriharsha Basavapatna #include <sys/types.h>		/* uid_t */
5828b1e50eSSriharsha Basavapatna #include <sys/param.h>		/* MAXNAMELEN */
5928b1e50eSSriharsha Basavapatna #include <pwd.h>		/* getpw*() */
6028b1e50eSSriharsha Basavapatna #include <auth_attr.h>		/* chkauthattr() */
6128b1e50eSSriharsha Basavapatna #include <secdb.h>		/* chkauthattr() */
6228b1e50eSSriharsha Basavapatna #include <ucred.h>		/* getpeerucred() */
6328b1e50eSSriharsha Basavapatna #include <errno.h>		/* errno */
6428b1e50eSSriharsha Basavapatna 
6528b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_ALLCONS	"solaris.vntsd.consoles" /* all-consoles auth */
6628b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_GRPCONS	"solaris.vntsd.console-" /* cons-group auth */
6728b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_PREFIXLEN	32			 /* max len of prefix */
6828b1e50eSSriharsha Basavapatna 
6928b1e50eSSriharsha Basavapatna /*
7028b1e50eSSriharsha Basavapatna  * socket_peer_euid()
7128b1e50eSSriharsha Basavapatna  *
7228b1e50eSSriharsha Basavapatna  * Return the effective UID (EUID) of the socket peer.
7328b1e50eSSriharsha Basavapatna  * If none, return -1.
7428b1e50eSSriharsha Basavapatna  *
7528b1e50eSSriharsha Basavapatna  * Parameters:
7628b1e50eSSriharsha Basavapatna  * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
7728b1e50eSSriharsha Basavapatna  *
7828b1e50eSSriharsha Basavapatna  * Returns:
7928b1e50eSSriharsha Basavapatna  * EUID if OK
8028b1e50eSSriharsha Basavapatna  * -1 on failure or unknown EUID (passed on from ucred_geteuid()).
8128b1e50eSSriharsha Basavapatna  */
8228b1e50eSSriharsha Basavapatna static uid_t
socket_peer_euid(int sock_fd)8328b1e50eSSriharsha Basavapatna socket_peer_euid(int sock_fd)
8428b1e50eSSriharsha Basavapatna {
8528b1e50eSSriharsha Basavapatna 	int		rc;
8628b1e50eSSriharsha Basavapatna 	uid_t		peer_euid;
8728b1e50eSSriharsha Basavapatna 	ucred_t		*ucredp = NULL;
8828b1e50eSSriharsha Basavapatna 
8928b1e50eSSriharsha Basavapatna 	/* Get info on the peer on the other side of the socket */
9028b1e50eSSriharsha Basavapatna 	rc = getpeerucred(sock_fd, &ucredp);
9128b1e50eSSriharsha Basavapatna 	if (rc == -1) {
9228b1e50eSSriharsha Basavapatna 		/* If errno is EINVAL, it's probably a non-local socket peer */
9328b1e50eSSriharsha Basavapatna 		return ((uid_t)-1);
9428b1e50eSSriharsha Basavapatna 	}
9528b1e50eSSriharsha Basavapatna 
9628b1e50eSSriharsha Basavapatna 	/* Extract effective UID (EUID) info for the socket peer process */
9728b1e50eSSriharsha Basavapatna 	peer_euid = ucred_geteuid(ucredp);
9828b1e50eSSriharsha Basavapatna 	ucred_free(ucredp);
9928b1e50eSSriharsha Basavapatna 
10028b1e50eSSriharsha Basavapatna 	/* Return EUID */
10128b1e50eSSriharsha Basavapatna 	return (peer_euid);
10228b1e50eSSriharsha Basavapatna }
10328b1e50eSSriharsha Basavapatna 
10428b1e50eSSriharsha Basavapatna /*
10528b1e50eSSriharsha Basavapatna  * auth_check_username()
10628b1e50eSSriharsha Basavapatna  *
10728b1e50eSSriharsha Basavapatna  * Check vntsd console authorization, given a user account.
10828b1e50eSSriharsha Basavapatna  *
10928b1e50eSSriharsha Basavapatna  * Parameters:
11028b1e50eSSriharsha Basavapatna  * username	The name of a user account to check authorization
11128b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization. The max
11228b1e50eSSriharsha Basavapatna  *              length of group name is MAXPATHLEN.
11328b1e50eSSriharsha Basavapatna  *
11428b1e50eSSriharsha Basavapatna  * Returns:
11528b1e50eSSriharsha Basavapatna  * 0 if OK (authorized), 1 on authorization failure.
11628b1e50eSSriharsha Basavapatna  */
11728b1e50eSSriharsha Basavapatna static int
auth_check_username(char * username,char * group_name)11828b1e50eSSriharsha Basavapatna auth_check_username(char *username, char *group_name)
11928b1e50eSSriharsha Basavapatna {
12028b1e50eSSriharsha Basavapatna 	int	auth_granted = 0;
12128b1e50eSSriharsha Basavapatna 	char	authname[VNTSD_AUTH_PREFIXLEN + MAXPATHLEN];
12228b1e50eSSriharsha Basavapatna 	size_t	len = VNTSD_AUTH_PREFIXLEN + MAXPATHLEN;
12328b1e50eSSriharsha Basavapatna 
12428b1e50eSSriharsha Basavapatna 	/* Sanity check: */
12528b1e50eSSriharsha Basavapatna 	if ((username == NULL) || (username[0] == '\0') ||
12628b1e50eSSriharsha Basavapatna 	    (group_name == NULL) || (group_name[0] == '\0')) {
12728b1e50eSSriharsha Basavapatna 		return (1); /* error (bad parameter) */
12828b1e50eSSriharsha Basavapatna 	}
12928b1e50eSSriharsha Basavapatna 
13028b1e50eSSriharsha Basavapatna 	(void) snprintf(authname, len, VNTSD_AUTH_GRPCONS"%s", group_name);
13128b1e50eSSriharsha Basavapatna 
13228b1e50eSSriharsha Basavapatna 	/*
13328b1e50eSSriharsha Basavapatna 	 * Do authorization checking.
13428b1e50eSSriharsha Basavapatna 	 * First, check if the user is authorized access to all consoles. If it
13528b1e50eSSriharsha Basavapatna 	 * fails, check authorization to the specific console group.
13628b1e50eSSriharsha Basavapatna 	 */
13728b1e50eSSriharsha Basavapatna 	auth_granted = chkauthattr(VNTSD_AUTH_ALLCONS, username);
13828b1e50eSSriharsha Basavapatna 	if (auth_granted)
13928b1e50eSSriharsha Basavapatna 		return (0);
14028b1e50eSSriharsha Basavapatna 
14128b1e50eSSriharsha Basavapatna 	auth_granted = chkauthattr(authname, username);
14228b1e50eSSriharsha Basavapatna 	if (auth_granted)
14328b1e50eSSriharsha Basavapatna 		return (0);
14428b1e50eSSriharsha Basavapatna 
14528b1e50eSSriharsha Basavapatna 	return (1);
14628b1e50eSSriharsha Basavapatna }
14728b1e50eSSriharsha Basavapatna 
14828b1e50eSSriharsha Basavapatna /*
14928b1e50eSSriharsha Basavapatna  * auth_check_euid()
15028b1e50eSSriharsha Basavapatna  *
15128b1e50eSSriharsha Basavapatna  * Check vntsd console authorization, given a EUID.
15228b1e50eSSriharsha Basavapatna  *
15328b1e50eSSriharsha Basavapatna  * Parameters:
15428b1e50eSSriharsha Basavapatna  * euid		The effective UID of a user account to check authorization
15528b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization
15628b1e50eSSriharsha Basavapatna  *
15728b1e50eSSriharsha Basavapatna  * Returns:
15828b1e50eSSriharsha Basavapatna  * 0 if OK (authorized), 1 on authorization failure.
15928b1e50eSSriharsha Basavapatna  */
16028b1e50eSSriharsha Basavapatna static int
auth_check_euid(uid_t euid,char * group_name)16128b1e50eSSriharsha Basavapatna auth_check_euid(uid_t euid, char *group_name)
16228b1e50eSSriharsha Basavapatna {
16328b1e50eSSriharsha Basavapatna 	struct passwd	*passwdp = NULL;
16428b1e50eSSriharsha Basavapatna 	char		*username = NULL;
16528b1e50eSSriharsha Basavapatna 
16628b1e50eSSriharsha Basavapatna 	/* If EUID is -1, then it's unknown, so fail */
16728b1e50eSSriharsha Basavapatna 	if (euid == (uid_t)-1) {
16828b1e50eSSriharsha Basavapatna 		return (1);
16928b1e50eSSriharsha Basavapatna 	}
17028b1e50eSSriharsha Basavapatna 
17128b1e50eSSriharsha Basavapatna 	/* Map EUID to user name */
17228b1e50eSSriharsha Basavapatna 	passwdp = getpwuid(euid);
17328b1e50eSSriharsha Basavapatna 	if (passwdp == NULL) { /* lookup failed */
17428b1e50eSSriharsha Basavapatna 		return (1);
17528b1e50eSSriharsha Basavapatna 	}
17628b1e50eSSriharsha Basavapatna 	username = passwdp->pw_name;
17728b1e50eSSriharsha Basavapatna 
17828b1e50eSSriharsha Basavapatna 	/* Do authorization check: */
17928b1e50eSSriharsha Basavapatna 	return (auth_check_username(username, group_name));
18028b1e50eSSriharsha Basavapatna }
18128b1e50eSSriharsha Basavapatna 
18228b1e50eSSriharsha Basavapatna /*
18328b1e50eSSriharsha Basavapatna  * auth_check_fd()
18428b1e50eSSriharsha Basavapatna  *
18528b1e50eSSriharsha Basavapatna  * Check vntsd authorization, given a fd of a socket. The socket fd is mapped
18628b1e50eSSriharsha Basavapatna  * to a pid (and should not be used for remote connections).
18728b1e50eSSriharsha Basavapatna  *
18828b1e50eSSriharsha Basavapatna  * Parameters:
18928b1e50eSSriharsha Basavapatna  * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
19028b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization
19128b1e50eSSriharsha Basavapatna  *
19228b1e50eSSriharsha Basavapatna  * Returns:
19328b1e50eSSriharsha Basavapatna  * B_TRUE if OK (authorized), B_FALSE on authorization failure.
19428b1e50eSSriharsha Basavapatna  */
19528b1e50eSSriharsha Basavapatna boolean_t
auth_check_fd(int sock_fd,char * group_name)19628b1e50eSSriharsha Basavapatna auth_check_fd(int sock_fd, char *group_name)
19728b1e50eSSriharsha Basavapatna {
19828b1e50eSSriharsha Basavapatna 	uid_t	peer_euid;
19928b1e50eSSriharsha Basavapatna 	int	rv;
20028b1e50eSSriharsha Basavapatna 
20128b1e50eSSriharsha Basavapatna 	peer_euid = socket_peer_euid(sock_fd);
20228b1e50eSSriharsha Basavapatna 	if (peer_euid == (uid_t)-1) { /* unknown EUID */
20328b1e50eSSriharsha Basavapatna 		return (B_FALSE);
20428b1e50eSSriharsha Basavapatna 	}
20528b1e50eSSriharsha Basavapatna 
20628b1e50eSSriharsha Basavapatna 	/* Do authorization check: */
20728b1e50eSSriharsha Basavapatna 	rv = auth_check_euid(peer_euid, group_name);
20828b1e50eSSriharsha Basavapatna 	if (rv != 0) {
20928b1e50eSSriharsha Basavapatna 		return (B_FALSE);
21028b1e50eSSriharsha Basavapatna 	}
21128b1e50eSSriharsha Basavapatna 	return (B_TRUE);
21228b1e50eSSriharsha Basavapatna }