2 Unix SMB/CIFS implementation.
3 Samba memory buffer functions
4 Copyright (C) Andrew Tridgell 1992-1997
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1997
6 Copyright (C) Jeremy Allison 1999
7 Copyright (C) Andrew Bartlett 2003.
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 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "../librpc/gen_ndr/ndr_schannel.h"
27 #define DBGC_CLASS DBGC_RPC_PARSE
30 * Dump a prs to a file: from the current location through to the end.
32 void prs_dump(const char *name
, int v
, prs_struct
*ps
)
34 prs_dump_region(name
, v
, ps
, ps
->data_offset
, ps
->buffer_size
);
38 * Dump from the start of the prs to the current location.
40 void prs_dump_before(const char *name
, int v
, prs_struct
*ps
)
42 prs_dump_region(name
, v
, ps
, 0, ps
->data_offset
);
46 * Dump everything from the start of the prs up to the current location.
48 void prs_dump_region(const char *name
, int v
, prs_struct
*ps
,
49 int from_off
, int to_off
)
54 if (DEBUGLEVEL
< 50) return;
57 if (asprintf(&fname
,"/tmp/%s_%d.%d.prs", name
, v
, i
) < 0) {
61 if (asprintf(&fname
,"/tmp/%s.%d.prs", name
, i
) < 0) {
65 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644);
66 if (fd
!= -1 || errno
!= EEXIST
) break;
69 sz
= write(fd
, ps
->data_p
+ from_off
, to_off
- from_off
);
71 if ( (sz
!= to_off
-from_off
) || (i
!= 0) ) {
72 DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname
, (unsigned long)sz
, (unsigned long)to_off
-from_off
, i
));
74 DEBUG(0,("created %s\n", fname
));
80 /*******************************************************************
81 Debug output for parsing info
83 XXXX side-effect of this function is to increase the debug depth XXXX.
85 ********************************************************************/
87 void prs_debug(prs_struct
*ps
, int depth
, const char *desc
, const char *fn_name
)
89 DEBUG(5+depth
, ("%s%06x %s %s\n", tab_depth(5+depth
,depth
), ps
->data_offset
, fn_name
, desc
));
93 * Initialise an expandable parse structure.
95 * @param size Initial buffer size. If >0, a new buffer will be
96 * created with malloc().
98 * @return False if allocation fails, otherwise True.
101 bool prs_init(prs_struct
*ps
, uint32 size
, TALLOC_CTX
*ctx
, bool io
)
105 ps
->bigendian_data
= RPC_LITTLE_ENDIAN
;
106 ps
->align
= RPC_PARSE_ALIGN
;
107 ps
->is_dynamic
= False
;
114 ps
->buffer_size
= size
;
115 if((ps
->data_p
= (char *)SMB_MALLOC((size_t)size
)) == NULL
) {
116 DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size
));
119 memset(ps
->data_p
, '\0', (size_t)size
);
120 ps
->is_dynamic
= True
; /* We own this memory. */
121 } else if (MARSHALLING(ps
)) {
122 /* If size is zero and we're marshalling we should allocate memory on demand. */
123 ps
->is_dynamic
= True
;
129 /*******************************************************************
130 Delete the memory in a parse structure - if we own it.
132 NOTE: Contrary to the somewhat confusing naming, this function is not
133 intended for freeing memory allocated by prs_alloc_mem(). That memory
134 is attached to the talloc context given by ps->mem_ctx.
135 ********************************************************************/
137 void prs_mem_free(prs_struct
*ps
)
140 SAFE_FREE(ps
->data_p
);
141 ps
->is_dynamic
= False
;
146 /*******************************************************************
147 Clear the memory in a parse structure.
148 ********************************************************************/
150 void prs_mem_clear(prs_struct
*ps
)
153 memset(ps
->data_p
, '\0', (size_t)ps
->buffer_size
);
156 /*******************************************************************
157 Allocate memory when unmarshalling... Always zero clears.
158 ********************************************************************/
160 #if defined(PARANOID_MALLOC_CHECKER)
161 char *prs_alloc_mem_(prs_struct
*ps
, size_t size
, unsigned int count
)
163 char *prs_alloc_mem(prs_struct
*ps
, size_t size
, unsigned int count
)
169 /* We can't call the type-safe version here. */
170 ret
= (char *)_talloc_zero_array(ps
->mem_ctx
, size
, count
,
176 /*******************************************************************
177 Return the current talloc context we're using.
178 ********************************************************************/
180 TALLOC_CTX
*prs_get_mem_context(prs_struct
*ps
)
185 /*******************************************************************
186 Hand some already allocated memory to a prs_struct.
187 ********************************************************************/
189 void prs_give_memory(prs_struct
*ps
, char *buf
, uint32 size
, bool is_dynamic
)
191 ps
->is_dynamic
= is_dynamic
;
193 ps
->buffer_size
= size
;
196 /*******************************************************************
197 Take some memory back from a prs_struct.
198 ********************************************************************/
200 char *prs_take_memory(prs_struct
*ps
, uint32
*psize
)
202 char *ret
= ps
->data_p
;
204 *psize
= ps
->buffer_size
;
205 ps
->is_dynamic
= False
;
210 /*******************************************************************
211 Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary.
212 ********************************************************************/
214 bool prs_set_buffer_size(prs_struct
*ps
, uint32 newsize
)
216 if (newsize
> ps
->buffer_size
)
217 return prs_force_grow(ps
, newsize
- ps
->buffer_size
);
219 if (newsize
< ps
->buffer_size
) {
220 ps
->buffer_size
= newsize
;
222 /* newsize == 0 acts as a free and set pointer to NULL */
224 SAFE_FREE(ps
->data_p
);
226 ps
->data_p
= (char *)SMB_REALLOC(ps
->data_p
, newsize
);
228 if (ps
->data_p
== NULL
) {
229 DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
230 (unsigned int)newsize
));
231 DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno
)));
240 /*******************************************************************
241 Attempt, if needed, to grow a data buffer.
242 Also depends on the data stream mode (io).
243 ********************************************************************/
245 bool prs_grow(prs_struct
*ps
, uint32 extra_space
)
249 ps
->grow_size
= MAX(ps
->grow_size
, ps
->data_offset
+ extra_space
);
251 if(ps
->data_offset
+ extra_space
<= ps
->buffer_size
)
255 * We cannot grow the buffer if we're not reading
256 * into the prs_struct, or if we don't own the memory.
259 if(UNMARSHALLING(ps
) || !ps
->is_dynamic
) {
260 DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
261 (unsigned int)extra_space
));
266 * Decide how much extra space we really need.
269 extra_space
-= (ps
->buffer_size
- ps
->data_offset
);
270 if(ps
->buffer_size
== 0) {
273 * Start with 128 bytes (arbitrary value), enough for small rpc
276 new_size
= MAX(128, extra_space
);
278 if((ps
->data_p
= (char *)SMB_MALLOC(new_size
)) == NULL
) {
279 DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size
));
282 memset(ps
->data_p
, '\0', (size_t)new_size
);
285 * If the current buffer size is bigger than the space needed,
286 * just double it, else add extra_space. Always keep 64 bytes
287 * more, so that after we added a large blob we don't have to
288 * realloc immediately again.
290 new_size
= MAX(ps
->buffer_size
*2,
291 ps
->buffer_size
+ extra_space
+ 64);
293 if ((ps
->data_p
= (char *)SMB_REALLOC(ps
->data_p
, new_size
)) == NULL
) {
294 DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
295 (unsigned int)new_size
));
299 memset(&ps
->data_p
[ps
->buffer_size
], '\0', (size_t)(new_size
- ps
->buffer_size
));
301 ps
->buffer_size
= new_size
;
306 /*******************************************************************
307 Attempt to force a data buffer to grow by len bytes.
308 This is only used when appending more data onto a prs_struct
309 when reading an rpc reply, before unmarshalling it.
310 ********************************************************************/
312 bool prs_force_grow(prs_struct
*ps
, uint32 extra_space
)
314 uint32 new_size
= ps
->buffer_size
+ extra_space
;
316 if(!UNMARSHALLING(ps
) || !ps
->is_dynamic
) {
317 DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
318 (unsigned int)extra_space
));
322 if((ps
->data_p
= (char *)SMB_REALLOC(ps
->data_p
, new_size
)) == NULL
) {
323 DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",
324 (unsigned int)new_size
));
328 memset(&ps
->data_p
[ps
->buffer_size
], '\0', (size_t)(new_size
- ps
->buffer_size
));
330 ps
->buffer_size
= new_size
;
335 /*******************************************************************
336 Get the data pointer (external interface).
337 ********************************************************************/
339 char *prs_data_p(prs_struct
*ps
)
344 /*******************************************************************
345 Get the current data size (external interface).
346 ********************************************************************/
348 uint32
prs_data_size(prs_struct
*ps
)
350 return ps
->buffer_size
;
353 /*******************************************************************
354 Fetch the current offset (external interface).
355 ********************************************************************/
357 uint32
prs_offset(prs_struct
*ps
)
359 return ps
->data_offset
;
362 /*******************************************************************
363 Set the current offset (external interface).
364 ********************************************************************/
366 bool prs_set_offset(prs_struct
*ps
, uint32 offset
)
368 if ((offset
> ps
->data_offset
)
369 && !prs_grow(ps
, offset
- ps
->data_offset
)) {
373 ps
->data_offset
= offset
;
377 /*******************************************************************
378 Append the data from one parse_struct into another.
379 ********************************************************************/
381 bool prs_append_prs_data(prs_struct
*dst
, prs_struct
*src
)
383 if (prs_offset(src
) == 0)
386 if(!prs_grow(dst
, prs_offset(src
)))
389 memcpy(&dst
->data_p
[dst
->data_offset
], src
->data_p
, (size_t)prs_offset(src
));
390 dst
->data_offset
+= prs_offset(src
);
395 /*******************************************************************
396 Append some data from one parse_struct into another.
397 ********************************************************************/
399 bool prs_append_some_data(prs_struct
*dst
, void *src_base
, uint32_t start
,
406 if(!prs_grow(dst
, len
)) {
410 memcpy(&dst
->data_p
[dst
->data_offset
], ((char *)src_base
) + start
, (size_t)len
);
411 dst
->data_offset
+= len
;
415 bool prs_append_some_prs_data(prs_struct
*dst
, prs_struct
*src
, int32 start
,
418 return prs_append_some_data(dst
, src
->data_p
, start
, len
);
421 /*******************************************************************
422 Append the data from a buffer into a parse_struct.
423 ********************************************************************/
425 bool prs_copy_data_in(prs_struct
*dst
, const char *src
, uint32 len
)
430 if(!prs_grow(dst
, len
))
433 memcpy(&dst
->data_p
[dst
->data_offset
], src
, (size_t)len
);
434 dst
->data_offset
+= len
;
439 /*******************************************************************
440 Copy some data from a parse_struct into a buffer.
441 ********************************************************************/
443 bool prs_copy_data_out(char *dst
, prs_struct
*src
, uint32 len
)
448 if(!prs_mem_get(src
, len
))
451 memcpy(dst
, &src
->data_p
[src
->data_offset
], (size_t)len
);
452 src
->data_offset
+= len
;
457 /*******************************************************************
458 Copy all the data from a parse_struct into a buffer.
459 ********************************************************************/
461 bool prs_copy_all_data_out(char *dst
, prs_struct
*src
)
463 uint32 len
= prs_offset(src
);
468 prs_set_offset(src
, 0);
469 return prs_copy_data_out(dst
, src
, len
);
472 /*******************************************************************
473 Set the data as X-endian (external interface).
474 ********************************************************************/
476 void prs_set_endian_data(prs_struct
*ps
, bool endian
)
478 ps
->bigendian_data
= endian
;
481 /*******************************************************************
482 Align a the data_len to a multiple of align bytes - filling with
484 ********************************************************************/
486 bool prs_align(prs_struct
*ps
)
488 uint32 mod
= ps
->data_offset
& (ps
->align
-1);
490 if (ps
->align
!= 0 && mod
!= 0) {
491 uint32 extra_space
= (ps
->align
- mod
);
492 if(!prs_grow(ps
, extra_space
))
494 memset(&ps
->data_p
[ps
->data_offset
], '\0', (size_t)extra_space
);
495 ps
->data_offset
+= extra_space
;
501 /******************************************************************
502 Align on a 2 byte boundary
503 *****************************************************************/
505 bool prs_align_uint16(prs_struct
*ps
)
508 uint8 old_align
= ps
->align
;
512 ps
->align
= old_align
;
517 /******************************************************************
518 Align on a 8 byte boundary
519 *****************************************************************/
521 bool prs_align_uint64(prs_struct
*ps
)
524 uint8 old_align
= ps
->align
;
528 ps
->align
= old_align
;
533 /******************************************************************
534 Align on a specific byte boundary
535 *****************************************************************/
537 bool prs_align_custom(prs_struct
*ps
, uint8 boundary
)
540 uint8 old_align
= ps
->align
;
542 ps
->align
= boundary
;
544 ps
->align
= old_align
;
551 /*******************************************************************
552 Align only if required (for the unistr2 string mainly)
553 ********************************************************************/
555 bool prs_align_needed(prs_struct
*ps
, uint32 needed
)
560 return prs_align(ps
);
563 /*******************************************************************
564 Ensure we can read/write to a given offset.
565 ********************************************************************/
567 char *prs_mem_get(prs_struct
*ps
, uint32 extra_size
)
569 if(UNMARSHALLING(ps
)) {
571 * If reading, ensure that we can read the requested size item.
573 if (ps
->data_offset
+ extra_size
> ps
->buffer_size
) {
574 DEBUG(0,("prs_mem_get: reading data of size %u would overrun "
575 "buffer by %u bytes.\n",
576 (unsigned int)extra_size
,
577 (unsigned int)(ps
->data_offset
+ extra_size
- ps
->buffer_size
) ));
582 * Writing - grow the buffer if needed.
584 if(!prs_grow(ps
, extra_size
))
587 return &ps
->data_p
[ps
->data_offset
];
590 /*******************************************************************
591 Change the struct type.
592 ********************************************************************/
594 void prs_switch_type(prs_struct
*ps
, bool io
)
596 if ((ps
->io
^ io
) == True
)
600 /*******************************************************************
601 Force a prs_struct to be dynamic even when it's size is 0.
602 ********************************************************************/
604 void prs_force_dynamic(prs_struct
*ps
)
609 /*******************************************************************
610 Associate a session key with a parse struct.
611 ********************************************************************/
613 void prs_set_session_key(prs_struct
*ps
, const char sess_key
[16])
615 ps
->sess_key
= sess_key
;
618 /*******************************************************************
620 ********************************************************************/
622 bool prs_uint8(const char *name
, prs_struct
*ps
, int depth
, uint8
*data8
)
624 char *q
= prs_mem_get(ps
, 1);
628 if (UNMARSHALLING(ps
))
633 DEBUGADD(5,("%s%04x %s: %02x\n", tab_depth(5,depth
), ps
->data_offset
, name
, *data8
));
635 ps
->data_offset
+= 1;
640 /*******************************************************************
642 ********************************************************************/
644 bool prs_uint16(const char *name
, prs_struct
*ps
, int depth
, uint16
*data16
)
646 char *q
= prs_mem_get(ps
, sizeof(uint16
));
650 if (UNMARSHALLING(ps
)) {
651 if (ps
->bigendian_data
)
652 *data16
= RSVAL(q
,0);
656 if (ps
->bigendian_data
)
662 DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth
), ps
->data_offset
, name
, *data16
));
664 ps
->data_offset
+= sizeof(uint16
);
669 /*******************************************************************
671 ********************************************************************/
673 bool prs_uint32(const char *name
, prs_struct
*ps
, int depth
, uint32
*data32
)
675 char *q
= prs_mem_get(ps
, sizeof(uint32
));
679 if (UNMARSHALLING(ps
)) {
680 if (ps
->bigendian_data
)
681 *data32
= RIVAL(q
,0);
685 if (ps
->bigendian_data
)
691 DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth
), ps
->data_offset
, name
, *data32
));
693 ps
->data_offset
+= sizeof(uint32
);
698 /*******************************************************************
700 ********************************************************************/
702 bool prs_int32(const char *name
, prs_struct
*ps
, int depth
, int32
*data32
)
704 char *q
= prs_mem_get(ps
, sizeof(int32
));
708 if (UNMARSHALLING(ps
)) {
709 if (ps
->bigendian_data
)
710 *data32
= RIVALS(q
,0);
712 *data32
= IVALS(q
,0);
714 if (ps
->bigendian_data
)
715 RSIVALS(q
,0,*data32
);
720 DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth
), ps
->data_offset
, name
, *data32
));
722 ps
->data_offset
+= sizeof(int32
);
727 /*******************************************************************
728 Stream a uint64_struct
729 ********************************************************************/
730 bool prs_uint64(const char *name
, prs_struct
*ps
, int depth
, uint64
*data64
)
732 if (UNMARSHALLING(ps
)) {
735 if (!prs_uint32(name
, ps
, depth
+1, &low
))
738 if (!prs_uint32(name
, ps
, depth
+1, &high
))
741 *data64
= ((uint64_t)high
<< 32) + low
;
745 uint32 high
= (*data64
) >> 32, low
= (*data64
) & 0xFFFFFFFF;
746 return prs_uint32(name
, ps
, depth
+1, &low
) &&
747 prs_uint32(name
, ps
, depth
+1, &high
);
751 /*******************************************************************
752 Stream a DCE error code
753 ********************************************************************/
755 bool prs_dcerpc_status(const char *name
, prs_struct
*ps
, int depth
, NTSTATUS
*status
)
757 char *q
= prs_mem_get(ps
, sizeof(uint32
));
761 if (UNMARSHALLING(ps
)) {
762 if (ps
->bigendian_data
)
763 *status
= NT_STATUS(RIVAL(q
,0));
765 *status
= NT_STATUS(IVAL(q
,0));
767 if (ps
->bigendian_data
)
768 RSIVAL(q
,0,NT_STATUS_V(*status
));
770 SIVAL(q
,0,NT_STATUS_V(*status
));
773 DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth
), ps
->data_offset
, name
,
774 dcerpc_errstr(debug_ctx(), NT_STATUS_V(*status
))));
776 ps
->data_offset
+= sizeof(uint32
);
781 /******************************************************************
782 Stream an array of uint8s. Length is number of uint8s.
783 ********************************************************************/
785 bool prs_uint8s(bool charmode
, const char *name
, prs_struct
*ps
, int depth
, uint8
*data8s
, int len
)
788 char *q
= prs_mem_get(ps
, len
);
792 if (UNMARSHALLING(ps
)) {
793 for (i
= 0; i
< len
; i
++)
794 data8s
[i
] = CVAL(q
,i
);
796 for (i
= 0; i
< len
; i
++)
797 SCVAL(q
, i
, data8s
[i
]);
800 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth
), ps
->data_offset
,name
));
802 print_asc(5, (unsigned char*)data8s
, len
);
804 for (i
= 0; i
< len
; i
++)
805 DEBUGADD(5,("%02x ", data8s
[i
]));
809 ps
->data_offset
+= len
;
814 /******************************************************************
815 Stream an array of uint16s. Length is number of uint16s.
816 ********************************************************************/
818 bool prs_uint16s(bool charmode
, const char *name
, prs_struct
*ps
, int depth
, uint16
*data16s
, int len
)
821 char *q
= prs_mem_get(ps
, len
* sizeof(uint16
));
825 if (UNMARSHALLING(ps
)) {
826 if (ps
->bigendian_data
) {
827 for (i
= 0; i
< len
; i
++)
828 data16s
[i
] = RSVAL(q
, 2*i
);
830 for (i
= 0; i
< len
; i
++)
831 data16s
[i
] = SVAL(q
, 2*i
);
834 if (ps
->bigendian_data
) {
835 for (i
= 0; i
< len
; i
++)
836 RSSVAL(q
, 2*i
, data16s
[i
]);
838 for (i
= 0; i
< len
; i
++)
839 SSVAL(q
, 2*i
, data16s
[i
]);
843 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth
), ps
->data_offset
, name
));
845 print_asc(5, (unsigned char*)data16s
, 2*len
);
847 for (i
= 0; i
< len
; i
++)
848 DEBUGADD(5,("%04x ", data16s
[i
]));
852 ps
->data_offset
+= (len
* sizeof(uint16
));
857 /******************************************************************
858 Stream an array of uint32s. Length is number of uint32s.
859 ********************************************************************/
861 bool prs_uint32s(bool charmode
, const char *name
, prs_struct
*ps
, int depth
, uint32
*data32s
, int len
)
864 char *q
= prs_mem_get(ps
, len
* sizeof(uint32
));
868 if (UNMARSHALLING(ps
)) {
869 if (ps
->bigendian_data
) {
870 for (i
= 0; i
< len
; i
++)
871 data32s
[i
] = RIVAL(q
, 4*i
);
873 for (i
= 0; i
< len
; i
++)
874 data32s
[i
] = IVAL(q
, 4*i
);
877 if (ps
->bigendian_data
) {
878 for (i
= 0; i
< len
; i
++)
879 RSIVAL(q
, 4*i
, data32s
[i
]);
881 for (i
= 0; i
< len
; i
++)
882 SIVAL(q
, 4*i
, data32s
[i
]);
886 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth
), ps
->data_offset
, name
));
888 print_asc(5, (unsigned char*)data32s
, 4*len
);
890 for (i
= 0; i
< len
; i
++)
891 DEBUGADD(5,("%08x ", data32s
[i
]));
895 ps
->data_offset
+= (len
* sizeof(uint32
));
900 /*******************************************************************
901 Stream a unicode null-terminated string. As the string is already
902 in little-endian format then do it as a stream of bytes.
903 ********************************************************************/
905 bool prs_unistr(const char *name
, prs_struct
*ps
, int depth
, UNISTR
*str
)
907 unsigned int len
= 0;
908 unsigned char *p
= (unsigned char *)str
->buffer
;
914 if (MARSHALLING(ps
)) {
916 for(len
= 0; str
->buffer
[len
] != 0; len
++)
919 q
= prs_mem_get(ps
, (len
+1)*2);
925 for(len
= 0; str
->buffer
[len
] != 0; len
++) {
926 if(ps
->bigendian_data
) {
927 /* swap bytes - p is little endian, q is big endian. */
943 * even if the string is 'empty' (only an \0 char)
944 * at this point the leading \0 hasn't been parsed.
954 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth
), ps
->data_offset
, name
));
955 print_asc(5, (unsigned char*)start
, 2*len
);
958 else { /* unmarshalling */
960 uint32 alloc_len
= 0;
961 q
= ps
->data_p
+ prs_offset(ps
);
964 * Work out how much space we need and talloc it.
966 max_len
= (ps
->buffer_size
- ps
->data_offset
)/sizeof(uint16
);
968 /* the test of the value of *ptr helps to catch the circumstance
969 where we have an emtpty (non-existent) string in the buffer */
970 for ( ptr
= (uint16
*)q
; *ptr
++ && (alloc_len
<= max_len
); alloc_len
++)
974 if (alloc_len
< max_len
)
977 /* should we allocate anything at all? */
978 str
->buffer
= PRS_ALLOC_MEM(ps
,uint16
,alloc_len
);
979 if ((str
->buffer
== NULL
) && (alloc_len
> 0))
982 p
= (unsigned char *)str
->buffer
;
985 /* the (len < alloc_len) test is to prevent us from overwriting
986 memory that is not ours...if we get that far, we have a non-null
987 terminated string in the buffer and have messed up somewhere */
988 while ((len
< alloc_len
) && (*(uint16
*)q
!= 0)) {
989 if(ps
->bigendian_data
)
991 /* swap bytes - q is big endian, p is little endian. */
992 p
[0] = (unsigned char)q
[1];
993 p
[1] = (unsigned char)q
[0];
998 p
[0] = (unsigned char)q
[0];
999 p
[1] = (unsigned char)q
[1];
1006 if (len
< alloc_len
) {
1007 /* NULL terminate the UNISTR */
1008 str
->buffer
[len
++] = '\0';
1011 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth
), ps
->data_offset
, name
));
1012 print_asc(5, (unsigned char*)str
->buffer
, 2*len
);
1013 DEBUGADD(5, ("\n"));
1016 /* set the offset in the prs_struct; 'len' points to the
1017 terminiating NULL in the UNISTR so we need to go one more
1019 ps
->data_offset
+= (len
)*2;
1025 /*******************************************************************
1026 Stream a null-terminated string. len is strlen, and therefore does
1027 not include the null-termination character.
1028 ********************************************************************/
1030 bool prs_string(const char *name
, prs_struct
*ps
, int depth
, char *str
, int max_buf_size
)
1036 if (UNMARSHALLING(ps
))
1037 len
= strlen(&ps
->data_p
[ps
->data_offset
]);
1041 len
= MIN(len
, (max_buf_size
-1));
1043 q
= prs_mem_get(ps
, len
+1);
1047 for(i
= 0; i
< len
; i
++) {
1048 if (UNMARSHALLING(ps
))
1054 /* The terminating null. */
1057 if (MARSHALLING(ps
)) {
1061 ps
->data_offset
+= len
+1;
1063 dump_data(5+depth
, (uint8
*)q
, len
);
1068 /*******************************************************************
1069 Create a digest over the entire packet (including the data), and
1070 MD5 it with the session key.
1071 ********************************************************************/
1073 static void schannel_digest(struct schannel_auth_struct
*a
,
1074 enum pipe_auth_level auth_level
,
1075 struct NL_AUTH_SIGNATURE
*verf
,
1076 char *data
, size_t data_len
,
1077 uchar digest_final
[16])
1079 uchar whole_packet_digest
[16];
1081 struct MD5Context ctx3
;
1087 SSVAL(sig
,0,verf
->SignatureAlgorithm
);
1088 SSVAL(sig
,2,verf
->SealAlgorithm
);
1089 SSVAL(sig
,4,verf
->Pad
);
1090 SSVAL(sig
,6,verf
->Flags
);
1092 /* verfiy the signature on the packet by MD5 over various bits */
1094 /* use our sequence number, which ensures the packet is not
1096 MD5Update(&ctx3
, zeros
, sizeof(zeros
));
1097 MD5Update(&ctx3
, sig
, 8);
1098 if (auth_level
== PIPE_AUTH_LEVEL_PRIVACY
) {
1099 MD5Update(&ctx3
, verf
->Confounder
, sizeof(verf
->Confounder
));
1101 MD5Update(&ctx3
, (const unsigned char *)data
, data_len
);
1102 MD5Final(whole_packet_digest
, &ctx3
);
1103 dump_data_pw("whole_packet_digest:\n", whole_packet_digest
, sizeof(whole_packet_digest
));
1105 /* MD5 this result and the session key, to prove that
1106 only a valid client could had produced this */
1107 hmac_md5(a
->sess_key
, whole_packet_digest
, sizeof(whole_packet_digest
), digest_final
);
1110 /*******************************************************************
1111 Calculate the key with which to encode the data payload
1112 ********************************************************************/
1114 static void schannel_get_sealing_key(struct schannel_auth_struct
*a
,
1115 struct NL_AUTH_SIGNATURE
*verf
,
1116 uchar sealing_key
[16])
1125 for (i
= 0; i
< sizeof(sess_kf0
); i
++) {
1126 sess_kf0
[i
] = a
->sess_key
[i
] ^ 0xf0;
1129 dump_data_pw("sess_kf0:\n", sess_kf0
, sizeof(sess_kf0
));
1131 /* MD5 of sess_kf0 and 4 zero bytes */
1132 hmac_md5(sess_kf0
, zeros
, 0x4, digest2
);
1133 dump_data_pw("digest2:\n", digest2
, sizeof(digest2
));
1135 /* MD5 of the above result, plus 8 bytes of sequence number */
1136 hmac_md5(digest2
, verf
->SequenceNumber
, sizeof(verf
->SequenceNumber
), sealing_key
);
1137 dump_data_pw("sealing_key:\n", sealing_key
, 16);
1140 /*******************************************************************
1141 Encode or Decode the sequence number (which is symmetric)
1142 ********************************************************************/
1144 static void schannel_deal_with_seq_num(struct schannel_auth_struct
*a
,
1145 struct NL_AUTH_SIGNATURE
*verf
)
1148 uchar sequence_key
[16];
1153 hmac_md5(a
->sess_key
, zeros
, sizeof(zeros
), digest1
);
1154 dump_data_pw("(sequence key) digest1:\n", digest1
, sizeof(digest1
));
1156 hmac_md5(digest1
, verf
->Checksum
, 8, sequence_key
);
1158 dump_data_pw("sequence_key:\n", sequence_key
, sizeof(sequence_key
));
1160 dump_data_pw("seq_num (before):\n", verf
->SequenceNumber
, sizeof(verf
->SequenceNumber
));
1161 arcfour_crypt(verf
->SequenceNumber
, sequence_key
, 8);
1162 dump_data_pw("seq_num (after):\n", verf
->SequenceNumber
, sizeof(verf
->SequenceNumber
));
1165 /*******************************************************************
1166 Encode a blob of data using the schannel alogrithm, also produceing
1167 a checksum over the original data. We currently only support
1168 signing and sealing togeather - the signing-only code is close, but not
1169 quite compatible with what MS does.
1170 ********************************************************************/
1172 void schannel_encode(struct schannel_auth_struct
*a
, enum pipe_auth_level auth_level
,
1173 enum schannel_direction direction
,
1174 struct NL_AUTH_SIGNATURE
*verf
,
1175 char *data
, size_t data_len
)
1177 uchar digest_final
[16];
1178 uchar confounder
[8];
1180 static const uchar nullbytes
[8] = { 0, };
1182 DEBUG(10,("SCHANNEL: schannel_encode seq_num=%d data_len=%lu\n", a
->seq_num
, (unsigned long)data_len
));
1184 /* fill the 'confounder' with random data */
1185 generate_random_buffer(confounder
, sizeof(confounder
));
1187 dump_data_pw("a->sess_key:\n", a
->sess_key
, sizeof(a
->sess_key
));
1189 RSIVAL(seq_num
, 0, a
->seq_num
);
1191 switch (direction
) {
1192 case SENDER_IS_INITIATOR
:
1193 SIVAL(seq_num
, 4, 0x80);
1195 case SENDER_IS_ACCEPTOR
:
1196 SIVAL(seq_num
, 4, 0x0);
1200 dump_data_pw("verf->SequenceNumber:\n", verf
->SequenceNumber
, sizeof(verf
->SequenceNumber
));
1202 if (auth_level
== PIPE_AUTH_LEVEL_PRIVACY
) {
1203 verf
->SealAlgorithm
= NL_SEAL_RC4
;
1205 verf
->SealAlgorithm
= NL_SEAL_NONE
;
1208 verf
->SignatureAlgorithm
= NL_SIGN_HMAC_MD5
;
1210 verf
->Flags
= 0x0000;
1212 memcpy(verf
->SequenceNumber
, seq_num
, sizeof(verf
->SequenceNumber
));
1213 memcpy(verf
->Checksum
, nullbytes
, sizeof(verf
->Checksum
));
1214 memcpy(verf
->Confounder
, confounder
, sizeof(verf
->Confounder
));
1216 /* produce a digest of the packet to prove it's legit (before we seal it) */
1217 schannel_digest(a
, auth_level
, verf
, data
, data_len
, digest_final
);
1218 memcpy(verf
->Checksum
, digest_final
, sizeof(verf
->Checksum
));
1220 if (auth_level
== PIPE_AUTH_LEVEL_PRIVACY
) {
1221 uchar sealing_key
[16];
1223 /* get the key to encode the data with */
1224 schannel_get_sealing_key(a
, verf
, sealing_key
);
1226 /* encode the verification data */
1227 dump_data_pw("verf->Confounder:\n", verf
->Confounder
, sizeof(verf
->Confounder
));
1228 arcfour_crypt(verf
->Confounder
, sealing_key
, 8);
1230 dump_data_pw("verf->Confounder_enc:\n", verf
->Confounder
, sizeof(verf
->Confounder
));
1232 /* encode the packet payload */
1233 dump_data_pw("data:\n", (const unsigned char *)data
, data_len
);
1234 arcfour_crypt((unsigned char *)data
, sealing_key
, data_len
);
1235 dump_data_pw("data_enc:\n", (const unsigned char *)data
, data_len
);
1238 /* encode the sequence number (key based on packet digest) */
1239 /* needs to be done after the sealing, as the original version
1240 is used in the sealing stuff... */
1241 schannel_deal_with_seq_num(a
, verf
);
1246 /*******************************************************************
1247 Decode a blob of data using the schannel alogrithm, also verifiying
1248 a checksum over the original data. We currently can verify signed messages,
1249 as well as decode sealed messages
1250 ********************************************************************/
1252 bool schannel_decode(struct schannel_auth_struct
*a
, enum pipe_auth_level auth_level
,
1253 enum schannel_direction direction
,
1254 struct NL_AUTH_SIGNATURE
*verf
, char *data
, size_t data_len
)
1256 uchar digest_final
[16];
1258 static const uchar schannel_seal_sig
[8] = SCHANNEL_SEAL_SIGNATURE
;
1259 static const uchar schannel_sign_sig
[8] = SCHANNEL_SIGN_SIGNATURE
;
1260 const uchar
*schannel_sig
= NULL
;
1264 DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a
->seq_num
, (unsigned long)data_len
));
1266 if (auth_level
== PIPE_AUTH_LEVEL_PRIVACY
) {
1267 schannel_sig
= schannel_seal_sig
;
1269 schannel_sig
= schannel_sign_sig
;
1272 /* Create the expected sequence number for comparison */
1273 RSIVAL(seq_num
, 0, a
->seq_num
);
1275 switch (direction
) {
1276 case SENDER_IS_INITIATOR
:
1277 SIVAL(seq_num
, 4, 0x80);
1279 case SENDER_IS_ACCEPTOR
:
1280 SIVAL(seq_num
, 4, 0x0);
1284 DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a
->seq_num
, (unsigned long)data_len
));
1285 dump_data_pw("a->sess_key:\n", a
->sess_key
, sizeof(a
->sess_key
));
1287 dump_data_pw("seq_num:\n", seq_num
, sizeof(seq_num
));
1289 /* extract the sequence number (key based on supplied packet digest) */
1290 /* needs to be done before the sealing, as the original version
1291 is used in the sealing stuff... */
1292 schannel_deal_with_seq_num(a
, verf
);
1294 if (memcmp(verf
->SequenceNumber
, seq_num
, sizeof(seq_num
))) {
1295 /* don't even bother with the below if the sequence number is out */
1296 /* The sequence number is MD5'ed with a key based on the whole-packet
1297 digest, as supplied by the client. We check that it's a valid
1298 checksum after the decode, below
1300 DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n"));
1301 dump_data(2, verf
->SequenceNumber
, sizeof(verf
->SequenceNumber
));
1302 DEBUG(2, ("should be:\n"));
1303 dump_data(2, seq_num
, sizeof(seq_num
));
1308 if (memcmp(&verf
->SignatureAlgorithm
, &schannel_sig
[0], 2) ||
1309 memcmp(&verf
->SealAlgorithm
, &schannel_sig
[2], 2) ||
1310 memcmp(&verf
->Pad
, &schannel_sig
[4], 2) ||
1311 memcmp(&verf
->Flags
, &schannel_sig
[6], 2)) {
1312 /* Validate that the other end sent the expected header */
1313 DEBUG(2, ("schannel_decode: FAILED: packet header:\n"));
1314 dump_data(2, (const uint8_t *)verf
, sizeof(schannel_sig
));
1315 DEBUG(2, ("should be:\n"));
1316 dump_data(2, schannel_sig
, sizeof(schannel_sig
));
1320 if (auth_level
== PIPE_AUTH_LEVEL_PRIVACY
) {
1321 uchar sealing_key
[16];
1323 /* get the key to extract the data with */
1324 schannel_get_sealing_key(a
, verf
, sealing_key
);
1326 /* extract the verification data */
1327 dump_data_pw("verf->Confounder:\n", verf
->Confounder
,
1328 sizeof(verf
->Confounder
));
1329 arcfour_crypt(verf
->Confounder
, sealing_key
, 8);
1331 dump_data_pw("verf->Confounder_dec:\n", verf
->Confounder
,
1332 sizeof(verf
->Confounder
));
1334 /* extract the packet payload */
1335 dump_data_pw("data :\n", (const unsigned char *)data
, data_len
);
1336 arcfour_crypt((unsigned char *)data
, sealing_key
, data_len
);
1337 dump_data_pw("datadec:\n", (const unsigned char *)data
, data_len
);
1340 /* digest includes 'data' after unsealing */
1341 schannel_digest(a
, auth_level
, verf
, data
, data_len
, digest_final
);
1343 dump_data_pw("Calculated digest:\n", digest_final
,
1344 sizeof(digest_final
));
1345 dump_data_pw("verf->Checksum:\n", verf
->Checksum
,
1346 sizeof(verf
->Checksum
));
1348 /* compare - if the client got the same result as us, then
1349 it must know the session key */
1350 return (memcmp(digest_final
, verf
->Checksum
,
1351 sizeof(verf
->Checksum
)) == 0);
1354 /*******************************************************************
1355 creates a new prs_struct containing a DATA_BLOB
1356 ********************************************************************/
1357 bool prs_init_data_blob(prs_struct
*prs
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
1359 if (!prs_init( prs
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
))
1363 if (!prs_copy_data_in(prs
, (char *)blob
->data
, blob
->length
))
1369 /*******************************************************************
1370 return the contents of a prs_struct in a DATA_BLOB
1371 ********************************************************************/
1372 bool prs_data_blob(prs_struct
*prs
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
1374 blob
->length
= prs_data_size(prs
);
1375 blob
->data
= (uint8
*)TALLOC_ZERO_SIZE(mem_ctx
, blob
->length
);
1377 /* set the pointer at the end of the buffer */
1378 prs_set_offset( prs
, prs_data_size(prs
) );
1380 if (!prs_copy_all_data_out((char *)blob
->data
, prs
))