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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright (c) 2016 by Delphix. All rights reserved. 25 * Copyright 2023 OmniOS Community Edition (OmniOSce) Association. 26 */ 27 28 #include <syslog.h> 29 #include <pwd.h> 30 #include <unistd.h> 31 #include <strings.h> 32 #include <security/pam_appl.h> 33 #include <security/pam_modules.h> 34 #include <libintl.h> 35 36 static int parse_allow_name(const char *, char *); 37 38 /* 39 * pam_sm_acct_mgmt main account managment routine. 40 * XXX: The routine just prints out a warning message. 41 * It may need to force the user to change their 42 * passwd. 43 */ 44 45 int 46 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) 47 { 48 const char *user; 49 const char *pg; 50 int i; 51 int debug __unused = 0; 52 int nowarn __unused = 0; 53 int error = 0; 54 55 if (argc == 0) 56 return (PAM_SUCCESS); 57 58 if (pam_get_item(pamh, PAM_USER, (const void **)&user) != PAM_SUCCESS) 59 return (PAM_SERVICE_ERR); 60 61 if (pam_get_item(pamh, PAM_SERVICE, (const void **)&pg) != PAM_SUCCESS) 62 return (PAM_SERVICE_ERR); 63 64 /* 65 * kludge alert. su needs to be handled specially for allow policy. 66 * we want to use the policy of the current user not the "destination" 67 * user. This will enable us to prevent su to root but not to rlogin, 68 * telnet, rsh, ftp to root. 69 * 70 * description of problem: user name is the "destination" name. not 71 * the current name. The allow policy needs to be applied to the 72 * current name in the case of su. user is "root" in this case and 73 * we will be getting the root policy instead of the user policy. 74 */ 75 if (strcmp(pg, "su") == 0) { 76 struct passwd *pw; 77 uid_t uid; 78 uid = getuid(); 79 pw = getpwuid(uid); 80 if (pw == NULL) 81 return (PAM_SYSTEM_ERR); 82 user = pw->pw_name; 83 } 84 85 if (user == 0 || *user == '\0' || (strcmp(user, "root") == 0)) 86 return (PAM_SUCCESS); 87 88 for (i = 0; i < argc; i++) { 89 if (strcasecmp(argv[i], "debug") == 0) 90 debug = 1; 91 else if (strcasecmp(argv[i], "nowarn") == 0) { 92 nowarn = 1; 93 flags = flags | PAM_SILENT; 94 } else if (strncmp(argv[i], "allow=", 6) == 0) 95 error |= parse_allow_name(user, (char *)(argv[i]+6)); 96 else 97 syslog(LOG_DEBUG, "illegal option %s", argv[i]); 98 } 99 return (error?PAM_SUCCESS:PAM_AUTH_ERR); 100 } 101 102 static char *getname(); 103 104 static int 105 parse_allow_name(const char *who, char *cp) 106 { 107 char name[256]; 108 109 /* catch "allow=" */ 110 if (*cp == '\0') 111 return (0); 112 while (cp) { 113 cp = getname(cp, name); 114 /* catch things such as =, and ,, */ 115 if (*name == '\0') 116 continue; 117 if (strcmp(who, name) == 0) 118 return (1); 119 } 120 return (0); 121 } 122 123 static char * 124 getname(char *cp, char *name) 125 { 126 /* force name to be initially null string */ 127 *name = '\0'; 128 129 /* end of string? */ 130 if (*cp == '\0') 131 return ((char *)0); 132 while (*cp) { 133 /* end of name? */ 134 if (*cp == ',' || *cp == '\0') 135 break; 136 *name++ = *cp++; 137 } 138 /* make name into string */ 139 *name++ = '\0'; 140 return ((*cp == '\0')? (char *)0 : ++cp); 141 } 142