gsskrb5: Add simple name attributes support
This adds Kerberos mechanism support for: - composite principal name export/import - getting rudimentary name attributes from GSS names using gss_get_name_attribute(): - all (raw) authorization data from the Ticket - all (raw) authorization data from the Authenticator - transit path - realm - component count - each component - gss_inquire_name() - gss_display_name_ext() (just for the hostbased service name type though) The test exercises almost all of the functionality, except for: - getting the PAC - getting authz-data from the Authenticator - getting the transit path TBD (much) later: - amend test_context to do minimal name attribute checks as well - gss_set_name_attribute() (to request authz-data) - gss_delete_name_attribute() - getting specific authorization data elements via URN fragments (as opposed to all of them) - parsing the PAC, extracting SIDs (each one as a separate value) - some configurable local policy (?) - plugin interface for additional local policy
This commit is contained in:

committed by
Nico Williams

parent
1cede09a0b
commit
be708ca3cf
@@ -43,42 +43,286 @@
|
||||
#include <gssapi.h>
|
||||
#include <gssapi_krb5.h>
|
||||
#include <gssapi_spnego.h>
|
||||
#include <krb5_asn1.h>
|
||||
#include <err.h>
|
||||
#include <getarg.h>
|
||||
|
||||
static void make_composite_name(CompositePrincipal *, gss_name_t *);
|
||||
static void assert_attr(gss_name_t, const char *, OM_uint32, gss_buffer_t,
|
||||
const char *, int, int, int);
|
||||
static void assert_attr_unavail(gss_name_t, const char *);
|
||||
static void assert_attr_set(gss_name_t, gss_buffer_set_t);
|
||||
|
||||
static void
|
||||
gss_print_errors (int min_stat)
|
||||
gss_print_errors(OM_uint32 stat, gss_OID mech)
|
||||
{
|
||||
OM_uint32 new_stat;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
gss_buffer_desc status_string;
|
||||
OM_uint32 junk;
|
||||
OM_uint32 more = 0;
|
||||
gss_buffer_desc buf = GSS_C_EMPTY_BUFFER;
|
||||
OM_uint32 ret;
|
||||
|
||||
if (mech) {
|
||||
junk = gss_oid_to_str(&junk, mech, &buf);
|
||||
if (junk == GSS_S_COMPLETE)
|
||||
fprintf(stderr, "mech = %.*s\n", (int)buf.length, buf.value);
|
||||
gss_release_buffer(&junk, &buf);
|
||||
}
|
||||
do {
|
||||
ret = gss_display_status (&new_stat,
|
||||
min_stat,
|
||||
GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,
|
||||
&msg_ctx,
|
||||
&status_string);
|
||||
if (!GSS_ERROR(ret)) {
|
||||
fprintf (stderr, "%.*s\n", (int)status_string.length,
|
||||
(char *)status_string.value);
|
||||
gss_release_buffer (&new_stat, &status_string);
|
||||
}
|
||||
} while (!GSS_ERROR(ret) && msg_ctx != 0);
|
||||
ret = gss_display_status(&junk,
|
||||
stat,
|
||||
mech ? GSS_C_MECH_CODE : GSS_C_GSS_CODE,
|
||||
mech,
|
||||
&more,
|
||||
&buf);
|
||||
if (ret != GSS_S_COMPLETE)
|
||||
errx(1, "gss_display_status() failed");
|
||||
fprintf(stderr, "%.*s\n", (int)buf.length, (char *)buf.value);
|
||||
gss_release_buffer(&junk, &buf);
|
||||
} while (more);
|
||||
}
|
||||
|
||||
static void
|
||||
gss_err(int exitval, int status, const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)))
|
||||
gss_err(int exitval,
|
||||
OM_uint32 maj,
|
||||
OM_uint32 min,
|
||||
gss_OID mech,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vwarnx (fmt, args);
|
||||
gss_print_errors (status);
|
||||
vwarnx(fmt, args);
|
||||
va_end(args);
|
||||
exit (exitval);
|
||||
gss_print_errors(maj, GSS_C_NO_OID);
|
||||
if (mech)
|
||||
gss_print_errors(min, mech);
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
#define MAKE_URN(tail) \
|
||||
{ sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail) - 1, \
|
||||
GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail }
|
||||
|
||||
/*
|
||||
* Test RFC6680 name attributes for Kerberos.
|
||||
*/
|
||||
static void
|
||||
check_name_attrs(void)
|
||||
{
|
||||
CompositePrincipal p;
|
||||
EncTicketPart *t;
|
||||
gss_buffer_desc v = GSS_C_EMPTY_BUFFER;
|
||||
gss_name_t n;
|
||||
OM_uint32 maj, min;
|
||||
int32_t ret;
|
||||
gss_buffer_desc attrs[] = {
|
||||
MAKE_URN("realm"),
|
||||
MAKE_URN("name-ncomp"),
|
||||
MAKE_URN("name-ncomp#0"),
|
||||
MAKE_URN("peer-realm"),
|
||||
MAKE_URN("ticket-authz-data"),
|
||||
MAKE_URN("transit-path"),
|
||||
MAKE_URN("canonical-name"),
|
||||
}; /* Set of attributes we expect to see indicated */
|
||||
gss_buffer_set_desc attr_set;
|
||||
size_t i, sz;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
attr_set.elements = attrs;
|
||||
/*
|
||||
* attr_set.count is set in each of the following sections to ever more
|
||||
* items.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Testing name attributes is pretty tricky.
|
||||
*
|
||||
* Our approach is to construct a composite name, construct an exported
|
||||
* composite name token for it, import it, then test the gss_inquire_name()
|
||||
* and gss_get_name_attribute() accessors, and then gss_display_name_ext().
|
||||
*
|
||||
* Ideally we'd test the accessors on names imported from query forms with
|
||||
* gss_import_name(), and on names from established contexts. However,
|
||||
* that belongs in the test_context program.
|
||||
*
|
||||
* TODO: Implement and test gss_set_name_attribute() and
|
||||
* gss_delete_name_attribute().
|
||||
*/
|
||||
|
||||
/* First construct and test an unauthenticated name */
|
||||
p.realm = estrdup("TEST.H5L.SE");
|
||||
p.name.name_type = KRB5_NT_PRINCIPAL;
|
||||
p.name.name_string.val = ecalloc(1, sizeof(p.name.name_string.val[0]));
|
||||
p.name.name_string.len = 1;
|
||||
p.name.name_string.val[0] = estrdup("someuser");
|
||||
p.nameattrs = NULL;
|
||||
make_composite_name(&p, &n);
|
||||
|
||||
/* Test the attributes we expect it to have */
|
||||
v.length = sizeof("TEST.H5L.SE") - 1;
|
||||
v.value = "TEST.H5L.SE";
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE,
|
||||
&v, "TEST.H5L.SE", 0, 1, 0);
|
||||
|
||||
i = 1;
|
||||
v.length = sizeof(size_t);
|
||||
v.value = &i;
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp",
|
||||
GSS_S_COMPLETE, &v, "1", 0, 1, 0);
|
||||
|
||||
v.length = sizeof("someuser") - 1;
|
||||
v.value = "someuser";
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0",
|
||||
GSS_S_COMPLETE, &v, "someuser", 0, 1, 0);
|
||||
|
||||
attr_set.count = 3;
|
||||
assert_attr_set(n, &attr_set);
|
||||
|
||||
/* Check that it does not have prefixed attributes */
|
||||
assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"realm");
|
||||
assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"name-ncomp");
|
||||
assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"name-ncomp#0");
|
||||
assert_attr_unavail(n, "what ever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"name-ncomp#0");
|
||||
|
||||
/* Check that it does not have various other supported attributes */
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm");
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#1");
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name");
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"ticket-authz-data#pac");
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
|
||||
"ticket-authz-data");
|
||||
assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "transit-path");
|
||||
|
||||
/* Exercise URN parser */
|
||||
assert_attr_unavail(n, "urn:whatever");
|
||||
assert_attr_unavail(n, "urn:whatever#");
|
||||
assert_attr_unavail(n, "urn:what#ever");
|
||||
assert_attr_unavail(n, "#");
|
||||
assert_attr_unavail(n, "#whatever");
|
||||
assert_attr_unavail(n, "whatever");
|
||||
assert_attr_unavail(n, "what ever");
|
||||
assert_attr_unavail(n, "what ever#");
|
||||
|
||||
/* Now test an authenticated name */
|
||||
gss_release_name(&min, &n);
|
||||
p.nameattrs = ecalloc(1, sizeof(p.nameattrs[0]));
|
||||
p.nameattrs->authenticated = 1;
|
||||
make_composite_name(&p, &n);
|
||||
|
||||
v.length = sizeof("TEST.H5L.SE") - 1;
|
||||
v.value = "TEST.H5L.SE";
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE,
|
||||
&v, "TEST.H5L.SE", 1, 1, 0);
|
||||
|
||||
i = 1;
|
||||
v.length = sizeof(size_t);
|
||||
v.value = &i;
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp",
|
||||
GSS_S_COMPLETE, &v, "1", 1, 1, 0);
|
||||
|
||||
v.length = sizeof("someuser") - 1;
|
||||
v.value = "someuser";
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0",
|
||||
GSS_S_COMPLETE, &v, "someuser", 1, 1, 0);
|
||||
|
||||
assert_attr_set(n, &attr_set);
|
||||
|
||||
/* Now add a peer realm */
|
||||
gss_release_name(&min, &n);
|
||||
p.nameattrs->peer_realm = ecalloc(1, sizeof(p.nameattrs->peer_realm[0]));
|
||||
p.nameattrs->peer_realm[0] = estrdup("FOO.TEST.H5L.SE");
|
||||
make_composite_name(&p, &n);
|
||||
|
||||
v.length = sizeof("FOO.TEST.H5L.SE") - 1;
|
||||
v.value = "FOO.TEST.H5L.SE";
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm",
|
||||
GSS_S_COMPLETE, &v, "FOO.TEST.H5L.SE", 1, 1, 0);
|
||||
attr_set.count = 4;
|
||||
assert_attr_set(n, &attr_set);
|
||||
|
||||
/* Now add canonical name and an authz-data element */
|
||||
gss_release_name(&min, &n);
|
||||
p.nameattrs->source = ecalloc(1, sizeof(p.nameattrs->source[0]));
|
||||
p.nameattrs->source->element = choice_PrincipalNameAttrSrc_enc_ticket_part;
|
||||
|
||||
t = &p.nameattrs->source->u.enc_ticket_part;
|
||||
t->cname.name_type = KRB5_NT_PRINCIPAL;
|
||||
t->cname.name_string.val = ecalloc(1, sizeof(t->cname.name_string.val[0]));
|
||||
t->crealm = estrdup("TEST.H5L.SE");
|
||||
t->cname.name_string.len = 1;
|
||||
t->cname.name_string.val[0] = estrdup("realusername");
|
||||
t->authorization_data = ecalloc(1, sizeof(t->authorization_data[0]));
|
||||
t->authorization_data->val =
|
||||
ecalloc(1, sizeof(t->authorization_data->val[0]));
|
||||
t->authorization_data->len = 1;
|
||||
t->authorization_data->val[0].ad_type =
|
||||
KRB5_AUTHDATA_ON_BEHALF_OF; /* whatever */
|
||||
t->authorization_data->val[0].ad_data.data =
|
||||
estrdup("foobar@TEST.H5L.SE");
|
||||
t->authorization_data->val[0].ad_data.length =
|
||||
sizeof("foobar@TEST.H5L.SE") - 1;
|
||||
make_composite_name(&p, &n);
|
||||
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name",
|
||||
GSS_S_COMPLETE, GSS_C_NO_BUFFER, "realusername@TEST.H5L.SE", 1,
|
||||
1, 0);
|
||||
|
||||
ASN1_MALLOC_ENCODE(AuthorizationData, v.value, v.length,
|
||||
t->authorization_data, &sz, ret);
|
||||
if (ret)
|
||||
errx(1, "Failed to encode AuthorizationData");
|
||||
|
||||
assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "ticket-authz-data",
|
||||
GSS_S_COMPLETE, &v, NULL, 0, 1, 0);
|
||||
free(v.value);
|
||||
|
||||
attr_set.count = 7;
|
||||
assert_attr_set(n, &attr_set);
|
||||
|
||||
gss_release_name(&min, &n);
|
||||
free_CompositePrincipal(&p);
|
||||
|
||||
/*
|
||||
* Test gss_display_name_ext() with a host-based service principal
|
||||
* "host/somehost.test.h5l.se@TEST.H5L.SE".
|
||||
*
|
||||
* Where gss_display_name() would display this as a Kerberos principal
|
||||
* name, gss_display_name_ext() with GSS_C_NT_HOSTBASED_SERVICE should
|
||||
* display it as "host@somehost.test.h5l.se".
|
||||
*/
|
||||
p.realm = estrdup("TEST.H5L.SE");
|
||||
p.name.name_type = KRB5_NT_SRV_HST;
|
||||
p.name.name_string.val = ecalloc(2, sizeof(p.name.name_string.val[0]));
|
||||
p.name.name_string.len = 2;
|
||||
p.name.name_string.val[0] = estrdup("host");
|
||||
p.name.name_string.val[1] = estrdup("somehost.test.h5l.se");
|
||||
p.nameattrs = NULL;
|
||||
make_composite_name(&p, &n);
|
||||
|
||||
maj = gss_display_name_ext(&min, n, GSS_C_NT_HOSTBASED_SERVICE, &v);
|
||||
if (maj)
|
||||
gss_err(1, maj, min, GSS_KRB5_MECHANISM, "display name ext");
|
||||
if (v.length != sizeof("host@somehost.test.h5l.se") - 1 ||
|
||||
strncmp(v.value, "host@somehost.test.h5l.se", v.length) != 0)
|
||||
errx(1, "display name ext");
|
||||
gss_release_buffer(&min, &v);
|
||||
gss_release_name(&min, &n);
|
||||
free_CompositePrincipal(&p);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* - test URN fragments for access to specific authorization data element
|
||||
* types
|
||||
* - test GSS_C_ATTR_LOCAL_LOGIN_USER support (requires configuration or
|
||||
* that we register a plugin here)
|
||||
*/
|
||||
}
|
||||
|
||||
static int version_flag = 0;
|
||||
@@ -145,7 +389,7 @@ main(int argc, char **argv)
|
||||
GSS_C_NT_HOSTBASED_SERVICE,
|
||||
&name);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "import name error");
|
||||
gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, "import name error");
|
||||
free(str);
|
||||
|
||||
if (anon_flag)
|
||||
@@ -158,13 +402,13 @@ main(int argc, char **argv)
|
||||
mech_oid,
|
||||
&MNname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "canonicalize name error");
|
||||
gss_err(1, maj_stat, min_stat, mech_oid, "canonicalize name error");
|
||||
|
||||
maj_stat = gss_export_name(&min_stat,
|
||||
MNname,
|
||||
&name_buffer);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "export name error (KRB5)");
|
||||
gss_err(1, maj_stat, min_stat, mech_oid, "export name error");
|
||||
|
||||
/*
|
||||
* Import the exported name and compare
|
||||
@@ -174,13 +418,13 @@ main(int argc, char **argv)
|
||||
GSS_C_NT_EXPORT_NAME,
|
||||
&MNname2);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "import name error (exported KRB5 name)");
|
||||
gss_err(1, maj_stat, min_stat, mech_oid, "export name error");
|
||||
|
||||
|
||||
maj_stat = gss_compare_name(&min_stat, MNname, MNname2, &equal);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
errx(1, "gss_compare_name");
|
||||
if (equal == anon_flag)
|
||||
gss_err(1, maj_stat, min_stat, mech_oid, "compare name error");
|
||||
if (equal && anon_flag)
|
||||
errx(1, "names %s equal", anon_flag ? "incorrectly" : "not");
|
||||
|
||||
gss_release_name(&min_stat, &MNname2);
|
||||
@@ -205,13 +449,13 @@ main(int argc, char **argv)
|
||||
GSS_C_NO_OID,
|
||||
&name);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "import (no oid) name error");
|
||||
gss_err(1, maj_stat, min_stat, NULL, "import (no oid) name error");
|
||||
|
||||
maj_stat = gss_import_name(&min_stat, &name_buffer,
|
||||
GSS_KRB5_NT_USER_NAME,
|
||||
&MNname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "import (krb5 mn) name error");
|
||||
gss_err(1, maj_stat, min_stat, NULL, "import (krb5 mn) name error");
|
||||
|
||||
free(str);
|
||||
|
||||
@@ -230,14 +474,16 @@ main(int argc, char **argv)
|
||||
GSS_SPNEGO_MECHANISM,
|
||||
&MNname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "canonicalize name error");
|
||||
gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM,
|
||||
"canonicalize name error");
|
||||
|
||||
|
||||
maj_stat = gss_export_name(&maj_stat,
|
||||
MNname,
|
||||
&name_buffer);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "export name error (SPNEGO)");
|
||||
gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM,
|
||||
"export name error (SPNEGO)");
|
||||
|
||||
gss_release_name(&min_stat, &MNname);
|
||||
gss_release_buffer(&min_stat, &name_buffer);
|
||||
@@ -253,29 +499,177 @@ main(int argc, char **argv)
|
||||
maj_stat = gss_import_name(&min_stat, &name_buffer,
|
||||
GSS_C_NT_ANONYMOUS, &name);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "import (anon) name error");
|
||||
gss_err(1, maj_stat, min_stat, GSS_C_NO_OID,
|
||||
"import (anon) name error");
|
||||
|
||||
maj_stat = gss_canonicalize_name(&min_stat, name,
|
||||
GSS_SANON_X25519_MECHANISM,
|
||||
&MNname);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "canonicalize (anon) name error");
|
||||
gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM,
|
||||
"canonicalize (anon) name error");
|
||||
|
||||
maj_stat = gss_display_name(&min_stat, MNname,
|
||||
&name_buffer, &name_type);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
gss_err(1, min_stat, "display_name (anon) name error");
|
||||
gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM,
|
||||
"display_name (anon) name error");
|
||||
|
||||
if (!gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS))
|
||||
gss_err(1, 0, "display name type not anonymous");
|
||||
errx(1, "display name type not anonymous");
|
||||
if (memcmp(name_buffer.value, "WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS",
|
||||
sizeof("WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS") - 1) != 0)
|
||||
gss_err(1, 0, "display name string not well known anonymous name");
|
||||
errx(1, "display name string not well known anonymous name");
|
||||
|
||||
gss_release_name(&min_stat, &MNname);
|
||||
gss_release_name(&min_stat, &name);
|
||||
gss_release_buffer(&min_stat, &name_buffer);
|
||||
}
|
||||
|
||||
check_name_attrs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copied from _gsskrb5_export_name_composite() */
|
||||
static void
|
||||
export_name_composite(CompositePrincipal *name, gss_buffer_t exported_name)
|
||||
{
|
||||
gss_buffer_desc inner = GSS_C_EMPTY_BUFFER;
|
||||
unsigned char *buf;
|
||||
int32_t ret;
|
||||
size_t sz;
|
||||
|
||||
ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length,
|
||||
(void *)name, &sz, ret);
|
||||
if (ret)
|
||||
errx(1, "Failed to encode exported composite name token");
|
||||
|
||||
exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length;
|
||||
exported_name->value = malloc(exported_name->length);
|
||||
if (exported_name->value == NULL)
|
||||
errx(1, "Failed to allocate exported composite name token");
|
||||
|
||||
/* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
|
||||
|
||||
buf = exported_name->value;
|
||||
buf[0] = 0x04;
|
||||
buf[1] = 0x02;
|
||||
buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
|
||||
buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
|
||||
buf[4] = 0x06;
|
||||
buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF;
|
||||
|
||||
memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
|
||||
buf += 6 + GSS_KRB5_MECHANISM->length;
|
||||
|
||||
buf[0] = (inner.length >> 24) & 0xff;
|
||||
buf[1] = (inner.length >> 16) & 0xff;
|
||||
buf[2] = (inner.length >> 8) & 0xff;
|
||||
buf[3] = (inner.length) & 0xff;
|
||||
buf += 4;
|
||||
|
||||
memcpy(buf, inner.value, inner.length);
|
||||
free(inner.value);
|
||||
}
|
||||
|
||||
static void
|
||||
make_composite_name(CompositePrincipal *princ, gss_name_t *n)
|
||||
{
|
||||
gss_buffer_desc token, exported;
|
||||
OM_uint32 maj, min;
|
||||
|
||||
export_name_composite(princ, &token);
|
||||
maj = gss_import_name(&min, &token, GSS_C_NT_COMPOSITE_EXPORT, n);
|
||||
if (maj)
|
||||
gss_err(1, maj, min, GSS_KRB5_MECHANISM, "import composite name");
|
||||
maj = gss_export_name_composite(&min, *n, &exported);
|
||||
if (maj)
|
||||
gss_err(1, maj, min, GSS_KRB5_MECHANISM, "export composite name");
|
||||
if (token.length != exported.length ||
|
||||
memcmp(token.value, exported.value, token.length) != 0)
|
||||
errx(1, "import/export composite token disagreement");
|
||||
gss_release_buffer(&min, &exported);
|
||||
free(token.value); /* Use free because we allocated this one */
|
||||
}
|
||||
|
||||
static void
|
||||
assert_attr(gss_name_t n,
|
||||
const char *aname,
|
||||
OM_uint32 exp_maj,
|
||||
gss_buffer_t exp_v,
|
||||
const char *exp_dv,
|
||||
int exp_authenticated,
|
||||
int exp_complete,
|
||||
int exp_multivalued)
|
||||
{
|
||||
gss_buffer_desc dv = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc v = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc a;
|
||||
OM_uint32 maj, min;
|
||||
int authenticated, complete, more;
|
||||
|
||||
a.value = (void*)(uintptr_t)aname;
|
||||
a.length = strlen(aname);
|
||||
more = 0;
|
||||
maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v,
|
||||
&dv, &more);
|
||||
if (maj != GSS_S_COMPLETE && maj != exp_maj)
|
||||
gss_err(1, maj, min, GSS_KRB5_MECHANISM,
|
||||
"import composite name error");
|
||||
if (maj == GSS_S_COMPLETE && maj != exp_maj)
|
||||
errx(1, "unexpected name attribute %s", aname);
|
||||
if (maj == GSS_S_COMPLETE) {
|
||||
if (exp_v &&
|
||||
(v.length != exp_v->length ||
|
||||
memcmp(v.value, exp_v->value, exp_v->length) != 0))
|
||||
errx(1, "import composite name: wrong %s value", aname);
|
||||
if (exp_dv &&
|
||||
(dv.length != strlen(exp_dv) ||
|
||||
strncmp(dv.value, exp_dv, dv.length) != 0))
|
||||
errx(1, "import composite name: wrong %s display value "
|
||||
"(wanted %s, got %.*s)", aname, exp_dv,
|
||||
(int)dv.length, (char *)dv.value);
|
||||
if (authenticated != exp_authenticated)
|
||||
errx(1, "import composite name: %s incorrectly marked "
|
||||
"%sauthenticated", aname, authenticated ? "" : "un");
|
||||
if (complete != exp_complete)
|
||||
errx(1, "import composite name: %s incorrectly marked "
|
||||
"%scomplete", aname, complete ? "" : "in");
|
||||
if (more != exp_multivalued)
|
||||
errx(1, "import composite name: %s incorrectly marked "
|
||||
"%s-valued", aname, more ? "multi" : "single");
|
||||
}
|
||||
gss_release_buffer(&min, &dv);
|
||||
gss_release_buffer(&min, &v);
|
||||
}
|
||||
|
||||
static void
|
||||
assert_attr_unavail(gss_name_t n, const char *aname)
|
||||
{
|
||||
assert_attr(n, aname, GSS_S_UNAVAILABLE, GSS_C_NO_BUFFER, NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
assert_attr_set(gss_name_t n, gss_buffer_set_t exp_as)
|
||||
{
|
||||
OM_uint32 maj, min;
|
||||
gss_buffer_set_t as = NULL;
|
||||
gss_OID MN_mech = GSS_C_NO_OID;
|
||||
size_t i;
|
||||
int name_is_MN = 0;
|
||||
|
||||
maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &as);
|
||||
if (maj)
|
||||
gss_err(1, maj, min, MN_mech, "inquire name");
|
||||
for (i = 0; i < as->count && i < exp_as->count; i++) {
|
||||
if (as->elements[i].length != exp_as->elements[i].length ||
|
||||
memcmp(as->elements[i].value, exp_as->elements[i].value,
|
||||
as->elements[i].length) != 0)
|
||||
errx(1, "attribute sets differ");
|
||||
}
|
||||
if (i < as->count)
|
||||
errx(1, "more attributes indicated than expected");
|
||||
if (i < exp_as->count)
|
||||
errx(1, "fewer attributes indicated than expected");
|
||||
gss_release_buffer_set(&min, &as);
|
||||
}
|
||||
|
Reference in New Issue
Block a user