xref: /illumos-gate/usr/src/lib/pam_modules/smbfs/smbfs_login.c (revision 0fb96ba1f1ce26ff8b286f8f928769a6afcb00a6)
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