preparing for release of alpha-2.6
[Samba/gbeck.git] / source / rpc_client / cli_login.c
blob6c970800dc244117c40e81579177c9ae6ec7cb12
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NT Domain Authentication SMB / MSRPC client
5 Copyright (C) Andrew Tridgell 1994-2000
6 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "rpc_parse.h"
25 #include "rpc_client.h"
26 #include "nterr.h"
28 extern int DEBUGLEVEL;
30 /****************************************************************************
31 Initialize domain session credentials.
32 ****************************************************************************/
34 uint32 cli_nt_setup_creds(const char *srv_name,
35 const char *domain,
36 const char *cli_hostname,
37 const char *trust_acct,
38 const uchar trust_pwd[16], uint16 sec_chan,
39 uint16 * validation_level)
41 DOM_CHAL clnt_chal;
42 DOM_CHAL srv_chal;
43 uint32 status;
44 UTIME zerotime;
45 uint8 sess_key[16];
46 DOM_CRED clnt_cred;
47 uint32 neg_flags = !lp_client_schannel()? 0x000001ff : 0x400001ff;
49 /******************* Request Challenge ********************/
51 generate_random_buffer(clnt_chal.data, 8, False);
53 /* send a client challenge; receive a server challenge */
54 status =
55 cli_net_req_chal(srv_name, cli_hostname, &clnt_chal, &srv_chal);
56 if (status != 0)
58 DEBUG(1, ("cli_nt_setup_creds: request challenge failed\n"));
59 return status;
62 /**************** Long-term Session key **************/
64 /* calculate the session key */
65 cred_session_key(&clnt_chal, &srv_chal, trust_pwd, sess_key);
66 memset(sess_key + 8, 0, 8);
68 /******************* Authenticate 2 ********************/
70 /* calculate auth-2 credentials */
71 zerotime.time = 0;
72 cred_create(sess_key, &clnt_chal, zerotime, &clnt_cred.challenge);
74 if (!cli_con_set_creds(srv_name, sess_key, &clnt_cred))
76 return NT_STATUS_ACCESS_DENIED | 0xC0000000;
79 /*
80 * Send client auth-2 challenge.
81 * Receive an auth-2 challenge response and check it.
83 status = cli_net_auth2(srv_name, trust_acct, cli_hostname,
84 sec_chan, &neg_flags, &srv_chal);
85 if (status != 0x0)
87 DEBUG(1,
88 ("cli_nt_setup_creds: auth2 challenge failed. status: %x\n",
89 status));
92 /* check the client secure channel status */
93 if (status == 0x0 &&
94 lp_client_schannel() == True &&
95 IS_BITS_CLR_ALL(neg_flags, 0x40000000))
97 /* netlogon secure channel was required, and not negotiated */
98 return NT_STATUS_ACCESS_DENIED | 0xC0000000;
101 if (status == 0x0 && IS_BITS_SET_ALL(neg_flags, 0x40000000))
103 extern cli_auth_fns cli_netsec_fns;
104 struct cli_connection *con = NULL;
105 struct netsec_creds creds;
107 safe_strcpy(creds.domain, domain, sizeof(creds.myname) - 1);
108 safe_strcpy(creds.myname, cli_hostname,
109 sizeof(creds.myname) - 1);
110 memcpy(creds.sess_key, sess_key, sizeof(creds.sess_key));
112 if (!cli_connection_init_auth(srv_name, PIPE_NETLOGON, &con,
113 &cli_netsec_fns,
114 (void *)&creds))
116 return NT_STATUS_ACCESS_DENIED | 0xC0000000;
118 if (!cli_con_set_creds(srv_name, sess_key, &clnt_cred))
120 cli_connection_free(con);
121 return NT_STATUS_ACCESS_DENIED | 0xC0000000;
125 if (IS_BITS_SET_ALL(neg_flags, 0x40))
127 (*validation_level) = 3;
129 else
131 (*validation_level) = 2;
134 return status;
137 /****************************************************************************
138 Set machine password.
139 ****************************************************************************/
141 BOOL cli_nt_srv_pwset(const char *srv_name, const char *cli_hostname,
142 const char *trust_acct,
143 const uchar * new_hashof_trust_pwd, uint16 sec_chan)
145 DEBUG(5, ("cli_nt_srv_pwset: %d\n", __LINE__));
147 #ifdef DEBUG_PASSWORD
148 dump_data(6, new_hashof_trust_pwd, 16);
149 #endif
151 /* send client srv_pwset challenge */
152 return cli_net_srv_pwset(srv_name, cli_hostname, trust_acct,
153 new_hashof_trust_pwd, sec_chan);
156 /****************************************************************************
157 NT login - general.
158 *NEVER* use this code. This method of doing a logon (sending the cleartext
159 password equivalents, protected by the session key) is inherently insecure
160 given the current design of the NT Domain system. JRA.
161 ****************************************************************************/
162 BOOL cli_nt_login_general(const char *srv_name, const char *cli_hostname,
163 const char *domain, const char *username,
164 uint32 luid_low,
165 const char *general,
166 NET_ID_INFO_CTR * ctr,
167 uint16 validation_level,
168 NET_USER_INFO_3 * user_info3)
170 uint8 sess_key[16];
171 NET_USER_INFO_CTR user_ctr;
172 uint32 status;
173 ZERO_STRUCT(user_ctr);
174 user_ctr.switch_value = validation_level;
176 DEBUG(5, ("cli_nt_login_general: %d\n", __LINE__));
178 #ifdef DEBUG_PASSWORD
180 DEBUG(100, ("\"general\" user password: "));
181 dump_data(100, general, strlen(general));
182 #endif
184 if (!cli_get_sesskey_srv(srv_name, sess_key))
186 DEBUG(1, ("could not obtain session key for %s\n", srv_name));
187 return NT_STATUS_ACCESS_DENIED;
190 /* indicate an "general" login */
191 ctr->switch_value = GENERAL_LOGON_TYPE;
193 /* Create the structure needed for SAM logon. */
194 make_id_info4(&ctr->auth.id4, domain, 0,
195 luid_low, 0, username, cli_hostname, general);
197 /* Send client sam-logon request - update credentials on success. */
198 status = cli_net_sam_logon(srv_name, cli_hostname, ctr, &user_ctr);
199 if (!net_user_info_3_copy_from_ctr(user_info3, &user_ctr))
201 status = NT_STATUS_INVALID_PARAMETER;
203 free_net_user_info_ctr(&user_ctr);
204 return status;
207 /****************************************************************************
208 NT login - interactive.
209 *NEVER* use this code. This method of doing a logon (sending the cleartext
210 password equivalents, protected by the session key) is inherently insecure
211 given the current design of the NT Domain system. JRA.
212 ****************************************************************************/
213 uint32 cli_nt_login_interactive(const char *srv_name, const char *cli_hostname,
214 const char *domain, const char *username,
215 uint32 luid_low,
216 const uchar * lm_owf_user_pwd,
217 const uchar * nt_owf_user_pwd,
218 NET_ID_INFO_CTR * ctr,
219 uint16 validation_level,
220 NET_USER_INFO_3 * user_info3)
222 uint32 status;
223 uint8 sess_key[16];
224 NET_USER_INFO_CTR user_ctr;
225 ZERO_STRUCT(user_ctr);
226 user_ctr.switch_value = validation_level;
228 DEBUG(5, ("cli_nt_login_interactive: %d\n", __LINE__));
230 dump_data_pw("nt owf of user password:\n", lm_owf_user_pwd, 16);
231 dump_data_pw("nt owf of user password:\n", nt_owf_user_pwd, 16);
233 if (!cli_get_sesskey_srv(srv_name, sess_key))
235 DEBUG(1, ("could not obtain session key for %s\n", srv_name));
236 return NT_STATUS_ACCESS_DENIED;
239 /* indicate an "interactive" login */
240 ctr->switch_value = INTERACTIVE_LOGON_TYPE;
242 /* Create the structure needed for SAM logon. */
243 make_id_info1(&ctr->auth.id1, domain, 0,
244 luid_low, 0,
245 username, cli_hostname,
246 (char *)sess_key, lm_owf_user_pwd, nt_owf_user_pwd);
248 /* Send client sam-logon request - update credentials on success. */
249 status = cli_net_sam_logon(srv_name, cli_hostname, ctr, &user_ctr);
250 if (!net_user_info_3_copy_from_ctr(user_info3, &user_ctr))
252 status = NT_STATUS_INVALID_PARAMETER;
254 free_net_user_info_ctr(&user_ctr);
256 memset(ctr->auth.id1.lm_owf.data, '\0',
257 sizeof(ctr->auth.id1.lm_owf.data));
258 memset(ctr->auth.id1.nt_owf.data, '\0',
259 sizeof(ctr->auth.id1.nt_owf.data));
261 return status;
264 /****************************************************************************
265 NT login - network.
266 *ALWAYS* use this call to validate a user as it does not expose plaintext
267 password equivalents over the network. JRA.
268 ****************************************************************************/
270 uint32 cli_nt_login_network(const char *srv_name, const char *cli_hostname,
271 const char *domain, const char *username,
272 uint32 luid_low, const char lm_chal[8],
273 const char *lm_chal_resp,
274 int lm_chal_len,
275 const char *nt_chal_resp,
276 int nt_chal_len,
277 NET_ID_INFO_CTR * ctr,
278 uint16 validation_level,
279 NET_USER_INFO_3 * user_info3)
281 uint8 sess_key[16];
282 uint32 status;
283 NET_USER_INFO_CTR user_ctr;
284 ZERO_STRUCT(user_ctr);
285 user_ctr.switch_value = validation_level;
287 DEBUG(5, ("cli_nt_login_network: %d\n", __LINE__));
289 if (!cli_get_sesskey_srv(srv_name, sess_key))
291 DEBUG(1, ("could not obtain session key for %s\n", srv_name));
292 return NT_STATUS_ACCESS_DENIED;
295 /* indicate a "network" login */
296 ctr->switch_value = NETWORK_LOGON_TYPE;
298 /* Create the structure needed for SAM logon. */
299 make_id_info2(&ctr->auth.id2, domain, 0,
300 luid_low, 0,
301 username, cli_hostname,
302 lm_chal,
303 lm_chal_resp, lm_chal_len, nt_chal_resp, nt_chal_len);
305 /* Send client sam-logon request - update credentials on success. */
306 status = cli_net_sam_logon(srv_name, cli_hostname, ctr, &user_ctr);
308 if (!net_user_info_3_copy_from_ctr(user_info3, &user_ctr))
310 status = NT_STATUS_INVALID_PARAMETER;
312 free_net_user_info_ctr(&user_ctr);
314 dump_data_pw("cli sess key:", sess_key, 8);
315 dump_data_pw("enc padding:", user_info3->padding, 8);
316 dump_data_pw("enc user sess key:", user_info3->user_sess_key, 16);
318 SamOEMhash(user_info3->user_sess_key, sess_key, 0);
319 SamOEMhash(user_info3->padding, sess_key, 3);
321 dump_data_pw("dec padding:", user_info3->padding, 8);
322 dump_data_pw("dec user sess key:", user_info3->user_sess_key, 16);
324 return status;
327 /****************************************************************************
328 NT Logoff.
329 ****************************************************************************/
330 BOOL cli_nt_logoff(const char *srv_name, const char *cli_hostname,
331 NET_ID_INFO_CTR * ctr)
333 DEBUG(5, ("cli_nt_logoff: %d\n", __LINE__));
335 /* Send client sam-logoff request - update credentials on success. */
336 return cli_net_sam_logoff(srv_name, cli_hostname, ctr);
339 /****************************************************************************
340 NT SAM database sync
341 ****************************************************************************/
342 BOOL net_sam_sync(const char *srv_name,
343 const char *domain,
344 const char *cli_hostname,
345 const char *trust_acct,
346 uchar trust_passwd[16],
347 SAM_DELTA_HDR hdr_deltas[MAX_SAM_DELTAS],
348 SAM_DELTA_CTR deltas[MAX_SAM_DELTAS], uint32 * num_deltas)
350 BOOL res = True;
351 uint16 validation_level;
353 *num_deltas = 0;
355 DEBUG(5, ("Attempting SAM sync with PDC: %s\n", srv_name));
357 res = res ? cli_nt_setup_creds(srv_name, domain, cli_hostname,
358 trust_acct,
359 trust_passwd,
360 SEC_CHAN_BDC,
361 &validation_level) == 0x0 : False;
363 memset(trust_passwd, 0, 16);
365 res = res ? cli_net_sam_sync(srv_name, cli_hostname,
366 0, num_deltas, hdr_deltas,
367 deltas) : False;
369 if (!res)
371 DEBUG(5, ("SAM synchronisation FAILED\n"));
372 return False;
375 DEBUG(5, ("SAM synchronisation returned %d entries\n", *num_deltas));
377 return True;