#include "k5-int.h"
#ifndef _KERNEL
#include <stdio.h>
#endif
void *
krb5int_realloc(
void *oldp,
size_t new_size,
size_t old_size)
{
#ifdef _KERNEL
char *newp = MALLOC(new_size);
bcopy(oldp, newp, old_size < new_size ? old_size : new_size);
FREE(oldp, old_size);
return (newp);
#else
return (realloc(oldp, new_size));
#endif
}
#define REALM_SEP '@'
#define COMPONENT_SEP '/'
static int
component_length_quoted(const krb5_data *src, int flags)
{
const char *cp = src->data;
int length = src->length;
int j;
int size = length;
if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
!(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
for (j = 0; j < length; j++,cp++)
if ((!no_realm && *cp == REALM_SEP) ||
*cp == COMPONENT_SEP ||
*cp == '\0' || *cp == '\\' || *cp == '\t' ||
*cp == '\n' || *cp == '\b')
size++;
}
return size;
}
static int
copy_component_quoting(char *dest, const krb5_data *src, int flags)
{
int j;
const char *cp = src->data;
char *q = dest;
int length = src->length;
if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
(void) memcpy(dest, src->data, src->length);
return src->length;
}
for (j=0; j < length; j++,cp++) {
int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
!(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
switch (*cp) {
case REALM_SEP:
if (no_realm) {
*q++ = *cp;
break;
}
case COMPONENT_SEP:
case '\\':
*q++ = '\\';
*q++ = *cp;
break;
case '\t':
*q++ = '\\';
*q++ = 't';
break;
case '\n':
*q++ = '\\';
*q++ = 'n';
break;
case '\b':
*q++ = '\\';
*q++ = 'b';
break;
#if 0
case ' ':
*q++ = '\\';
*q++ = ' ';
break;
#endif
case '\0':
*q++ = '\\';
*q++ = '0';
break;
default:
*q++ = *cp;
}
}
return q - dest;
}
static krb5_error_code
k5_unparse_name(krb5_context context, krb5_const_principal principal,
int flags, char **name, unsigned int *size)
{
#if 0
char *cp;
int length;
#endif
char *q;
int i;
krb5_int32 nelem;
unsigned int totalsize = 0;
#ifndef _KERNEL
char *default_realm = NULL;
#endif
krb5_error_code ret = 0;
if (!principal || !name)
return KRB5_PARSE_MALFORMED;
#ifndef _KERNEL
if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) {
krb5_principal_data p;
ret = krb5_get_default_realm(context, &default_realm);
if (ret != 0)
goto cleanup;
krb5_princ_realm(context, &p)->length = strlen(default_realm);
krb5_princ_realm(context, &p)->data = default_realm;
if (krb5_realm_compare(context, &p, principal))
flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
}
#endif
if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
totalsize += component_length_quoted(krb5_princ_realm(context,
principal),
flags);
totalsize++;
}
nelem = krb5_princ_size(context, principal);
for (i = 0; i < (int) nelem; i++) {
#if 0
cp = krb5_princ_component(context, principal, i)->data;
#endif
totalsize += component_length_quoted(krb5_princ_component(context, principal, i), flags);
totalsize++;
}
if (nelem == 0)
totalsize++;
if (size) {
if (*name && (*size < totalsize)) {
*name = krb5int_realloc(*name, totalsize, *size);
} else {
*name = MALLOC(totalsize);
}
*size = totalsize;
} else {
*name = MALLOC(totalsize);
}
if (!*name) {
ret = ENOMEM;
goto cleanup;
}
q = *name;
for (i = 0; i < (int) nelem; i++) {
#if 0
cp = krb5_princ_component(context, principal, i)->data;
length = krb5_princ_component(context, principal, i)->length;
#endif
q += copy_component_quoting(q,
krb5_princ_component(context,
principal,
i),
flags);
*q++ = COMPONENT_SEP;
}
if (i > 0)
q--;
if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
*q++ = REALM_SEP;
q += copy_component_quoting(q, krb5_princ_realm(context, principal), flags);
}
*q++ = '\0';
cleanup:
#ifndef _KERNEL
if (default_realm != NULL)
krb5_free_default_realm(context, default_realm);
#endif
return ret;
}
krb5_error_code KRB5_CALLCONV
krb5_unparse_name(krb5_context context, krb5_const_principal principal, register char **name)
{
if (name != NULL)
*name = NULL;
return k5_unparse_name(context, principal, 0, name, NULL);
}
krb5_error_code KRB5_CALLCONV
krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal,
char **name, unsigned int *size)
{
return k5_unparse_name(context, principal, 0, name, size);
}
krb5_error_code KRB5_CALLCONV
krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
int flags, char **name)
{
if (name != NULL)
*name = NULL;
return k5_unparse_name(context, principal, flags, name, NULL);
}
krb5_error_code KRB5_CALLCONV
krb5_unparse_name_flags_ext(krb5_context context, krb5_const_principal principal,
int flags, char **name, unsigned int *size)
{
return k5_unparse_name(context, principal, flags, name, size);
}