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