Decode the PAC! This patch just decodes it and then frees it, so it's just
[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 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         return pac_contents;
43 }
44
45 static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
46                             prs_struct *ps, int depth)
47 {
48         if (NULL == sid_and_attr)
49                 return False;
50
51         prs_debug(ps, depth, desc, "pac_io_krb_sids");
52         depth++;
53
54         if (UNMARSHALLING(ps)) {
55                 sid_and_attr->sid = 
56                         (DOM_SID2 * ) prs_alloc_mem(ps, sizeof(DOM_SID2));
57                 if (!sid_and_attr->sid) {
58                         DEBUG(3, ("No memory available\n"));
59                         return False;
60                 }
61         }
62
63         if(!smb_io_dom_sid2("sid", sid_and_attr->sid, ps, depth))
64                 return False;
65
66         return True;
67 }
68
69
70 static BOOL pac_io_krb_attrs(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
71                              prs_struct *ps, int depth)
72 {
73         if (NULL == sid_and_attr)
74                 return False;
75
76         prs_debug(ps, depth, desc, "pac_io_krb_attrs");
77         depth++;
78
79         if (!prs_uint32("sid_ptr", ps, depth, &sid_and_attr->sid_ptr))
80                 return False;
81         if (!prs_uint32("attrs", ps, depth, &sid_and_attr->attrs))
82                 return False;
83
84         return True;
85 }
86
87 static BOOL pac_io_krb_sid_and_attr_array(const char *desc, 
88                                           KRB_SID_AND_ATTR_ARRAY *array,
89                                           uint32 num,
90                                           prs_struct *ps, int depth)
91 {
92         int i;
93
94         if (NULL == array)
95                 return False;
96
97         prs_debug(ps, depth, desc, "pac_io_krb_sid_and_attr_array");
98         depth++;
99
100
101         if (!prs_uint32("count", ps, depth, &array->count))
102                 return False;
103
104         if (UNMARSHALLING(ps)) {
105                 array->krb_sid_and_attrs = (KRB_SID_AND_ATTRS *)
106                         prs_alloc_mem(ps, sizeof(KRB_SID_AND_ATTRS) * num);
107                 if (!array->krb_sid_and_attrs) {
108                         DEBUG(3, ("No memory available\n"));
109                         return False;
110                 }
111         }
112
113         for (i=0; i<num; i++) {
114                 if (!pac_io_krb_attrs(desc, 
115                                       &array->krb_sid_and_attrs[i],
116                                       ps, depth))
117                         return False;
118
119         }
120         for (i=0; i<num; i++) {
121                 if (!pac_io_krb_sids(desc, 
122                                      &array->krb_sid_and_attrs[i],
123                                      ps, depth))
124                         return False;
125
126         }
127
128         return True;
129
130 }
131
132 static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 
133                                   prs_struct *ps, int depth)
134 {
135         uint32 garbage;
136         if (NULL == info)
137                 return False;
138
139         prs_debug(ps, depth, desc, "pac_io_pac_logon_info");
140         depth++;
141
142         if (!prs_uint32("unknown", ps, depth, &garbage))
143                 return False;
144         if (!prs_uint32("unknown", ps, depth, &garbage))
145                 return False;
146         if (!prs_uint32("bufferlen", ps, depth, &garbage))
147                 return False;
148         if (!prs_uint32("bufferlenhi", ps, depth, &garbage))
149                 return False;
150         if (!prs_uint32("pointer", ps, depth, &garbage))
151                 return False;
152
153         if (!smb_io_time("logon_time", &info->logon_time, ps, depth))
154                 return False;
155         if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth))
156                 return False;
157         if (!smb_io_time("kickoff_time", &info->kickoff_time, ps, depth))
158                 return False;
159         if (!smb_io_time("pass_last_set_time", &info->pass_last_set_time, 
160                          ps, depth))
161                 return False;
162         if (!smb_io_time("pass_can_change_time", &info->pass_can_change_time, 
163                          ps, depth))
164                 return False;
165         if (!smb_io_time("pass_must_change_time", &info->pass_must_change_time,
166                          ps, depth))
167                 return False;
168
169         if (!smb_io_unihdr("hdr_user_name", &info->hdr_user_name, ps, depth))
170                 return False;
171         if (!smb_io_unihdr("hdr_full_name", &info->hdr_full_name, ps, depth))
172                 return False;
173         if (!smb_io_unihdr("hdr_logon_script", &info->hdr_logon_script, 
174                            ps, depth))
175                 return False;
176         if (!smb_io_unihdr("hdr_profile_path", &info->hdr_profile_path, 
177                            ps, depth))
178                 return False;
179         if (!smb_io_unihdr("hdr_home_dir", &info->hdr_home_dir, ps, depth))
180                 return False;
181         if (!smb_io_unihdr("hdr_dir_drive", &info->hdr_dir_drive, ps, depth))
182                 return False;
183
184         if (!prs_uint16("logon_count", ps, depth, &info->logon_count))
185                 return False;
186         if (!prs_uint16("reserved12", ps, depth, &info->reserved12))
187                 return False;
188         if (!prs_uint32("user_rid", ps, depth, &info->user_rid))
189                 return False;
190         if (!prs_uint32("group_rid", ps, depth, &info->group_rid))
191                 return False;
192         if (!prs_uint32("group_count", ps, depth, &info->group_count))
193                 return False;
194         /* I haven't seen this contain anything yet, but when it does
195            we will have to make sure we decode the contents in the middle
196            all the unistr2s ... */
197         if (!prs_uint32("group_mem_ptr", ps, depth, 
198                         &info->group_membership_ptr))
199                 return False;
200         if (!prs_uint32("user_flags", ps, depth, &info->user_flags))
201                 return False;
202
203         if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0]))
204                 return False;
205         if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1]))
206                 return False;
207         if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2]))
208                 return False;
209         if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3]))
210                 return False;
211         
212         if (!smb_io_unihdr("hdr_dom_controller", 
213                            &info->hdr_dom_controller, ps, depth))
214                 return False;
215         if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth))
216                 return False;
217
218         /* this should be followed, but just get ptr for now */
219         if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid))
220                 return False;
221
222         if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0]))
223                 return False;
224         if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1]))
225                 return False;
226
227         /* might be acb_info */
228         if (!prs_uint32("reserved17", ps, depth, &info->reserved17))
229                 return False;
230
231
232         if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0]))
233                 return False;
234         if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1]))
235                 return False;
236         if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2]))
237                 return False;
238         if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3]))
239                 return False;
240         if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4]))
241                 return False;
242         if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5]))
243                 return False;
244         if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6]))
245                 return False;
246
247         if (!prs_uint32("sid_count", ps, depth, &info->sid_count))
248                 return False;
249         if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids))
250                 return False;
251         if (!prs_uint32("ptr_res_group_dom_sid", ps, depth, 
252                         &info->ptr_res_group_dom_sid))
253                 return False;
254         if (!prs_uint32("res_group_count", ps, depth, &info->res_group_count))
255                 return False;
256         if (!prs_uint32("ptr_res_group_sids", ps, depth, 
257                         &info->ptr_res_group_sids))
258                 return False;
259
260         if(!smb_io_unistr2("uni_user_name", &info->uni_user_name, 
261                            info->hdr_user_name.buffer, ps, depth))
262                 return False;
263         if(!smb_io_unistr2("uni_full_name", &info->uni_full_name, 
264                            info->hdr_full_name.buffer, ps, depth))
265                 return False;
266         if(!smb_io_unistr2("uni_logon_script", &info->uni_logon_script, 
267                            info->hdr_logon_script.buffer, ps, depth))
268                 return False;
269         if(!smb_io_unistr2("uni_profile_path", &info->uni_profile_path,
270                            info->hdr_profile_path.buffer, ps, depth))
271                 return False;
272         if(!smb_io_unistr2("uni_home_dir", &info->uni_home_dir,
273                            info->hdr_home_dir.buffer, ps, depth))
274                 return False;
275         if(!smb_io_unistr2("uni_dir_drive", &info->uni_dir_drive,
276                            info->hdr_dir_drive.buffer, ps, depth))
277                 return False;
278
279         /* the group membership list will need to be handled here */
280
281         if(!smb_io_unistr2("uni_dom_controller", &info->uni_dom_controller,
282                            info->hdr_dom_controller.buffer, ps, depth))
283                 return False;
284         if(!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, 
285                            info->hdr_dom_name.buffer, ps, depth))
286                 return False;
287
288         if(info->ptr_dom_sid)
289                 if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
290                         return False;
291
292         
293         if (info->sid_count && info->ptr_extra_sids) {
294                 if (!pac_io_krb_sid_and_attr_array("extra_sids", 
295                                                    &info->extra_sids,
296                                                    info->sid_count,
297                                                    ps, depth))
298                         return False;
299         }               
300
301
302         return True;
303 }
304
305
306 static BOOL pac_io_pac_signature_data(const char *desc, 
307                                       PAC_SIGNATURE_DATA *data, uint32 length,
308                                       prs_struct *ps, int depth)
309 {
310         uint32 siglen = length - sizeof(uint32);
311         if (NULL == data)
312                 return False;
313
314         prs_debug(ps, depth, desc, "pac_io_pac_signature_data");
315         depth++;
316
317         if (!prs_uint32("type", ps, depth, &data->type))
318                 return False;
319         if (UNMARSHALLING(ps)) {
320                 data->signature = prs_alloc_mem(ps, siglen);
321                 if (!data->signature) {
322                         DEBUG(3, ("No memory available\n"));
323                         return False;
324                 }
325         }
326         if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen))
327                 return False;
328
329         return True;
330 }
331
332 static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
333                                     prs_struct *ps, int depth)
334 {
335         if (NULL == hdr)
336                 return False;
337
338         prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr");
339         depth++;
340
341         if (!prs_align(ps))
342                 return False;
343
344         if (hdr->offset != prs_offset(ps)) {
345                 DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n",
346                           hdr->offset, prs_offset(ps)));
347                 prs_set_offset(ps, hdr->offset);
348         }
349
350         if (UNMARSHALLING(ps) && hdr->size > 0) {
351                 hdr->ctr = (PAC_INFO_CTR *) 
352                         prs_alloc_mem(ps, sizeof(PAC_INFO_CTR));
353                 if (!hdr->ctr) {
354                         DEBUG(3, ("No memory available\n"));
355                         return False;
356                 }
357         }
358
359         switch(hdr->type) {
360         case PAC_TYPE_LOGON_INFO:
361                 DEBUG(5, ("PAC_TYPE_LOGON_INFO\n"));
362                 if (UNMARSHALLING(ps))
363                         hdr->ctr->pac.logon_info = (PAC_LOGON_INFO *)
364                                 prs_alloc_mem(ps, sizeof(PAC_LOGON_INFO));
365                 if (!hdr->ctr->pac.logon_info) {
366                         DEBUG(3, ("No memory available\n"));
367                         return False;
368                 }
369                 if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info,
370                                            ps, depth))
371                         return False;
372                 break;
373
374         case PAC_TYPE_SERVER_CHECKSUM:
375                 DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n"));
376                 if (UNMARSHALLING(ps))
377                         hdr->ctr->pac.srv_cksum = (PAC_SIGNATURE_DATA *)
378                                 prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA));
379                 if (!hdr->ctr->pac.srv_cksum) {
380                         DEBUG(3, ("No memory available\n"));
381                         return False;
382                 }
383                 if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum,
384                                                hdr->size, ps, depth))
385                         return False;
386                 break;
387
388         case PAC_TYPE_PRIVSVR_CHECKSUM:
389                 DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n"));
390                 if (UNMARSHALLING(ps))
391                         hdr->ctr->pac.privsrv_cksum = (PAC_SIGNATURE_DATA *)
392                                 prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA));
393                 if (!hdr->ctr->pac.privsrv_cksum) {
394                         DEBUG(3, ("No memory available\n"));
395                         return False;
396                 }
397                 if (!pac_io_pac_signature_data(desc, 
398                                                hdr->ctr->pac.privsrv_cksum,
399                                                hdr->size, ps, depth))
400                         return False;
401                 break;
402
403         default:
404                 /* dont' know, so we need to skip it */
405                 DEBUG(3, ("unknown PAC type %d\n", hdr->type));
406                 prs_set_offset(ps, prs_offset(ps) + hdr->size);
407         }
408
409         return True;
410 }
411
412 static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, 
413                                 prs_struct *ps, int depth)
414 {
415         if (NULL == hdr)
416                 return False;
417
418         prs_debug(ps, depth, desc, "pac_io_pac_info_hdr");
419         depth++;
420
421         if (!prs_align(ps))
422                 return False;
423         if (!prs_uint32("type", ps, depth, &hdr->type))
424                 return False;
425         if (!prs_uint32("size", ps, depth, &hdr->size))
426                 return False;
427         if (!prs_uint32("offset", ps, depth, &hdr->offset))
428                 return False;
429         if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi))
430                 return False;
431
432         return True;
433 }
434
435 static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, 
436                             prs_struct *ps, int depth)
437 {
438         int i;
439
440         if (NULL == data)
441                 return False;
442
443         prs_debug(ps, depth, desc, "pac_io_pac_data");
444         depth++;
445
446         if (!prs_align(ps))
447                 return False;
448         if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers))
449                 return False;
450         if (!prs_uint32("version", ps, depth, &data->version))
451                 return False;
452
453         if (UNMARSHALLING(ps) && data->num_buffers > 0) {
454                 if ((data->pac_info_hdr_ptr = (PAC_INFO_HDR *) 
455                      prs_alloc_mem(ps, sizeof(PAC_INFO_HDR) * 
456                                    data->num_buffers)) == NULL) {
457                         return False;
458                 }
459         }
460
461         for (i=0; i<data->num_buffers; i++) {
462                 if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, 
463                                          depth))
464                         return False;
465         }
466
467         for (i=0; i<data->num_buffers; i++) {
468                 if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i],
469                                              ps, depth))
470                         return False;
471         }
472
473         return True;
474 }
475
476 PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx)
477 {
478         DATA_BLOB pac_data_blob = unwrap_pac(auth_data);
479         prs_struct ps;
480         PAC_DATA *pac_data;
481
482         DEBUG(5,("dump_pac_data\n"));
483         prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL);
484         prs_copy_data_in(&ps, pac_data_blob.data, pac_data_blob.length);
485         prs_set_offset(&ps, 0);
486
487         pac_data = (PAC_DATA *) talloc_zero(ctx, sizeof(PAC_DATA));
488         pac_io_pac_data("pac data", pac_data, &ps, 0);
489
490         prs_mem_free(&ps);
491
492         return pac_data;
493 }
494
495 #endif