#include "k5-int.h"
#define REALM_SEP '@'
#define COMPONENT_SEP '/'
#define QUOTECHAR '\\'
#define FCOMPNUM 10
krb5_error_code KRB5_CALLCONV
krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal)
{
register const char *cp;
register char *q;
register int i,c,size;
int components = 0;
const char *parsed_realm = NULL;
int fcompsize[FCOMPNUM];
unsigned int realmsize = 0;
char *default_realm = NULL;
int default_realm_size = 0;
char *tmpdata;
krb5_principal principal;
krb5_error_code retval;
size = 0;
for (i=0,cp = name; (c = *cp); cp++) {
if (c == QUOTECHAR) {
cp++;
if (!(c = *cp))
return(KRB5_PARSE_MALFORMED);
size++;
continue;
} else if (c == COMPONENT_SEP) {
if (parsed_realm)
return(KRB5_PARSE_MALFORMED);
if (i < FCOMPNUM) {
fcompsize[i] = size;
}
size = 0;
i++;
} else if (c == REALM_SEP) {
if (parsed_realm)
return(KRB5_PARSE_MALFORMED);
parsed_realm = cp+1;
if (i < FCOMPNUM) {
fcompsize[i] = size;
}
size = 0;
} else
size++;
}
if (parsed_realm)
realmsize = size;
else if (i < FCOMPNUM)
fcompsize[i] = size;
components = i + 1;
principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
if (!principal) {
return(ENOMEM);
}
principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
if (!principal->data) {
free((char *)principal);
return ENOMEM;
}
principal->length = components;
if (!parsed_realm) {
if (!default_realm) {
retval = krb5_get_default_realm(context, &default_realm);
if (retval) {
krb5_xfree(principal->data);
krb5_xfree((char *)principal);
return(retval);
}
default_realm_size = strlen(default_realm);
}
realmsize = default_realm_size;
}
if (components >= FCOMPNUM) {
size = 0;
parsed_realm = NULL;
for (i=0,cp = name; (c = *cp); cp++) {
if (c == QUOTECHAR) {
cp++;
size++;
} else if (c == COMPONENT_SEP) {
if (krb5_princ_size(context, principal) > i)
krb5_princ_component(context, principal, i)->length = size;
size = 0;
i++;
} else if (c == REALM_SEP) {
if (krb5_princ_size(context, principal) > i)
krb5_princ_component(context, principal, i)->length = size;
size = 0;
parsed_realm = cp+1;
} else
size++;
}
if (parsed_realm)
krb5_princ_realm(context, principal)->length = size;
else
if (krb5_princ_size(context, principal) > i)
krb5_princ_component(context, principal, i)->length = size;
if (i + 1 != components) {
#if !defined(_WIN32)
fprintf(stderr,
"Programming error in krb5_parse_name!");
#endif
assert(i + 1 == components);
abort();
}
} else {
for (i=0; i < components; i++)
krb5_princ_component(context, principal, i)->length = fcompsize[i];
}
tmpdata = malloc(realmsize+1);
if (tmpdata == 0) {
krb5_xfree(principal->data);
krb5_xfree(principal);
krb5_xfree(default_realm);
return ENOMEM;
}
krb5_princ_set_realm_length(context, principal, realmsize);
krb5_princ_set_realm_data(context, principal, tmpdata);
for (i=0; i < components; i++) {
char *tmpdata2 =
malloc(krb5_princ_component(context, principal, i)->length + 1);
if (!tmpdata2) {
for (i--; i >= 0; i--)
krb5_xfree(krb5_princ_component(context, principal, i)->data);
krb5_xfree(krb5_princ_realm(context, principal)->data);
krb5_xfree(principal->data);
krb5_xfree(principal);
krb5_xfree(default_realm);
return(ENOMEM);
}
krb5_princ_component(context, principal, i)->data = tmpdata2;
krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
}
q = krb5_princ_component(context, principal, 0)->data;
for (i=0,cp = name; (c = *cp); cp++) {
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;
}
} else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) {
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++ = c;
}
*q++ = '\0';
if (!parsed_realm)
strcpy(krb5_princ_realm(context, principal)->data, default_realm);
krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
principal->magic = KV5M_PRINCIPAL;
principal->realm.magic = KV5M_DATA;
*nprincipal = principal;
krb5_xfree(default_realm);
return(0);
}