2 Unix SMB/CIFS implementation.
4 Winbind daemon - pam auth funcions
6 Copyright (C) Andrew Tridgell 2000
7 Copyright (C) Tim Potter 2001
8 Copyright (C) Andrew Bartlett 2001-2002
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Return a password structure from a username. */
29 enum winbindd_result
winbindd_pam_auth(struct winbindd_cli_state
*state
)
32 fstring name_domain
, name_user
;
34 unsigned char trust_passwd
[16];
35 time_t last_change_time
;
37 NET_USER_INFO_3 info3
;
38 struct cli_state
*cli
= NULL
;
40 TALLOC_CTX
*mem_ctx
= NULL
;
44 extern pstring global_myname
;
46 DEBUG(3, ("[%5d]: pam auth %s\n", state
->pid
,
47 state
->request
.data
.auth
.user
));
49 if (!(mem_ctx
= talloc_init_named("winbind pam auth for %s", state
->request
.data
.auth
.user
))) {
50 DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n"));
51 result
= NT_STATUS_NO_MEMORY
;
55 /* Parse domain and username */
57 if (!parse_domain_user(state
->request
.data
.auth
.user
, name_domain
,
59 DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state
->request
.data
.auth
.user
));
60 result
= NT_STATUS_INVALID_PARAMETER
;
64 passlen
= strlen(state
->request
.data
.auth
.pass
);
67 unsigned char local_lm_response
[24];
68 unsigned char local_nt_response
[24];
70 generate_random_buffer(chal
, 8, False
);
71 SMBencrypt( (const uchar
*)state
->request
.data
.auth
.pass
, chal
, local_lm_response
);
73 SMBNTencrypt((const uchar
*)state
->request
.data
.auth
.pass
, chal
, local_nt_response
);
75 lm_resp
= data_blob_talloc(mem_ctx
, local_lm_response
, sizeof(local_lm_response
));
76 nt_resp
= data_blob_talloc(mem_ctx
, local_nt_response
, sizeof(local_nt_response
));
80 * Get the machine account password for our primary domain
83 if (!secrets_fetch_trust_account_password(
84 lp_workgroup(), trust_passwd
, &last_change_time
)) {
85 DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
86 "password for domain %s\n", lp_workgroup()));
87 result
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
91 /* We really don't care what LUID we give the user. */
93 generate_random_buffer( (unsigned char *)&smb_uid_low
, 4, False
);
97 /* Don't shut this down - it belongs to the connection cache code */
98 result
= cm_get_netlogon_cli(lp_workgroup(), trust_passwd
, &cli
);
100 if (!NT_STATUS_IS_OK(result
)) {
101 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
105 result
= cli_netlogon_sam_network_logon(cli
, mem_ctx
,
106 name_user
, name_domain
,
113 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
114 fstrcpy(state
->response
.data
.auth
.nt_status_string
, nt_errstr(result
));
115 fstrcpy(state
->response
.data
.auth
.error_string
, nt_errstr(result
));
116 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
118 DEBUG(NT_STATUS_IS_OK(result
) ? 5 : 2, ("Plain-text authenticaion for user %s returned %s (PAM: %d)\n",
119 state
->request
.data
.auth
.user
,
120 state
->response
.data
.auth
.nt_status_string
,
121 state
->response
.data
.auth
.pam_error
));
124 talloc_destroy(mem_ctx
);
126 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
129 #ifdef WITH_WINBIND_AUTH_CRAP
130 /* Challenge Response Authentication Protocol */
132 enum winbindd_result
winbindd_pam_auth_crap(struct winbindd_cli_state
*state
)
135 unsigned char trust_passwd
[16];
136 time_t last_change_time
;
137 NET_USER_INFO_3 info3
;
138 struct cli_state
*cli
= NULL
;
139 TALLOC_CTX
*mem_ctx
= NULL
;
140 const char *domain
= NULL
;
142 DATA_BLOB lm_resp
, nt_resp
;
144 extern pstring global_myname
;
146 DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state
->pid
,
147 state
->request
.data
.auth_crap
.domain
, state
->request
.data
.auth_crap
.user
));
149 if (!(mem_ctx
= talloc_init_named("winbind pam auth crap for %s", state
->request
.data
.auth
.user
))) {
150 DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
151 result
= NT_STATUS_NO_MEMORY
;
155 if (*state
->request
.data
.auth_crap
.domain
) {
156 domain
= talloc_strdup(mem_ctx
, state
->request
.data
.auth_crap
.domain
);
157 } else if (lp_winbind_use_default_domain()) {
158 domain
= talloc_strdup(mem_ctx
, lp_workgroup());
160 DEBUG(5,("no domain specified with username (%s) - failing auth\n", state
->request
.data
.auth
.user
));
161 result
= NT_STATUS_INVALID_PARAMETER
;
166 DEBUG(0,("winbindd_pam_auth_crap: talloc_strdup failed!\n"));
167 result
= NT_STATUS_NO_MEMORY
;
171 lm_resp
= data_blob_talloc(mem_ctx
, state
->request
.data
.auth_crap
.lm_resp
, state
->request
.data
.auth_crap
.lm_resp_len
);
172 nt_resp
= data_blob_talloc(mem_ctx
, state
->request
.data
.auth_crap
.nt_resp
, state
->request
.data
.auth_crap
.nt_resp_len
);
175 * Get the machine account password for our primary domain
178 if (!secrets_fetch_trust_account_password(
179 lp_workgroup(), trust_passwd
, &last_change_time
)) {
180 DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
181 "password for domain %s\n", lp_workgroup()));
182 result
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
188 /* Don't shut this down - it belongs to the connection cache code */
189 result
= cm_get_netlogon_cli(lp_workgroup(), trust_passwd
, &cli
);
191 if (!NT_STATUS_IS_OK(result
)) {
192 DEBUG(3, ("could not open handle to NETLOGON pipe (%s)\n", nt_errstr(result
)));
196 result
= cli_netlogon_sam_network_logon(cli
, mem_ctx
,
197 state
->request
.data
.auth_crap
.user
, domain
,
198 global_myname
, state
->request
.data
.auth_crap
.chal
,
204 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
205 fstrcpy(state
->response
.data
.auth
.nt_status_string
, nt_errstr(result
));
206 fstrcpy(state
->response
.data
.auth
.error_string
, nt_errstr(result
));
207 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
209 DEBUG(NT_STATUS_IS_OK(result
) ? 5 : 2, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n",
210 state
->request
.data
.auth_crap
.domain
,
211 state
->request
.data
.auth_crap
.user
,
212 state
->response
.data
.auth
.nt_status_string
,
213 state
->response
.data
.auth
.pam_error
));
216 talloc_destroy(mem_ctx
);
218 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
221 #endif /* WITH_WINBIND_AUTH_CRAP */
223 /* Change a user password */
225 enum winbindd_result
winbindd_pam_chauthtok(struct winbindd_cli_state
*state
)
228 char *oldpass
, *newpass
;
229 fstring domain
, user
;
232 DEBUG(3, ("[%5d]: pam chauthtok %s\n", state
->pid
,
233 state
->request
.data
.chauthtok
.user
));
238 return WINBINDD_ERROR
;
240 if (!parse_domain_user(state
->request
.data
.chauthtok
.user
, domain
,
242 result
= NT_STATUS_INVALID_PARAMETER
;
246 /* Change password */
248 oldpass
= state
->request
.data
.chauthtok
.oldpass
;
249 newpass
= state
->request
.data
.chauthtok
.newpass
;
253 if (!(hnd
= cm_get_sam_handle(domain
))) {
254 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain
));
255 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
259 if (!cli_oem_change_password(hnd
->cli
, user
, newpass
, oldpass
)) {
260 DEBUG(1, ("password change failed for user %s/%s\n", domain
,
262 result
= NT_STATUS_WRONG_PASSWORD
;
264 result
= NT_STATUS_OK
;
268 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
269 fstrcpy(state
->response
.data
.auth
.nt_status_string
, nt_errstr(result
));
270 fstrcpy(state
->response
.data
.auth
.error_string
, nt_errstr(result
));
271 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
273 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;