diff options
Diffstat (limited to 'src/lib/krb5/krb/parse.c')
-rw-r--r-- | src/lib/krb5/krb/parse.c | 123 |
1 files changed, 88 insertions, 35 deletions
diff --git a/src/lib/krb5/krb/parse.c b/src/lib/krb5/krb/parse.c index c6b1f6e..5c70549 100644 --- a/src/lib/krb5/krb/parse.c +++ b/src/lib/krb5/krb/parse.c @@ -1,7 +1,7 @@ /* * lib/krb5/krb/parse.c * - * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -59,17 +59,17 @@ #define FCOMPNUM 10 - /* * May the fleas of a thousand camels infest the ISO, they who think * that arbitrarily large multi-component names are a Good Thing..... */ -krb5_error_code KRB5_CALLCONV -krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal) +static krb5_error_code +k5_parse_name(krb5_context context, const char *name, + int flags, krb5_principal *nprincipal) { register const char *cp; register char *q; - register int i,c,size; + register int i,c,size; int components = 0; const char *parsed_realm = NULL; int fcompsize[FCOMPNUM]; @@ -79,24 +79,28 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip char *tmpdata; krb5_principal principal; krb5_error_code retval; - + unsigned int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); + int first_at; + /* * Pass 1. Find out how many components there are to the name, - * and get string sizes for the first FCOMPNUM components. + * and get string sizes for the first FCOMPNUM components. For + * enterprise principal names (UPNs), there is only a single + * component. */ size = 0; - for (i=0,cp = name; (c = *cp); cp++) { + for (i=0,cp = name, first_at = 1; (c = *cp); cp++) { if (c == QUOTECHAR) { cp++; if (!(c = *cp)) /* - * QUOTECHAR can't be at the last - * character of the name! - */ + * QUOTECHAR can't be at the last + * character of the name! + */ return(KRB5_PARSE_MALFORMED); size++; continue; - } else if (c == COMPONENT_SEP) { + } else if (c == COMPONENT_SEP && !enterprise) { if (parsed_realm) /* * Shouldn't see a component separator @@ -108,22 +112,26 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip } size = 0; i++; - } else if (c == REALM_SEP) { + } else if (c == REALM_SEP && (!enterprise || !first_at)) { if (parsed_realm) /* * Multiple realm separaters * not allowed; zero-length realms are. */ return(KRB5_PARSE_MALFORMED); - parsed_realm = cp+1; + parsed_realm = cp + 1; if (i < FCOMPNUM) { fcompsize[i] = size; } size = 0; - } else + } else { + if (c == REALM_SEP && enterprise && first_at) + first_at = 0; + size++; + } } - if (parsed_realm) + if (parsed_realm != NULL) realmsize = size; else if (i < FCOMPNUM) fcompsize[i] = size; @@ -133,20 +141,30 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip * component pieces */ principal = (krb5_principal)malloc(sizeof(krb5_principal_data)); - if (!principal) { - return(ENOMEM); + if (principal == NULL) { + return(ENOMEM); } principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components); - if (!principal->data) { - free((char *)principal); + if (principal->data == NULL) { + krb5_xfree((char *)principal); return ENOMEM; } principal->length = components; + /* - * If a realm was not found, then use the defualt realm.... + * If a realm was not found, then use the default realm, unless + * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the + * realm will be empty. */ if (!parsed_realm) { - if (!default_realm) { + if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) { + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, + "Principal %s is missing required realm", name); + krb5_xfree(principal->data); + krb5_xfree(principal); + return KRB5_PARSE_MALFORMED; + } + if (!default_realm && (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) == 0) { retval = krb5_get_default_realm(context, &default_realm); if (retval) { krb5_xfree(principal->data); @@ -156,7 +174,14 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip default_realm_size = strlen(default_realm); } realmsize = default_realm_size; + } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, + "Principal %s has realm present", name); + krb5_xfree(principal->data); + krb5_xfree(principal); + return KRB5_PARSE_MALFORMED; } + /* * Pass 2. Happens only if there were more than FCOMPNUM * component; if this happens, someone should be shot @@ -208,7 +233,7 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip /* * Now, we need to allocate the space for the strings themselves..... */ - tmpdata = malloc(realmsize+1); + tmpdata = malloc(realmsize + 1); if (tmpdata == 0) { krb5_xfree(principal->data); krb5_xfree(principal); @@ -220,7 +245,7 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip for (i=0; i < components; i++) { char *tmpdata2 = malloc(krb5_princ_component(context, principal, i)->length + 1); - if (!tmpdata2) { + if (tmpdata2 == NULL) { for (i--; i >= 0; i--) krb5_xfree(krb5_princ_component(context, principal, i)->data); krb5_xfree(krb5_princ_realm(context, principal)->data); @@ -239,7 +264,7 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip * allocated. */ q = krb5_princ_component(context, principal, 0)->data; - for (i=0,cp = name; (c = *cp); cp++) { + for (i=0,cp = name, first_at = 1; (c = *cp); cp++) { if (c == QUOTECHAR) { cp++; switch (c = *cp) { @@ -257,29 +282,57 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincip break; default: *q++ = c; + break; } - } else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) { + } else if (c == COMPONENT_SEP && !enterprise) { + i++; + *q++ = '\0'; + q = krb5_princ_component(context, principal, i)->data; + } else if (c == REALM_SEP && (!enterprise || !first_at)) { i++; *q++ = '\0'; - if (c == COMPONENT_SEP) - q = krb5_princ_component(context, principal, i)->data; - else - q = krb5_princ_realm(context, principal)->data; - } else + q = krb5_princ_realm(context, principal)->data; + } else { + if (c == REALM_SEP && enterprise && first_at) + first_at = 0; + *q++ = c; + } } *q++ = '\0'; - if (!parsed_realm) - strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize + 1); + if (!parsed_realm) { + if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) + (krb5_princ_realm(context, principal)->data)[0] = '\0'; + else + strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize+1); + } /* * Alright, we're done. Now stuff a pointer to this monstrosity * into the return variable, and let's get out of here. */ - krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL; + if (enterprise) + krb5_princ_type(context, principal) = KRB5_NT_ENTERPRISE_PRINCIPAL; + else + krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL; principal->magic = KV5M_PRINCIPAL; principal->realm.magic = KV5M_DATA; *nprincipal = principal; - krb5_xfree(default_realm); + if (default_realm != NULL) + krb5_xfree(default_realm); + return(0); } + +krb5_error_code KRB5_CALLCONV +krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal) +{ + return k5_parse_name(context, name, 0, nprincipal); +} + +krb5_error_code KRB5_CALLCONV +krb5_parse_name_flags(krb5_context context, const char *name, + int flags, krb5_principal *nprincipal) +{ + return k5_parse_name(context, name, flags, nprincipal); +} |