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