4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 * krb5_parse_name() routine.
29 * Rewritten by Theodore Ts'o to properly handle arbitrary quoted
30 * characters in the principal name.
37 * converts a single-string representation of the name to the
38 * multi-part principal format used in the protocols.
40 * principal will point to allocated storage which should be freed by
41 * the caller (using krb5_free_principal) after use.
43 * Conventions: / is used to separate components. If @ is present in the
44 * string, then the rest of the string after it represents the realm name.
45 * Otherwise the local realm name is used.
48 * KRB5_PARSE_MALFORMED badly formatted string
50 * also returns system errors:
51 * ENOMEM malloc failed/out of memory
53 * get_default_realm() is called; it may return other errors.
57 #define COMPONENT_SEP '/'
58 #define QUOTECHAR '\\'
64 * May the fleas of a thousand camels infest the ISO, they who think
65 * that arbitrarily large multi-component names are a Good Thing.....
67 krb5_error_code KRB5_CALLCONV
68 krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal)
70 register const char *cp;
72 register int i,c,size;
74 const char *parsed_realm = NULL;
75 int fcompsize[FCOMPNUM];
76 unsigned int realmsize = 0;
77 char *default_realm = NULL;
78 int default_realm_size = 0;
80 krb5_principal principal;
81 krb5_error_code retval;
84 * Pass 1. Find out how many components there are to the name,
85 * and get string sizes for the first FCOMPNUM components.
88 for (i=0,cp = name; (c = *cp); cp++) {
93 * QUOTECHAR can't be at the last
94 * character of the name!
96 return(KRB5_PARSE_MALFORMED);
99 } else if (c == COMPONENT_SEP) {
102 * Shouldn't see a component separator
103 * after we've parsed out the realm name!
105 return(KRB5_PARSE_MALFORMED);
111 } else if (c == REALM_SEP) {
114 * Multiple realm separaters
115 * not allowed; zero-length realms are.
117 return(KRB5_PARSE_MALFORMED);
128 else if (i < FCOMPNUM)
132 * Now, we allocate the principal structure and all of its
135 principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
139 principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
140 if (!principal->data) {
141 free((char *)principal);
144 principal->length = components;
146 * If a realm was not found, then use the defualt realm....
149 if (!default_realm) {
150 retval = krb5_get_default_realm(context, &default_realm);
152 krb5_xfree(principal->data);
153 krb5_xfree((char *)principal);
156 default_realm_size = strlen(default_realm);
158 realmsize = default_realm_size;
161 * Pass 2. Happens only if there were more than FCOMPNUM
162 * component; if this happens, someone should be shot
163 * immediately. Nevertheless, we will attempt to handle said
164 * case..... <martyred sigh>
166 if (components >= FCOMPNUM) {
169 for (i=0,cp = name; (c = *cp); cp++) {
170 if (c == QUOTECHAR) {
173 } else if (c == COMPONENT_SEP) {
174 if (krb5_princ_size(context, principal) > i)
175 krb5_princ_component(context, principal, i)->length = size;
178 } else if (c == REALM_SEP) {
179 if (krb5_princ_size(context, principal) > i)
180 krb5_princ_component(context, principal, i)->length = size;
187 krb5_princ_realm(context, principal)->length = size;
189 if (krb5_princ_size(context, principal) > i)
190 krb5_princ_component(context, principal, i)->length = size;
191 if (i + 1 != components) {
194 "Programming error in krb5_parse_name!");
196 assert(i + 1 == components);
201 * If there were fewer than FCOMPSIZE components (the
202 * usual case), then just copy the sizes to the
203 * principal structure
205 for (i=0; i < components; i++)
206 krb5_princ_component(context, principal, i)->length = fcompsize[i];
209 * Now, we need to allocate the space for the strings themselves.....
211 tmpdata = malloc(realmsize+1);
213 krb5_xfree(principal->data);
214 krb5_xfree(principal);
215 krb5_xfree(default_realm);
218 krb5_princ_set_realm_length(context, principal, realmsize);
219 krb5_princ_set_realm_data(context, principal, tmpdata);
220 for (i=0; i < components; i++) {
222 malloc(krb5_princ_component(context, principal, i)->length + 1);
224 for (i--; i >= 0; i--)
225 krb5_xfree(krb5_princ_component(context, principal, i)->data);
226 krb5_xfree(krb5_princ_realm(context, principal)->data);
227 krb5_xfree(principal->data);
228 krb5_xfree(principal);
229 krb5_xfree(default_realm);
232 krb5_princ_component(context, principal, i)->data = tmpdata2;
233 krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
237 * Pass 3. Now we go through the string a *third* time, this
238 * time filling in the krb5_principal structure which we just
241 q = krb5_princ_component(context, principal, 0)->data;
242 for (i=0,cp = name; (c = *cp); cp++) {
243 if (c == QUOTECHAR) {
261 } else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) {
264 if (c == COMPONENT_SEP)
265 q = krb5_princ_component(context, principal, i)->data;
267 q = krb5_princ_realm(context, principal)->data;
273 strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize + 1);
275 * Alright, we're done. Now stuff a pointer to this monstrosity
276 * into the return variable, and let's get out of here.
278 krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
279 principal->magic = KV5M_PRINCIPAL;
280 principal->realm.magic = KV5M_DATA;
281 *nprincipal = principal;
283 krb5_xfree(default_realm);