2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
38 struct PAC_INFO_BUFFER
{
48 struct PAC_INFO_BUFFER buffers
[1];
51 struct krb5_pac_data
{
54 struct PAC_INFO_BUFFER
*server_checksum
;
55 struct PAC_INFO_BUFFER
*privsvr_checksum
;
56 struct PAC_INFO_BUFFER
*logon_name
;
59 #define PAC_ALIGNMENT 8
61 #define PACTYPE_SIZE 8
62 #define PAC_INFO_BUFFER_SIZE 16
64 #define PAC_SERVER_CHECKSUM 6
65 #define PAC_PRIVSVR_CHECKSUM 7
66 #define PAC_LOGON_NAME 10
67 #define PAC_CONSTRAINED_DELEGATION 11
69 #define CHECK(r,f,l) \
71 if (((r) = f ) != 0) { \
72 krb5_clear_error_string(context); \
77 static const char zeros
[PAC_ALIGNMENT
] = { 0 };
84 krb5_pac_parse(krb5_context context
, const void *ptr
, size_t len
,
89 krb5_storage
*sp
= NULL
;
90 uint32_t i
, tmp
, tmp2
, header_end
;
92 p
= calloc(1, sizeof(*p
));
95 krb5_set_error_string(context
, "out of memory");
99 sp
= krb5_storage_from_readonly_mem(ptr
, len
);
102 krb5_set_error_string(context
, "out of memory");
105 krb5_storage_set_flags(sp
, KRB5_STORAGE_BYTEORDER_LE
);
107 CHECK(ret
, krb5_ret_uint32(sp
, &tmp
), out
);
108 CHECK(ret
, krb5_ret_uint32(sp
, &tmp2
), out
);
110 krb5_set_error_string(context
, "PAC have too few buffer");
111 ret
= EINVAL
; /* Too few buffers */
115 krb5_set_error_string(context
, "PAC have wrong version");
116 ret
= EINVAL
; /* Wrong version */
121 sizeof(*p
->pac
) + (sizeof(p
->pac
->buffers
[0]) * (tmp
- 1)));
122 if (p
->pac
== NULL
) {
123 krb5_set_error_string(context
, "out of memory");
128 p
->pac
->numbuffers
= tmp
;
129 p
->pac
->version
= tmp2
;
131 header_end
= PACTYPE_SIZE
+ (PAC_INFO_BUFFER_SIZE
* p
->pac
->numbuffers
);
132 if (header_end
> len
) {
137 for (i
= 0; i
< p
->pac
->numbuffers
; i
++) {
138 CHECK(ret
, krb5_ret_uint32(sp
, &p
->pac
->buffers
[i
].type
), out
);
139 CHECK(ret
, krb5_ret_uint32(sp
, &p
->pac
->buffers
[i
].buffersize
), out
);
140 CHECK(ret
, krb5_ret_uint32(sp
, &p
->pac
->buffers
[i
].offset_lo
), out
);
141 CHECK(ret
, krb5_ret_uint32(sp
, &p
->pac
->buffers
[i
].offset_hi
), out
);
143 /* consistency checks */
144 if (p
->pac
->buffers
[i
].offset_lo
& (PAC_ALIGNMENT
- 1)) {
145 krb5_set_error_string(context
, "PAC out of allignment");
149 if (p
->pac
->buffers
[i
].offset_hi
) {
150 krb5_set_error_string(context
, "PAC high offset set");
154 if (p
->pac
->buffers
[i
].offset_lo
> len
) {
155 krb5_set_error_string(context
, "PAC offset off end");
159 if (p
->pac
->buffers
[i
].offset_lo
< header_end
) {
160 krb5_set_error_string(context
, "PAC offset inside header: %d %d",
161 p
->pac
->buffers
[i
].offset_lo
, header_end
);
165 if (p
->pac
->buffers
[i
].buffersize
> len
- p
->pac
->buffers
[i
].offset_lo
){
166 krb5_set_error_string(context
, "PAC length off end");
171 /* let save pointer to data we need later */
172 if (p
->pac
->buffers
[i
].type
== PAC_SERVER_CHECKSUM
) {
173 if (p
->server_checksum
) {
174 krb5_set_error_string(context
, "PAC have two server checksums");
178 p
->server_checksum
= &p
->pac
->buffers
[i
];
179 } else if (p
->pac
->buffers
[i
].type
== PAC_PRIVSVR_CHECKSUM
) {
180 if (p
->privsvr_checksum
) {
181 krb5_set_error_string(context
, "PAC have two KDC checksums");
185 p
->privsvr_checksum
= &p
->pac
->buffers
[i
];
186 } else if (p
->pac
->buffers
[i
].type
== PAC_LOGON_NAME
) {
188 krb5_set_error_string(context
, "PAC have two logon names");
192 p
->logon_name
= &p
->pac
->buffers
[i
];
196 ret
= krb5_data_copy(&p
->data
, ptr
, len
);
200 krb5_storage_free(sp
);
207 krb5_storage_free(sp
);
219 krb5_pac_init(krb5_context context
, krb5_pac
*pac
)
224 p
= calloc(1, sizeof(*p
));
226 krb5_set_error_string(context
, "out of memory");
230 p
->pac
= calloc(1, sizeof(*p
->pac
));
231 if (p
->pac
== NULL
) {
233 krb5_set_error_string(context
, "out of memory");
237 ret
= krb5_data_alloc(&p
->data
, PACTYPE_SIZE
);
241 krb5_set_error_string(context
, "out of memory");
251 krb5_pac_add_buffer(krb5_context context
, krb5_pac p
,
252 uint32_t type
, const krb5_data
*data
)
256 size_t len
, offset
, header_end
, old_end
;
259 len
= p
->pac
->numbuffers
;
261 ptr
= realloc(p
->pac
,
262 sizeof(*p
->pac
) + (sizeof(p
->pac
->buffers
[0]) * len
));
264 krb5_set_error_string(context
, "out of memory");
269 for (i
= 0; i
< len
; i
++)
270 p
->pac
->buffers
[i
].offset_lo
+= PAC_INFO_BUFFER_SIZE
;
272 offset
= p
->data
.length
+ PAC_INFO_BUFFER_SIZE
;
274 p
->pac
->buffers
[len
].type
= type
;
275 p
->pac
->buffers
[len
].buffersize
= data
->length
;
276 p
->pac
->buffers
[len
].offset_lo
= offset
;
277 p
->pac
->buffers
[len
].offset_hi
= 0;
279 old_end
= p
->data
.length
;
280 len
= p
->data
.length
+ data
->length
+ PAC_INFO_BUFFER_SIZE
;
281 if (len
< p
->data
.length
) {
282 krb5_set_error_string(context
, "integer overrun");
286 /* align to PAC_ALIGNMENT */
287 len
= ((len
+ PAC_ALIGNMENT
- 1) / PAC_ALIGNMENT
) * PAC_ALIGNMENT
;
289 ret
= krb5_data_realloc(&p
->data
, len
);
291 krb5_set_error_string(context
, "out of memory");
296 * make place for new PAC INFO BUFFER header
298 header_end
= PACTYPE_SIZE
+ (PAC_INFO_BUFFER_SIZE
* p
->pac
->numbuffers
);
299 memmove((unsigned char *)p
->data
.data
+ header_end
+ PAC_INFO_BUFFER_SIZE
,
300 (unsigned char *)p
->data
.data
+ header_end
,
301 old_end
- header_end
);
302 memset((unsigned char *)p
->data
.data
+ header_end
, 0, PAC_INFO_BUFFER_SIZE
);
305 * copy in new data part
308 memcpy((unsigned char *)p
->data
.data
+ offset
,
309 data
->data
, data
->length
);
310 memset((unsigned char *)p
->data
.data
+ offset
+ data
->length
,
311 0, p
->data
.length
- offset
- data
->length
);
313 p
->pac
->numbuffers
+= 1;
319 krb5_pac_get_buffer(krb5_context context
, krb5_pac p
,
320 uint32_t type
, krb5_data
*data
)
326 * Hide the checksums from external consumers
329 if (type
== PAC_PRIVSVR_CHECKSUM
|| type
== PAC_SERVER_CHECKSUM
) {
330 ret
= krb5_data_alloc(data
, 16);
332 krb5_set_error_string(context
, "out of memory");
335 memset(data
->data
, 0, data
->length
);
339 for (i
= 0; i
< p
->pac
->numbuffers
; i
++) {
340 size_t len
= p
->pac
->buffers
[i
].buffersize
;
341 size_t offset
= p
->pac
->buffers
[i
].offset_lo
;
343 if (p
->pac
->buffers
[i
].type
!= type
)
346 ret
= krb5_data_copy(data
, (unsigned char *)p
->data
.data
+ offset
, len
);
348 krb5_set_error_string(context
, "Out of memory");
353 krb5_set_error_string(context
, "No PAC buffer of type %lu was found",
354 (unsigned long)type
);
363 krb5_pac_get_types(krb5_context context
,
370 *types
= calloc(p
->pac
->numbuffers
, sizeof(*types
));
371 if (*types
== NULL
) {
373 krb5_set_error_string(context
, "out of memory");
376 for (i
= 0; i
< p
->pac
->numbuffers
; i
++)
377 (*types
)[i
] = p
->pac
->buffers
[i
].type
;
378 *len
= p
->pac
->numbuffers
;
388 krb5_pac_free(krb5_context context
, krb5_pac pac
)
390 krb5_data_free(&pac
->data
);
399 static krb5_error_code
400 verify_checksum(krb5_context context
,
401 const struct PAC_INFO_BUFFER
*sig
,
402 const krb5_data
*data
,
403 void *ptr
, size_t len
,
404 const krb5_keyblock
*key
)
406 krb5_crypto crypto
= NULL
;
407 krb5_storage
*sp
= NULL
;
412 memset(&cksum
, 0, sizeof(cksum
));
414 sp
= krb5_storage_from_mem((char *)data
->data
+ sig
->offset_lo
,
417 krb5_set_error_string(context
, "out of memory");
420 krb5_storage_set_flags(sp
, KRB5_STORAGE_BYTEORDER_LE
);
422 CHECK(ret
, krb5_ret_uint32(sp
, &type
), out
);
423 cksum
.cksumtype
= type
;
424 cksum
.checksum
.length
=
425 sig
->buffersize
- krb5_storage_seek(sp
, 0, SEEK_CUR
);
426 cksum
.checksum
.data
= malloc(cksum
.checksum
.length
);
427 if (cksum
.checksum
.data
== NULL
) {
428 krb5_set_error_string(context
, "out of memory");
432 ret
= krb5_storage_read(sp
, cksum
.checksum
.data
, cksum
.checksum
.length
);
433 if (ret
!= cksum
.checksum
.length
) {
434 krb5_set_error_string(context
, "PAC checksum missing checksum");
439 if (!krb5_checksum_is_keyed(context
, cksum
.cksumtype
)) {
440 krb5_set_error_string (context
, "Checksum type %d not keyed",
446 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
450 ret
= krb5_verify_checksum(context
, crypto
, KRB5_KU_OTHER_CKSUM
,
452 free(cksum
.checksum
.data
);
453 krb5_crypto_destroy(context
, crypto
);
454 krb5_storage_free(sp
);
459 if (cksum
.checksum
.data
)
460 free(cksum
.checksum
.data
);
462 krb5_storage_free(sp
);
464 krb5_crypto_destroy(context
, crypto
);
468 static krb5_error_code
469 create_checksum(krb5_context context
,
470 const krb5_keyblock
*key
,
471 void *data
, size_t datalen
,
472 void *sig
, size_t siglen
)
474 krb5_crypto crypto
= NULL
;
478 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
482 ret
= krb5_create_checksum(context
, crypto
, KRB5_KU_OTHER_CKSUM
, 0,
483 data
, datalen
, &cksum
);
484 krb5_crypto_destroy(context
, crypto
);
488 if (cksum
.checksum
.length
!= siglen
) {
489 krb5_set_error_string(context
, "pac checksum wrong length");
490 free_Checksum(&cksum
);
494 memcpy(sig
, cksum
.checksum
.data
, siglen
);
495 free_Checksum(&cksum
);
505 #define NTTIME_EPOCH 0x019DB1DED53E8000LL
508 unix2nttime(time_t unix_time
)
511 wt
= unix_time
* (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH
;
515 static krb5_error_code
516 verify_logonname(krb5_context context
,
517 const struct PAC_INFO_BUFFER
*logon_name
,
518 const krb5_data
*data
,
520 krb5_const_principal principal
)
524 uint32_t time1
, time2
;
529 sp
= krb5_storage_from_readonly_mem((const char *)data
->data
+ logon_name
->offset_lo
,
530 logon_name
->buffersize
);
532 krb5_set_error_string(context
, "Out of memory");
536 krb5_storage_set_flags(sp
, KRB5_STORAGE_BYTEORDER_LE
);
538 CHECK(ret
, krb5_ret_uint32(sp
, &time1
), out
);
539 CHECK(ret
, krb5_ret_uint32(sp
, &time2
), out
);
543 t1
= unix2nttime(authtime
);
544 t2
= ((uint64_t)time2
<< 32) | time1
;
546 krb5_storage_free(sp
);
547 krb5_set_error_string(context
, "PAC timestamp mismatch");
551 CHECK(ret
, krb5_ret_uint16(sp
, &len
), out
);
553 krb5_storage_free(sp
);
554 krb5_set_error_string(context
, "PAC logon name length missing");
560 krb5_storage_free(sp
);
561 krb5_set_error_string(context
, "Out of memory");
564 ret
= krb5_storage_read(sp
, s
, len
);
566 krb5_storage_free(sp
);
567 krb5_set_error_string(context
, "Failed to read pac logon name");
570 krb5_storage_free(sp
);
571 #if 1 /* cheat for now */
576 krb5_set_error_string(context
, "PAC logon name malformed");
580 for (i
= 0; i
< len
/ 2; i
++) {
581 if (s
[(i
* 2) + 1]) {
582 krb5_set_error_string(context
, "PAC logon name not ASCII");
595 ucs2
= malloc(sizeof(ucs2
[0]) * len
/ 2);
598 ucs2len
= wind_ucs2read(s
, len
/ 2, ucs2
);
602 ret
= wind_ucs2toutf8(ucs2
, ucs2len
, NULL
, &u8len
);
605 s
= malloc(u8len
+ 1);
608 wind_ucs2toutf8(ucs2
, ucs2len
, s
, &u8len
);
612 ret
= krb5_parse_name_flags(context
, s
, KRB5_PRINCIPAL_PARSE_NO_REALM
, &p2
);
617 if (krb5_principal_compare_any_realm(context
, principal
, p2
) != TRUE
) {
618 krb5_set_error_string(context
, "PAC logon name mismatch");
621 krb5_free_principal(context
, p2
);
631 static krb5_error_code
632 build_logon_name(krb5_context context
,
634 krb5_const_principal principal
,
643 t
= unix2nttime(authtime
);
645 krb5_data_zero(logon
);
647 sp
= krb5_storage_emem();
649 krb5_set_error_string(context
, "out of memory");
652 krb5_storage_set_flags(sp
, KRB5_STORAGE_BYTEORDER_LE
);
654 CHECK(ret
, krb5_store_uint32(sp
, t
& 0xffffffff), out
);
655 CHECK(ret
, krb5_store_uint32(sp
, t
>> 32), out
);
657 ret
= krb5_unparse_name_flags(context
, principal
,
658 KRB5_PRINCIPAL_UNPARSE_NO_REALM
, &s
);
664 CHECK(ret
, krb5_store_uint16(sp
, len
* 2), out
);
666 #if 1 /* cheat for now */
667 s2
= malloc(len
* 2);
673 for (i
= 0; i
< len
; i
++) {
679 /* write libwind code here */
682 ret
= krb5_storage_write(sp
, s2
, len
* 2);
684 if (ret
!= len
* 2) {
688 ret
= krb5_storage_to_data(sp
, logon
);
691 krb5_storage_free(sp
);
695 krb5_storage_free(sp
);
705 krb5_pac_verify(krb5_context context
,
708 krb5_const_principal principal
,
709 const krb5_keyblock
*server
,
710 const krb5_keyblock
*privsvr
)
714 if (pac
->server_checksum
== NULL
) {
715 krb5_set_error_string(context
, "PAC missing server checksum");
718 if (pac
->privsvr_checksum
== NULL
) {
719 krb5_set_error_string(context
, "PAC missing kdc checksum");
722 if (pac
->logon_name
== NULL
) {
723 krb5_set_error_string(context
, "PAC missing logon name");
727 ret
= verify_logonname(context
,
736 * in the service case, clean out data option of the privsvr and
737 * server checksum before checking the checksum.
742 ret
= krb5_copy_data(context
, &pac
->data
, ©
);
746 if (pac
->server_checksum
->buffersize
< 4)
748 if (pac
->privsvr_checksum
->buffersize
< 4)
751 memset((char *)copy
->data
+ pac
->server_checksum
->offset_lo
+ 4,
753 pac
->server_checksum
->buffersize
- 4);
755 memset((char *)copy
->data
+ pac
->privsvr_checksum
->offset_lo
+ 4,
757 pac
->privsvr_checksum
->buffersize
- 4);
759 ret
= verify_checksum(context
,
760 pac
->server_checksum
,
765 krb5_free_data(context
, copy
);
770 ret
= verify_checksum(context
,
771 pac
->privsvr_checksum
,
773 (char *)pac
->data
.data
774 + pac
->server_checksum
->offset_lo
+ 4,
775 pac
->server_checksum
->buffersize
- 4,
788 static krb5_error_code
789 fill_zeros(krb5_context context
, krb5_storage
*sp
, size_t len
)
796 if (l
> sizeof(zeros
))
798 sret
= krb5_storage_write(sp
, zeros
, l
);
800 krb5_set_error_string(context
, "out of memory");
808 static krb5_error_code
809 pac_checksum(krb5_context context
,
810 const krb5_keyblock
*key
,
814 krb5_cksumtype cktype
;
816 krb5_crypto crypto
= NULL
;
818 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
822 ret
= krb5_crypto_get_checksum_type(context
, crypto
, &cktype
);
823 ret
= krb5_crypto_destroy(context
, crypto
);
827 if (krb5_checksum_is_keyed(context
, cktype
) == FALSE
) {
828 krb5_set_error_string(context
, "PAC checksum type is not keyed");
832 ret
= krb5_checksumsize(context
, cktype
, cksumsize
);
836 *cksumtype
= (uint32_t)cktype
;
842 _krb5_pac_sign(krb5_context context
,
845 krb5_principal principal
,
846 const krb5_keyblock
*server_key
,
847 const krb5_keyblock
*priv_key
,
851 krb5_storage
*sp
= NULL
, *spdata
= NULL
;
853 size_t server_size
, priv_size
;
854 uint32_t server_offset
= 0, priv_offset
= 0;
855 uint32_t server_cksumtype
= 0, priv_cksumtype
= 0;
859 krb5_data_zero(&logon
);
861 if (p
->logon_name
== NULL
)
863 if (p
->server_checksum
== NULL
)
865 if (p
->privsvr_checksum
== NULL
)
871 ptr
= realloc(p
->pac
, sizeof(*p
->pac
) + (sizeof(p
->pac
->buffers
[0]) * (p
->pac
->numbuffers
+ num
- 1)));
873 krb5_set_error_string(context
, "out of memory");
878 if (p
->logon_name
== NULL
) {
879 p
->logon_name
= &p
->pac
->buffers
[p
->pac
->numbuffers
++];
880 memset(p
->logon_name
, 0, sizeof(*p
->logon_name
));
881 p
->logon_name
->type
= PAC_LOGON_NAME
;
883 if (p
->server_checksum
== NULL
) {
884 p
->server_checksum
= &p
->pac
->buffers
[p
->pac
->numbuffers
++];
885 memset(p
->server_checksum
, 0, sizeof(*p
->server_checksum
));
886 p
->server_checksum
->type
= PAC_SERVER_CHECKSUM
;
888 if (p
->privsvr_checksum
== NULL
) {
889 p
->privsvr_checksum
= &p
->pac
->buffers
[p
->pac
->numbuffers
++];
890 memset(p
->privsvr_checksum
, 0, sizeof(*p
->privsvr_checksum
));
891 p
->privsvr_checksum
->type
= PAC_PRIVSVR_CHECKSUM
;
895 /* Calculate LOGON NAME */
896 ret
= build_logon_name(context
, authtime
, principal
, &logon
);
900 /* Set lengths for checksum */
901 ret
= pac_checksum(context
, server_key
, &server_cksumtype
, &server_size
);
904 ret
= pac_checksum(context
, priv_key
, &priv_cksumtype
, &priv_size
);
909 sp
= krb5_storage_emem();
911 krb5_set_error_string(context
, "out of memory");
914 krb5_storage_set_flags(sp
, KRB5_STORAGE_BYTEORDER_LE
);
916 spdata
= krb5_storage_emem();
917 if (spdata
== NULL
) {
918 krb5_storage_free(sp
);
919 krb5_set_error_string(context
, "out of memory");
922 krb5_storage_set_flags(spdata
, KRB5_STORAGE_BYTEORDER_LE
);
924 CHECK(ret
, krb5_store_uint32(sp
, p
->pac
->numbuffers
), out
);
925 CHECK(ret
, krb5_store_uint32(sp
, p
->pac
->version
), out
);
927 end
= PACTYPE_SIZE
+ (PAC_INFO_BUFFER_SIZE
* p
->pac
->numbuffers
);
929 for (i
= 0; i
< p
->pac
->numbuffers
; i
++) {
936 if (p
->pac
->buffers
[i
].type
== PAC_SERVER_CHECKSUM
) {
937 len
= server_size
+ 4;
938 server_offset
= end
+ 4;
939 CHECK(ret
, krb5_store_uint32(spdata
, server_cksumtype
), out
);
940 CHECK(ret
, fill_zeros(context
, spdata
, server_size
), out
);
941 } else if (p
->pac
->buffers
[i
].type
== PAC_PRIVSVR_CHECKSUM
) {
943 priv_offset
= end
+ 4;
944 CHECK(ret
, krb5_store_uint32(spdata
, priv_cksumtype
), out
);
945 CHECK(ret
, fill_zeros(context
, spdata
, priv_size
), out
);
946 } else if (p
->pac
->buffers
[i
].type
== PAC_LOGON_NAME
) {
947 len
= krb5_storage_write(spdata
, logon
.data
, logon
.length
);
948 if (logon
.length
!= len
) {
953 len
= p
->pac
->buffers
[i
].buffersize
;
954 ptr
= (char *)p
->data
.data
+ p
->pac
->buffers
[i
].offset_lo
;
956 sret
= krb5_storage_write(spdata
, ptr
, len
);
958 krb5_set_error_string(context
, "out of memory");
962 /* XXX if not aligned, fill_zeros */
966 CHECK(ret
, krb5_store_uint32(sp
, p
->pac
->buffers
[i
].type
), out
);
967 CHECK(ret
, krb5_store_uint32(sp
, len
), out
);
968 CHECK(ret
, krb5_store_uint32(sp
, end
), out
);
969 CHECK(ret
, krb5_store_uint32(sp
, 0), out
);
971 /* advance data endpointer and align */
976 e
= ((end
+ PAC_ALIGNMENT
- 1) / PAC_ALIGNMENT
) * PAC_ALIGNMENT
;
978 CHECK(ret
, fill_zeros(context
, spdata
, e
- end
), out
);
985 /* assert (server_offset != 0 && priv_offset != 0); */
988 ret
= krb5_storage_to_data(spdata
, &d
);
990 krb5_set_error_string(context
, "out of memory");
993 ret
= krb5_storage_write(sp
, d
.data
, d
.length
);
994 if (ret
!= d
.length
) {
996 krb5_set_error_string(context
, "out of memory");
1002 ret
= krb5_storage_to_data(sp
, &d
);
1004 krb5_set_error_string(context
, "out of memory");
1010 ret
= create_checksum(context
, server_key
,
1012 (char *)d
.data
+ server_offset
, server_size
);
1018 ret
= create_checksum(context
, priv_key
,
1019 (char *)d
.data
+ server_offset
, server_size
,
1020 (char *)d
.data
+ priv_offset
, priv_size
);
1029 krb5_data_free(&logon
);
1030 krb5_storage_free(sp
);
1031 krb5_storage_free(spdata
);
1035 krb5_data_free(&logon
);
1037 krb5_storage_free(sp
);
1039 krb5_storage_free(spdata
);