first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[gd/samba/.git] / source / rpc_parse / parse_net.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  *  
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.
13  *  
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.
18  *  
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.
22  */
23
24 #include "includes.h"
25 #include "nterr.h"
26
27 extern int DEBUGLEVEL;
28
29 /*******************************************************************
30  Reads or writes a structure.
31 ********************************************************************/
32
33 static BOOL net_io_neg_flags(char *desc, NEG_FLAGS *neg, prs_struct *ps, int depth)
34 {
35         if (neg == NULL)
36                 return False;
37
38         prs_debug(ps, depth, desc, "net_io_neg_flags");
39         depth++;
40
41         if(!prs_align(ps))
42                 return False;
43         
44         if(!prs_uint32("neg_flags", ps, depth, &neg->neg_flags))
45                 return False;
46
47         return True;
48 }
49
50 /*******************************************************************
51  Inits a NETLOGON_INFO_3 structure.
52 ********************************************************************/
53
54 static void init_netinfo_3(NETLOGON_INFO_3 *info, uint32 flags, uint32 logon_attempts)
55 {
56         info->flags          = flags;
57         info->logon_attempts = logon_attempts;
58         info->reserved_1     = 0x0;
59         info->reserved_2     = 0x0;
60         info->reserved_3     = 0x0;
61         info->reserved_4     = 0x0;
62         info->reserved_5     = 0x0;
63 }
64
65 /*******************************************************************
66  Reads or writes a NETLOGON_INFO_3 structure.
67 ********************************************************************/
68
69 static BOOL net_io_netinfo_3(char *desc,  NETLOGON_INFO_3 *info, prs_struct *ps, int depth)
70 {
71         if (info == NULL)
72                 return False;
73
74         prs_debug(ps, depth, desc, "net_io_netinfo_3");
75         depth++;
76
77         if(!prs_align(ps))
78                 return False;
79
80         if(!prs_uint32("flags         ", ps, depth, &info->flags))
81                 return False;
82         if(!prs_uint32("logon_attempts", ps, depth, &info->logon_attempts))
83                 return False;
84         if(!prs_uint32("reserved_1    ", ps, depth, &info->reserved_1))
85                 return False;
86         if(!prs_uint32("reserved_2    ", ps, depth, &info->reserved_2))
87                 return False;
88         if(!prs_uint32("reserved_3    ", ps, depth, &info->reserved_3))
89                 return False;
90         if(!prs_uint32("reserved_4    ", ps, depth, &info->reserved_4))
91                 return False;
92         if(!prs_uint32("reserved_5    ", ps, depth, &info->reserved_5))
93                 return False;
94
95         return True;
96 }
97
98
99 /*******************************************************************
100  Inits a NETLOGON_INFO_1 structure.
101 ********************************************************************/
102
103 static void init_netinfo_1(NETLOGON_INFO_1 *info, uint32 flags, uint32 pdc_status)
104 {
105         info->flags      = flags;
106         info->pdc_status = pdc_status;
107 }
108
109 /*******************************************************************
110  Reads or writes a NETLOGON_INFO_1 structure.
111 ********************************************************************/
112
113 static BOOL net_io_netinfo_1(char *desc, NETLOGON_INFO_1 *info, prs_struct *ps, int depth)
114 {
115         if (info == NULL)
116                 return False;
117
118         prs_debug(ps, depth, desc, "net_io_netinfo_1");
119         depth++;
120
121         if(!prs_align(ps))
122                 return False;
123         
124         if(!prs_uint32("flags     ", ps, depth, &info->flags))
125                 return False;
126         if(!prs_uint32("pdc_status", ps, depth, &info->pdc_status))
127                 return False;
128
129         return True;
130 }
131
132 /*******************************************************************
133  Inits a NETLOGON_INFO_2 structure.
134 ********************************************************************/
135
136 static void init_netinfo_2(NETLOGON_INFO_2 *info, uint32 flags, uint32 pdc_status,
137                                 uint32 tc_status, char *trusted_dc_name)
138 {
139         int len_dc_name = strlen(trusted_dc_name);
140         info->flags      = flags;
141         info->pdc_status = pdc_status;
142         info->ptr_trusted_dc_name = 1;
143         info->tc_status  = tc_status;
144
145         if (trusted_dc_name != NULL)
146                 init_unistr2(&(info->uni_trusted_dc_name), trusted_dc_name, len_dc_name+1);
147         else
148                 init_unistr2(&(info->uni_trusted_dc_name), "", 1);
149 }
150
151 /*******************************************************************
152  Reads or writes a NETLOGON_INFO_2 structure.
153 ********************************************************************/
154
155 static BOOL net_io_netinfo_2(char *desc, NETLOGON_INFO_2 *info, prs_struct *ps, int depth)
156 {
157         if (info == NULL)
158                 return False;
159
160         prs_debug(ps, depth, desc, "net_io_netinfo_2");
161         depth++;
162
163         if(!prs_align(ps))
164                 return False;
165         
166         if(!prs_uint32("flags              ", ps, depth, &info->flags))
167                 return False;
168         if(!prs_uint32("pdc_status         ", ps, depth, &info->pdc_status))
169                 return False;
170         if(!prs_uint32("ptr_trusted_dc_name", ps, depth, &info->ptr_trusted_dc_name))
171                 return False;
172         if(!prs_uint32("tc_status          ", ps, depth, &info->tc_status))
173                 return False;
174
175         if (info->ptr_trusted_dc_name != 0) {
176                 if(!smb_io_unistr2("unistr2", &info->uni_trusted_dc_name, info->ptr_trusted_dc_name, ps, depth))
177                         return False;
178         }
179
180         if(!prs_align(ps))
181                 return False;
182
183         return True;
184 }
185
186 /*******************************************************************
187  Reads or writes an NET_Q_LOGON_CTRL2 structure.
188 ********************************************************************/
189
190 BOOL net_io_q_logon_ctrl2(char *desc, NET_Q_LOGON_CTRL2 *q_l, prs_struct *ps, int depth)
191 {
192         if (q_l == NULL)
193                 return False;
194
195         prs_debug(ps, depth, desc, "net_io_q_logon_ctrl2");
196         depth++;
197
198         if(!prs_align(ps))
199                 return False;
200
201         if(!prs_uint32("ptr          ", ps, depth, &q_l->ptr))
202                 return False;
203
204         if(!smb_io_unistr2 ("", &q_l->uni_server_name, q_l->ptr, ps, depth))
205                 return False;
206
207         if(!prs_align(ps))
208                 return False;
209
210         if(!prs_uint32("function_code", ps, depth, &q_l->function_code))
211                 return False;
212         if(!prs_uint32("query_level  ", ps, depth, &q_l->query_level))
213                 return False;
214         if(!prs_uint32("switch_value ", ps, depth, &q_l->switch_value))
215                 return False;
216
217         return True;
218 }
219
220 /*******************************************************************
221  Inits an NET_R_LOGON_CTRL2 structure.
222 ********************************************************************/
223
224 void init_r_logon_ctrl2(NET_R_LOGON_CTRL2 *r_l, uint32 query_level,
225                                 uint32 flags, uint32 pdc_status, uint32 logon_attempts,
226                                 uint32 tc_status, char *trusted_domain_name)
227 {
228         DEBUG(5,("make_r_logon_ctrl2\n"));
229
230         r_l->switch_value  = query_level; /* should only be 0x1 */
231
232         switch (query_level) {
233         case 1:
234                 r_l->ptr = 1; /* undocumented pointer */
235                 init_netinfo_1(&r_l->logon.info1, flags, pdc_status);   
236                 r_l->status = 0;
237                 break;
238         case 2:
239                 r_l->ptr = 1; /* undocumented pointer */
240                 init_netinfo_2(&r_l->logon.info2, flags, pdc_status,
241                                tc_status, trusted_domain_name); 
242                 r_l->status = 0;
243                 break;
244         case 3:
245                 r_l->ptr = 1; /* undocumented pointer */
246                 init_netinfo_3(&(r_l->logon.info3), flags, logon_attempts);     
247                 r_l->status = 0;
248                 break;
249         default:
250                 DEBUG(2,("init_r_logon_ctrl2: unsupported switch value %d\n",
251                         r_l->switch_value));
252                 r_l->ptr = 0; /* undocumented pointer */
253
254                 /* take a guess at an error code... */
255                 r_l->status = NT_STATUS_INVALID_INFO_CLASS;
256                 break;
257         }
258 }
259
260 /*******************************************************************
261  Reads or writes an NET_R_LOGON_CTRL2 structure.
262 ********************************************************************/
263
264 BOOL net_io_r_logon_ctrl2(char *desc, NET_R_LOGON_CTRL2 *r_l, prs_struct *ps, int depth)
265 {
266         if (r_l == NULL)
267                 return False;
268
269         prs_debug(ps, depth, desc, "net_io_r_logon_ctrl2");
270         depth++;
271
272         if(!prs_uint32("switch_value ", ps, depth, &r_l->switch_value))
273                 return False;
274         if(!prs_uint32("ptr          ", ps, depth, &r_l->ptr))
275                 return False;
276
277         if (r_l->ptr != 0) {
278                 switch (r_l->switch_value) {
279                 case 1:
280                         if(!net_io_netinfo_1("", &r_l->logon.info1, ps, depth))
281                                 return False;
282                         break;
283                 case 2:
284                         if(!net_io_netinfo_2("", &r_l->logon.info2, ps, depth))
285                                 return False;
286                         break;
287                 case 3:
288                         if(!net_io_netinfo_3("", &r_l->logon.info3, ps, depth))
289                                 return False;
290                         break;
291                 default:
292                         DEBUG(2,("net_io_r_logon_ctrl2: unsupported switch value %d\n",
293                                 r_l->switch_value));
294                         break;
295                 }
296         }
297
298         if(!prs_uint32("status       ", ps, depth, &r_l->status))
299                 return False;
300
301         return True;
302 }
303
304 /*******************************************************************
305  Inits an NET_R_TRUST_DOM_LIST structure.
306 ********************************************************************/
307
308 void init_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t,
309                         uint32 num_doms, char *dom_name)
310 {
311         int i = 0;
312
313         DEBUG(5,("make_r_trust_dom\n"));
314
315         for (i = 0; i < MAX_TRUST_DOMS; i++) {
316                 r_t->uni_trust_dom_name[i].uni_str_len = 0;
317                 r_t->uni_trust_dom_name[i].uni_max_len = 0;
318         }
319         if (num_doms > MAX_TRUST_DOMS)
320                 num_doms = MAX_TRUST_DOMS;
321
322         for (i = 0; i < num_doms; i++) {
323                 fstring domain_name;
324                 fstrcpy(domain_name, dom_name);
325                 strupper(domain_name);
326                 init_unistr2(&r_t->uni_trust_dom_name[i], domain_name, strlen(domain_name)+1);
327                 /* the use of UNISTR2 here is non-standard. */
328                 r_t->uni_trust_dom_name[i].undoc = 0x1;
329         }
330         
331         r_t->status = 0;
332 }
333
334 /*******************************************************************
335  Reads or writes an NET_R_TRUST_DOM_LIST structure.
336 ********************************************************************/
337
338 BOOL net_io_r_trust_dom(char *desc, NET_R_TRUST_DOM_LIST *r_t, prs_struct *ps, int depth)
339 {
340         int i;
341         if (r_t == NULL)
342                  return False;
343
344         prs_debug(ps, depth, desc, "net_io_r_trust_dom");
345         depth++;
346
347         for (i = 0; i < MAX_TRUST_DOMS; i++) {
348                 if (r_t->uni_trust_dom_name[i].uni_str_len == 0)
349                         break;
350                 if(!smb_io_unistr2("", &r_t->uni_trust_dom_name[i], True, ps, depth))
351                          return False;
352         }
353
354         if(!prs_uint32("status", ps, depth, &r_t->status))
355                  return False;
356
357         return True;
358 }
359
360
361 /*******************************************************************
362  Reads or writes an NET_Q_TRUST_DOM_LIST structure.
363 ********************************************************************/
364
365 BOOL net_io_q_trust_dom(char *desc, NET_Q_TRUST_DOM_LIST *q_l, prs_struct *ps, int depth)
366 {
367         if (q_l == NULL)
368                  return False;
369
370         prs_debug(ps, depth, desc, "net_io_q_trust_dom");
371         depth++;
372
373         if(!prs_uint32("ptr          ", ps, depth, &q_l->ptr))
374                  return False;
375         if(!smb_io_unistr2 ("", &q_l->uni_server_name, q_l->ptr, ps, depth))
376                  return False;
377
378         if(!prs_align(ps))
379                  return False;
380
381         if(!prs_uint32("function_code", ps, depth, &q_l->function_code))
382                  return False;
383
384         return True;
385 }
386
387 /*******************************************************************
388  Inits an NET_Q_REQ_CHAL structure.
389 ********************************************************************/
390
391 void init_q_req_chal(NET_Q_REQ_CHAL *q_c,
392                                 char *logon_srv, char *logon_clnt,
393                                 DOM_CHAL *clnt_chal)
394 {
395         DEBUG(5,("make_q_req_chal: %d\n", __LINE__));
396
397         q_c->undoc_buffer = 1; /* don't know what this buffer is */
398
399         init_unistr2(&q_c->uni_logon_srv, logon_srv , strlen(logon_srv )+1);
400         init_unistr2(&q_c->uni_logon_clnt, logon_clnt, strlen(logon_clnt)+1);
401
402         memcpy(q_c->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
403
404         DEBUG(5,("make_q_req_chal: %d\n", __LINE__));
405 }
406
407 /*******************************************************************
408  Reads or writes an NET_Q_REQ_CHAL structure.
409 ********************************************************************/
410
411 BOOL net_io_q_req_chal(char *desc,  NET_Q_REQ_CHAL *q_c, prs_struct *ps, int depth)
412 {
413         int old_align;
414
415         if (q_c == NULL)
416                 return False;
417
418         prs_debug(ps, depth, desc, "net_io_q_req_chal");
419         depth++;
420
421         if(!prs_align(ps))
422                 return False;
423     
424         if(!prs_uint32("undoc_buffer", ps, depth, &q_c->undoc_buffer))
425                 return False;
426
427         if(!smb_io_unistr2("", &q_c->uni_logon_srv, True, ps, depth)) /* logon server unicode string */
428                 return False;
429         if(!smb_io_unistr2("", &q_c->uni_logon_clnt, True, ps, depth)) /* logon client unicode string */
430                 return False;
431
432         old_align = ps->align;
433         ps->align = 0;
434         /* client challenge is _not_ aligned after the unicode strings */
435         if(!smb_io_chal("", &q_c->clnt_chal, ps, depth)) {
436                 /* client challenge */
437                 ps->align = old_align;
438                 return False;
439         }
440         ps->align = old_align;
441
442         return True;
443 }
444
445 /*******************************************************************
446  Reads or writes a structure.
447 ********************************************************************/
448
449 BOOL net_io_r_req_chal(char *desc, NET_R_REQ_CHAL *r_c, prs_struct *ps, int depth)
450 {
451         if (r_c == NULL)
452                 return False;
453
454         prs_debug(ps, depth, desc, "net_io_r_req_chal");
455         depth++;
456
457         if(!prs_align(ps))
458                 return False;
459     
460         if(!smb_io_chal("", &r_c->srv_chal, ps, depth)) /* server challenge */
461                 return False;
462
463         if(!prs_uint32("status", ps, depth, &r_c->status))
464                 return False;
465
466         return True;
467 }
468
469
470 /*******************************************************************
471  Inits a NET_Q_AUTH_2 struct.
472 ********************************************************************/
473
474 void init_q_auth_2(NET_Q_AUTH_2 *q_a,
475                 char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
476                 DOM_CHAL *clnt_chal, uint32 clnt_flgs)
477 {
478         DEBUG(5,("init_q_auth_2: %d\n", __LINE__));
479
480         init_log_info(&q_a->clnt_id, logon_srv, acct_name, sec_chan, comp_name);
481         memcpy(q_a->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
482         q_a->clnt_flgs.neg_flags = clnt_flgs;
483
484         DEBUG(5,("init_q_auth_2: %d\n", __LINE__));
485 }
486
487 /*******************************************************************
488  Reads or writes a structure.
489 ********************************************************************/
490
491 BOOL net_io_q_auth_2(char *desc, NET_Q_AUTH_2 *q_a, prs_struct *ps, int depth)
492 {
493         int old_align;
494         if (q_a == NULL)
495                 return False;
496
497         prs_debug(ps, depth, desc, "net_io_q_auth_2");
498         depth++;
499
500         if(!prs_align(ps))
501                 return False;
502     
503         if(!smb_io_log_info ("", &q_a->clnt_id, ps, depth)) /* client identification info */
504                 return False;
505         /* client challenge is _not_ aligned */
506         old_align = ps->align;
507         ps->align = 0;
508         if(!smb_io_chal("", &q_a->clnt_chal, ps, depth)) {
509                 /* client-calculated credentials */
510                 ps->align = old_align;
511                 return False;
512         }
513         ps->align = old_align;
514         if(!net_io_neg_flags("", &q_a->clnt_flgs, ps, depth))
515                 return False;
516
517         return True;
518 }
519
520 /*******************************************************************
521  Reads or writes a structure.
522 ********************************************************************/
523
524 BOOL net_io_r_auth_2(char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int depth)
525 {
526         if (r_a == NULL)
527                 return False;
528
529         prs_debug(ps, depth, desc, "net_io_r_auth_2");
530         depth++;
531
532         if(!prs_align(ps))
533                 return False;
534     
535         if(!smb_io_chal("", &r_a->srv_chal, ps, depth)) /* server challenge */
536                 return False;
537         if(!net_io_neg_flags("", &r_a->srv_flgs, ps, depth))
538                 return False;
539
540         if(!prs_uint32("status", ps, depth, &r_a->status))
541                 return False;
542
543         return True;
544 }
545
546
547 /*******************************************************************
548  Inits a NET_Q_SRV_PWSET.
549 ********************************************************************/
550
551 void init_q_srv_pwset(NET_Q_SRV_PWSET *q_s, char *logon_srv, char *acct_name, 
552                 uint16 sec_chan, char *comp_name, DOM_CRED *cred, char nt_cypher[16])
553 {
554         DEBUG(5,("make_q_srv_pwset\n"));
555
556         init_clnt_info(&q_s->clnt_id, logon_srv, acct_name, sec_chan, comp_name, cred);
557
558         memcpy(q_s->pwd, nt_cypher, sizeof(q_s->pwd)); 
559 }
560
561 /*******************************************************************
562  Reads or writes a structure.
563 ********************************************************************/
564
565 BOOL net_io_q_srv_pwset(char *desc, NET_Q_SRV_PWSET *q_s, prs_struct *ps, int depth)
566 {
567         if (q_s == NULL)
568                 return False;
569
570         prs_debug(ps, depth, desc, "net_io_q_srv_pwset");
571         depth++;
572
573         if(!prs_align(ps))
574                 return False;
575     
576         if(!smb_io_clnt_info("", &q_s->clnt_id, ps, depth)) /* client identification/authentication info */
577                 return False;
578         if(!prs_uint8s (False, "pwd", ps, depth, q_s->pwd, 16)) /* new password - undocumented */
579                 return False;
580
581         return True;
582 }
583
584 /*******************************************************************
585  Reads or writes a structure.
586 ********************************************************************/
587
588 BOOL net_io_r_srv_pwset(char *desc, NET_R_SRV_PWSET *r_s, prs_struct *ps, int depth)
589 {
590         if (r_s == NULL)
591                 return False;
592
593         prs_debug(ps, depth, desc, "net_io_r_srv_pwset");
594         depth++;
595
596         if(!prs_align(ps))
597                 return False;
598     
599         if(!smb_io_cred("", &r_s->srv_cred, ps, depth)) /* server challenge */
600                 return False;
601
602         if(!prs_uint32("status", ps, depth, &r_s->status))
603                 return False;
604
605         return True;
606 }
607
608 /*************************************************************************
609  Init DOM_SID2 array from a string containing multiple sids
610  *************************************************************************/
611
612 static int init_dom_sid2s(char *sids_str, DOM_SID2 *sids, int max_sids)
613 {
614         char *ptr;
615         pstring s2;
616         int count = 0;
617
618         DEBUG(4,("init_dom_sid2s: %s\n", sids_str ? sids_str:""));
619
620         if(sids_str) {
621                 for (count = 0, ptr = sids_str; 
622                   next_token(&ptr, s2, NULL, sizeof(s2)) && count < max_sids; count++) {
623                         DOM_SID tmpsid;
624                         string_to_sid(&tmpsid, s2);
625                         init_dom_sid2(&sids[count], &tmpsid);
626                 }
627         }
628
629         return count;
630 }
631
632 /*******************************************************************
633  Inits a NET_ID_INFO_1 structure.
634 ********************************************************************/
635
636 void init_id_info1(NET_ID_INFO_1 *id, char *domain_name,
637                                 uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high,
638                                 char *user_name, char *wksta_name,
639                                 char sess_key[16],
640                                 unsigned char lm_cypher[16], unsigned char nt_cypher[16])
641 {
642         int len_domain_name = strlen(domain_name);
643         int len_user_name   = strlen(user_name  );
644         int len_wksta_name  = strlen(wksta_name );
645
646         unsigned char lm_owf[16];
647         unsigned char nt_owf[16];
648
649         DEBUG(5,("make_id_info1: %d\n", __LINE__));
650
651         id->ptr_id_info1 = 1;
652
653         init_uni_hdr(&id->hdr_domain_name, len_domain_name);
654
655         id->param_ctrl = param_ctrl;
656         init_logon_id(&id->logon_id, log_id_low, log_id_high);
657
658         init_uni_hdr(&id->hdr_user_name, len_user_name);
659         init_uni_hdr(&id->hdr_wksta_name, len_wksta_name);
660
661         if (lm_cypher && nt_cypher) {
662                 unsigned char key[16];
663 #ifdef DEBUG_PASSWORD
664                 DEBUG(100,("lm cypher:"));
665                 dump_data(100, (char *)lm_cypher, 16);
666
667                 DEBUG(100,("nt cypher:"));
668                 dump_data(100, (char *)nt_cypher, 16);
669 #endif
670
671                 memset(key, 0, 16);
672                 memcpy(key, sess_key, 8);
673
674                 memcpy(lm_owf, lm_cypher, 16);
675                 SamOEMhash(lm_owf, key, False);
676                 memcpy(nt_owf, nt_cypher, 16);
677                 SamOEMhash(nt_owf, key, False);
678
679 #ifdef DEBUG_PASSWORD
680                 DEBUG(100,("encrypt of lm owf password:"));
681                 dump_data(100, (char *)lm_owf, 16);
682
683                 DEBUG(100,("encrypt of nt owf password:"));
684                 dump_data(100, (char *)nt_owf, 16);
685 #endif
686                 /* set up pointers to cypher blocks */
687                 lm_cypher = lm_owf;
688                 nt_cypher = nt_owf;
689         }
690
691         init_owf_info(&id->lm_owf, lm_cypher);
692         init_owf_info(&id->nt_owf, nt_cypher);
693
694         init_unistr2(&id->uni_domain_name, domain_name, len_domain_name);
695         init_unistr2(&id->uni_user_name, user_name, len_user_name);
696         init_unistr2(&id->uni_wksta_name, wksta_name, len_wksta_name);
697 }
698
699 /*******************************************************************
700  Reads or writes an NET_ID_INFO_1 structure.
701 ********************************************************************/
702
703 static BOOL net_io_id_info1(char *desc,  NET_ID_INFO_1 *id, prs_struct *ps, int depth)
704 {
705         if (id == NULL)
706                 return False;
707
708         prs_debug(ps, depth, desc, "net_io_id_info1");
709         depth++;
710
711         if(!prs_align(ps))
712                 return False;
713         
714         if(!prs_uint32("ptr_id_info1", ps, depth, &id->ptr_id_info1))
715                 return False;
716
717         if (id->ptr_id_info1 != 0) {
718                 if(!smb_io_unihdr("unihdr", &id->hdr_domain_name, ps, depth))
719                         return False;
720
721                 if(!prs_uint32("param_ctrl", ps, depth, &id->param_ctrl))
722                         return False;
723                 if(!smb_io_logon_id("", &id->logon_id, ps, depth))
724                         return False;
725
726                 if(!smb_io_unihdr("unihdr", &id->hdr_user_name, ps, depth))
727                         return False;
728                 if(!smb_io_unihdr("unihdr", &id->hdr_wksta_name, ps, depth))
729                         return False;
730
731                 if(!smb_io_owf_info("", &id->lm_owf, ps, depth))
732                         return False;
733                 if(!smb_io_owf_info("", &id->nt_owf, ps, depth))
734                         return False;
735
736                 if(!smb_io_unistr2("unistr2", &id->uni_domain_name,
737                                 id->hdr_domain_name.buffer, ps, depth))
738                         return False;
739                 if(!smb_io_unistr2("unistr2", &id->uni_user_name,
740                                 id->hdr_user_name.buffer, ps, depth))
741                         return False;
742                 if(!smb_io_unistr2("unistr2", &id->uni_wksta_name,
743                                 id->hdr_wksta_name.buffer, ps, depth))
744                         return False;
745         }
746
747         return True;
748 }
749
750 /*******************************************************************
751 Inits a NET_ID_INFO_2 structure.
752
753 This is a network logon packet. The log_id parameters
754 are what an NT server would generate for LUID once the
755 user is logged on. I don't think we care about them.
756
757 Note that this has no access to the NT and LM hashed passwords,
758 so it forwards the challenge, and the NT and LM responses (24
759 bytes each) over the secure channel to the Domain controller
760 for it to say yea or nay. This is the preferred method of 
761 checking for a logon as it doesn't export the password
762 hashes to anyone who has compromised the secure channel. JRA.
763 ********************************************************************/
764
765 void init_id_info2(NET_ID_INFO_2 *id, char *domain_name,
766                                 uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high,
767                                 char *user_name, char *wksta_name,
768                                 unsigned char lm_challenge[8],
769                                 unsigned char lm_chal_resp[24],
770                                 unsigned char nt_chal_resp[24])
771 {
772         int len_domain_name = strlen(domain_name);
773         int len_user_name   = strlen(user_name  );
774         int len_wksta_name  = strlen(wksta_name );
775         int nt_chal_resp_len = ((nt_chal_resp != NULL) ? 24 : 0);
776         int lm_chal_resp_len = ((lm_chal_resp != NULL) ? 24 : 0);
777         unsigned char lm_owf[24];
778         unsigned char nt_owf[24];
779
780         DEBUG(5,("init_id_info2: %d\n", __LINE__));
781
782         id->ptr_id_info2 = 1;
783
784         init_uni_hdr(&id->hdr_domain_name, len_domain_name);
785
786         id->param_ctrl = param_ctrl;
787         init_logon_id(&id->logon_id, log_id_low, log_id_high);
788
789         init_uni_hdr(&id->hdr_user_name, len_user_name);
790         init_uni_hdr(&id->hdr_wksta_name, len_wksta_name);
791
792         if (nt_chal_resp) {
793                 /* oops.  can only send what-ever-it-is direct */
794                 memcpy(nt_owf, nt_chal_resp, 24);
795                 nt_chal_resp = nt_owf;
796         }
797         if (lm_chal_resp) {
798                 /* oops.  can only send what-ever-it-is direct */
799                 memcpy(lm_owf, lm_chal_resp, 24);
800                 lm_chal_resp = lm_owf;
801         }
802
803         memcpy(id->lm_chal, lm_challenge, sizeof(id->lm_chal));
804         init_str_hdr(&id->hdr_nt_chal_resp, 24, nt_chal_resp_len, (nt_chal_resp != NULL) ? 1 : 0);
805         init_str_hdr(&id->hdr_lm_chal_resp, 24, lm_chal_resp_len, (lm_chal_resp != NULL) ? 1 : 0);
806
807         init_unistr2(&id->uni_domain_name, domain_name, len_domain_name);
808         init_unistr2(&id->uni_user_name, user_name, len_user_name);
809         init_unistr2(&id->uni_wksta_name, wksta_name, len_wksta_name);
810
811         init_string2(&id->nt_chal_resp, (char *)nt_chal_resp, nt_chal_resp_len);
812         init_string2(&id->lm_chal_resp, (char *)lm_chal_resp, lm_chal_resp_len);
813 }
814
815 /*******************************************************************
816  Reads or writes an NET_ID_INFO_2 structure.
817 ********************************************************************/
818
819 static BOOL net_io_id_info2(char *desc,  NET_ID_INFO_2 *id, prs_struct *ps, int depth)
820 {
821         if (id == NULL)
822                 return False;
823
824         prs_debug(ps, depth, desc, "net_io_id_info2");
825         depth++;
826
827         if(!prs_align(ps))
828                 return False;
829         
830         if(!prs_uint32("ptr_id_info2", ps, depth, &id->ptr_id_info2))
831                 return False;
832
833         if (id->ptr_id_info2 != 0) {
834                 if(!smb_io_unihdr("unihdr", &id->hdr_domain_name, ps, depth))
835                         return False;
836
837                 if(!prs_uint32("param_ctrl", ps, depth, &id->param_ctrl))
838                         return False;
839                 if(!smb_io_logon_id("", &id->logon_id, ps, depth))
840                         return False;
841
842                 if(!smb_io_unihdr("unihdr", &id->hdr_user_name, ps, depth))
843                         return False;
844                 if(!smb_io_unihdr("unihdr", &id->hdr_wksta_name, ps, depth))
845                         return False;
846
847                 if(!prs_uint8s (False, "lm_chal", ps, depth, id->lm_chal, 8)) /* lm 8 byte challenge */
848                         return False;
849
850                 if(!smb_io_strhdr("hdr_nt_chal_resp", &id->hdr_nt_chal_resp, ps, depth))
851                         return False;
852                 if(!smb_io_strhdr("hdr_lm_chal_resp", &id->hdr_lm_chal_resp, ps, depth))
853                         return False;
854
855                 if(!smb_io_unistr2("uni_domain_name", &id->uni_domain_name,
856                                 id->hdr_domain_name.buffer, ps, depth))
857                         return False;
858                 if(!smb_io_unistr2("uni_user_name  ", &id->uni_user_name,
859                                 id->hdr_user_name.buffer, ps, depth))
860                         return False;
861                 if(!smb_io_unistr2("uni_wksta_name ", &id->uni_wksta_name,
862                                 id->hdr_wksta_name.buffer, ps, depth))
863                         return False;
864                 if(!smb_io_string2("nt_chal_resp", &id->nt_chal_resp,
865                                 id->hdr_nt_chal_resp.buffer, ps, depth))
866                         return False;
867                 if(!smb_io_string2("lm_chal_resp", &id->lm_chal_resp,
868                                 id->hdr_lm_chal_resp.buffer, ps, depth))
869                         return False;
870         }
871
872         return True;
873 }
874
875
876 /*******************************************************************
877  Inits a DOM_SAM_INFO structure.
878 ********************************************************************/
879
880 void init_sam_info(DOM_SAM_INFO *sam,
881                                 char *logon_srv, char *comp_name, DOM_CRED *clnt_cred,
882                                 DOM_CRED *rtn_cred, uint16 logon_level,
883                                 NET_ID_INFO_CTR *ctr)
884 {
885         DEBUG(5,("init_sam_info: %d\n", __LINE__));
886
887         init_clnt_info2(&(sam->client), logon_srv, comp_name, clnt_cred);
888
889         if (rtn_cred != NULL) {
890                 sam->ptr_rtn_cred = 1;
891                 memcpy(&sam->rtn_cred, rtn_cred, sizeof(sam->rtn_cred));
892         } else {
893                 sam->ptr_rtn_cred = 0;
894         }
895
896         sam->logon_level  = logon_level;
897         sam->ctr          = ctr;
898 }
899
900 /*******************************************************************
901  Reads or writes a DOM_SAM_INFO structure.
902 ********************************************************************/
903
904 static BOOL net_io_id_info_ctr(char *desc, NET_ID_INFO_CTR *ctr, prs_struct *ps, int depth)
905 {
906         if (ctr == NULL)
907                 return False;
908
909         prs_debug(ps, depth, desc, "smb_io_sam_info");
910         depth++;
911
912         /* don't 4-byte align here! */
913
914         if(!prs_uint16("switch_value ", ps, depth, &ctr->switch_value))
915                 return False;
916
917         switch (ctr->switch_value) {
918         case 1:
919                 if(!net_io_id_info1("", &ctr->auth.id1, ps, depth))
920                         return False;
921                 break;
922         case 2:
923                 if(!net_io_id_info2("", &ctr->auth.id2, ps, depth))
924                         return False;
925                 break;
926         default:
927                 /* PANIC! */
928                 DEBUG(4,("smb_io_sam_info: unknown switch_value!\n"));
929                 break;
930         }
931
932         return True;
933 }
934
935 /*******************************************************************
936  Reads or writes a DOM_SAM_INFO structure.
937  ********************************************************************/
938
939 static BOOL smb_io_sam_info(char *desc, DOM_SAM_INFO *sam, prs_struct *ps, int depth)
940 {
941         if (sam == NULL)
942                 return False;
943
944         prs_debug(ps, depth, desc, "smb_io_sam_info");
945         depth++;
946
947         if(!prs_align(ps))
948                 return False;
949         
950         if(!smb_io_clnt_info2("", &sam->client, ps, depth))
951                 return False;
952
953         if(!prs_uint32("ptr_rtn_cred ", ps, depth, &sam->ptr_rtn_cred))
954                 return False;
955         if(!smb_io_cred("", &sam->rtn_cred, ps, depth))
956                 return False;
957
958         if(!prs_uint16("logon_level  ", ps, depth, &sam->logon_level))
959                 return False;
960
961         if (sam->logon_level != 0 && sam->ctr != NULL) {
962                 if(!net_io_id_info_ctr("logon_info", sam->ctr, ps, depth))
963                         return False;
964         }
965
966         return True;
967 }
968
969 /*************************************************************************
970  Init
971  *************************************************************************/
972
973 void init_net_user_info3(NET_USER_INFO_3 *usr,
974
975         NTTIME *logon_time,
976         NTTIME *logoff_time,
977         NTTIME *kickoff_time,
978         NTTIME *pass_last_set_time,
979         NTTIME *pass_can_change_time,
980         NTTIME *pass_must_change_time,
981
982         char *user_name,
983         char *full_name,
984         char *logon_script,
985         char *profile_path,
986         char *home_dir,
987         char *dir_drive,
988
989         uint16 logon_count,
990         uint16 bad_pw_count,
991
992         uint32 user_id,
993         uint32 group_id,
994         uint32 num_groups,
995         DOM_GID *gids,
996         uint32 user_flgs,
997
998         char sess_key[16],
999
1000         char *logon_srv,
1001         char *logon_dom,
1002
1003         DOM_SID *dom_sid,
1004         char *other_sids)
1005 {
1006         /* only cope with one "other" sid, right now. */
1007         /* need to count the number of space-delimited sids */
1008         int i;
1009         int num_other_sids = 0;
1010
1011         int len_user_name    = strlen(user_name   );
1012         int len_full_name    = strlen(full_name   );
1013         int len_logon_script = strlen(logon_script);
1014         int len_profile_path = strlen(profile_path);
1015         int len_home_dir     = strlen(home_dir    );
1016         int len_dir_drive    = strlen(dir_drive   );
1017
1018         int len_logon_srv    = strlen(logon_srv);
1019         int len_logon_dom    = strlen(logon_dom);
1020
1021     memset(usr, '\0', sizeof(*usr));
1022
1023         usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */
1024
1025         usr->logon_time            = *logon_time;
1026         usr->logoff_time           = *logoff_time;
1027         usr->kickoff_time          = *kickoff_time;
1028         usr->pass_last_set_time    = *pass_last_set_time;
1029         usr->pass_can_change_time  = *pass_can_change_time;
1030         usr->pass_must_change_time = *pass_must_change_time;
1031
1032         init_uni_hdr(&usr->hdr_user_name, len_user_name);
1033         init_uni_hdr(&usr->hdr_full_name, len_full_name);
1034         init_uni_hdr(&usr->hdr_logon_script, len_logon_script);
1035         init_uni_hdr(&usr->hdr_profile_path, len_profile_path);
1036         init_uni_hdr(&usr->hdr_home_dir, len_home_dir);
1037         init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive);
1038
1039         usr->logon_count = logon_count;
1040         usr->bad_pw_count = bad_pw_count;
1041
1042         usr->user_id = user_id;
1043         usr->group_id = group_id;
1044         usr->num_groups = num_groups;
1045         usr->buffer_groups = 1; /* indicates fill in groups, below, even if there are none */
1046         usr->user_flgs = user_flgs;
1047
1048         if (sess_key != NULL)
1049                 memcpy(usr->user_sess_key, sess_key, sizeof(usr->user_sess_key));
1050         else
1051                 memset((char *)usr->user_sess_key, '\0', sizeof(usr->user_sess_key));
1052
1053         init_uni_hdr(&usr->hdr_logon_srv, len_logon_srv);
1054         init_uni_hdr(&usr->hdr_logon_dom, len_logon_dom);
1055
1056         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
1057
1058         memset((char *)usr->padding, '\0', sizeof(usr->padding));
1059
1060         num_other_sids = init_dom_sid2s(other_sids, usr->other_sids, LSA_MAX_SIDS);
1061
1062         usr->num_other_sids = num_other_sids;
1063         usr->buffer_other_sids = (num_other_sids != 0) ? 1 : 0; 
1064         
1065         init_unistr2(&usr->uni_user_name, user_name, len_user_name);
1066         init_unistr2(&usr->uni_full_name, full_name, len_full_name);
1067         init_unistr2(&usr->uni_logon_script, logon_script, len_logon_script);
1068         init_unistr2(&usr->uni_profile_path, profile_path, len_profile_path);
1069         init_unistr2(&usr->uni_home_dir, home_dir, len_home_dir);
1070         init_unistr2(&usr->uni_dir_drive, dir_drive, len_dir_drive);
1071
1072         usr->num_groups2 = num_groups;
1073
1074         SMB_ASSERT_ARRAY(usr->gids, num_groups);
1075
1076         for (i = 0; i < num_groups; i++)
1077                 usr->gids[i] = gids[i];
1078
1079         init_unistr2(&usr->uni_logon_srv, logon_srv, len_logon_srv);
1080         init_unistr2(&usr->uni_logon_dom, logon_dom, len_logon_dom);
1081
1082         init_dom_sid2(&usr->dom_sid, dom_sid);
1083         /* "other" sids are set up above */
1084 }
1085
1086
1087 /*******************************************************************
1088  Reads or writes a structure.
1089 ********************************************************************/
1090
1091 static BOOL net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, int depth)
1092 {
1093         int i;
1094
1095         if (usr == NULL)
1096                 return False;
1097
1098         prs_debug(ps, depth, desc, "lsa_io_lsa_user_info");
1099         depth++;
1100
1101         if(!prs_align(ps))
1102                 return False;
1103         
1104         if(!prs_uint32("ptr_user_info ", ps, depth, &usr->ptr_user_info))
1105                 return False;
1106
1107         if (usr->ptr_user_info == 0)
1108                 return True;
1109
1110         if(!smb_io_time("time", &usr->logon_time, ps, depth)) /* logon time */
1111                 return False;
1112         if(!smb_io_time("time", &usr->logoff_time, ps, depth)) /* logoff time */
1113                 return False;
1114         if(!smb_io_time("time", &usr->kickoff_time, ps, depth)) /* kickoff time */
1115                 return False;
1116         if(!smb_io_time("time", &usr->pass_last_set_time, ps, depth)) /* password last set time */
1117                 return False;
1118         if(!smb_io_time("time", &usr->pass_can_change_time , ps, depth)) /* password can change time */
1119                 return False;
1120         if(!smb_io_time("time", &usr->pass_must_change_time, ps, depth)) /* password must change time */
1121                 return False;
1122
1123         if(!smb_io_unihdr("unihdr", &usr->hdr_user_name, ps, depth)) /* username unicode string header */
1124                 return False;
1125         if(!smb_io_unihdr("unihdr", &usr->hdr_full_name, ps, depth)) /* user's full name unicode string header */
1126                 return False;
1127         if(!smb_io_unihdr("unihdr", &usr->hdr_logon_script, ps, depth)) /* logon script unicode string header */
1128                 return False;
1129         if(!smb_io_unihdr("unihdr", &usr->hdr_profile_path, ps, depth)) /* profile path unicode string header */
1130                 return False;
1131         if(!smb_io_unihdr("unihdr", &usr->hdr_home_dir, ps, depth)) /* home directory unicode string header */
1132                 return False;
1133         if(!smb_io_unihdr("unihdr", &usr->hdr_dir_drive, ps, depth)) /* home directory drive unicode string header */
1134                 return False;
1135
1136         if(!prs_uint16("logon_count   ", ps, depth, &usr->logon_count))  /* logon count */
1137                 return False;
1138         if(!prs_uint16("bad_pw_count  ", ps, depth, &usr->bad_pw_count)) /* bad password count */
1139                 return False;
1140
1141         if(!prs_uint32("user_id       ", ps, depth, &usr->user_id))       /* User ID */
1142                 return False;
1143         if(!prs_uint32("group_id      ", ps, depth, &usr->group_id))      /* Group ID */
1144                 return False;
1145         if(!prs_uint32("num_groups    ", ps, depth, &usr->num_groups))    /* num groups */
1146                 return False;
1147         if(!prs_uint32("buffer_groups ", ps, depth, &usr->buffer_groups)) /* undocumented buffer pointer to groups. */
1148                 return False;
1149         if(!prs_uint32("user_flgs     ", ps, depth, &usr->user_flgs))     /* user flags */
1150                 return False;
1151
1152         if(!prs_uint8s(False, "user_sess_key", ps, depth, usr->user_sess_key, 16)) /* unused user session key */
1153                 return False;
1154
1155         if(!smb_io_unihdr("unihdr", &usr->hdr_logon_srv, ps, depth)) /* logon server unicode string header */
1156                 return False;
1157         if(!smb_io_unihdr("unihdr", &usr->hdr_logon_dom, ps, depth)) /* logon domain unicode string header */
1158                 return False;
1159
1160         if(!prs_uint32("buffer_dom_id ", ps, depth, &usr->buffer_dom_id)) /* undocumented logon domain id pointer */
1161                 return False;
1162         if(!prs_uint8s (False, "padding       ", ps, depth, usr->padding, 40)) /* unused padding bytes? */
1163                 return False;
1164
1165         if(!prs_uint32("num_other_sids", ps, depth, &usr->num_other_sids)) /* 0 - num_sids */
1166                 return False;
1167         if(!prs_uint32("buffer_other_sids", ps, depth, &usr->buffer_other_sids)) /* NULL - undocumented pointer to SIDs. */
1168                 return False;
1169                 
1170         if(!smb_io_unistr2("unistr2", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */
1171                 return False;
1172         if(!smb_io_unistr2("unistr2", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */
1173                 return False;
1174         if(!smb_io_unistr2("unistr2", &usr->uni_logon_script, usr->hdr_logon_script.buffer, ps, depth)) /* logon script unicode string */
1175                 return False;
1176         if(!smb_io_unistr2("unistr2", &usr->uni_profile_path, usr->hdr_profile_path.buffer, ps, depth)) /* profile path unicode string */
1177                 return False;
1178         if(!smb_io_unistr2("unistr2", &usr->uni_home_dir, usr->hdr_home_dir.buffer, ps, depth)) /* home directory unicode string */
1179                 return False;
1180         if(!smb_io_unistr2("unistr2", &usr->uni_dir_drive, usr->hdr_dir_drive.buffer, ps, depth)) /* home directory drive unicode string */
1181                 return False;
1182
1183         if(!prs_align(ps))
1184                 return False;
1185         if(!prs_uint32("num_groups2   ", ps, depth, &usr->num_groups2))        /* num groups */
1186                 return False;
1187         SMB_ASSERT_ARRAY(usr->gids, usr->num_groups2);
1188         for (i = 0; i < usr->num_groups2; i++) {
1189                 if(!smb_io_gid("", &usr->gids[i], ps, depth)) /* group info */
1190                         return False;
1191         }
1192
1193         if(!smb_io_unistr2("unistr2", &usr->uni_logon_srv, usr->hdr_logon_srv.buffer, ps, depth)) /* logon server unicode string */
1194                 return False;
1195         if(!smb_io_unistr2("unistr2", &usr->uni_logon_dom, usr->hdr_logon_srv.buffer, ps, depth)) /* logon domain unicode string */
1196                 return False;
1197
1198         if(!smb_io_dom_sid2("", &usr->dom_sid, ps, depth))           /* domain SID */
1199                 return False;
1200
1201         SMB_ASSERT_ARRAY(usr->other_sids, usr->num_other_sids);
1202
1203         for (i = 0; i < usr->num_other_sids; i++) {
1204                 if(!smb_io_dom_sid2("", &usr->other_sids[i], ps, depth)) /* other domain SIDs */
1205                         return False;
1206         }
1207
1208         return True;
1209 }
1210
1211 /*******************************************************************
1212  Reads or writes a structure.
1213 ********************************************************************/
1214
1215 BOOL net_io_q_sam_logon(char *desc, NET_Q_SAM_LOGON *q_l, prs_struct *ps, int depth)
1216 {
1217         if (q_l == NULL)
1218                 return False;
1219
1220         prs_debug(ps, depth, desc, "net_io_q_sam_logon");
1221         depth++;
1222
1223         if(!prs_align(ps))
1224                 return False;
1225         
1226         if(!smb_io_sam_info("", &q_l->sam_id, ps, depth))           /* domain SID */
1227                 return False;
1228
1229         if(!prs_uint16("validation_level", ps, depth, &q_l->validation_level))
1230                 return False;
1231
1232         return True;
1233 }
1234
1235 /*******************************************************************
1236  Reads or writes a structure.
1237 ********************************************************************/
1238
1239 BOOL net_io_r_sam_logon(char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, int depth)
1240 {
1241         if (r_l == NULL)
1242                 return False;
1243
1244         prs_debug(ps, depth, desc, "net_io_r_sam_logon");
1245         depth++;
1246
1247         if(!prs_uint32("buffer_creds", ps, depth, &r_l->buffer_creds)) /* undocumented buffer pointer */
1248                 return False;
1249         if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials.  server time stamp appears to be ignored. */
1250                 return False;
1251
1252         if(!prs_uint16("switch_value", ps, depth, &r_l->switch_value))
1253                 return False;
1254         if(!prs_align(ps))
1255                 return False;
1256
1257         if (r_l->switch_value != 0) {
1258                 if(!net_io_user_info3("", r_l->user, ps, depth))
1259                         return False;
1260         }
1261
1262         if(!prs_uint32("auth_resp   ", ps, depth, &r_l->auth_resp)) /* 1 - Authoritative response; 0 - Non-Auth? */
1263                 return False;
1264
1265         if(!prs_uint32("status      ", ps, depth, &r_l->status))
1266                 return False;
1267
1268         if(!prs_align(ps))
1269                 return False;
1270
1271         return True;
1272 }
1273
1274 /*******************************************************************
1275  Reads or writes a structure.
1276 ********************************************************************/
1277
1278 BOOL net_io_q_sam_logoff(char *desc,  NET_Q_SAM_LOGOFF *q_l, prs_struct *ps, int depth)
1279 {
1280         if (q_l == NULL)
1281                 return False;
1282
1283         prs_debug(ps, depth, desc, "net_io_q_sam_logoff");
1284         depth++;
1285
1286         if(!prs_align(ps))
1287                 return False;
1288         
1289         if(!smb_io_sam_info("", &q_l->sam_id, ps, depth))           /* domain SID */
1290                 return False;
1291
1292         return True;
1293 }
1294
1295 /*******************************************************************
1296  Reads or writes a structure.
1297 ********************************************************************/
1298
1299 BOOL net_io_r_sam_logoff(char *desc, NET_R_SAM_LOGOFF *r_l, prs_struct *ps, int depth)
1300 {
1301         if (r_l == NULL)
1302                 return False;
1303
1304         prs_debug(ps, depth, desc, "net_io_r_sam_logoff");
1305         depth++;
1306
1307         if(!prs_align(ps))
1308                 return False;
1309         
1310         if(!prs_uint32("buffer_creds", ps, depth, &r_l->buffer_creds)) /* undocumented buffer pointer */
1311                 return False;
1312         if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials.  server time stamp appears to be ignored. */
1313                 return False;
1314
1315         if(!prs_uint32("status      ", ps, depth, &r_l->status))
1316                 return False;
1317
1318         return True;
1319 }