2 Unix SMB/Netbios implementation.
5 Winbind daemon - pam auuth funcions
7 Copyright (C) Andrew Tridgell 2000
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
27 form DOMAIN\user into a domain and a user */
29 static BOOL
wb_parse_domain_user(char *domuser
, fstring domain
, fstring user
)
32 char *sep
= lp_winbind_separator();
34 p
= strchr(domuser
,*sep
);
40 fstrcpy(domain
, domuser
);
41 domain
[PTR_DIFF(p
, domuser
)] = 0;
46 /* Return a password structure from a username. Specify whether cached data
49 enum winbindd_result
winbindd_pam_auth(struct winbindd_cli_state
*state
)
51 BOOL result
, user_exists
;
52 fstring name_domain
, name_user
;
55 DEBUG(3, ("[%5d]: pam auth %s\n", state
->pid
,
56 state
->request
.data
.auth
.user
));
58 /* Parse domain and username */
60 if (!wb_parse_domain_user(state
->request
.data
.auth
.user
, name_domain
,
62 return WINBINDD_ERROR
;
64 passlen
= strlen(state
->request
.data
.auth
.pass
);
66 /* So domain_client_validate() actually opens a new connection
67 for each authentication performed. This can theoretically
68 be optimised to use an already open IPC$ connection. */
70 result
= domain_client_validate(name_user
, name_domain
,
71 state
->request
.data
.auth
.pass
,
73 state
->request
.data
.auth
.pass
,
74 passlen
, &user_exists
, NULL
);
76 return result
? WINBINDD_OK
: WINBINDD_ERROR
;
79 /* Challenge Response Authentication Protocol */
81 #if ALLOW_WINBIND_AUTH_CRAP
82 enum winbindd_result
winbindd_pam_auth_crap(struct winbindd_cli_state
*state
)
85 fstring name_domain
, name_user
;
86 unsigned char trust_passwd
[16];
87 time_t last_change_time
;
89 NET_USER_INFO_3 info3
;
91 struct cli_state
*cli
;
93 DEBUG(3, ("[%5d]: pam auth crap %s\n", state
->pid
,
94 state
->request
.data
.auth_crap
.user
));
96 /* Parse domain and username */
98 if (!wb_parse_domain_user(state
->request
.data
.auth_crap
.user
, name_domain
,
100 return WINBINDD_ERROR
;
103 * Get the machine account password for our primary domain
106 if (!secrets_fetch_trust_account_password(
107 lp_workgroup(), trust_passwd
, &last_change_time
)) {
108 DEBUG(0, ("winbindd_pam_auth_crap: could not fetch trust account "
109 "password for domain %s\n", lp_workgroup()));
110 return WINBINDD_ERROR
;
113 /* We really don't care what LUID we give the user. */
115 generate_random_buffer( (unsigned char *)&smb_uid_low
, 4, False
);
119 result
= cm_get_netlogon_cli(lp_workgroup(), trust_passwd
, &cli
);
121 if (!NT_STATUS_IS_OK(result
)) {
122 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
126 result
= cli_nt_login_network(cli
, name_domain
, name_user
, smb_uid_low
,
127 state
->request
.data
.auth_crap
.chal
,
128 state
->request
.data
.auth_crap
.lm_resp
,
129 state
->request
.data
.auth_crap
.nt_resp
,
135 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
139 /* Change a user password */
141 enum winbindd_result
winbindd_pam_chauthtok(struct winbindd_cli_state
*state
)
143 char *oldpass
, *newpass
;
144 fstring domain
, user
;
145 uchar nt_oldhash
[16];
146 uchar lm_oldhash
[16];
148 DEBUG(3, ("[%5d]: pam chauthtok %s\n", state
->pid
,
149 state
->request
.data
.chauthtok
.user
));
154 return WINBINDD_ERROR
;
156 if (!wb_parse_domain_user(state
->request
.data
.chauthtok
.user
, domain
, user
))
157 return WINBINDD_ERROR
;
159 oldpass
= state
->request
.data
.chauthtok
.oldpass
;
160 newpass
= state
->request
.data
.chauthtok
.newpass
;
162 nt_lm_owf_gen(oldpass
, nt_oldhash
, lm_oldhash
);
164 /* Change password */
170 if (!msrpc_sam_ntchange_pwd(server_state
.controller
, domain
, user
,
171 lm_oldhash
, nt_oldhash
, newpass
)) {
172 DEBUG(0, ("password change failed for user %s/%s\n", domain
, user
));
173 return WINBINDD_ERROR
;