/* * Construct list of realms between client and server. */ static krb5_error_code rtree_hier_realms(krb5_context context, const krb5_data *client, const krb5_data *server, krb5_data **realms, size_t *nrealms, int sep) { krb5_error_code retval; struct hstate c, s; krb5_data *ctweens = NULL, *stweens = NULL, *twp, *r, *rp; size_t nctween, nstween; *realms = NULL; *nrealms = 0; r = rp = NULL; c.str = client->data; c.len = client->length; c.dot = c.tail = NULL; s.str = server->data; s.len = server->length; s.dot = s.tail = NULL; comtail(&c, &s, sep); adjtail(&c, &s, sep); retval = rtree_hier_tweens(context, &c, &ctweens, &nctween, 1, sep); if (retval) goto error; retval = rtree_hier_tweens(context, &s, &stweens, &nstween, 0, sep); if (retval) goto error; rp = r = calloc(nctween + nstween, sizeof(krb5_data)); if (r == NULL) { retval = ENOMEM; goto error; } /* Copy client realm "tweens" forward. */ for (twp = ctweens; twp < &ctweens[nctween]; twp++) { retval = krb5int_copy_data_contents(context, twp, rp); if (retval) goto error; rp++; } /* Copy server realm "tweens" backward. */ for (twp = &stweens[nstween]; twp-- > stweens;) { retval = krb5int_copy_data_contents(context, twp, rp); if (retval) goto error; rp++; } error: free(ctweens); free(stweens); if (retval) { free_realmlist(context, r, rp - r); return retval; } *realms = r; *nrealms = rp - r; return 0; }
/* * Build tree by hierarchical traversal. */ static krb5_error_code rtree_hier_tree( krb5_context context, const krb5_data *client, const krb5_data *server, krb5_principal **rettree, int sep) { krb5_error_code retval; krb5_data *realms; const krb5_data *dstrealm, *srcrealm; krb5_principal *tree, *pprinc; size_t nrealms, nprincs, i; *rettree = NULL; retval = rtree_hier_realms(context, client, server, &realms, &nrealms, sep); if (retval) return retval; nprincs = nrealms; pprinc = tree = calloc(nprincs + 1, sizeof(krb5_principal)); if (tree == NULL) { retval = ENOMEM; goto error; } for (i = 0; i < nrealms; i++) tree[i] = NULL; srcrealm = client; for (i = 0; i < nrealms; i++) { dstrealm = &realms[i]; retval = krb5_tgtname(context, dstrealm, srcrealm, pprinc++); if (retval) goto error; srcrealm = dstrealm; } *rettree = tree; free_realmlist(context, realms, nrealms); return 0; error: while (pprinc != NULL && pprinc > tree) { krb5_free_principal(context, *--pprinc); *pprinc = NULL; } free_realmlist(context, realms, nrealms); free(tree); return retval; }