First version that compiles. Much more to do.....
[kai/samba.git] / source / rpc_client / cli_netlogon.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-1997,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7  *  Copyright (C) Paul Ashton                       1997.
8  *  Copyright (C) Jeremy Allison                    1998.
9  *
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.
14  *  
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.
19  *  
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.
23  */
24
25
26 #ifdef SYSLOG
27 #undef SYSLOG
28 #endif
29
30 #include "includes.h"
31
32 extern int DEBUGLEVEL;
33 extern pstring global_myname;
34 extern fstring global_myworkgroup;
35
36 /****************************************************************************
37 do a LSA Logon Control2
38 ****************************************************************************/
39
40 BOOL do_net_logon_ctrl2(struct cli_state *cli, uint32 status_level)
41 {
42   prs_struct rbuf;
43   prs_struct buf; 
44   NET_Q_LOGON_CTRL2 q_l;
45   BOOL ok = False;
46
47   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
48   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
49
50   /* create and send a MSRPC command with api NET_LOGON_CTRL2 */
51
52   DEBUG(4,("do_net_logon_ctrl2 from %s status level:%x\n",
53            global_myname, status_level));
54
55   /* store the parameters */
56   make_q_logon_ctrl2(&q_l, cli->srv_name_slash, status_level);
57
58   /* turn parameters into data stream */
59   net_io_q_logon_ctrl2("", &q_l,  &buf, 0);
60
61   /* send the data on \PIPE\ */
62   if (rpc_api_pipe_req(cli, NET_LOGON_CTRL2, &buf, &rbuf))
63   {
64     NET_R_LOGON_CTRL2 r_l;
65
66     net_io_r_logon_ctrl2("", &r_l, &rbuf, 0);
67     ok = (rbuf.offset != 0);
68                 
69     if (ok && r_l.status != 0)
70     {
71       /* report error code */
72       DEBUG(0,("do_net_logon_ctrl2: Error %s\n", get_nt_error_msg(r_l.status)));
73       cli->nt_error = r_l.status;
74       ok = False;
75     }
76   }
77
78   prs_mem_free(&rbuf);
79   prs_mem_free(&buf );
80
81   return ok;
82 }
83
84 /****************************************************************************
85 LSA Authenticate 2
86
87 Send the client credential, receive back a server credential.
88 Ensure that the server credential returned matches the session key 
89 encrypt of the server challenge originally received. JRA.
90 ****************************************************************************/
91
92 BOOL cli_net_auth2(struct cli_state *cli, uint16 sec_chan, 
93                    uint32 neg_flags, DOM_CHAL *srv_chal)
94 {
95   prs_struct rbuf;
96   prs_struct buf; 
97   NET_Q_AUTH_2 q_a;
98   BOOL ok = False;
99
100   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
101   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
102
103   /* create and send a MSRPC command with api NET_AUTH2 */
104
105   DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %lx\n",
106          cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname,
107          credstr(cli->clnt_cred.challenge.data), neg_flags));
108
109   /* store the parameters */
110   make_q_auth_2(&q_a, cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname,
111                 &cli->clnt_cred.challenge, neg_flags);
112
113   /* turn parameters into data stream */
114   net_io_q_auth_2("", &q_a,  &buf, 0);
115
116   /* send the data on \PIPE\ */
117   if (rpc_api_pipe_req(cli, NET_AUTH2, &buf, &rbuf))
118   {
119     NET_R_AUTH_2 r_a;
120
121     net_io_r_auth_2("", &r_a, &rbuf, 0);
122     ok = (rbuf.offset != 0);
123                 
124     if (ok && r_a.status != 0)
125     {
126       /* report error code */
127       DEBUG(0,("cli_net_auth2: Error %s\n", get_nt_error_msg(r_a.status)));
128       cli->nt_error = r_a.status;
129       ok = False;
130     }
131
132     if (ok)
133     {
134       /* 
135        * Check the returned value using the initial
136        * server received challenge.
137        */
138       UTIME zerotime;
139
140       zerotime.time = 0;
141       if(cred_assert( &r_a.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
142         /*
143          * Server replied with bad credential. Fail.
144          */
145         DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
146 password ?).\n", cli->desthost ));
147         ok = False;
148       }
149     }
150
151     if (ok && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags)
152     {
153       /* report different neg_flags */
154       DEBUG(0,("cli_net_auth2: error neg_flags (q,r) differ - (%lx,%lx)\n",
155           q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags));
156       ok = False;
157     }
158
159   }
160
161   prs_mem_free(&rbuf);
162   prs_mem_free(&buf );
163
164   return ok;
165 }
166
167 /****************************************************************************
168 LSA Request Challenge. Sends our challenge to server, then gets
169 server response. These are used to generate the credentials.
170 ****************************************************************************/
171
172 BOOL cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal)
173 {
174   prs_struct rbuf;
175   prs_struct buf; 
176   NET_Q_REQ_CHAL q_c;
177   BOOL valid_chal = False;
178
179   if (srv_chal == NULL || clnt_chal == NULL)
180     return False;
181
182   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
183   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
184
185   /* create and send a MSRPC command with api NET_REQCHAL */
186
187   DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n",
188          cli->desthost, global_myname, credstr(clnt_chal->data)));
189
190   /* store the parameters */
191   make_q_req_chal(&q_c, cli->srv_name_slash, global_myname, clnt_chal);
192
193   /* turn parameters into data stream */
194   net_io_q_req_chal("", &q_c,  &buf, 0);
195
196   /* send the data on \PIPE\ */
197   if (rpc_api_pipe_req(cli, NET_REQCHAL, &buf, &rbuf))
198   {
199     NET_R_REQ_CHAL r_c;
200     BOOL ok;
201
202     net_io_r_req_chal("", &r_c, &rbuf, 0);
203     ok = (rbuf.offset != 0);
204                 
205     if (ok && r_c.status != 0)
206     {
207       /* report error code */
208       DEBUG(0,("cli_net_req_chal: Error %s\n", get_nt_error_msg(r_c.status)));
209       cli->nt_error = r_c.status;
210       ok = False;
211     }
212
213     if (ok)
214     {
215       /* ok, at last: we're happy. return the challenge */
216       memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data));
217       valid_chal = True;
218     }
219   }
220
221   prs_mem_free(&rbuf);
222   prs_mem_free(&buf );
223
224   return valid_chal;
225 }
226
227 #if 0
228 /***************************************************************************
229 do a LSA Server Password Set
230 ****************************************************************************/
231
232 BOOL do_net_srv_pwset(struct cli_state *cli, uint16 fnum,
233                       uchar sess_key[16], DOM_CRED *sto_clnt_cred,
234                       char *logon_srv, char *mach_acct, uint16 sec_chan_type,
235                       char *comp_name, DOM_CRED *clnt_cred, DOM_CRED *srv_cred,
236                       uint8 nt_owf_new_mach_pwd[16])
237 {
238   prs_struct rbuf;
239   prs_struct buf; 
240   NET_Q_SRV_PWSET q_s;
241   BOOL valid_cred = False;
242
243   if (srv_cred == NULL || clnt_cred == NULL)
244     return False;
245
246   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
247   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
248
249
250   /* create and send a MSRPC command with api NET_SRV_PWSET */
251
252   DEBUG(4,("LSA Server Password Set: srv:%s acct:%s sc: %d mc: %s clnt %s %lx\n",
253            cli->srv_name_slash, mach_acct, sec_chan_type, comp_name,
254            credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time));
255
256   /* store the parameters */
257   make_q_srv_pwset(&q_s, sess_key, logon_srv, mach_acct, sec_chan_type,
258                    comp_name, clnt_cred, nt_owf_new_mach_pwd);
259
260   /* turn parameters into data stream */
261   net_io_q_srv_pwset("", &q_s,  &buf, 0);
262
263   /* send the data on \PIPE\ */
264   if (rpc_api_pipe_req(cli, NET_SRVPWSET, &buf, &rbuf))
265   {
266     NET_R_SRV_PWSET r_s;
267     BOOL ok;
268
269     net_io_r_srv_pwset("", &r_s, &rbuf, 0);
270     ok = (rbuf.offset != 0);
271                 
272     if (ok && r_s.status != 0)
273     {
274       /* report error code */
275       DEBUG(0,("NET_R_SRV_PWSET: %s\n", get_nt_error_msg(r_s.status)));
276       cli->nt_error = r_s.status;
277       ok = False;
278     }
279
280     if (ok)
281     {
282       if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_cred)))
283       {
284         DEBUG(5, ("do_net_srv_pwset: server credential check OK\n"));
285         /* ok, at last: we're happy. return the challenge */
286         memcpy(srv_cred, &(r_s.srv_cred), sizeof(r_s.srv_cred));
287         valid_cred = True;
288       }
289       else
290       {
291         DEBUG(5, ("do_net_srv_pwset: server credential check failed\n"));
292       }
293     }
294   }
295
296   prs_mem_free(&rbuf);
297   prs_mem_free(&buf );
298
299   return valid_cred;
300 }
301 #endif
302
303 /***************************************************************************
304 LSA SAM Logon.
305 ****************************************************************************/
306
307 BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr, 
308                        NET_USER_INFO_3 *user_info3)
309 {
310   DOM_CRED new_clnt_cred;
311   prs_struct rbuf;
312   prs_struct buf; 
313   uint16 validation_level = 3;
314   NET_Q_SAM_LOGON q_s;
315   BOOL ok = False;
316
317   /*
318    * Create the new client credentials.
319    */
320
321   cli->clnt_cred.timestamp.time = time(NULL);
322
323   memcpy(&new_clnt_cred, &cli->clnt_cred, sizeof(new_clnt_cred));
324
325   /* Calculate the new credentials. */
326   cred_create(cli->sess_key, &(cli->clnt_cred.challenge),
327               new_clnt_cred.timestamp, &(new_clnt_cred.challenge));
328
329   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
330   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
331
332   /* create and send a MSRPC command with api NET_SAMLOGON */
333
334   DEBUG(4,("cli_net_sam_logon: srv:%s mc:%s clnt %s %lx ll: %d\n",
335              cli->srv_name_slash, global_myname, 
336              credstr(new_clnt_cred.challenge.data), cli->clnt_cred.timestamp.time,
337              ctr->switch_value));
338
339   /* store the parameters */
340   make_sam_info(&(q_s.sam_id), cli->srv_name_slash, global_myname,
341          &new_clnt_cred, NULL, ctr->switch_value, ctr, validation_level);
342
343   /* turn parameters into data stream */
344   net_io_q_sam_logon("", &q_s,  &buf, 0);
345
346   /* send the data on \PIPE\ */
347   if (rpc_api_pipe_req(cli, NET_SAMLOGON, &buf, &rbuf))
348   {
349     NET_R_SAM_LOGON r_s;
350
351     r_s.user = user_info3;
352
353     net_io_r_sam_logon("", &r_s, &rbuf, 0);
354     ok = (rbuf.offset != 0);
355                 
356     if (ok && r_s.status != 0)
357     {
358       /* report error code */
359       DEBUG(0,("cli_net_sam_logon: %s\n", get_nt_error_msg(r_s.status)));
360       cli->nt_error = r_s.status;
361       ok = False;
362     }
363
364     /* Update the credentials. */
365     if (clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds)) == 0)
366     {
367       /*
368        * Server replied with bad credential. Fail.
369        */
370       DEBUG(0,("cli_net_sam_logon: server %s replied with bad credential (bad machine \
371 password ?).\n", cli->desthost ));
372         ok = False;
373     }
374
375     if (ok && r_s.switch_value != 3)
376     {
377       /* report different switch_value */
378       DEBUG(0,("cli_net_sam_logon: switch_value of 3 expected %x\n",
379                    r_s.switch_value));
380       ok = False;
381     }
382   }
383
384   prs_mem_free(&rbuf);
385   prs_mem_free(&buf );
386
387   return ok;
388 }
389
390 /***************************************************************************
391 LSA SAM Logoff.
392 ****************************************************************************/
393
394 BOOL cli_net_sam_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr)
395 {
396   DOM_CRED new_clnt_cred;
397   prs_struct rbuf;
398   prs_struct buf; 
399   NET_Q_SAM_LOGOFF q_s;
400   uint16 validation_level = 3;
401   BOOL ok = False;
402
403   /*
404    * Create the new client credentials.
405    */
406
407   cli->clnt_cred.timestamp.time = time(NULL);
408
409   memcpy(&new_clnt_cred, &cli->clnt_cred, sizeof(new_clnt_cred));
410
411   /* Calculate the new credentials. */
412   cred_create(cli->sess_key, &(cli->clnt_cred.challenge),
413               new_clnt_cred.timestamp, &(new_clnt_cred.challenge));
414
415   prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
416   prs_init(&rbuf, 0,    4, SAFETY_MARGIN, True );
417
418   /* create and send a MSRPC command with api NET_SAMLOGOFF */
419
420   DEBUG(4,("cli_net_sam_logoff: srv:%s mc:%s clnt %s %lx ll: %d\n",
421             cli->srv_name_slash, global_myname,
422             credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time,
423             ctr->switch_value));
424
425   /* store the parameters */
426   make_sam_info(&(q_s.sam_id), cli->srv_name_slash, global_myname,
427                 &new_clnt_cred, NULL, ctr->switch_value, ctr, validation_level);
428
429   /* turn parameters into data stream */
430   net_io_q_sam_logoff("", &q_s,  &buf, 0);
431
432   /* send the data on \PIPE\ */
433   if (rpc_api_pipe_req(cli, NET_SAMLOGOFF, &buf, &rbuf))
434   {
435     NET_R_SAM_LOGOFF r_s;
436
437     net_io_r_sam_logoff("", &r_s, &rbuf, 0);
438     ok = (rbuf.offset != 0);
439                 
440     if (ok && r_s.status != 0)
441     {
442       /* report error code */
443       DEBUG(0,("cli_net_sam_logoff: %s\n", get_nt_error_msg(r_s.status)));
444       cli->nt_error = r_s.status;
445       ok = False;
446     }
447
448     /* Update the credentials. */
449     if (clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds)) == 0)
450     {
451       /*
452        * Server replied with bad credential. Fail.
453        */
454       DEBUG(0,("cli_net_sam_logoff: server %s replied with bad credential (bad machine \
455 password ?).\n", cli->desthost ));
456         ok = False;
457     }
458   }
459
460   prs_mem_free(&rbuf);
461   prs_mem_free(&buf );
462
463   return ok;
464 }