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 seperator (%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 result
= cm_get_netlogon_cli(lp_workgroup(), trust_passwd
, &cli
);
99 if (!NT_STATUS_IS_OK(result
)) {
100 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
101 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
105 result
= cli_netlogon_sam_network_logon(cli
, mem_ctx
,
106 name_user
, name_domain
,
111 uni_group_cache_store_netlogon(mem_ctx
, &info3
);
117 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
118 fstrcpy(state
->response
.data
.auth
.nt_status_string
, get_nt_error_msg(result
));
119 fstrcpy(state
->response
.data
.auth
.error_string
, get_nt_error_msg(result
));
120 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
122 DEBUG(2, ("Plain-text authenticaion for user %s returned %s (PAM: %d)\n",
123 state
->request
.data
.auth
.user
,
124 state
->response
.data
.auth
.nt_status_string
,
125 state
->response
.data
.auth
.pam_error
));
128 talloc_destroy(mem_ctx
);
130 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
133 /* Challenge Response Authentication Protocol */
135 enum winbindd_result
winbindd_pam_auth_crap(struct winbindd_cli_state
*state
)
138 unsigned char trust_passwd
[16];
139 time_t last_change_time
;
140 NET_USER_INFO_3 info3
;
141 struct cli_state
*cli
= NULL
;
142 TALLOC_CTX
*mem_ctx
= NULL
;
143 const char *domain
= NULL
;
145 DATA_BLOB lm_resp
, nt_resp
;
147 extern pstring global_myname
;
149 DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state
->pid
,
150 state
->request
.data
.auth_crap
.domain
, state
->request
.data
.auth_crap
.user
));
152 if (!(mem_ctx
= talloc_init_named("winbind pam auth crap for %s", state
->request
.data
.auth
.user
))) {
153 DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
154 result
= NT_STATUS_NO_MEMORY
;
158 if (*state
->request
.data
.auth_crap
.domain
) {
159 domain
= talloc_strdup(mem_ctx
, state
->request
.data
.auth_crap
.domain
);
160 } else if (lp_winbind_use_default_domain()) {
161 domain
= talloc_strdup(mem_ctx
, lp_workgroup());
163 DEBUG(5,("no domain specified with username (%s) - failing auth\n", state
->request
.data
.auth
.user
));
164 result
= NT_STATUS_INVALID_PARAMETER
;
169 DEBUG(0,("winbindd_pam_auth_crap: talloc_strdup failed!\n"));
170 result
= NT_STATUS_NO_MEMORY
;
174 lm_resp
= data_blob_talloc(mem_ctx
, state
->request
.data
.auth_crap
.lm_resp
, state
->request
.data
.auth_crap
.lm_resp_len
);
175 nt_resp
= data_blob_talloc(mem_ctx
, state
->request
.data
.auth_crap
.nt_resp
, state
->request
.data
.auth_crap
.nt_resp_len
);
178 * Get the machine account password for our primary domain
181 if (!secrets_fetch_trust_account_password(
182 lp_workgroup(), trust_passwd
, &last_change_time
)) {
183 DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
184 "password for domain %s\n", lp_workgroup()));
185 result
= NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
191 result
= cm_get_netlogon_cli(lp_workgroup(), trust_passwd
, &cli
);
193 if (!NT_STATUS_IS_OK(result
)) {
194 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
198 result
= cli_netlogon_sam_network_logon(cli
, mem_ctx
,
199 state
->request
.data
.auth_crap
.user
, domain
,
200 global_myname
, state
->request
.data
.auth_crap
.chal
,
204 if (NT_STATUS_IS_OK(result
)) {
205 uni_group_cache_store_netlogon(mem_ctx
, &info3
);
213 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
214 fstrcpy(state
->response
.data
.auth
.nt_status_string
, get_nt_error_msg(result
));
215 fstrcpy(state
->response
.data
.auth
.error_string
, get_nt_error_msg(result
));
216 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
218 DEBUG(2, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n",
219 state
->request
.data
.auth_crap
.domain
,
220 state
->request
.data
.auth_crap
.user
,
221 state
->response
.data
.auth
.nt_status_string
,
222 state
->response
.data
.auth
.pam_error
));
225 talloc_destroy(mem_ctx
);
227 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
230 /* Change a user password */
232 enum winbindd_result
winbindd_pam_chauthtok(struct winbindd_cli_state
*state
)
235 char *oldpass
, *newpass
;
236 fstring domain
, user
;
239 DEBUG(3, ("[%5d]: pam chauthtok %s\n", state
->pid
,
240 state
->request
.data
.chauthtok
.user
));
245 return WINBINDD_ERROR
;
247 if (!parse_domain_user(state
->request
.data
.chauthtok
.user
, domain
,
249 result
= NT_STATUS_INVALID_PARAMETER
;
253 /* Change password */
255 oldpass
= state
->request
.data
.chauthtok
.oldpass
;
256 newpass
= state
->request
.data
.chauthtok
.newpass
;
260 if (!(hnd
= cm_get_sam_handle(domain
))) {
261 DEBUG(1, ("could not get SAM handle on DC for %s\n", domain
));
262 result
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
266 if (!cli_oem_change_password(hnd
->cli
, user
, newpass
, oldpass
)) {
267 DEBUG(1, ("password change failed for user %s/%s\n", domain
,
269 result
= NT_STATUS_WRONG_PASSWORD
;
271 result
= NT_STATUS_OK
;
275 state
->response
.data
.auth
.nt_status
= NT_STATUS_V(result
);
276 fstrcpy(state
->response
.data
.auth
.nt_status_string
, get_nt_error_msg(result
));
277 fstrcpy(state
->response
.data
.auth
.error_string
, get_nt_error_msg(result
));
278 state
->response
.data
.auth
.pam_error
= nt_status_to_pam(result
);
280 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;