krb5_error_code samba_make_krb5_pac(krb5_context context, DATA_BLOB *pac_blob, krb5_pac *pac) { krb5_data pac_data; krb5_error_code ret; /* The user account may be set not to want the PAC */ if (!pac_blob) { return 0; } ret = krb5_data_copy(&pac_data, pac_blob->data, pac_blob->length); if (ret != 0) { return ret; } ret = krb5_pac_init(context, pac); if (ret != 0) { krb5_data_free(&pac_data); return ret; } ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data); krb5_data_free(&pac_data); if (ret != 0) { return ret; } return ret; }
static krb5_error_code pac_generate(void *ctx, krb5_context context, struct hdb_entry_ex *client, krb5_pac *pac) { krb5_error_code ret; krb5_data data; krb5_warnx(context, "pac generate"); data.data = "\x00\x01"; data.length = 2; ret = krb5_pac_init(context, pac); if (ret) return ret; ret = krb5_pac_add_buffer(context, *pac, 1, &data); if (ret) return ret; return 0; }
static krb5_error_code mspac_set_attribute(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_boolean complete, const krb5_data *attribute, const krb5_data *value) { struct mspac_context *pacctx = (struct mspac_context *)request_context; krb5_error_code code; krb5_ui_4 type; if (pacctx->pac == NULL) return ENOENT; code = mspac_attr2type(attribute, &type); if (code != 0) return code; /* -1 is a magic type that refers to the entire PAC */ if (type == (krb5_ui_4)-1) { krb5_pac newpac; code = krb5_pac_parse(kcontext, value->data, value->length, &newpac); if (code != 0) return code; krb5_pac_free(kcontext, pacctx->pac); pacctx->pac = newpac; } else { code = krb5_pac_add_buffer(kcontext, pacctx->pac, type, value); } return code; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_pac pac; krb5_data data; krb5_principal p, p2; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_contex"); krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); ret = krb5_parse_name_flags(context, user, KRB5_PRINCIPAL_PARSE_NO_REALM, &p); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_pac_parse(context, saved_pac, sizeof(saved_pac), &pac); if (ret) krb5_err(context, 1, ret, "krb5_pac_parse"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) krb5_err(context, 1, ret, "krb5_pac_verify"); ret = _krb5_pac_sign(context, pac, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) krb5_err(context, 1, ret, "_krb5_pac_sign"); krb5_pac_free(context, pac); ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_data_free(&data); if (ret) krb5_err(context, 1, ret, "krb5_pac_parse 2"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) krb5_err(context, 1, ret, "krb5_pac_verify 2"); /* make a copy and try to reproduce it */ { uint32_t *list; size_t len, i; krb5_pac pac2; ret = krb5_pac_init(context, &pac2); if (ret) krb5_err(context, 1, ret, "krb5_pac_init"); /* our two user buffer plus the three "system" buffers */ ret = krb5_pac_get_types(context, pac, &len, &list); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_types"); for (i = 0; i < len; i++) { /* skip server_cksum, privsvr_cksum, and logon_name */ if (list[i] == 6 || list[i] == 7 || list[i] == 10) continue; ret = krb5_pac_get_buffer(context, pac, list[i], &data); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_buffer"); if (list[i] == 1) { if (type_1_length != data.length) krb5_errx(context, 1, "type 1 have wrong length: %lu", (unsigned long)data.length); } else krb5_errx(context, 1, "unknown type %lu", (unsigned long)list[i]); ret = krb5_pac_add_buffer(context, pac2, list[i], &data); if (ret) krb5_err(context, 1, ret, "krb5_pac_add_buffer"); krb5_data_free(&data); } free(list); ret = _krb5_pac_sign(context, pac2, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) krb5_err(context, 1, ret, "_krb5_pac_sign 4"); krb5_pac_free(context, pac2); ret = krb5_pac_parse(context, data.data, data.length, &pac2); krb5_data_free(&data); if (ret) krb5_err(context, 1, ret, "krb5_pac_parse 4"); ret = krb5_pac_verify(context, pac2, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) krb5_err(context, 1, ret, "krb5_pac_verify 4"); krb5_pac_free(context, pac2); } krb5_pac_free(context, pac); /* * check pac from Christian */ ret = krb5_parse_name_flags(context, user2, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); if (ret) krb5_err(context, 1, ret, "krb5_parse_name"); ret = krb5_pac_parse(context, saved_pac2, sizeof(saved_pac2) -1, &pac); if (ret) krb5_err(context, 1, ret, "krb5_pac_parse"); ret = krb5_pac_verify(context, pac, authtime2, p2, &member_keyblock2, NULL); if (ret) krb5_err(context, 1, ret, "krb5_pac_verify c1"); krb5_pac_free(context, pac); krb5_free_principal(context, p2); /* * Test empty free */ ret = krb5_pac_init(context, &pac); if (ret) krb5_err(context, 1, ret, "krb5_pac_init"); krb5_pac_free(context, pac); /* * Test add remove buffer */ ret = krb5_pac_init(context, &pac); if (ret) krb5_err(context, 1, ret, "krb5_pac_init"); { const krb5_data cdata = { 2, "\x00\x01" } ; ret = krb5_pac_add_buffer(context, pac, 1, &cdata); if (ret) krb5_err(context, 1, ret, "krb5_pac_add_buffer"); } { ret = krb5_pac_get_buffer(context, pac, 1, &data); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); krb5_data_free(&data); } { const krb5_data cdata = { 2, "\x02\x00" } ; ret = krb5_pac_add_buffer(context, pac, 2, &cdata); if (ret) krb5_err(context, 1, ret, "krb5_pac_add_buffer"); } { ret = krb5_pac_get_buffer(context, pac, 1, &data); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); krb5_data_free(&data); /* */ ret = krb5_pac_get_buffer(context, pac, 2, &data); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x02\x00", 2) != 0) krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); krb5_data_free(&data); } ret = _krb5_pac_sign(context, pac, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) krb5_err(context, 1, ret, "_krb5_pac_sign"); krb5_pac_free(context, pac); ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_data_free(&data); if (ret) krb5_err(context, 1, ret, "krb5_pac_parse 3"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) krb5_err(context, 1, ret, "krb5_pac_verify 3"); { uint32_t *list; size_t len; /* our two user buffer plus the three "system" buffers */ ret = krb5_pac_get_types(context, pac, &len, &list); if (ret) krb5_err(context, 1, ret, "krb5_pac_get_types"); if (len != 5) krb5_errx(context, 1, "list wrong length"); free(list); } krb5_pac_free(context, pac); krb5_free_principal(context, p); krb5_free_context(context); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_pac pac; krb5_data data; krb5_principal p; ret = krb5_init_context(&context); if (ret) err(NULL, 0, "krb5_init_contex"); krb5_set_default_realm(context, "WIN2K3.THINKER.LOCAL"); ret = krb5_parse_name(context, user, &p); if (ret) err(context, ret, "krb5_parse_name"); ret = krb5_pac_parse(context, saved_pac, sizeof(saved_pac), &pac); if (ret) err(context, ret, "krb5_pac_parse"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) err(context, ret, "krb5_pac_verify"); ret = krb5int_pac_sign(context, pac, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) err(context, ret, "krb5int_pac_sign"); krb5_pac_free(context, pac); ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_free_data_contents(context, &data); if (ret) err(context, ret, "krb5_pac_parse 2"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) err(context, ret, "krb5_pac_verify 2"); /* make a copy and try to reproduce it */ { uint32_t *list; size_t len, i; krb5_pac pac2; ret = krb5_pac_init(context, &pac2); if (ret) err(context, ret, "krb5_pac_init"); /* our two user buffer plus the three "system" buffers */ ret = krb5_pac_get_types(context, pac, &len, &list); if (ret) err(context, ret, "krb5_pac_get_types"); for (i = 0; i < len; i++) { /* skip server_cksum, privsvr_cksum, and logon_name */ if (list[i] == 6 || list[i] == 7 || list[i] == 10) continue; ret = krb5_pac_get_buffer(context, pac, list[i], &data); if (ret) err(context, ret, "krb5_pac_get_buffer"); if (list[i] == 1) { if (type_1_length != data.length) err(context, 0, "type 1 have wrong length: %lu", (unsigned long)data.length); } else err(context, 0, "unknown type %lu", (unsigned long)list[i]); ret = krb5_pac_add_buffer(context, pac2, list[i], &data); if (ret) err(context, ret, "krb5_pac_add_buffer"); krb5_free_data_contents(context, &data); } free(list); ret = krb5int_pac_sign(context, pac2, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) err(context, ret, "krb5int_pac_sign 4"); krb5_pac_free(context, pac2); ret = krb5_pac_parse(context, data.data, data.length, &pac2); if (ret) err(context, ret, "krb5_pac_parse 4"); ret = krb5_pac_verify(context, pac2, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) err(context, ret, "krb5_pac_verify 4"); krb5_free_data_contents(context, &data); krb5_pac_free(context, pac2); } krb5_pac_free(context, pac); /* * Test empty free */ ret = krb5_pac_init(context, &pac); if (ret) err(context, ret, "krb5_pac_init"); krb5_pac_free(context, pac); /* * Test add remove buffer */ ret = krb5_pac_init(context, &pac); if (ret) err(context, ret, "krb5_pac_init"); { const krb5_data cdata = { 0, 2, "\x00\x01" } ; ret = krb5_pac_add_buffer(context, pac, 1, &cdata); if (ret) err(context, ret, "krb5_pac_add_buffer"); } { ret = krb5_pac_get_buffer(context, pac, 1, &data); if (ret) err(context, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) err(context, 0, "krb5_pac_get_buffer data not the same"); krb5_free_data_contents(context, &data); } { const krb5_data cdata = { 0, 2, "\x02\x00" } ; ret = krb5_pac_add_buffer(context, pac, 2, &cdata); if (ret) err(context, ret, "krb5_pac_add_buffer"); } { ret = krb5_pac_get_buffer(context, pac, 1, &data); if (ret) err(context, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) err(context, 0, "krb5_pac_get_buffer data not the same"); krb5_free_data_contents(context, &data); /* */ ret = krb5_pac_get_buffer(context, pac, 2, &data); if (ret) err(context, ret, "krb5_pac_get_buffer"); if (data.length != 2 || memcmp(data.data, "\x02\x00", 2) != 0) err(context, 0, "krb5_pac_get_buffer data not the same"); krb5_free_data_contents(context, &data); } ret = krb5int_pac_sign(context, pac, authtime, p, &member_keyblock, &kdc_keyblock, &data); if (ret) err(context, ret, "krb5int_pac_sign"); krb5_pac_free(context, pac); ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_free_data_contents(context, &data); if (ret) err(context, ret, "krb5_pac_parse 3"); ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock, &kdc_keyblock); if (ret) err(context, ret, "krb5_pac_verify 3"); { uint32_t *list; size_t len; /* our two user buffer plus the three "system" buffers */ ret = krb5_pac_get_types(context, pac, &len, &list); if (ret) err(context, ret, "krb5_pac_get_types"); if (len != 5) err(context, 0, "list wrong length"); free(list); } krb5_pac_free(context, pac); krb5_free_principal(context, p); krb5_free_context(context); return 0; }