parse.c revision ba7b222e36bac28710a7f43739283302b617e7f5
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*
* Copyright 1990,1991,2008 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*
* krb5_parse_name() routine.
*
* Rewritten by Theodore Ts'o to properly handle arbitrary quoted
* characters in the principal name.
*/
#include "k5-int.h"
/*
* converts a single-string representation of the name to the
* multi-part principal format used in the protocols.
*
* principal will point to allocated storage which should be freed by
* the caller (using krb5_free_principal) after use.
*
* Conventions: / is used to separate components. If @ is present in the
* string, then the rest of the string after it represents the realm name.
* Otherwise the local realm name is used.
*
* error return:
* KRB5_PARSE_MALFORMED badly formatted string
*
* also returns system errors:
*
* get_default_realm() is called; it may return other errors.
*/
#define REALM_SEP '@'
#define COMPONENT_SEP '/'
#define QUOTECHAR '\\'
#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.....
*/
static krb5_error_code
/*LINTED*/
{
register const char *cp;
register char *q;
register int i,c,size;
int components = 0;
const char *parsed_realm = NULL;
unsigned int realmsize = 0;
#ifndef _KERNEL
char *default_realm = NULL;
int default_realm_size = 0;
#endif
char *tmpdata;
int first_at;
*nprincipal = NULL;
/*
* Pass 1. Find out how many components there are to the name,
* and get string sizes for the first FCOMPNUM components. For
* enterprise principal names (UPNs), there is only a single
* component.
*/
size = 0;
/*LINTED*/
if (c == QUOTECHAR) {
cp++;
/*LINTED*/
if (!(c = *cp))
/*
* QUOTECHAR can't be at the last
* character of the name!
*/
return(KRB5_PARSE_MALFORMED);
size++;
continue;
} else if (c == COMPONENT_SEP && !enterprise) {
if (parsed_realm)
/*
* Shouldn't see a component separator
* after we've parsed out the realm name!
*/
return(KRB5_PARSE_MALFORMED);
if (i < FCOMPNUM) {
}
size = 0;
i++;
if (parsed_realm)
/*
* Multiple realm separaters
* not allowed; zero-length realms are.
*/
return(KRB5_PARSE_MALFORMED);
if (i < FCOMPNUM) {
}
size = 0;
} else {
first_at = 0;
size++;
}
}
if (parsed_realm != NULL)
else if (i < FCOMPNUM)
components = i + 1;
/*
* Now, we allocate the principal structure and all of its
* component pieces
*/
return(ENOMEM);
}
return ENOMEM;
}
/*
* 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.
*/
#ifndef _KERNEL
if (!parsed_realm) {
if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
"Principal %s is missing required realm", name);
return KRB5_PARSE_MALFORMED;
}
if (retval) {
return(retval);
}
}
} else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
"Principal %s has realm present", name);
return KRB5_PARSE_MALFORMED;
}
#endif
/*
* Pass 2. Happens only if there were more than FCOMPNUM
* component; if this happens, someone should be shot
* immediately. Nevertheless, we will attempt to handle said
* case..... <martyred sigh>
*/
if (components >= FCOMPNUM) {
size = 0;
parsed_realm = NULL;
/*LINTED*/
if (c == QUOTECHAR) {
cp++;
size++;
} else if (c == COMPONENT_SEP) {
size = 0;
i++;
} else if (c == REALM_SEP) {
size = 0;
} else
size++;
}
if (parsed_realm)
else
if (i + 1 != components) {
#ifndef _KERNEL
#if !defined(_WIN32)
"Programming error in krb5_parse_name!");
#endif
abort();
#else
#endif /* !_KERNEL */
}
} else {
/*
* If there were fewer than FCOMPSIZE components (the
* usual case), then just copy the sizes to the
* principal structure
*/
for (i=0; i < components; i++)
}
/*
* Now, we need to allocate the space for the strings themselves.....
*/
if (tmpdata == 0) {
#ifndef _KERNEL
#endif
return ENOMEM;
}
for (i=0; i < components; i++) {
char *tmpdata2 =
for (i--; i >= 0; i--)
#ifndef _KERNEL
#endif
return(ENOMEM);
}
}
/*
* Pass 3. Now we go through the string a *third* time, this
* time filling in the krb5_principal structure which we just
* allocated.
*/
/*LINTED*/
if (c == QUOTECHAR) {
cp++;
switch (c = *cp) {
case 'n':
*q++ = '\n';
break;
case 't':
*q++ = '\t';
break;
case 'b':
*q++ = '\b';
break;
case '0':
*q++ = '\0';
break;
default:
*q++ = c;
break;
}
} else if (c == COMPONENT_SEP && !enterprise) {
i++;
*q++ = '\0';
i++;
*q++ = '\0';
} else {
first_at = 0;
*q++ = c;
}
}
*q++ = '\0';
/*LINTED*/
if (!parsed_realm) {
#ifndef _KERNEL
else
#endif
}
/*
* Alright, we're done. Now stuff a pointer to this monstrosity
* into the return variable, and let's get out of here.
*/
if (enterprise)
else
*nprincipal = principal;
#ifndef _KERNEL
if (default_realm != NULL)
#endif
return(0);
}
{
}
{
}