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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2023 OmniOS Community Edition (OmniOSce) Association. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/varargs.h> 30 #include <string.h> 31 #include <syslog.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <pwd.h> 35 #include <nss_dbdefs.h> 36 37 #include <security/pam_appl.h> 38 #include <security/pam_modules.h> 39 #include <security/pam_impl.h> 40 41 #include <libintl.h> 42 #include <passwdutil.h> 43 44 #include <errno.h> 45 #include <netsmb/smb_keychain.h> 46 47 /*ARGSUSED*/ 48 int 49 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) 50 { 51 return (PAM_IGNORE); 52 } 53 54 int 55 pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 56 { 57 boolean_t debug = B_FALSE; 58 char dom[20]; 59 const char *user; 60 const char *pw; 61 const char *service; 62 struct passwd pwbuf; 63 char buf[NSS_BUFLEN_PASSWD]; 64 char *home; 65 uid_t uid; 66 int res = PAM_SUCCESS; 67 int i, mask; 68 69 for (i = 0; i < argc; i++) { 70 if (strcmp(argv[i], "debug") == 0) 71 debug = B_TRUE; 72 } 73 74 /* Since our creds don't time out, ignore a refresh. */ 75 if ((flags & PAM_REFRESH_CRED) != 0) 76 return (PAM_IGNORE); 77 78 /* Check for unknown options */ 79 mask = PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED | PAM_DELETE_CRED; 80 if ((flags & ~mask) != 0) 81 return (PAM_IGNORE); 82 83 (void) pam_get_item(pamh, PAM_SERVICE, (const void **)&service); 84 (void) pam_get_item(pamh, PAM_USER, (const void **)&user); 85 86 if (user == NULL || *user == '\0') { 87 __pam_log(LOG_AUTH | LOG_ERR, 88 "pam_smbfs_login: username is empty"); 89 return (PAM_IGNORE); 90 } 91 if (getpwnam_r(user, &pwbuf, buf, sizeof (buf)) == NULL) { 92 __pam_log(LOG_AUTH | LOG_ERR, 93 "pam_smbfs_login: username %s can't be found", user); 94 return (PAM_IGNORE); 95 } 96 uid = pwbuf.pw_uid; 97 home = pwbuf.pw_dir; 98 99 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **)&pw); 100 if (pw == NULL) { 101 /* 102 * A module on the stack has removed PAM_AUTHTOK. 103 */ 104 return (PAM_IGNORE); 105 } 106 107 res = smbfs_default_dom_usr(home, NULL, dom, sizeof (dom), NULL, 0); 108 if (res != 0) 109 (void) strcpy(dom, "WORKGROUP"); 110 111 if (debug) 112 __pam_log(LOG_AUTH | LOG_DEBUG, 113 "pam_smbfs_login: service %s, dom %s, user %s", 114 service, dom, user); 115 116 if ((flags & (PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED)) != 0) 117 res = smbfs_keychain_add(uid, dom, user, pw); 118 119 if ((flags & PAM_DELETE_CRED) != 0) 120 res = smbfs_keychain_del(uid, dom, user); 121 122 /* 123 * map errors to user messages and PAM return codes. 124 */ 125 switch (res) { 126 case SMB_KEYCHAIN_SUCCESS: 127 if (debug) 128 __pam_log(LOG_AUTH | LOG_DEBUG, 129 "smbfs password successfully stored for %s", user); 130 break; 131 132 case SMB_KEYCHAIN_BADPASSWD: 133 __pam_log(LOG_AUTH | LOG_ERR, "smbfs password is invalid"); 134 break; 135 136 case SMB_KEYCHAIN_BADDOMAIN: 137 __pam_log(LOG_AUTH | LOG_ERR, 138 "%s: smbfs domain %s is invalid", service, dom); 139 break; 140 141 case SMB_KEYCHAIN_BADUSER: 142 __pam_log(LOG_AUTH | LOG_ERR, "smbfs user %s is invalid", user); 143 break; 144 145 case SMB_KEYCHAIN_NODRIVER: 146 __pam_log(LOG_AUTH | LOG_ERR, 147 "driver open failed (%s), smbfs password not stored", 148 strerror(errno)); 149 break; 150 151 case SMB_KEYCHAIN_UNKNOWN: 152 __pam_log(LOG_AUTH | LOG_ERR, 153 "Unexpected failure, smbfs password not stored"); 154 break; 155 156 default: 157 __pam_log(LOG_AUTH | LOG_ERR, 158 "driver ioctl failed (%s), smbfs password not stored", 159 strerror(errno)); 160 break; 161 } 162 163 return (PAM_IGNORE); 164 } 165