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(1M). 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
socket_peer_euid(int sock_fd)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
auth_check_username(char * username,char * group_name)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
auth_check_euid(uid_t euid,char * group_name)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
auth_check_fd(int sock_fd,char * group_name)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