libc: make stdio_impl.h an internal libc header
[unleashed/tickless.git] / usr / src / lib / pam_modules / smb / smb_passwd.c
blobf52ab90356438ca07dd8b84046c007caa3835e45
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
30 #include <string.h>
31 #include <syslog.h>
32 #include <stdlib.h>
34 #include <security/pam_appl.h>
35 #include <security/pam_modules.h>
36 #include <security/pam_impl.h>
38 #include <libintl.h>
39 #include <passwdutil.h>
41 #include <smbsrv/libsmb.h>
43 /*PRINTFLIKE3*/
44 static void
45 error(boolean_t nowarn, pam_handle_t *pamh, char *fmt, ...)
47 va_list ap;
48 char message[PAM_MAX_MSG_SIZE];
50 if (nowarn)
51 return;
53 va_start(ap, fmt);
54 (void) vsnprintf(message, sizeof (message), fmt, ap);
55 (void) __pam_display_msg(pamh, PAM_ERROR_MSG, 1, &message,
56 NULL);
57 va_end(ap);
60 /*PRINTFLIKE3*/
61 static void
62 info(boolean_t nowarn, pam_handle_t *pamh, char *fmt, ...)
64 va_list ap;
65 char message[PAM_MAX_MSG_SIZE];
67 if (nowarn)
68 return;
70 va_start(ap, fmt);
71 (void) vsnprintf(message, sizeof (message), fmt, ap);
72 (void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1, &message,
73 NULL);
74 va_end(ap);
77 int
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;
84 char *newpw;
85 char *service;
86 int privileged;
87 int res;
88 int i;
90 for (i = 0; i < argc; i++) {
91 if (strcmp(argv[i], "debug") == 0)
92 debug = B_TRUE;
93 else if (strcmp(argv[i], "nowarn") == 0)
94 nowarn = B_TRUE;
97 if ((flags & PAM_PRELIM_CHECK) != 0)
98 return (PAM_IGNORE);
100 if ((flags & PAM_UPDATE_AUTHTOK) == 0)
101 return (PAM_SYSTEM_ERR);
103 if ((flags & PAM_SILENT) != 0)
104 nowarn = B_TRUE;
106 if (debug)
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);
120 if (newpw == NULL) {
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,
132 &privileged);
133 if (res != PWU_SUCCESS) {
134 switch (res) {
135 case PWU_NOT_FOUND:
136 /* if not a local user, ignore */
137 if (debug) {
138 __pam_log(LOG_AUTH | LOG_DEBUG,
139 "pam_smb_passwd: %s is not local", user);
141 return (PAM_IGNORE);
142 case PWU_DENIED:
143 return (PAM_PERM_DENIED);
145 return (PAM_SYSTEM_ERR);
148 smb_pwd_init(B_FALSE);
150 res = smb_pwd_setpasswd(user, newpw);
152 smb_pwd_fini();
155 * now map the various return states to user messages
156 * and PAM return codes.
158 switch (res) {
159 case SMB_PWE_SUCCESS:
160 info(nowarn, pamh, dgettext(TEXT_DOMAIN,
161 "%s: SMB password successfully changed for %s"),
162 service, user);
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."),
176 service);
177 return (PAM_SYSTEM_ERR);
179 case SMB_PWE_BUSY:
180 error(nowarn, pamh, dgettext(TEXT_DOMAIN,
181 "%s: SMB password database busy. Try again later."),
182 service);
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."),
194 service, user);
195 return (PAM_IGNORE);
197 case SMB_PWE_DENIED:
198 return (PAM_PERM_DENIED);
200 default:
201 res = PAM_SYSTEM_ERR;
202 break;
205 return (res);