/* * 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 /* uid_t */ #include /* MAXNAMELEN */ #include /* getpw*() */ #include /* chkauthattr() */ #include /* chkauthattr() */ #include /* getpeerucred() */ #include /* 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); }