aboutsummaryrefslogtreecommitdiff
path: root/src/lib/krb5/krb/unparse.c
blob: 7c8858d51032553b88b0d904a1f40e4dfa772f26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * $Source$
 * $Author$
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * For copying and distribution information, please see the file
 * <krb5/copyright.h>.
 *
 * krb5_unparse_name() routine
 *
 * Rewritten by Theodore Ts'o to propoerly unparse principal names
 * which have the component or realm separator as part of one of their
 * components.
 */

#if !defined(lint) && !defined(SABER)
static char rcsid_unparse_c[] =
"$Id$";
#endif	/* !lint & !SABER */

#include <stdio.h>
#include <krb5/krb5.h>
#include <krb5/ext-proto.h>

/*
 * converts the multi-part principal format used in the protocols to a
 * single-string representation of the name. 
 *  
 * The name returned is in allocated storage and should be freed by
 * the caller when finished.
 *
 * Conventions: / is used to separate components; @ is used to
 * separate the realm from the rest of the name.  If '/', '@', or '\0'
 * appear in any the component, they will be representing using
 * backslash encoding.  ("\/", "\@", or '\0', respectively)
 *
 * returns system errors XXX
 */

#define REALM_SEP	'@'
#define	COMPONENT_SEP	'/'

krb5_error_code
krb5_unparse_name_ext(principal, name, size)
krb5_const_principal principal;
register char **name;
int	*size;
{
	register char *cp, *q;
	register int i,j;
	register int totalsize = 0;
	int	length;

	if (!principal[0] || !principal[1])
		return KRB5_PARSE_MALFORMED;
	for (i = 0; principal[i]; i++) {
		cp = principal[i]->data;
		length = principal[i]->length;
		for (j=0; j < length; j++,cp++)
			if (*cp == REALM_SEP || *cp == COMPONENT_SEP ||
			    *cp == '\0' || *cp == '\\' || *cp == '\t')
				totalsize += 2;
			else
				totalsize++;
		totalsize++;	/* This is for the separator */
	}

	/*
	 *  we need only n-1 seps for n components, but we need an
	 * extra byte for the NULL at the end
	 */
	if (*name) {
		if (*size < (totalsize)) {
			*size = totalsize;
			*name = realloc(*name, totalsize);
		}
	} else {
		*name = malloc(totalsize);	/* room for null */
		if (size)
			*size = totalsize;
	}
	
	if (!*name)
		return ENOMEM;

	q = *name;
	
	for (i = 1; principal[i]; i++) {
		cp = principal[i]->data;
		length = principal[i]->length;
		for (j=0; j < length; j++,cp++) {
			switch (*cp) {
			case COMPONENT_SEP:
			case REALM_SEP:
			case '\t':
			case '\\':
				*q++ = '\\';
				*q++ = *cp;
				break;
			case '\0':
				*q++ = '\\';
				*q++ = '0';
				break;
			default:
				*q++ = *cp;
			}
		}
		*q++ = COMPONENT_SEP;
	}

	q--;			/* Back up last component separator */
	*q++ = REALM_SEP;
	
	cp = principal[0]->data;
	length = principal[0]->length;
	for (j=0; j < length; j++,cp++) {
		switch (*cp) {
		case COMPONENT_SEP:
		case REALM_SEP:
		case '\t':
		case '\\':
			*q++ = '\\';
			*q++ = *cp;
			break;
		case '\0':
			*q++ = '\\';
			*q++ = '0';
			break;
		default:
			*q++ = *cp;
		}
	}
	*q++ = '\0';
	
    return 0;
}

krb5_error_code
krb5_unparse_name(principal, name)
krb5_const_principal principal;
register char **name;
{
	*name = NULL;
	return(krb5_unparse_name_ext(principal, name, NULL));
}