summaryrefslogtreecommitdiff
path: root/usr/src/cmd/vntsd/auth.c
blob: e3c3e6995fc53e734829a2cdbe13b4979e8d44cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Authorization checking:
 *
 * These functions check 'vntsd' authorization to access guest consoles.
 * The mechanism used is Solaris authorizations. The local client (telnet)
 * process requesting the connection to a console is verified to have the
 * required authorization.
 *
 * Authorizations available are to access the console of any/all guests or to
 * access the consoles of a specific console group. A client connecting to the
 * console through telnet must have the appropriate authorization from file
 * /etc/security/auth_attr.
 *
 * The all-consoles authorization is added during vntsd installation:
 * solaris.vntsd.consoles:::Access All LDoms Guest Consoles::
 *
 * Example of a specific console group authorization based on the name of the
 * console group (added manually by a user with 'vntsd.grant' authorization,
 * such as 'root'); the group name in this example is "ldg1" :
 * solaris.vntsd.console-ldg1:::Access Specific LDoms Guest Console::
 *
 * Specific users are authorized with usermod(1M). To add an authorization
 * (to /etc/user_attr) type a command similar to this (when user NOT
 * logged in):
 *
 *    To authorize a user 'user1' to access all guest consoles:
 *    # usermod -A solaris.vntsd.consoles user1
 *
 */

#include <sys/types.h>		/* uid_t */
#include <sys/param.h>		/* MAXNAMELEN */
#include <pwd.h>		/* getpw*() */
#include <auth_attr.h>		/* chkauthattr() */
#include <secdb.h>		/* chkauthattr() */
#include <ucred.h>		/* getpeerucred() */
#include <errno.h>		/* errno */

#define	VNTSD_AUTH_ALLCONS	"solaris.vntsd.consoles" /* all-consoles auth */
#define	VNTSD_AUTH_GRPCONS	"solaris.vntsd.console-" /* cons-group auth */
#define	VNTSD_AUTH_PREFIXLEN	32			 /* max len of prefix */

/*
 * socket_peer_euid()
 *
 * Return the effective UID (EUID) of the socket peer.
 * If none, return -1.
 *
 * Parameters:
 * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
 *
 * Returns:
 * EUID if OK
 * -1 on failure or unknown EUID (passed on from ucred_geteuid()).
 */
static uid_t
socket_peer_euid(int sock_fd)
{
	int		rc;
	uid_t		peer_euid;
	ucred_t		*ucredp = NULL;

	/* Get info on the peer on the other side of the socket */
	rc = getpeerucred(sock_fd, &ucredp);
	if (rc == -1) {
		/* If errno is EINVAL, it's probably a non-local socket peer */
		return ((uid_t)-1);
	}

	/* Extract effective UID (EUID) info for the socket peer process */
	peer_euid = ucred_geteuid(ucredp);
	ucred_free(ucredp);

	/* Return EUID */
	return (peer_euid);
}

/*
 * auth_check_username()
 *
 * Check vntsd console authorization, given a user account.
 *
 * Parameters:
 * username	The name of a user account to check authorization
 * group_name	The name of the console group to check authorization. The max
 *              length of group name is MAXPATHLEN.
 *
 * Returns:
 * 0 if OK (authorized), 1 on authorization failure.
 */
static int
auth_check_username(char *username, char *group_name)
{
	int	auth_granted = 0;
	char	authname[VNTSD_AUTH_PREFIXLEN + MAXPATHLEN];
	size_t	len = VNTSD_AUTH_PREFIXLEN + MAXPATHLEN;

	/* Sanity check: */
	if ((username == NULL) || (username[0] == '\0') ||
	    (group_name == NULL) || (group_name[0] == '\0')) {
		return (1); /* error (bad parameter) */
	}

	(void) snprintf(authname, len, VNTSD_AUTH_GRPCONS"%s", group_name);

	/*
	 * Do authorization checking.
	 * First, check if the user is authorized access to all consoles. If it
	 * fails, check authorization to the specific console group.
	 */
	auth_granted = chkauthattr(VNTSD_AUTH_ALLCONS, username);
	if (auth_granted)
		return (0);

	auth_granted = chkauthattr(authname, username);
	if (auth_granted)
		return (0);

	return (1);
}

/*
 * auth_check_euid()
 *
 * Check vntsd console authorization, given a EUID.
 *
 * Parameters:
 * euid		The effective UID of a user account to check authorization
 * group_name	The name of the console group to check authorization
 *
 * Returns:
 * 0 if OK (authorized), 1 on authorization failure.
 */
static int
auth_check_euid(uid_t euid, char *group_name)
{
	struct passwd	*passwdp = NULL;
	char		*username = NULL;

	/* If EUID is -1, then it's unknown, so fail */
	if (euid == (uid_t)-1) {
		return (1);
	}

	/* Map EUID to user name */
	passwdp = getpwuid(euid);
	if (passwdp == NULL) { /* lookup failed */
		return (1);
	}
	username = passwdp->pw_name;

	/* Do authorization check: */
	return (auth_check_username(username, group_name));
}

/*
 * auth_check_fd()
 *
 * Check vntsd authorization, given a fd of a socket. The socket fd is mapped
 * to a pid (and should not be used for remote connections).
 *
 * Parameters:
 * sock_fd	The socket fd of a locally-connected socket (mapped to a pid)
 * group_name	The name of the console group to check authorization
 *
 * Returns:
 * B_TRUE if OK (authorized), B_FALSE on authorization failure.
 */
boolean_t
auth_check_fd(int sock_fd, char *group_name)
{
	uid_t	peer_euid;
	int	rv;

	peer_euid = socket_peer_euid(sock_fd);
	if (peer_euid == (uid_t)-1) { /* unknown EUID */
		return (B_FALSE);
	}

	/* Do authorization check: */
	rv = auth_check_euid(peer_euid, group_name);
	if (rv != 0) {
		return (B_FALSE);
	}
	return (B_TRUE);
}