xref: /titanic_44/usr/src/cmd/vntsd/auth.c (revision 28b1e50e4eed7be353f9778497714aab53ef2a0d)
1*28b1e50eSSriharsha Basavapatna /*
2*28b1e50eSSriharsha Basavapatna  * CDDL HEADER START
3*28b1e50eSSriharsha Basavapatna  *
4*28b1e50eSSriharsha Basavapatna  * The contents of this file are subject to the terms of the
5*28b1e50eSSriharsha Basavapatna  * Common Development and Distribution License (the "License").
6*28b1e50eSSriharsha Basavapatna  * You may not use this file except in compliance with the License.
7*28b1e50eSSriharsha Basavapatna  *
8*28b1e50eSSriharsha Basavapatna  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*28b1e50eSSriharsha Basavapatna  * or http://www.opensolaris.org/os/licensing.
10*28b1e50eSSriharsha Basavapatna  * See the License for the specific language governing permissions
11*28b1e50eSSriharsha Basavapatna  * and limitations under the License.
12*28b1e50eSSriharsha Basavapatna  *
13*28b1e50eSSriharsha Basavapatna  * When distributing Covered Code, include this CDDL HEADER in each
14*28b1e50eSSriharsha Basavapatna  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*28b1e50eSSriharsha Basavapatna  * If applicable, add the following below this CDDL HEADER, with the
16*28b1e50eSSriharsha Basavapatna  * fields enclosed by brackets "[]" replaced with your own identifying
17*28b1e50eSSriharsha Basavapatna  * information: Portions Copyright [yyyy] [name of copyright owner]
18*28b1e50eSSriharsha Basavapatna  *
19*28b1e50eSSriharsha Basavapatna  * CDDL HEADER END
20*28b1e50eSSriharsha Basavapatna  */
21*28b1e50eSSriharsha Basavapatna 
22*28b1e50eSSriharsha Basavapatna /*
23*28b1e50eSSriharsha Basavapatna  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*28b1e50eSSriharsha Basavapatna  * Use is subject to license terms.
25*28b1e50eSSriharsha Basavapatna  */
26*28b1e50eSSriharsha Basavapatna 
27*28b1e50eSSriharsha Basavapatna /*
28*28b1e50eSSriharsha Basavapatna  * Authorization checking:
29*28b1e50eSSriharsha Basavapatna  *
30*28b1e50eSSriharsha Basavapatna  * These functions check 'vntsd' authorization to access guest consoles.
31*28b1e50eSSriharsha Basavapatna  * The mechanism used is Solaris authorizations. The local client (telnet)
32*28b1e50eSSriharsha Basavapatna  * process requesting the connection to a console is verified to have the
33*28b1e50eSSriharsha Basavapatna  * required authorization.
34*28b1e50eSSriharsha Basavapatna  *
35*28b1e50eSSriharsha Basavapatna  * Authorizations available are to access the console of any/all guests or to
36*28b1e50eSSriharsha Basavapatna  * access the consoles of a specific console group. A client connecting to the
37*28b1e50eSSriharsha Basavapatna  * console through telnet must have the appropriate authorization from file
38*28b1e50eSSriharsha Basavapatna  * /etc/security/auth_attr.
39*28b1e50eSSriharsha Basavapatna  *
40*28b1e50eSSriharsha Basavapatna  * The all-consoles authorization is added during vntsd installation:
41*28b1e50eSSriharsha Basavapatna  * solaris.vntsd.consoles:::Access All LDoms Guest Consoles::
42*28b1e50eSSriharsha Basavapatna  *
43*28b1e50eSSriharsha Basavapatna  * Example of a specific console group authorization based on the name of the
44*28b1e50eSSriharsha Basavapatna  * console group (added manually by a user with 'vntsd.grant' authorization,
45*28b1e50eSSriharsha Basavapatna  * such as 'root'); the group name in this example is "ldg1" :
46*28b1e50eSSriharsha Basavapatna  * solaris.vntsd.console-ldg1:::Access Specific LDoms Guest Console::
47*28b1e50eSSriharsha Basavapatna  *
48*28b1e50eSSriharsha Basavapatna  * Specific users are authorized with usermod(1M). To add an authorization
49*28b1e50eSSriharsha Basavapatna  * (to /etc/user_attr) type a command similar to this (when user NOT
50*28b1e50eSSriharsha Basavapatna  * logged in):
51*28b1e50eSSriharsha Basavapatna  *
52*28b1e50eSSriharsha Basavapatna  *    To authorize a user 'user1' to access all guest consoles:
53*28b1e50eSSriharsha Basavapatna  *    # usermod -A solaris.vntsd.consoles user1
54*28b1e50eSSriharsha Basavapatna  *
55*28b1e50eSSriharsha Basavapatna  */
56*28b1e50eSSriharsha Basavapatna 
57*28b1e50eSSriharsha Basavapatna #include <sys/types.h>		/* uid_t */
58*28b1e50eSSriharsha Basavapatna #include <sys/param.h>		/* MAXNAMELEN */
59*28b1e50eSSriharsha Basavapatna #include <pwd.h>		/* getpw*() */
60*28b1e50eSSriharsha Basavapatna #include <auth_attr.h>		/* chkauthattr() */
61*28b1e50eSSriharsha Basavapatna #include <secdb.h>		/* chkauthattr() */
62*28b1e50eSSriharsha Basavapatna #include <ucred.h>		/* getpeerucred() */
63*28b1e50eSSriharsha Basavapatna #include <errno.h>		/* errno */
64*28b1e50eSSriharsha Basavapatna 
65*28b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_ALLCONS	"solaris.vntsd.consoles" /* all-consoles auth */
66*28b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_GRPCONS	"solaris.vntsd.console-" /* cons-group auth */
67*28b1e50eSSriharsha Basavapatna #define	VNTSD_AUTH_PREFIXLEN	32			 /* max len of prefix */
68*28b1e50eSSriharsha Basavapatna 
69*28b1e50eSSriharsha Basavapatna /*
70*28b1e50eSSriharsha Basavapatna  * socket_peer_euid()
71*28b1e50eSSriharsha Basavapatna  *
72*28b1e50eSSriharsha Basavapatna  * Return the effective UID (EUID) of the socket peer.
73*28b1e50eSSriharsha Basavapatna  * If none, return -1.
74*28b1e50eSSriharsha Basavapatna  *
75*28b1e50eSSriharsha Basavapatna  * Parameters:
76*28b1e50eSSriharsha Basavapatna  * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
77*28b1e50eSSriharsha Basavapatna  *
78*28b1e50eSSriharsha Basavapatna  * Returns:
79*28b1e50eSSriharsha Basavapatna  * EUID if OK
80*28b1e50eSSriharsha Basavapatna  * -1 on failure or unknown EUID (passed on from ucred_geteuid()).
81*28b1e50eSSriharsha Basavapatna  */
82*28b1e50eSSriharsha Basavapatna static uid_t
socket_peer_euid(int sock_fd)83*28b1e50eSSriharsha Basavapatna socket_peer_euid(int sock_fd)
84*28b1e50eSSriharsha Basavapatna {
85*28b1e50eSSriharsha Basavapatna 	int		rc;
86*28b1e50eSSriharsha Basavapatna 	uid_t		peer_euid;
87*28b1e50eSSriharsha Basavapatna 	ucred_t		*ucredp = NULL;
88*28b1e50eSSriharsha Basavapatna 
89*28b1e50eSSriharsha Basavapatna 	/* Get info on the peer on the other side of the socket */
90*28b1e50eSSriharsha Basavapatna 	rc = getpeerucred(sock_fd, &ucredp);
91*28b1e50eSSriharsha Basavapatna 	if (rc == -1) {
92*28b1e50eSSriharsha Basavapatna 		/* If errno is EINVAL, it's probably a non-local socket peer */
93*28b1e50eSSriharsha Basavapatna 		return ((uid_t)-1);
94*28b1e50eSSriharsha Basavapatna 	}
95*28b1e50eSSriharsha Basavapatna 
96*28b1e50eSSriharsha Basavapatna 	/* Extract effective UID (EUID) info for the socket peer process */
97*28b1e50eSSriharsha Basavapatna 	peer_euid = ucred_geteuid(ucredp);
98*28b1e50eSSriharsha Basavapatna 	ucred_free(ucredp);
99*28b1e50eSSriharsha Basavapatna 
100*28b1e50eSSriharsha Basavapatna 	/* Return EUID */
101*28b1e50eSSriharsha Basavapatna 	return (peer_euid);
102*28b1e50eSSriharsha Basavapatna }
103*28b1e50eSSriharsha Basavapatna 
104*28b1e50eSSriharsha Basavapatna /*
105*28b1e50eSSriharsha Basavapatna  * auth_check_username()
106*28b1e50eSSriharsha Basavapatna  *
107*28b1e50eSSriharsha Basavapatna  * Check vntsd console authorization, given a user account.
108*28b1e50eSSriharsha Basavapatna  *
109*28b1e50eSSriharsha Basavapatna  * Parameters:
110*28b1e50eSSriharsha Basavapatna  * username	The name of a user account to check authorization
111*28b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization. The max
112*28b1e50eSSriharsha Basavapatna  *              length of group name is MAXPATHLEN.
113*28b1e50eSSriharsha Basavapatna  *
114*28b1e50eSSriharsha Basavapatna  * Returns:
115*28b1e50eSSriharsha Basavapatna  * 0 if OK (authorized), 1 on authorization failure.
116*28b1e50eSSriharsha Basavapatna  */
117*28b1e50eSSriharsha Basavapatna static int
auth_check_username(char * username,char * group_name)118*28b1e50eSSriharsha Basavapatna auth_check_username(char *username, char *group_name)
119*28b1e50eSSriharsha Basavapatna {
120*28b1e50eSSriharsha Basavapatna 	int	auth_granted = 0;
121*28b1e50eSSriharsha Basavapatna 	char	authname[VNTSD_AUTH_PREFIXLEN + MAXPATHLEN];
122*28b1e50eSSriharsha Basavapatna 	size_t	len = VNTSD_AUTH_PREFIXLEN + MAXPATHLEN;
123*28b1e50eSSriharsha Basavapatna 
124*28b1e50eSSriharsha Basavapatna 	/* Sanity check: */
125*28b1e50eSSriharsha Basavapatna 	if ((username == NULL) || (username[0] == '\0') ||
126*28b1e50eSSriharsha Basavapatna 	    (group_name == NULL) || (group_name[0] == '\0')) {
127*28b1e50eSSriharsha Basavapatna 		return (1); /* error (bad parameter) */
128*28b1e50eSSriharsha Basavapatna 	}
129*28b1e50eSSriharsha Basavapatna 
130*28b1e50eSSriharsha Basavapatna 	(void) snprintf(authname, len, VNTSD_AUTH_GRPCONS"%s", group_name);
131*28b1e50eSSriharsha Basavapatna 
132*28b1e50eSSriharsha Basavapatna 	/*
133*28b1e50eSSriharsha Basavapatna 	 * Do authorization checking.
134*28b1e50eSSriharsha Basavapatna 	 * First, check if the user is authorized access to all consoles. If it
135*28b1e50eSSriharsha Basavapatna 	 * fails, check authorization to the specific console group.
136*28b1e50eSSriharsha Basavapatna 	 */
137*28b1e50eSSriharsha Basavapatna 	auth_granted = chkauthattr(VNTSD_AUTH_ALLCONS, username);
138*28b1e50eSSriharsha Basavapatna 	if (auth_granted)
139*28b1e50eSSriharsha Basavapatna 		return (0);
140*28b1e50eSSriharsha Basavapatna 
141*28b1e50eSSriharsha Basavapatna 	auth_granted = chkauthattr(authname, username);
142*28b1e50eSSriharsha Basavapatna 	if (auth_granted)
143*28b1e50eSSriharsha Basavapatna 		return (0);
144*28b1e50eSSriharsha Basavapatna 
145*28b1e50eSSriharsha Basavapatna 	return (1);
146*28b1e50eSSriharsha Basavapatna }
147*28b1e50eSSriharsha Basavapatna 
148*28b1e50eSSriharsha Basavapatna /*
149*28b1e50eSSriharsha Basavapatna  * auth_check_euid()
150*28b1e50eSSriharsha Basavapatna  *
151*28b1e50eSSriharsha Basavapatna  * Check vntsd console authorization, given a EUID.
152*28b1e50eSSriharsha Basavapatna  *
153*28b1e50eSSriharsha Basavapatna  * Parameters:
154*28b1e50eSSriharsha Basavapatna  * euid		The effective UID of a user account to check authorization
155*28b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization
156*28b1e50eSSriharsha Basavapatna  *
157*28b1e50eSSriharsha Basavapatna  * Returns:
158*28b1e50eSSriharsha Basavapatna  * 0 if OK (authorized), 1 on authorization failure.
159*28b1e50eSSriharsha Basavapatna  */
160*28b1e50eSSriharsha Basavapatna static int
auth_check_euid(uid_t euid,char * group_name)161*28b1e50eSSriharsha Basavapatna auth_check_euid(uid_t euid, char *group_name)
162*28b1e50eSSriharsha Basavapatna {
163*28b1e50eSSriharsha Basavapatna 	struct passwd	*passwdp = NULL;
164*28b1e50eSSriharsha Basavapatna 	char		*username = NULL;
165*28b1e50eSSriharsha Basavapatna 
166*28b1e50eSSriharsha Basavapatna 	/* If EUID is -1, then it's unknown, so fail */
167*28b1e50eSSriharsha Basavapatna 	if (euid == (uid_t)-1) {
168*28b1e50eSSriharsha Basavapatna 		return (1);
169*28b1e50eSSriharsha Basavapatna 	}
170*28b1e50eSSriharsha Basavapatna 
171*28b1e50eSSriharsha Basavapatna 	/* Map EUID to user name */
172*28b1e50eSSriharsha Basavapatna 	passwdp = getpwuid(euid);
173*28b1e50eSSriharsha Basavapatna 	if (passwdp == NULL) { /* lookup failed */
174*28b1e50eSSriharsha Basavapatna 		return (1);
175*28b1e50eSSriharsha Basavapatna 	}
176*28b1e50eSSriharsha Basavapatna 	username = passwdp->pw_name;
177*28b1e50eSSriharsha Basavapatna 
178*28b1e50eSSriharsha Basavapatna 	/* Do authorization check: */
179*28b1e50eSSriharsha Basavapatna 	return (auth_check_username(username, group_name));
180*28b1e50eSSriharsha Basavapatna }
181*28b1e50eSSriharsha Basavapatna 
182*28b1e50eSSriharsha Basavapatna /*
183*28b1e50eSSriharsha Basavapatna  * auth_check_fd()
184*28b1e50eSSriharsha Basavapatna  *
185*28b1e50eSSriharsha Basavapatna  * Check vntsd authorization, given a fd of a socket. The socket fd is mapped
186*28b1e50eSSriharsha Basavapatna  * to a pid (and should not be used for remote connections).
187*28b1e50eSSriharsha Basavapatna  *
188*28b1e50eSSriharsha Basavapatna  * Parameters:
189*28b1e50eSSriharsha Basavapatna  * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
190*28b1e50eSSriharsha Basavapatna  * group_name	The name of the console group to check authorization
191*28b1e50eSSriharsha Basavapatna  *
192*28b1e50eSSriharsha Basavapatna  * Returns:
193*28b1e50eSSriharsha Basavapatna  * B_TRUE if OK (authorized), B_FALSE on authorization failure.
194*28b1e50eSSriharsha Basavapatna  */
195*28b1e50eSSriharsha Basavapatna boolean_t
auth_check_fd(int sock_fd,char * group_name)196*28b1e50eSSriharsha Basavapatna auth_check_fd(int sock_fd, char *group_name)
197*28b1e50eSSriharsha Basavapatna {
198*28b1e50eSSriharsha Basavapatna 	uid_t	peer_euid;
199*28b1e50eSSriharsha Basavapatna 	int	rv;
200*28b1e50eSSriharsha Basavapatna 
201*28b1e50eSSriharsha Basavapatna 	peer_euid = socket_peer_euid(sock_fd);
202*28b1e50eSSriharsha Basavapatna 	if (peer_euid == (uid_t)-1) { /* unknown EUID */
203*28b1e50eSSriharsha Basavapatna 		return (B_FALSE);
204*28b1e50eSSriharsha Basavapatna 	}
205*28b1e50eSSriharsha Basavapatna 
206*28b1e50eSSriharsha Basavapatna 	/* Do authorization check: */
207*28b1e50eSSriharsha Basavapatna 	rv = auth_check_euid(peer_euid, group_name);
208*28b1e50eSSriharsha Basavapatna 	if (rv != 0) {
209*28b1e50eSSriharsha Basavapatna 		return (B_FALSE);
210*28b1e50eSSriharsha Basavapatna 	}
211*28b1e50eSSriharsha Basavapatna 	return (B_TRUE);
212*28b1e50eSSriharsha Basavapatna }
213