r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/samba.git] / source / libads / authdata.c
1 /* 
2    Unix SMB/CIFS implementation.
3    kerberos authorization data (PAC) utility library
4    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003   
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #ifdef HAVE_KRB5
24
25 static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data)
26 {
27         DATA_BLOB pac_contents;
28         ASN1_DATA data;
29         int data_type;
30
31         asn1_load(&data, *auth_data);
32         asn1_start_tag(&data, ASN1_SEQUENCE(0));
33         asn1_start_tag(&data, ASN1_SEQUENCE(0));
34         asn1_start_tag(&data, ASN1_CONTEXT(0));
35         asn1_read_Integer(&data, &data_type);
36         asn1_end_tag(&data);
37         asn1_start_tag(&data, ASN1_CONTEXT(1));
38         asn1_read_OctetString(&data, &pac_contents);
39         asn1_end_tag(&data);
40         asn1_end_tag(&data);
41         asn1_end_tag(&data);
42         asn1_free(&data);
43         return pac_contents;
44 }
45
46 static BOOL pac_io_unknown_type_10(const char *desc, UNKNOWN_TYPE_10 *type_10,
47                                    prs_struct *ps, int depth)
48 {
49         if (NULL == type_10)
50                 return False;
51
52         prs_debug(ps, depth, desc, "pac_io_unknown_type_10");
53         depth++;
54
55         if (!smb_io_time("unknown_time", &type_10->unknown_time, ps, depth))
56                 return False;
57
58         if (!prs_uint16("len", ps, depth, &type_10->len))
59                 return False;
60
61         if (UNMARSHALLING(ps) && type_10->len) {
62                 type_10->username = PRS_ALLOC_MEM(ps, uint16, type_10->len);
63                 if (!type_10->username) {
64                         DEBUG(3, ("No memory available\n"));
65                         return False;
66                 }
67         }
68
69         if (!prs_uint16s(True, "name", ps, depth, type_10->username, 
70                          (type_10->len / sizeof(uint16))))
71                 return False;
72
73         return True;
74
75 }
76
77
78 static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
79                             prs_struct *ps, int depth)
80 {
81         if (NULL == sid_and_attr)
82                 return False;
83
84         prs_debug(ps, depth, desc, "pac_io_krb_sids");
85         depth++;
86
87         if (UNMARSHALLING(ps)) {
88                 sid_and_attr->sid = PRS_ALLOC_MEM(ps, DOM_SID2, 1);
89                 if (!sid_and_attr->sid) {
90                         DEBUG(3, ("No memory available\n"));
91                         return False;
92                 }
93         }
94
95         if(!smb_io_dom_sid2("sid", sid_and_attr->sid, ps, depth))
96                 return False;
97
98         return True;
99 }
100
101
102 static BOOL pac_io_krb_attrs(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
103                              prs_struct *ps, int depth)
104 {
105         if (NULL == sid_and_attr)
106                 return False;
107
108         prs_debug(ps, depth, desc, "pac_io_krb_attrs");
109         depth++;
110
111         if (!prs_uint32("sid_ptr", ps, depth, &sid_and_attr->sid_ptr))
112                 return False;
113         if (!prs_uint32("attrs", ps, depth, &sid_and_attr->attrs))
114                 return False;
115
116         return True;
117 }
118
119 static BOOL pac_io_krb_sid_and_attr_array(const char *desc, 
120                                           KRB_SID_AND_ATTR_ARRAY *array,
121                                           uint32 num,
122                                           prs_struct *ps, int depth)
123 {
124         int i;
125
126         if (NULL == array)
127                 return False;
128
129         prs_debug(ps, depth, desc, "pac_io_krb_sid_and_attr_array");
130         depth++;
131
132
133         if (!prs_uint32("count", ps, depth, &array->count))
134                 return False;
135
136         if (UNMARSHALLING(ps)) {
137                 array->krb_sid_and_attrs = PRS_ALLOC_MEM(ps, KRB_SID_AND_ATTRS, num);
138                 if (!array->krb_sid_and_attrs) {
139                         DEBUG(3, ("No memory available\n"));
140                         return False;
141                 }
142         }
143
144         for (i=0; i<num; i++) {
145                 if (!pac_io_krb_attrs(desc, 
146                                       &array->krb_sid_and_attrs[i],
147                                       ps, depth))
148                         return False;
149
150         }
151         for (i=0; i<num; i++) {
152                 if (!pac_io_krb_sids(desc, 
153                                      &array->krb_sid_and_attrs[i],
154                                      ps, depth))
155                         return False;
156
157         }
158
159         return True;
160
161 }
162
163 static BOOL pac_io_group_membership(const char *desc, 
164                                     GROUP_MEMBERSHIP *membership,
165                                     prs_struct *ps, int depth)
166 {
167         if (NULL == membership)
168                 return False;
169
170         prs_debug(ps, depth, desc, "pac_io_group_membership");
171         depth++;
172
173         if (!prs_uint32("rid", ps, depth, &membership->rid))
174                 return False;
175         if (!prs_uint32("attrs", ps, depth, &membership->attrs))
176                 return False;
177
178         return True;
179 }
180
181
182 static BOOL pac_io_group_membership_array(const char *desc, 
183                                           GROUP_MEMBERSHIP_ARRAY *array,
184                                           uint32 num,
185                                           prs_struct *ps, int depth)
186 {
187         int i;
188
189         if (NULL == array)
190                 return False;
191
192         prs_debug(ps, depth, desc, "pac_io_group_membership_array");
193         depth++;
194
195
196         if (!prs_uint32("count", ps, depth, &array->count))
197                 return False;
198
199         if (UNMARSHALLING(ps)) {
200                 array->group_membership = PRS_ALLOC_MEM(ps, GROUP_MEMBERSHIP, num);
201                 if (!array->group_membership) {
202                         DEBUG(3, ("No memory available\n"));
203                         return False;
204                 }
205         }
206
207         for (i=0; i<num; i++) {
208                 if (!pac_io_group_membership(desc, 
209                                              &array->group_membership[i],
210                                              ps, depth))
211                         return False;
212
213         }
214
215         return True;
216
217 }
218
219 static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 
220                                   prs_struct *ps, int depth)
221 {
222         uint32 garbage;
223         if (NULL == info)
224                 return False;
225
226         prs_debug(ps, depth, desc, "pac_io_pac_logon_info");
227         depth++;
228
229         if (!prs_uint32("unknown", ps, depth, &garbage))
230                 return False;
231         if (!prs_uint32("unknown", ps, depth, &garbage))
232                 return False;
233         if (!prs_uint32("bufferlen", ps, depth, &garbage))
234                 return False;
235         if (!prs_uint32("bufferlenhi", ps, depth, &garbage))
236                 return False;
237         if (!prs_uint32("pointer", ps, depth, &garbage))
238                 return False;
239
240         if (!smb_io_time("logon_time", &info->logon_time, ps, depth))
241                 return False;
242         if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth))
243                 return False;
244         if (!smb_io_time("kickoff_time", &info->kickoff_time, ps, depth))
245                 return False;
246         if (!smb_io_time("pass_last_set_time", &info->pass_last_set_time, 
247                          ps, depth))
248                 return False;
249         if (!smb_io_time("pass_can_change_time", &info->pass_can_change_time, 
250                          ps, depth))
251                 return False;
252         if (!smb_io_time("pass_must_change_time", &info->pass_must_change_time,
253                          ps, depth))
254                 return False;
255
256         if (!smb_io_unihdr("hdr_user_name", &info->hdr_user_name, ps, depth))
257                 return False;
258         if (!smb_io_unihdr("hdr_full_name", &info->hdr_full_name, ps, depth))
259                 return False;
260         if (!smb_io_unihdr("hdr_logon_script", &info->hdr_logon_script, 
261                            ps, depth))
262                 return False;
263         if (!smb_io_unihdr("hdr_profile_path", &info->hdr_profile_path, 
264                            ps, depth))
265                 return False;
266         if (!smb_io_unihdr("hdr_home_dir", &info->hdr_home_dir, ps, depth))
267                 return False;
268         if (!smb_io_unihdr("hdr_dir_drive", &info->hdr_dir_drive, ps, depth))
269                 return False;
270
271         if (!prs_uint16("logon_count", ps, depth, &info->logon_count))
272                 return False;
273         if (!prs_uint16("reserved12", ps, depth, &info->reserved12))
274                 return False;
275         if (!prs_uint32("user_rid", ps, depth, &info->user_rid))
276                 return False;
277         if (!prs_uint32("group_rid", ps, depth, &info->group_rid))
278                 return False;
279         if (!prs_uint32("group_count", ps, depth, &info->group_count))
280                 return False;
281         /* I haven't seen this contain anything yet, but when it does
282            we will have to make sure we decode the contents in the middle
283            all the unistr2s ... */
284         if (!prs_uint32("group_mem_ptr", ps, depth, 
285                         &info->group_membership_ptr))
286                 return False;
287         if (!prs_uint32("user_flags", ps, depth, &info->user_flags))
288                 return False;
289
290         if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0]))
291                 return False;
292         if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1]))
293                 return False;
294         if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2]))
295                 return False;
296         if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3]))
297                 return False;
298         
299         if (!smb_io_unihdr("hdr_dom_controller", 
300                            &info->hdr_dom_controller, ps, depth))
301                 return False;
302         if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth))
303                 return False;
304
305         /* this should be followed, but just get ptr for now */
306         if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid))
307                 return False;
308
309         if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0]))
310                 return False;
311         if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1]))
312                 return False;
313
314         /* might be acb_info */
315         if (!prs_uint32("reserved17", ps, depth, &info->reserved17))
316                 return False;
317
318
319         if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0]))
320                 return False;
321         if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1]))
322                 return False;
323         if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2]))
324                 return False;
325         if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3]))
326                 return False;
327         if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4]))
328                 return False;
329         if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5]))
330                 return False;
331         if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6]))
332                 return False;
333
334         if (!prs_uint32("sid_count", ps, depth, &info->sid_count))
335                 return False;
336         if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids))
337                 return False;
338         if (!prs_uint32("ptr_res_group_dom_sid", ps, depth, 
339                         &info->ptr_res_group_dom_sid))
340                 return False;
341         if (!prs_uint32("res_group_count", ps, depth, &info->res_group_count))
342                 return False;
343         if (!prs_uint32("ptr_res_groups", ps, depth, &info->ptr_res_groups))
344                 return False;
345
346         if(!smb_io_unistr2("uni_user_name", &info->uni_user_name, 
347                            info->hdr_user_name.buffer, ps, depth))
348                 return False;
349         if(!smb_io_unistr2("uni_full_name", &info->uni_full_name, 
350                            info->hdr_full_name.buffer, ps, depth))
351                 return False;
352         if(!smb_io_unistr2("uni_logon_script", &info->uni_logon_script, 
353                            info->hdr_logon_script.buffer, ps, depth))
354                 return False;
355         if(!smb_io_unistr2("uni_profile_path", &info->uni_profile_path,
356                            info->hdr_profile_path.buffer, ps, depth))
357                 return False;
358         if(!smb_io_unistr2("uni_home_dir", &info->uni_home_dir,
359                            info->hdr_home_dir.buffer, ps, depth))
360                 return False;
361         if(!smb_io_unistr2("uni_dir_drive", &info->uni_dir_drive,
362                            info->hdr_dir_drive.buffer, ps, depth))
363                 return False;
364
365         if (info->group_membership_ptr) {
366                 if (!pac_io_group_membership_array("group membership",
367                                                    &info->groups,
368                                                    info->group_count,
369                                                    ps, depth))
370                         return False;
371         }
372
373
374         if(!smb_io_unistr2("uni_dom_controller", &info->uni_dom_controller,
375                            info->hdr_dom_controller.buffer, ps, depth))
376                 return False;
377         if(!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, 
378                            info->hdr_dom_name.buffer, ps, depth))
379                 return False;
380
381         if(info->ptr_dom_sid)
382                 if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
383                         return False;
384
385         
386         if (info->sid_count && info->ptr_extra_sids)
387                 if (!pac_io_krb_sid_and_attr_array("extra_sids", 
388                                                    &info->extra_sids,
389                                                    info->sid_count,
390                                                    ps, depth))
391                         return False;
392
393         if (info->ptr_res_group_dom_sid)
394                 if (!smb_io_dom_sid2("res_group_dom_sid", 
395                                      &info->res_group_dom_sid, ps, depth))
396                         return False;
397
398         if (info->ptr_res_groups)
399                 if (!pac_io_group_membership_array("res group membership",
400                                                    &info->res_groups,
401                                                    info->res_group_count,
402                                                    ps, depth))
403                         return False;
404
405         return True;
406 }
407
408
409 static BOOL pac_io_pac_signature_data(const char *desc, 
410                                       PAC_SIGNATURE_DATA *data, uint32 length,
411                                       prs_struct *ps, int depth)
412 {
413         uint32 siglen = length - sizeof(uint32);
414         if (NULL == data)
415                 return False;
416
417         prs_debug(ps, depth, desc, "pac_io_pac_signature_data");
418         depth++;
419
420         if (!prs_uint32("type", ps, depth, &data->type))
421                 return False;
422         if (UNMARSHALLING(ps)) {
423                 data->signature = PRS_ALLOC_MEM(ps, unsigned char, siglen);
424                 if (!data->signature) {
425                         DEBUG(3, ("No memory available\n"));
426                         return False;
427                 }
428         }
429         if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen))
430                 return False;
431
432         return True;
433 }
434
435 static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
436                                     prs_struct *ps, int depth)
437 {
438         if (NULL == hdr)
439                 return False;
440
441         prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr");
442         depth++;
443
444         if (!prs_align(ps))
445                 return False;
446
447         if (hdr->offset != prs_offset(ps)) {
448                 DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n",
449                           hdr->offset, prs_offset(ps)));
450                 prs_set_offset(ps, hdr->offset);
451         }
452
453         if (UNMARSHALLING(ps) && hdr->size > 0) {
454                 hdr->ctr = PRS_ALLOC_MEM(ps, PAC_INFO_CTR, 1);
455                 if (!hdr->ctr) {
456                         DEBUG(3, ("No memory available\n"));
457                         return False;
458                 }
459         }
460
461         switch(hdr->type) {
462         case PAC_TYPE_LOGON_INFO:
463                 DEBUG(5, ("PAC_TYPE_LOGON_INFO\n"));
464                 if (UNMARSHALLING(ps))
465                         hdr->ctr->pac.logon_info = PRS_ALLOC_MEM(ps, PAC_LOGON_INFO, 1);
466                 if (!hdr->ctr->pac.logon_info) {
467                         DEBUG(3, ("No memory available\n"));
468                         return False;
469                 }
470                 if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info,
471                                            ps, depth))
472                         return False;
473                 break;
474
475         case PAC_TYPE_SERVER_CHECKSUM:
476                 DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n"));
477                 if (UNMARSHALLING(ps))
478                         hdr->ctr->pac.srv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1);
479                 if (!hdr->ctr->pac.srv_cksum) {
480                         DEBUG(3, ("No memory available\n"));
481                         return False;
482                 }
483                 if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum,
484                                                hdr->size, ps, depth))
485                         return False;
486                 break;
487
488         case PAC_TYPE_PRIVSVR_CHECKSUM:
489                 DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n"));
490                 if (UNMARSHALLING(ps))
491                         hdr->ctr->pac.privsrv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1);
492                 if (!hdr->ctr->pac.privsrv_cksum) {
493                         DEBUG(3, ("No memory available\n"));
494                         return False;
495                 }
496                 if (!pac_io_pac_signature_data(desc, 
497                                                hdr->ctr->pac.privsrv_cksum,
498                                                hdr->size, ps, depth))
499                         return False;
500                 break;
501
502         case PAC_TYPE_UNKNOWN_10:
503                 DEBUG(5, ("PAC_TYPE_UNKNOWN_10\n"));
504                 if (UNMARSHALLING(ps))
505                         hdr->ctr->pac.type_10 = PRS_ALLOC_MEM(ps, UNKNOWN_TYPE_10, 1);
506                 if (!hdr->ctr->pac.type_10) {
507                         DEBUG(3, ("No memory available\n"));
508                         return False;
509                 }
510                 if (!pac_io_unknown_type_10(desc, hdr->ctr->pac.type_10,
511                                             ps, depth))
512                         return False;
513                 break;
514
515         default:
516                 /* dont' know, so we need to skip it */
517                 DEBUG(3, ("unknown PAC type %d\n", hdr->type));
518                 prs_set_offset(ps, prs_offset(ps) + hdr->size);
519         }
520
521         return True;
522 }
523
524 static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, 
525                                 prs_struct *ps, int depth)
526 {
527         if (NULL == hdr)
528                 return False;
529
530         prs_debug(ps, depth, desc, "pac_io_pac_info_hdr");
531         depth++;
532
533         if (!prs_align(ps))
534                 return False;
535         if (!prs_uint32("type", ps, depth, &hdr->type))
536                 return False;
537         if (!prs_uint32("size", ps, depth, &hdr->size))
538                 return False;
539         if (!prs_uint32("offset", ps, depth, &hdr->offset))
540                 return False;
541         if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi))
542                 return False;
543
544         return True;
545 }
546
547 static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, 
548                             prs_struct *ps, int depth)
549 {
550         int i;
551
552         if (NULL == data)
553                 return False;
554
555         prs_debug(ps, depth, desc, "pac_io_pac_data");
556         depth++;
557
558         if (!prs_align(ps))
559                 return False;
560         if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers))
561                 return False;
562         if (!prs_uint32("version", ps, depth, &data->version))
563                 return False;
564
565         if (UNMARSHALLING(ps) && data->num_buffers > 0) {
566                 if ((data->pac_info_hdr_ptr = PRS_ALLOC_MEM(ps, PAC_INFO_HDR, data->num_buffers)) == NULL) {
567                         return False;
568                 }
569         }
570
571         for (i=0; i<data->num_buffers; i++) {
572                 if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, 
573                                          depth))
574                         return False;
575         }
576
577         for (i=0; i<data->num_buffers; i++) {
578                 if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i],
579                                              ps, depth))
580                         return False;
581         }
582
583         return True;
584 }
585
586 PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx)
587 {
588         DATA_BLOB pac_data_blob = unwrap_pac(auth_data);
589         prs_struct ps;
590         PAC_DATA *pac_data;
591
592         DEBUG(5,("dump_pac_data\n"));
593         prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL);
594         prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length);
595         prs_set_offset(&ps, 0);
596
597         data_blob_free(&pac_data_blob);
598
599         pac_data = TALLOC_ZERO_P(ctx, PAC_DATA);
600         pac_io_pac_data("pac data", pac_data, &ps, 0);
601
602         prs_mem_free(&ps);
603
604         return pac_data;
605 }
606
607 #endif