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.
36 * converts a single-string representation of the name to the
37 * multi-part principal format used in the protocols.
39 * principal will point to allocated storage which should be freed by
40 * the caller (using krb5_free_principal) after use.
42 * Conventions: / is used to separate components. If @ is present in the
43 * string, then the rest of the string after it represents the realm name.
44 * Otherwise the local realm name is used.
47 * KRB5_PARSE_MALFORMED badly formatted string
49 * also returns system errors:
50 * ENOMEM malloc failed/out of memory
52 * get_default_realm() is called; it may return other errors.
56 #define COMPONENT_SEP '/'
57 #define QUOTECHAR '\\'
63 * May the fleas of a thousand camels infest the ISO, they who think
64 * that arbitrarily large multi-component names are a Good Thing.....
66 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
67 krb5_parse_name(context, name, nprincipal)
70 krb5_principal FAR *nprincipal;
72 register const char *cp;
74 register int i,c,size;
76 const char *parsed_realm = NULL;
77 int fcompsize[FCOMPNUM];
78 unsigned int realmsize = 0;
79 static char *default_realm = NULL;
80 static int default_realm_size = 0;
82 krb5_principal principal;
83 krb5_error_code retval;
86 * Pass 1. Find out how many components there are to the name,
87 * and get string sizes for the first FCOMPNUM components.
90 for (i=0,cp = name; (c = *cp); cp++) {
95 * QUOTECHAR can't be at the last
96 * character of the name!
98 return(KRB5_PARSE_MALFORMED);
101 } else if (c == COMPONENT_SEP) {
104 * Shouldn't see a component separator
105 * after we've parsed out the realm name!
107 return(KRB5_PARSE_MALFORMED);
113 } else if (c == REALM_SEP) {
114 if (parsed_realm || !*(cp+1))
116 * Multiple realm separaters or null
117 * realm names are not allowed!
119 return(KRB5_PARSE_MALFORMED);
130 else if (i < FCOMPNUM)
134 * Now, we allocate the principal structure and all of its
137 principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
141 principal->data = (krb5_data *) malloc(sizeof(krb5_data) * components);
142 if (!principal->data) {
143 free((char *)principal);
146 principal->length = components;
148 * If a realm was not found, then use the defualt realm....
151 if (!default_realm) {
152 retval = krb5_get_default_realm(context, &default_realm);
154 krb5_xfree(principal->data);
155 krb5_xfree((char *)principal);
158 default_realm_size = strlen(default_realm);
160 realmsize = default_realm_size;
163 * Pass 2. Happens only if there were more than FCOMPNUM
164 * component; if this happens, someone should be shot
165 * immediately. Nevertheless, we will attempt to handle said
166 * case..... <martyred sigh>
168 if (components >= FCOMPNUM) {
171 for (i=0,cp = name; (c = *cp); cp++) {
172 if (c == QUOTECHAR) {
175 } else if (c == COMPONENT_SEP) {
176 krb5_princ_component(context, principal, i)->length = size;
179 } else if (c == REALM_SEP) {
180 krb5_princ_component(context, principal, i)->length = size;
187 krb5_princ_realm(context, principal)->length = size;
189 krb5_princ_component(context, principal, i)->length = size;
190 if (i + 1 != components) {
191 #if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh)
193 "Programming error in krb5_parse_name!");
196 /* Need to come up with windows error handling mechanism */
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);
217 krb5_princ_set_realm_length(context, principal, realmsize);
218 krb5_princ_set_realm_data(context, principal, tmpdata);
219 for (i=0; i < components; i++) {
221 malloc(krb5_princ_component(context, principal, i)->length + 1);
223 for (i--; i >= 0; i--)
224 krb5_xfree(krb5_princ_component(context, principal, i)->data);
225 krb5_xfree(krb5_princ_realm(context, principal)->data);
226 krb5_xfree(principal->data);
227 krb5_xfree(principal);
230 krb5_princ_component(context, principal, i)->data = tmpdata;
231 krb5_princ_component(context, principal, i)->magic = KV5M_DATA;
235 * Pass 3. Now we go through the string a *third* time, this
236 * time filling in the krb5_principal structure which we just
239 q = krb5_princ_component(context, principal, 0)->data;
240 for (i=0,cp = name; (c = *cp); cp++) {
241 if (c == QUOTECHAR) {
259 } else if ((c == COMPONENT_SEP) || (c == REALM_SEP)) {
262 if (c == COMPONENT_SEP)
263 q = krb5_princ_component(context, principal, i)->data;
265 q = krb5_princ_realm(context, principal)->data;
271 strcpy(krb5_princ_realm(context, principal)->data, default_realm);
273 * Alright, we're done. Now stuff a pointer to this monstrosity
274 * into the return variable, and let's get out of here.
276 krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL;
277 principal->magic = KV5M_PRINCIPAL;
278 principal->realm.magic = KV5M_DATA;
279 *nprincipal = principal;