aboutsummaryrefslogtreecommitdiff
path: root/src/lib/krb5/krb/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/krb5/krb/parse.c')
-rw-r--r--src/lib/krb5/krb/parse.c123
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);
+}