1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/pac.c */
4 * Copyright 2008 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
30 /* draft-brezak-win2k-krb-authz-00 */
33 * Add a buffer to the provided PAC and update header.
36 k5_pac_add_buffer(krb5_context context,
39 const krb5_data *data,
40 krb5_boolean zerofill,
44 size_t header_len, i, pad = 0;
47 assert((data->data == NULL) == zerofill);
49 /* Check there isn't already a buffer of this type */
50 if (k5_pac_locate_buffer(context, pac, type, NULL) == 0) {
54 header = (PACTYPE *)realloc(pac->pac,
56 (pac->pac->cBuffers * sizeof(PAC_INFO_BUFFER)));
62 header_len = PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH);
64 if (data->length % PAC_ALIGNMENT)
65 pad = PAC_ALIGNMENT - (data->length % PAC_ALIGNMENT);
67 pac_data = realloc(pac->data.data,
68 pac->data.length + PAC_INFO_BUFFER_LENGTH + data->length + pad);
69 if (pac_data == NULL) {
72 pac->data.data = pac_data;
74 /* Update offsets of existing buffers */
75 for (i = 0; i < pac->pac->cBuffers; i++)
76 pac->pac->Buffers[i].Offset += PAC_INFO_BUFFER_LENGTH;
78 /* Make room for new PAC_INFO_BUFFER */
79 memmove(pac->data.data + header_len + PAC_INFO_BUFFER_LENGTH,
80 pac->data.data + header_len,
81 pac->data.length - header_len);
82 memset(pac->data.data + header_len, 0, PAC_INFO_BUFFER_LENGTH);
84 /* Initialise new PAC_INFO_BUFFER */
85 pac->pac->Buffers[i].ulType = type;
86 pac->pac->Buffers[i].cbBufferSize = data->length;
87 pac->pac->Buffers[i].Offset = pac->data.length + PAC_INFO_BUFFER_LENGTH;
88 assert((pac->pac->Buffers[i].Offset % PAC_ALIGNMENT) == 0);
90 /* Copy in new PAC data and zero padding bytes */
92 memset(pac->data.data + pac->pac->Buffers[i].Offset, 0, data->length);
94 memcpy(pac->data.data + pac->pac->Buffers[i].Offset, data->data, data->length);
96 memset(pac->data.data + pac->pac->Buffers[i].Offset + data->length, 0, pad);
99 pac->data.length += PAC_INFO_BUFFER_LENGTH + data->length + pad;
101 if (out_data != NULL) {
102 out_data->data = pac->data.data + pac->pac->Buffers[i].Offset;
103 out_data->length = data->length;
106 pac->verified = FALSE;
111 krb5_error_code KRB5_CALLCONV
112 krb5_pac_add_buffer(krb5_context context,
115 const krb5_data *data)
117 return k5_pac_add_buffer(context, pac, type, data, FALSE, NULL);
124 krb5_pac_free(krb5_context context,
128 if (pac->data.data != NULL) {
129 memset(pac->data.data, 0, pac->data.length);
130 free(pac->data.data);
132 if (pac->pac != NULL)
134 memset(pac, 0, sizeof(*pac));
140 k5_pac_locate_buffer(krb5_context context,
145 PAC_INFO_BUFFER *buffer = NULL;
151 for (i = 0; i < pac->pac->cBuffers; i++) {
152 if (pac->pac->Buffers[i].ulType == type) {
154 buffer = &pac->pac->Buffers[i];
163 assert(buffer->Offset + buffer->cbBufferSize <= pac->data.length);
166 data->length = buffer->cbBufferSize;
167 data->data = pac->data.data + buffer->Offset;
174 * Find a buffer and copy data into output
176 krb5_error_code KRB5_CALLCONV
177 krb5_pac_get_buffer(krb5_context context,
185 ret = k5_pac_locate_buffer(context, pac, type, &d);
189 data->data = malloc(d.length);
190 if (data->data == NULL)
193 data->length = d.length;
194 memcpy(data->data, d.data, d.length);
200 * Return an array of the types of data in the PAC
202 krb5_error_code KRB5_CALLCONV
203 krb5_pac_get_types(krb5_context context,
210 *types = (krb5_ui_4 *)malloc(pac->pac->cBuffers * sizeof(krb5_ui_4));
214 *len = pac->pac->cBuffers;
216 for (i = 0; i < pac->pac->cBuffers; i++)
217 (*types)[i] = pac->pac->Buffers[i].ulType;
225 krb5_error_code KRB5_CALLCONV
226 krb5_pac_init(krb5_context context,
231 pac = (krb5_pac)malloc(sizeof(*pac));
235 pac->pac = (PACTYPE *)malloc(sizeof(PACTYPE));
236 if (pac->pac == NULL) {
241 pac->pac->cBuffers = 0;
242 pac->pac->Version = 0;
244 pac->data.length = PACTYPE_LENGTH;
245 pac->data.data = calloc(1, pac->data.length);
246 if (pac->data.data == NULL) {
247 krb5_pac_free(context, pac);
251 pac->verified = FALSE;
258 static krb5_error_code
259 k5_pac_copy(krb5_context context,
265 krb5_error_code code;
268 cbuffers = src->pac->cBuffers;
272 header_len = sizeof(PACTYPE) + cbuffers * sizeof(PAC_INFO_BUFFER);
274 pac = (krb5_pac)malloc(sizeof(*pac));
278 pac->pac = (PACTYPE *)malloc(header_len);
279 if (pac->pac == NULL) {
284 memcpy(pac->pac, src->pac, header_len);
286 code = krb5int_copy_data_contents(context, &src->data, &pac->data);
293 pac->verified = src->verified;
300 * Parse the supplied data into the PAC allocated by this function
302 krb5_error_code KRB5_CALLCONV
303 krb5_pac_parse(krb5_context context,
310 const unsigned char *p = (const unsigned char *)ptr;
313 krb5_ui_4 cbuffers, version;
317 if (len < PACTYPE_LENGTH)
320 cbuffers = load_32_le(p);
322 version = load_32_le(p);
328 header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
329 if (len < header_len)
332 ret = krb5_pac_init(context, &pac);
336 pac->pac = (PACTYPE *)realloc(pac->pac,
337 sizeof(PACTYPE) + ((cbuffers - 1) * sizeof(PAC_INFO_BUFFER)));
338 if (pac->pac == NULL) {
339 krb5_pac_free(context, pac);
343 pac->pac->cBuffers = cbuffers;
344 pac->pac->Version = version;
346 for (i = 0; i < pac->pac->cBuffers; i++) {
347 PAC_INFO_BUFFER *buffer = &pac->pac->Buffers[i];
349 buffer->ulType = load_32_le(p);
351 buffer->cbBufferSize = load_32_le(p);
353 buffer->Offset = load_64_le(p);
356 if (buffer->Offset % PAC_ALIGNMENT) {
357 krb5_pac_free(context, pac);
360 if (buffer->Offset < header_len ||
361 buffer->Offset + buffer->cbBufferSize > len) {
362 krb5_pac_free(context, pac);
367 pac->data.data = realloc(pac->data.data, len);
368 if (pac->data.data == NULL) {
369 krb5_pac_free(context, pac);
372 memcpy(pac->data.data, ptr, len);
374 pac->data.length = len;
381 static krb5_error_code
382 k5_time_to_seconds_since_1970(krb5_int64 ntTime,
383 krb5_timestamp *elapsedSeconds)
389 abstime = ntTime > 0 ? ntTime - NT_TIME_EPOCH : -ntTime;
391 if (abstime > KRB5_INT32_MAX)
394 *elapsedSeconds = abstime;
400 k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds,
403 *ntTime = elapsedSeconds;
405 if (elapsedSeconds > 0)
406 *ntTime += NT_TIME_EPOCH;
414 k5_pac_validate_client(krb5_context context,
416 krb5_timestamp authtime,
417 krb5_const_principal principal)
420 krb5_data client_info;
423 krb5_timestamp pac_authtime;
424 krb5_ui_2 pac_princname_length;
425 krb5_int64 pac_nt_authtime;
426 krb5_principal pac_principal;
428 ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO,
433 if (client_info.length < PAC_CLIENT_INFO_LENGTH)
436 p = (unsigned char *)client_info.data;
437 pac_nt_authtime = load_64_le(p);
439 pac_princname_length = load_16_le(p);
442 ret = k5_time_to_seconds_since_1970(pac_nt_authtime, &pac_authtime);
446 if (client_info.length < PAC_CLIENT_INFO_LENGTH + pac_princname_length ||
447 pac_princname_length % 2)
450 ret = krb5int_ucs2lecs_to_utf8s(p, (size_t)pac_princname_length / 2,
451 &pac_princname, NULL);
455 ret = krb5_parse_name_flags(context, pac_princname,
456 KRB5_PRINCIPAL_PARSE_NO_REALM, &pac_principal);
464 if (pac_authtime != authtime ||
465 !krb5_principal_compare_flags(context,
468 KRB5_PRINCIPAL_COMPARE_IGNORE_REALM))
469 ret = KRB5KRB_AP_WRONG_PRINC;
471 krb5_free_principal(context, pac_principal);
476 static krb5_error_code
477 k5_pac_zero_signature(krb5_context context,
482 PAC_INFO_BUFFER *buffer = NULL;
485 assert(type == KRB5_PAC_SERVER_CHECKSUM ||
486 type == KRB5_PAC_PRIVSVR_CHECKSUM);
487 assert(data->length >= pac->data.length);
489 for (i = 0; i < pac->pac->cBuffers; i++) {
490 if (pac->pac->Buffers[i].ulType == type) {
491 buffer = &pac->pac->Buffers[i];
499 if (buffer->Offset + buffer->cbBufferSize > pac->data.length)
502 if (buffer->cbBufferSize < PAC_SIGNATURE_DATA_LENGTH)
503 return KRB5_BAD_MSIZE;
505 /* Zero out the data portion of the checksum only */
506 memset(data->data + buffer->Offset + PAC_SIGNATURE_DATA_LENGTH,
508 buffer->cbBufferSize - PAC_SIGNATURE_DATA_LENGTH);
513 static krb5_error_code
514 k5_pac_verify_server_checksum(krb5_context context,
516 const krb5_keyblock *server)
519 krb5_data pac_data; /* PAC with zeroed checksums */
520 krb5_checksum checksum;
521 krb5_data checksum_data;
525 ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
530 if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH)
531 return KRB5_BAD_MSIZE;
533 p = (krb5_octet *)checksum_data.data;
534 checksum.checksum_type = load_32_le(p);
535 checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
536 checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
537 if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
538 return KRB5KRB_AP_ERR_INAPP_CKSUM;
540 pac_data.length = pac->data.length;
541 pac_data.data = malloc(pac->data.length);
542 if (pac_data.data == NULL)
545 memcpy(pac_data.data, pac->data.data, pac->data.length);
547 /* Zero out both checksum buffers */
548 ret = k5_pac_zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM,
555 ret = k5_pac_zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
562 ret = krb5_c_verify_checksum(context, server,
563 KRB5_KEYUSAGE_APP_DATA_CKSUM,
564 &pac_data, &checksum, &valid);
573 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
578 static krb5_error_code
579 k5_pac_verify_kdc_checksum(krb5_context context,
581 const krb5_keyblock *privsvr)
584 krb5_data server_checksum, privsvr_checksum;
585 krb5_checksum checksum;
589 ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
594 if (privsvr_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
595 return KRB5_BAD_MSIZE;
597 ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
602 if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
603 return KRB5_BAD_MSIZE;
605 p = (krb5_octet *)privsvr_checksum.data;
606 checksum.checksum_type = load_32_le(p);
607 checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH;
608 checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
609 if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
610 return KRB5KRB_AP_ERR_INAPP_CKSUM;
612 server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
613 server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
615 ret = krb5_c_verify_checksum(context, privsvr,
616 KRB5_KEYUSAGE_APP_DATA_CKSUM,
617 &server_checksum, &checksum, &valid);
622 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
627 krb5_error_code KRB5_CALLCONV
628 krb5_pac_verify(krb5_context context,
630 krb5_timestamp authtime,
631 krb5_const_principal principal,
632 const krb5_keyblock *server,
633 const krb5_keyblock *privsvr)
637 if (server != NULL) {
638 ret = k5_pac_verify_server_checksum(context, pac, server);
643 if (privsvr != NULL) {
644 ret = k5_pac_verify_kdc_checksum(context, pac, privsvr);
649 if (principal != NULL) {
650 ret = k5_pac_validate_client(context, pac, authtime, principal);
655 pac->verified = TRUE;
661 * PAC auth data attribute backend
663 struct mspac_context {
667 static krb5_error_code
668 mspac_init(krb5_context kcontext, void **plugin_context)
670 *plugin_context = NULL;
675 mspac_flags(krb5_context kcontext,
676 void *plugin_context,
677 krb5_authdatatype ad_type,
680 *flags = AD_USAGE_TGS_REQ;
684 mspac_fini(krb5_context kcontext, void *plugin_context)
689 static krb5_error_code
690 mspac_request_init(krb5_context kcontext,
691 krb5_authdata_context context,
692 void *plugin_context,
693 void **request_context)
695 struct mspac_context *pacctx;
697 pacctx = (struct mspac_context *)malloc(sizeof(*pacctx));
703 *request_context = pacctx;
708 static krb5_error_code
709 mspac_import_authdata(krb5_context kcontext,
710 krb5_authdata_context context,
711 void *plugin_context,
712 void *request_context,
713 krb5_authdata **authdata,
714 krb5_boolean kdc_issued,
715 krb5_const_principal kdc_issuer)
717 krb5_error_code code;
718 struct mspac_context *pacctx = (struct mspac_context *)request_context;
723 if (pacctx->pac != NULL) {
724 krb5_pac_free(kcontext, pacctx->pac);
728 assert(authdata[0] != NULL);
729 assert((authdata[0]->ad_type & AD_TYPE_FIELD_TYPE_MASK) ==
730 KRB5_AUTHDATA_WIN2K_PAC);
732 code = krb5_pac_parse(kcontext, authdata[0]->contents,
733 authdata[0]->length, &pacctx->pac);
738 static krb5_error_code
739 mspac_export_authdata(krb5_context kcontext,
740 krb5_authdata_context context,
741 void *plugin_context,
742 void *request_context,
744 krb5_authdata ***out_authdata)
746 struct mspac_context *pacctx = (struct mspac_context *)request_context;
747 krb5_error_code code;
748 krb5_authdata **authdata;
751 if (pacctx->pac == NULL)
754 authdata = calloc(2, sizeof(krb5_authdata *));
755 if (authdata == NULL)
758 authdata[0] = calloc(1, sizeof(krb5_authdata));
759 if (authdata[0] == NULL) {
765 code = krb5int_copy_data_contents(kcontext, &pacctx->pac->data, &data);
767 krb5_free_authdata(kcontext, authdata);
771 authdata[0]->magic = KV5M_AUTHDATA;
772 authdata[0]->ad_type = KRB5_AUTHDATA_WIN2K_PAC;
773 authdata[0]->length = data.length;
774 authdata[0]->contents = (krb5_octet *)data.data;
778 *out_authdata = authdata;
783 static krb5_error_code
784 mspac_verify(krb5_context kcontext,
785 krb5_authdata_context context,
786 void *plugin_context,
787 void *request_context,
788 const krb5_auth_context *auth_context,
789 const krb5_keyblock *key,
790 const krb5_ap_req *req)
792 krb5_error_code code;
793 struct mspac_context *pacctx = (struct mspac_context *)request_context;
795 if (pacctx->pac == NULL)
798 code = krb5_pac_verify(kcontext, pacctx->pac,
799 req->ticket->enc_part2->times.authtime,
800 req->ticket->enc_part2->client, key, NULL);
802 TRACE_MSPAC_VERIFY_FAIL(kcontext, code);
805 * If the above verification failed, don't fail the whole authentication,
806 * just don't mark the PAC as verified. A checksum mismatch can occur if
807 * the PAC was copied from a cross-realm TGT by an ignorant KDC, and Apple
808 * Mac OS X Server Open Directory (as of 10.6) generates PACs with no
809 * server checksum at all.
815 mspac_request_fini(krb5_context kcontext,
816 krb5_authdata_context context,
817 void *plugin_context,
818 void *request_context)
820 struct mspac_context *pacctx = (struct mspac_context *)request_context;
822 if (pacctx != NULL) {
823 if (pacctx->pac != NULL)
824 krb5_pac_free(kcontext, pacctx->pac);
830 #define STRLENOF(x) (sizeof((x)) - 1)
835 } mspac_attribute_types[] = {
836 { (krb5_ui_4)-1, { KV5M_DATA, STRLENOF("urn:mspac:"),
838 { KRB5_PAC_LOGON_INFO, { KV5M_DATA,
839 STRLENOF("urn:mspac:logon-info"),
840 "urn:mspac:logon-info" } },
841 { KRB5_PAC_CREDENTIALS_INFO, { KV5M_DATA,
842 STRLENOF("urn:mspac:credentials-info"),
843 "urn:mspac:credentials-info" } },
844 { KRB5_PAC_SERVER_CHECKSUM, { KV5M_DATA,
845 STRLENOF("urn:mspac:server-checksum"),
846 "urn:mspac:server-checksum" } },
847 { KRB5_PAC_PRIVSVR_CHECKSUM, { KV5M_DATA,
848 STRLENOF("urn:mspac:privsvr-checksum"),
849 "urn:mspac:privsvr-checksum" } },
850 { KRB5_PAC_CLIENT_INFO, { KV5M_DATA,
851 STRLENOF("urn:mspac:client-info"),
852 "urn:mspac:client-info" } },
853 { KRB5_PAC_DELEGATION_INFO, { KV5M_DATA,
854 STRLENOF("urn:mspac:delegation-info"),
855 "urn:mspac:delegation-info" } },
856 { KRB5_PAC_UPN_DNS_INFO, { KV5M_DATA,
857 STRLENOF("urn:mspac:upn-dns-info"),
858 "urn:mspac:upn-dns-info" } },
861 #define MSPAC_ATTRIBUTE_COUNT (sizeof(mspac_attribute_types)/sizeof(mspac_attribute_types[0]))
863 static krb5_error_code
864 mspac_type2attr(krb5_ui_4 type, krb5_data *attr)
868 for (i = 0; i < MSPAC_ATTRIBUTE_COUNT; i++) {
869 if (mspac_attribute_types[i].type == type) {
870 *attr = mspac_attribute_types[i].attribute;
878 static krb5_error_code
879 mspac_attr2type(const krb5_data *attr, krb5_ui_4 *type)
883 for (i = 0; i < MSPAC_ATTRIBUTE_COUNT; i++) {
884 if (attr->length == mspac_attribute_types[i].attribute.length &&
885 strncasecmp(attr->data, mspac_attribute_types[i].attribute.data, attr->length) == 0) {
886 *type = mspac_attribute_types[i].type;
891 if (attr->length > STRLENOF("urn:mspac:") &&
892 strncasecmp(attr->data, "urn:mspac:", STRLENOF("urn:mspac:")) == 0)
894 char *p = &attr->data[STRLENOF("urn:mspac:")];
897 *type = strtoul(p, &endptr, 10);
898 if (*type != 0 && *endptr == '\0')
905 static krb5_error_code
906 mspac_get_attribute_types(krb5_context kcontext,
907 krb5_authdata_context context,
908 void *plugin_context,
909 void *request_context,
910 krb5_data **out_attrs)
912 struct mspac_context *pacctx = (struct mspac_context *)request_context;
915 krb5_error_code code;
917 if (pacctx->pac == NULL)
920 attrs = calloc(1 + pacctx->pac->pac->cBuffers + 1, sizeof(krb5_data));
927 code = krb5int_copy_data_contents(kcontext,
928 &mspac_attribute_types[0].attribute,
936 for (i = 0; i < pacctx->pac->pac->cBuffers; i++) {
939 code = mspac_type2attr(pacctx->pac->pac->Buffers[i].ulType, &attr);
941 code = krb5int_copy_data_contents(kcontext, &attr, &attrs[j++]);
943 krb5int_free_data_list(kcontext, attrs);
949 length = asprintf(&attrs[j].data, "urn:mspac:%d",
950 pacctx->pac->pac->Buffers[i].ulType);
952 krb5int_free_data_list(kcontext, attrs);
955 attrs[j++].length = length;
958 attrs[j].data = NULL;
966 static krb5_error_code
967 mspac_get_attribute(krb5_context kcontext,
968 krb5_authdata_context context,
969 void *plugin_context,
970 void *request_context,
971 const krb5_data *attribute,
972 krb5_boolean *authenticated,
973 krb5_boolean *complete,
975 krb5_data *display_value,
978 struct mspac_context *pacctx = (struct mspac_context *)request_context;
979 krb5_error_code code;
982 if (display_value != NULL) {
983 display_value->data = NULL;
984 display_value->length = 0;
987 if (*more != -1 || pacctx->pac == NULL)
990 /* If it didn't verify, pretend it didn't exist. */
991 if (!pacctx->pac->verified) {
992 TRACE_MSPAC_DISCARD_UNVERF(kcontext);
996 code = mspac_attr2type(attribute, &type);
1000 /* -1 is a magic type that refers to the entire PAC */
1001 if (type == (krb5_ui_4)-1) {
1003 code = krb5int_copy_data_contents(kcontext,
1010 code = krb5_pac_get_buffer(kcontext, pacctx->pac, type, value);
1012 code = k5_pac_locate_buffer(kcontext, pacctx->pac, type, NULL);
1015 *authenticated = pacctx->pac->verified;
1024 static krb5_error_code
1025 mspac_set_attribute(krb5_context kcontext,
1026 krb5_authdata_context context,
1027 void *plugin_context,
1028 void *request_context,
1029 krb5_boolean complete,
1030 const krb5_data *attribute,
1031 const krb5_data *value)
1033 struct mspac_context *pacctx = (struct mspac_context *)request_context;
1034 krb5_error_code code;
1037 if (pacctx->pac == NULL)
1040 code = mspac_attr2type(attribute, &type);
1044 /* -1 is a magic type that refers to the entire PAC */
1045 if (type == (krb5_ui_4)-1) {
1048 code = krb5_pac_parse(kcontext, value->data, value->length, &newpac);
1052 krb5_pac_free(kcontext, pacctx->pac);
1053 pacctx->pac = newpac;
1055 code = krb5_pac_add_buffer(kcontext, pacctx->pac, type, value);
1061 static krb5_error_code
1062 mspac_export_internal(krb5_context kcontext,
1063 krb5_authdata_context context,
1064 void *plugin_context,
1065 void *request_context,
1066 krb5_boolean restrict_authenticated,
1069 struct mspac_context *pacctx = (struct mspac_context *)request_context;
1070 krb5_error_code code;
1075 if (pacctx->pac == NULL)
1078 if (restrict_authenticated && (pacctx->pac->verified) == FALSE)
1081 code = krb5_pac_parse(kcontext, pacctx->pac->data.data,
1082 pacctx->pac->data.length, &pac);
1084 pac->verified = pacctx->pac->verified;
1092 mspac_free_internal(krb5_context kcontext,
1093 krb5_authdata_context context,
1094 void *plugin_context,
1095 void *request_context,
1099 krb5_pac_free(kcontext, (krb5_pac)ptr);
1104 static krb5_error_code
1105 mspac_size(krb5_context kcontext,
1106 krb5_authdata_context context,
1107 void *plugin_context,
1108 void *request_context,
1111 struct mspac_context *pacctx = (struct mspac_context *)request_context;
1113 *sizep += sizeof(krb5_int32);
1115 if (pacctx->pac != NULL)
1116 *sizep += pacctx->pac->data.length;
1118 *sizep += sizeof(krb5_int32);
1123 static krb5_error_code
1124 mspac_externalize(krb5_context kcontext,
1125 krb5_authdata_context context,
1126 void *plugin_context,
1127 void *request_context,
1128 krb5_octet **buffer,
1131 krb5_error_code code = 0;
1132 struct mspac_context *pacctx = (struct mspac_context *)request_context;
1133 size_t required = 0;
1138 remain = *lenremain;
1140 if (pacctx->pac != NULL) {
1141 mspac_size(kcontext, context, plugin_context,
1142 request_context, &required);
1144 if (required <= remain) {
1145 krb5_ser_pack_int32((krb5_int32)pacctx->pac->data.length,
1147 krb5_ser_pack_bytes((krb5_octet *)pacctx->pac->data.data,
1148 (size_t)pacctx->pac->data.length,
1150 krb5_ser_pack_int32((krb5_int32)pacctx->pac->verified,
1156 krb5_ser_pack_int32(0, &bp, &remain); /* length */
1157 krb5_ser_pack_int32(0, &bp, &remain); /* verified */
1161 *lenremain = remain;
1166 static krb5_error_code
1167 mspac_internalize(krb5_context kcontext,
1168 krb5_authdata_context context,
1169 void *plugin_context,
1170 void *request_context,
1171 krb5_octet **buffer,
1174 struct mspac_context *pacctx = (struct mspac_context *)request_context;
1175 krb5_error_code code;
1179 krb5_pac pac = NULL;
1182 remain = *lenremain;
1185 code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
1190 code = krb5_pac_parse(kcontext, bp, ibuf, &pac);
1199 code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
1201 krb5_pac_free(kcontext, pac);
1206 pac->verified = (ibuf != 0);
1209 if (pacctx->pac != NULL) {
1210 krb5_pac_free(kcontext, pacctx->pac);
1216 *lenremain = remain;
1221 static krb5_error_code
1222 mspac_copy(krb5_context kcontext,
1223 krb5_authdata_context context,
1224 void *plugin_context,
1225 void *request_context,
1226 void *dst_plugin_context,
1227 void *dst_request_context)
1229 struct mspac_context *srcctx = (struct mspac_context *)request_context;
1230 struct mspac_context *dstctx = (struct mspac_context *)dst_request_context;
1231 krb5_error_code code = 0;
1233 assert(dstctx != NULL);
1234 assert(dstctx->pac == NULL);
1236 if (srcctx->pac != NULL)
1237 code = k5_pac_copy(kcontext, srcctx->pac, &dstctx->pac);
1242 static krb5_authdatatype mspac_ad_types[] = { KRB5_AUTHDATA_WIN2K_PAC, 0 };
1244 krb5plugin_authdata_client_ftable_v0 krb5int_mspac_authdata_client_ftable = {
1252 mspac_get_attribute_types,
1253 mspac_get_attribute,
1254 mspac_set_attribute,
1255 NULL, /* delete_attribute_proc */
1256 mspac_export_authdata,
1257 mspac_import_authdata,
1258 mspac_export_internal,
1259 mspac_free_internal,