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