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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
29 #include <sys/varargs.h>
34 #include <security/pam_appl.h>
35 #include <security/pam_modules.h>
36 #include <security/pam_impl.h>
39 #include <passwdutil.h>
41 #include <smbsrv/libsmb.h>
45 error(boolean_t nowarn
, pam_handle_t
*pamh
, char *fmt
, ...)
48 char message
[PAM_MAX_MSG_SIZE
];
54 (void) vsnprintf(message
, sizeof (message
), fmt
, ap
);
55 (void) __pam_display_msg(pamh
, PAM_ERROR_MSG
, 1, &message
,
62 info(boolean_t nowarn
, pam_handle_t
*pamh
, char *fmt
, ...)
65 char message
[PAM_MAX_MSG_SIZE
];
71 (void) vsnprintf(message
, sizeof (message
), fmt
, ap
);
72 (void) __pam_display_msg(pamh
, PAM_TEXT_INFO
, 1, &message
,
78 pam_sm_chauthtok(pam_handle_t
*pamh
, int flags
, int argc
, const char **argv
)
80 boolean_t debug
= B_FALSE
;
81 boolean_t nowarn
= B_FALSE
;
82 pwu_repository_t files_rep
;
83 char *user
, *local_user
;
90 for (i
= 0; i
< argc
; i
++) {
91 if (strcmp(argv
[i
], "debug") == 0)
93 else if (strcmp(argv
[i
], "nowarn") == 0)
97 if ((flags
& PAM_PRELIM_CHECK
) != 0)
100 if ((flags
& PAM_UPDATE_AUTHTOK
) == 0)
101 return (PAM_SYSTEM_ERR
);
103 if ((flags
& PAM_SILENT
) != 0)
107 __pam_log(LOG_AUTH
| LOG_DEBUG
,
108 "pam_smb_passwd: storing authtok");
110 (void) pam_get_item(pamh
, PAM_SERVICE
, (void **)&service
);
111 (void) pam_get_item(pamh
, PAM_USER
, (void **)&user
);
113 if (user
== NULL
|| *user
== '\0') {
114 __pam_log(LOG_AUTH
| LOG_ERR
,
115 "pam_smb_passwd: username is empty");
116 return (PAM_USER_UNKNOWN
);
119 (void) pam_get_item(pamh
, PAM_AUTHTOK
, (void **)&newpw
);
122 * A module on the stack has removed PAM_AUTHTOK. We fail
124 return (PAM_AUTHTOK_ERR
);
127 /* Check to see if this is a local user */
128 files_rep
.type
= "files";
129 files_rep
.scope
= NULL
;
130 files_rep
.scope_len
= 0;
131 res
= __user_to_authenticate(user
, &files_rep
, &local_user
,
133 if (res
!= PWU_SUCCESS
) {
136 /* if not a local user, ignore */
138 __pam_log(LOG_AUTH
| LOG_DEBUG
,
139 "pam_smb_passwd: %s is not local", user
);
143 return (PAM_PERM_DENIED
);
145 return (PAM_SYSTEM_ERR
);
148 smb_pwd_init(B_FALSE
);
150 res
= smb_pwd_setpasswd(user
, newpw
);
155 * now map the various return states to user messages
156 * and PAM return codes.
159 case SMB_PWE_SUCCESS
:
160 info(nowarn
, pamh
, dgettext(TEXT_DOMAIN
,
161 "%s: SMB password successfully changed for %s"),
163 return (PAM_SUCCESS
);
165 case SMB_PWE_STAT_FAILED
:
166 __pam_log(LOG_AUTH
| LOG_ERR
,
167 "%s: stat of SMB password file failed", service
);
168 return (PAM_SYSTEM_ERR
);
170 case SMB_PWE_OPEN_FAILED
:
171 case SMB_PWE_WRITE_FAILED
:
172 case SMB_PWE_CLOSE_FAILED
:
173 case SMB_PWE_UPDATE_FAILED
:
174 error(nowarn
, pamh
, dgettext(TEXT_DOMAIN
,
175 "%s: Unexpected failure. SMB password database unchanged."),
177 return (PAM_SYSTEM_ERR
);
180 error(nowarn
, pamh
, dgettext(TEXT_DOMAIN
,
181 "%s: SMB password database busy. Try again later."),
184 return (PAM_AUTHTOK_LOCK_BUSY
);
186 case SMB_PWE_USER_UNKNOWN
:
187 error(nowarn
, pamh
, dgettext(TEXT_DOMAIN
,
188 "%s: %s does not exist."), service
, user
);
189 return (PAM_USER_UNKNOWN
);
191 case SMB_PWE_USER_DISABLE
:
192 error(nowarn
, pamh
, dgettext(TEXT_DOMAIN
,
193 "%s: %s is disable. SMB password database unchanged."),
198 return (PAM_PERM_DENIED
);
201 res
= PAM_SYSTEM_ERR
;