parse.c revision 505d05c73a6e56769f263d4803b22eddd168ee24
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*
* Copyright 1990,1991 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"
#ifndef _KERNEL
#include <assert.h>
#include <stdarg.h>
#endif
/*
* 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.....
*/
/*ARGSUSED*/
{
const char *cp;
char *q;
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;
/*
* Pass 1. Find out how many components there are to the name,
* and get string sizes for the first FCOMPNUM components.
*/
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) {
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++;
} else if (c == REALM_SEP) {
/*
* Multiple realm separaters or null
* realm names are not allowed!
*/
return (KRB5_PARSE_MALFORMED);
if (i < FCOMPNUM) {
}
size = 0;
} else
size++;
}
if (parsed_realm)
else if (i < FCOMPNUM)
components = i + 1;
/*
* Now, we allocate the principal structure and all of its
* component pieces
*/
if (!principal) {
return (ENOMEM);
}
return (ENOMEM);
}
/*
* If a realm was not found, then use the default realm....
*/
/*
* In the kernel we import the ctx and it always contains the
* default realm
*/
#ifndef _KERNEL
if (!parsed_realm) {
if (!default_realm) {
if (retval) {
sizeof (krb5_data) * components);
krb5_xfree_wrap((char *)principal,
sizeof (krb5_principal_data));
return (retval);
}
}
}
#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
"Programming error in krb5_parse_name!");
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) {
sizeof (krb5_data) * components);
krb5_xfree_wrap((char *)principal,
sizeof (krb5_principal_data));
#ifndef _KERNEL
if (default_realm)
#endif
return (ENOMEM);
}
for (i = 0; i < components; i++) {
if (!tmpdata2) {
/*
* Release the principle and realm strings remembering
* that we allocated one additional byte beyond the
* 'length' to hold the string terminating zero byte.
* It's critical that the free size match the malloc
* size.
*/
for (i--; i >= 0; i--)
#ifndef _KERNEL
if (default_realm)
#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++ = (char) c;
}
} else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) {
i++;
*q++ = '\0';
if (c == COMPONENT_SEP)
else
} else
*q++ = (char) c;
}
*q++ = '\0';
if (!parsed_realm)
#ifndef _KERNEL
#endif
/*
* Alright, we're done. Now stuff a pointer to this monstrosity
* into the return variable, and let's get out of here.
*/
*nprincipal = principal;
#ifndef _KERNEL
if (default_realm)
#endif
return(0);
}