/* Internalize a keyblock and convert it to a key. */ static krb5_error_code intern_key(krb5_context ctx, krb5_key *key, krb5_octet **bp, size_t *sp) { krb5_keyblock *keyblock; krb5_error_code ret; ret = krb5_internalize_opaque(ctx, KV5M_KEYBLOCK, (krb5_pointer *) &keyblock, bp, sp); if (ret != 0) return ret; ret = krb5_k_create_key(ctx, keyblock, key); krb5_free_keyblock(ctx, keyblock); return ret; }
/* * krb5_auth_context_internalize() - Internalize the krb5_auth_context. */ static krb5_error_code krb5_auth_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_auth_context auth_context; krb5_int32 ibuf; krb5_octet *bp; size_t remain; krb5_int32 ivlen; krb5_int32 tag; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_AUTH_CONTEXT) { kret = ENOMEM; /* Get memory for the auth_context */ if ((remain >= (5*sizeof(krb5_int32))) && (auth_context = (krb5_auth_context) calloc(1, sizeof(struct _krb5_auth_context)))) { /* Get auth_context_flags */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->auth_context_flags = ibuf; /* Get remote_seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->remote_seq_number = ibuf; /* Get local_seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->local_seq_number = ibuf; /* Get req_cksumtype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->req_cksumtype = (krb5_cksumtype) ibuf; /* Get safe_cksumtype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->safe_cksumtype = (krb5_cksumtype) ibuf; /* Get length of i_vector */ (void) krb5_ser_unpack_int32(&ivlen, &bp, &remain); if (ivlen) { if ((auth_context->i_vector = (krb5_pointer) malloc((size_t)ivlen))) kret = krb5_ser_unpack_bytes(auth_context->i_vector, (size_t) ivlen, &bp, &remain); else kret = ENOMEM; } else kret = 0; /* Peek at next token */ tag = 0; if (!kret) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); /* This is the remote_addr */ if (!kret && (tag == TOKEN_RADDR)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> remote_addr, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the remote_port */ if (!kret && (tag == TOKEN_RPORT)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> remote_port, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the local_addr */ if (!kret && (tag == TOKEN_LADDR)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> local_addr, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the local_port */ if (!kret && (tag == TOKEN_LPORT)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> local_port, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the keyblock */ if (!kret && (tag == TOKEN_KEYBLOCK)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context->keyblock, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the send_subkey */ if (!kret && (tag == TOKEN_LSKBLOCK)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context-> send_subkey, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the recv_subkey */ if (!kret) { if (tag == TOKEN_RSKBLOCK) { kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context-> recv_subkey, &bp, &remain); } else { /* * We read the next tag, but it's not of any use here, so * we effectively 'unget' it here. */ bp -= sizeof(krb5_int32); remain += sizeof(krb5_int32); } } /* Now find the authentp */ if (!kret) { if ((kret = krb5_internalize_opaque(kcontext, KV5M_AUTHENTICATOR, (krb5_pointer *) &auth_context->authentp, &bp, &remain))) { if (kret == EINVAL) kret = 0; } } /* Finally, find the trailer */ if (!kret) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf != KV5M_AUTH_CONTEXT)) kret = EINVAL; } if (!kret) { *buffer = bp; *lenremain = remain; auth_context->magic = KV5M_AUTH_CONTEXT; *argp = (krb5_pointer) auth_context; } else krb5_auth_con_free(kcontext, auth_context); } } return(kret); }
static krb5_error_code s4u2proxy_internalize(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_octet **buffer, size_t *lenremain) { struct s4u2proxy_context *s4uctx = (struct s4u2proxy_context *)request_context; krb5_error_code code; krb5_int32 ibuf; krb5_octet *bp; size_t remain; int count; krb5_principal *delegated = NULL; bp = *buffer; remain = *lenremain; /* version */ code = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (code != 0) goto cleanup; if (ibuf != 1) { code = EINVAL; goto cleanup; } /* count */ code = krb5_ser_unpack_int32(&count, &bp, &remain); if (code != 0) goto cleanup; if (count > 65535) return ERANGE; /* let's set some reasonable limits here */ else if (count > 0) { int i; delegated = k5calloc(count + 1, sizeof(krb5_principal), &code); if (delegated == NULL) goto cleanup; for (i = 0; i < count; i++) { code = krb5_internalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer *)&delegated[i], &bp, &remain); if (code != 0) goto cleanup; } delegated[i] = NULL; } code = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (code != 0) goto cleanup; s4u2proxy_free_internal(kcontext, context, plugin_context, request_context, s4uctx->delegated); s4uctx->count = count; s4uctx->delegated = delegated; s4uctx->authenticated = (ibuf != 0); delegated = NULL; *buffer = bp; *lenremain = remain; cleanup: s4u2proxy_free_internal(kcontext, context, plugin_context, request_context, delegated); return code; }
/* * krb5_authenticator_internalize() - Internalize the krb5_authenticator. */ static krb5_error_code krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_authenticator *authenticator; krb5_int32 ibuf; krb5_octet *bp; size_t remain; int i; krb5_int32 nadata; size_t len; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_AUTHENTICATOR) { kret = ENOMEM; /* Get memory for the authenticator */ if ((remain >= (3*sizeof(krb5_int32))) && (authenticator = (krb5_authenticator *) calloc(1, sizeof(krb5_authenticator)))) { /* Get ctime */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->ctime = (krb5_timestamp) ibuf; /* Get cusec */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->cusec = ibuf; /* Get seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->seq_number = ibuf; kret = 0; /* Attempt to read in the client */ kret = krb5_internalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer *) &authenticator->client, &bp, &remain); if (kret == EINVAL) kret = 0; /* Attempt to read in the checksum */ if (!kret) { kret = krb5_internalize_opaque(kcontext, KV5M_CHECKSUM, (krb5_pointer *) &authenticator->checksum, &bp, &remain); if (kret == EINVAL) kret = 0; } /* Attempt to read in the subkey */ if (!kret) { kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &authenticator->subkey, &bp, &remain); if (kret == EINVAL) kret = 0; } /* Attempt to read in the authorization data count */ if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { nadata = ibuf; len = (size_t) (nadata + 1); /* Get memory for the authorization data pointers */ if ((authenticator->authorization_data = (krb5_authdata **) calloc(len, sizeof(krb5_authdata *)))) { for (i=0; !kret && (i<nadata); i++) { kret = krb5_internalize_opaque(kcontext, KV5M_AUTHDATA, (krb5_pointer *) &authenticator-> authorization_data[i], &bp, &remain); } /* Finally, find the trailer */ if (!kret) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf == KV5M_AUTHENTICATOR)) authenticator->magic = KV5M_AUTHENTICATOR; else kret = EINVAL; } } } if (!kret) { *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) authenticator; } else krb5_free_authenticator(kcontext, authenticator); } } return(kret); }
/* * Do a serialization test. */ static krb5_error_code ser_data(int verbose, char *msg, krb5_pointer ctx, krb5_magic dtype) { krb5_error_code kret; krb5_context ser_ctx; krb5_pointer nctx; krb5_octet *outrep, *ibuf, *outrep2; size_t outlen, ilen, outlen2; /* Initialize context and initialize all Kerberos serializers */ if ((kret = krb5_init_context(&ser_ctx))) { printf("Couldn't initialize krb5 library: %s\n", error_message(kret)); exit(1); } krb5_ser_context_init(ser_ctx); krb5_ser_auth_context_init(ser_ctx); krb5_ser_ccache_init(ser_ctx); krb5_ser_rcache_init(ser_ctx); krb5_ser_keytab_init(ser_ctx); /* Externalize the data */ kret = krb5_externalize_data(ser_ctx, ctx, &outrep, &outlen); if (!kret) { if (verbose) { printf("%s: externalized in %d bytes\n", msg, outlen); print_erep(outrep, outlen); } /* Now attempt to re-constitute it */ ibuf = outrep; ilen = outlen; kret = krb5_internalize_opaque(ser_ctx, dtype, (krb5_pointer *) &nctx, &ibuf, &ilen); if (!kret) { if (ilen) printf("%s: %d bytes left over after internalize\n", msg, ilen); /* Now attempt to re-externalize it */ kret = krb5_externalize_data(ser_ctx, nctx, &outrep2, &outlen2); if (!kret) { /* Compare the results. */ if ((outlen2 != outlen) || memcmp(outrep, outrep2, outlen)) { printf("%s: comparison failed\n", msg); print_erep(outrep2, outlen2); } else { if (verbose) printf("%s: compare succeeded\n", msg); } krb5_xfree(outrep2); } else printf("%s: second externalize returned %d\n", msg, kret); /* Free the data */ switch (dtype) { case KV5M_CONTEXT: krb5_free_context((krb5_context) nctx); break; case KV5M_AUTH_CONTEXT: if (nctx) { krb5_auth_context actx; actx = (krb5_auth_context) nctx; if (actx->i_vector) krb5_xfree(actx->i_vector); } krb5_auth_con_free(ser_ctx, (krb5_auth_context) nctx); break; case KV5M_CCACHE: krb5_cc_close(ser_ctx, (krb5_ccache) nctx); break; case KV5M_RCACHE: krb5_rc_close(ser_ctx, (krb5_rcache) nctx); break; case KV5M_KEYTAB: krb5_kt_close(ser_ctx, (krb5_keytab) nctx); break; case KV5M_ENCRYPT_BLOCK: if (nctx) { krb5_encrypt_block *eblock; eblock = (krb5_encrypt_block *) nctx; #if 0 if (eblock->priv && eblock->priv_size) krb5_xfree(eblock->priv); #endif if (eblock->key) krb5_free_keyblock(ser_ctx, eblock->key); krb5_xfree(eblock); } break; case KV5M_PRINCIPAL: krb5_free_principal(ser_ctx, (krb5_principal) nctx); break; case KV5M_CHECKSUM: krb5_free_checksum(ser_ctx, (krb5_checksum *) nctx); break; default: printf("don't know how to free %d\n", dtype); break; } } else printf("%s: internalize returned %d\n", msg, kret); krb5_xfree(outrep); } else printf("%s: externalize_data returned %d\n", msg, kret); krb5_free_context(ser_ctx); return(kret); }
/* * krb5_context_internalize() - Internalize the krb5_context. */ static krb5_error_code krb5_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_context context; krb5_int32 ibuf; krb5_octet *bp; size_t remain; int i; bp = *buffer; remain = *lenremain; /* Read our magic number */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) return (EINVAL); if (ibuf != KV5M_CONTEXT) return (EINVAL); /* Get memory for the context */ context = (krb5_context) MALLOC(sizeof(struct _krb5_context)); if (!context) return (ENOMEM); (void) memset(context, 0, sizeof(struct _krb5_context)); /* Get the size of the default realm */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; if (ibuf) { context->default_realm = (char *) MALLOC((size_t) ibuf+1); if (!context->default_realm) { kret = ENOMEM; goto cleanup; } kret = krb5_ser_unpack_bytes((krb5_octet *) context->default_realm, (size_t) ibuf, &bp, &remain); if (kret) goto cleanup; context->default_realm[ibuf] = '\0'; } /* Get the number of in_tkt_ktypes */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->in_tkt_ktype_count = (int) ibuf; context->in_tkt_ktypes = (krb5_enctype *) MALLOC(sizeof(krb5_enctype) * (context->in_tkt_ktype_count+1)); if (!context->in_tkt_ktypes) { kret = ENOMEM; goto cleanup; } (void) memset(context->in_tkt_ktypes, 0, (sizeof(krb5_enctype) * (context->in_tkt_ktype_count + 1))); for (i=0; i<context->in_tkt_ktype_count; i++) { if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->in_tkt_ktypes[i] = (krb5_enctype) ibuf; } /* Get the number of tgs_ktypes */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->tgs_ktype_count = (int) ibuf; context->tgs_ktypes = (krb5_enctype *) MALLOC(sizeof(krb5_enctype) * (context->tgs_ktype_count+1)); if (!context->tgs_ktypes) { kret = ENOMEM; goto cleanup; } (void) memset(context->tgs_ktypes, 0, (sizeof(krb5_enctype) * (context->tgs_ktype_count + 1))); for (i=0; i<context->tgs_ktype_count; i++) { if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->tgs_ktypes[i] = (krb5_enctype) ibuf; } /* Allowable checksum */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->clockskew = (krb5_deltat) ibuf; /* kdc_req_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->kdc_req_sumtype = (krb5_cksumtype) ibuf; /* default ap_req_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->default_ap_req_sumtype = (krb5_cksumtype) ibuf; /* default_safe_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->default_safe_sumtype = (krb5_cksumtype) ibuf; /* kdc_default_options */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->kdc_default_options = (krb5_flags) ibuf; /* library_options */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->library_options = (krb5_flags) ibuf; /* profile_secure */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->profile_secure = (krb5_boolean) ibuf; /* fcc_default_format */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->fcc_default_format = (int) ibuf; /* scc_default_format */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->scc_default_format = (int) ibuf; /* Attempt to read in the os_context. It's an array now, but we still treat it in most places as a separate object with a pointer. */ { krb5_os_context osp = 0; kret = krb5_internalize_opaque(kcontext, KV5M_OS_CONTEXT, (krb5_pointer *) &osp, &bp, &remain); if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; /* Put the newly allocated data into the krb5_context structure where we're really keeping it these days. */ if (osp) *context->os_context = *osp; free(osp); } /* Attempt to read in the db_context */ kret = krb5_internalize_opaque(kcontext, KV5M_DB_CONTEXT, (krb5_pointer *) &context->db_context, &bp, &remain); if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; #ifndef _KERNEL /* Attempt to read in the profile */ kret = krb5_internalize_opaque(kcontext, PROF_MAGIC_PROFILE, (krb5_pointer *) &context->profile, &bp, &remain); #endif if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; /* Finally, find the trailer */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; if (ibuf != KV5M_CONTEXT) { kret = EINVAL; goto cleanup; } context->magic = KV5M_CONTEXT; *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) context; return 0; cleanup: if (context) krb5_free_context(context); return(kret); }