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 26 #pragma ident "%Z%%M% %I% %E% SMI" 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 /*ARGSUSED*/ 55 int 56 pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 57 { 58 boolean_t debug = B_FALSE; 59 char dom[20]; 60 char *user; 61 char *pw; 62 char *service; 63 struct passwd pwbuf; 64 char buf[NSS_BUFLEN_PASSWD]; 65 char *home; 66 uid_t uid; 67 int res = PAM_SUCCESS; 68 int i, mask; 69 70 for (i = 0; i < argc; i++) { 71 if (strcmp(argv[i], "debug") == 0) 72 debug = B_TRUE; 73 } 74 75 /* Since our creds don't time out, ignore a refresh. */ 76 if ((flags & PAM_REFRESH_CRED) != 0) 77 return (PAM_IGNORE); 78 79 /* Check for unknown options */ 80 mask = PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED | PAM_DELETE_CRED; 81 if ((flags & ~mask) != 0) 82 return (PAM_IGNORE); 83 84 (void) pam_get_item(pamh, PAM_SERVICE, (void **)&service); 85 (void) pam_get_item(pamh, PAM_USER, (void **)&user); 86 87 if (user == NULL || *user == '\0') { 88 __pam_log(LOG_AUTH | LOG_ERR, 89 "pam_smbfs_login: username is empty"); 90 return (PAM_IGNORE); 91 } 92 if (getpwnam_r(user, &pwbuf, buf, sizeof (buf)) == NULL) { 93 __pam_log(LOG_AUTH | LOG_ERR, 94 "pam_smbfs_login: username %s can't be found", user); 95 return (PAM_IGNORE); 96 } 97 uid = pwbuf.pw_uid; 98 home = pwbuf.pw_dir; 99 100 (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&pw); 101 if (pw == NULL) { 102 /* 103 * A module on the stack has removed PAM_AUTHTOK. 104 */ 105 return (PAM_IGNORE); 106 } 107 108 res = smbfs_default_dom_usr(home, NULL, dom, sizeof (dom), NULL, 0); 109 if (res != 0) 110 (void) strcpy(dom, "WORKGROUP"); 111 112 if (debug) 113 __pam_log(LOG_AUTH | LOG_DEBUG, 114 "pam_smbfs_login: service %s, dom %s, user %s", 115 service, dom, user); 116 117 if ((flags & (PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED)) != 0) 118 res = smbfs_keychain_add(uid, dom, user, pw); 119 120 if ((flags & PAM_DELETE_CRED) != 0) 121 res = smbfs_keychain_del(uid, dom, user); 122 123 /* 124 * map errors to user messages and PAM return codes. 125 */ 126 switch (res) { 127 case SMB_KEYCHAIN_SUCCESS: 128 if (debug) 129 __pam_log(LOG_AUTH | LOG_DEBUG, 130 "smbfs password successfully stored for %s", user); 131 break; 132 133 case SMB_KEYCHAIN_BADPASSWD: 134 __pam_log(LOG_AUTH | LOG_ERR, "smbfs password is invalid"); 135 break; 136 137 case SMB_KEYCHAIN_BADDOMAIN: 138 __pam_log(LOG_AUTH | LOG_ERR, 139 "%s: smbfs domain %s is invalid", service, dom); 140 break; 141 142 case SMB_KEYCHAIN_BADUSER: 143 __pam_log(LOG_AUTH | LOG_ERR, "smbfs user %s is invalid", user); 144 break; 145 146 case SMB_KEYCHAIN_NODRIVER: 147 __pam_log(LOG_AUTH | LOG_ERR, 148 "driver open failed (%s), smbfs password not stored", 149 strerror(errno)); 150 break; 151 152 case SMB_KEYCHAIN_UNKNOWN: 153 __pam_log(LOG_AUTH | LOG_ERR, 154 "Unexpected failure, smbfs password not stored"); 155 break; 156 157 default: 158 __pam_log(LOG_AUTH | LOG_ERR, 159 "driver ioctl failed (%s), smbfs password not stored", 160 strerror(errno)); 161 break; 162 } 163 164 return (PAM_IGNORE); 165 } 166