1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 /* 8 * lib/krb5/krb/unparse.c 9 * 10 * Copyright 1990 by the Massachusetts Institute of Technology. 11 * All Rights Reserved. 12 * 13 * Export of this software from the United States of America may 14 * require a specific license from the United States Government. 15 * It is the responsibility of any person or organization contemplating 16 * export to obtain such a license before exporting. 17 * 18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 19 * distribute this software and its documentation for any purpose and 20 * without fee is hereby granted, provided that the above copyright 21 * notice appear in all copies and that both that copyright notice and 22 * this permission notice appear in supporting documentation, and that 23 * the name of M.I.T. not be used in advertising or publicity pertaining 24 * to distribution of the software without specific, written prior 25 * permission. M.I.T. makes no representations about the suitability of 26 * this software for any purpose. It is provided "as is" without express 27 * or implied warranty. 28 * 29 * 30 * krb5_unparse_name() routine 31 * 32 * Rewritten by Theodore Ts'o to properly unparse principal names 33 * which have the component or realm separator as part of one of their 34 * components. 35 */ 36 37 38 #include <k5-int.h> 39 #ifndef _KERNEL 40 #include <stdio.h> 41 #endif 42 43 /* 44 * converts the multi-part principal format used in the protocols to a 45 * single-string representation of the name. 46 * 47 * The name returned is in allocated storage and should be freed by 48 * the caller when finished. 49 * 50 * Conventions: / is used to separate components; @ is used to 51 * separate the realm from the rest of the name. If '/', '@', or '\0' 52 * appear in any the component, they will be representing using 53 * backslash encoding. ("\/", "\@", or '\0', respectively) 54 * 55 * returns error 56 * KRB_PARSE_MALFORMED principal is invalid (does not contain 57 * at least 2 components) 58 * also returns system errors 59 * ENOMEM unable to allocate memory for string 60 */ 61 62 #define REALM_SEP '@' 63 #define COMPONENT_SEP '/' 64 65 /*ARGSUSED*/ 66 krb5_error_code KRB5_CALLCONV 67 krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, register char **name, unsigned int *size) 68 { 69 register char *cp, *q; 70 register int i,j; 71 int length; 72 krb5_int32 nelem; 73 register unsigned int totalsize = 0; 74 75 if (!principal || !name) 76 return KRB5_PARSE_MALFORMED; 77 78 cp = krb5_princ_realm(context, principal)->data; 79 length = krb5_princ_realm(context, principal)->length; 80 totalsize += length; 81 for (j = 0; j < length; j++,cp++) 82 if (*cp == REALM_SEP || *cp == COMPONENT_SEP || 83 *cp == '\0' || *cp == '\\' || *cp == '\t' || 84 *cp == '\n' || *cp == '\b') 85 totalsize++; 86 totalsize++; /* This is for the separator */ 87 88 nelem = krb5_princ_size(context, principal); 89 for (i = 0; i < (int) nelem; i++) { 90 cp = krb5_princ_component(context, principal, i)->data; 91 length = krb5_princ_component(context, principal, i)->length; 92 totalsize += length; 93 for (j=0; j < length; j++,cp++) 94 if (*cp == REALM_SEP || *cp == COMPONENT_SEP || 95 *cp == '\0' || *cp == '\\' || *cp == '\t' || 96 *cp == '\n' || *cp == '\b') 97 totalsize++; 98 totalsize++; /* This is for the separator */ 99 } 100 if (nelem == 0 ) 101 totalsize++; 102 103 /* 104 * Allocate space for the ascii string; if space has been 105 * provided, use it, realloc'ing it if necessary. 106 * 107 * We need only n-1 seperators for n components, but we need 108 * an extra byte for the NULL at the end. 109 */ 110 /*The realloc case seems to be bogus 111 * We never pass non-null name 112 */ 113 114 /* if (*name) { 115 if (*size < (totalsize)) { 116 *size = totalsize; 117 *name = realloc(*name, totalsize); 118 } 119 } else { 120 */ 121 122 *name = MALLOC(totalsize); 123 if (size) 124 *size = totalsize; 125 126 if (!*name) 127 return ENOMEM; 128 129 q = *name; 130 131 for (i = 0; i < (int) nelem; i++) { 132 cp = krb5_princ_component(context, principal, i)->data; 133 length = krb5_princ_component(context, principal, i)->length; 134 for (j=0; j < length; j++,cp++) { 135 switch (*cp) { 136 case COMPONENT_SEP: 137 case REALM_SEP: 138 case '\\': 139 *q++ = '\\'; 140 *q++ = *cp; 141 break; 142 case '\t': 143 *q++ = '\\'; 144 *q++ = 't'; 145 break; 146 case '\n': 147 *q++ = '\\'; 148 *q++ = 'n'; 149 break; 150 case '\b': 151 *q++ = '\\'; 152 *q++ = 'b'; 153 break; 154 case '\0': 155 *q++ = '\\'; 156 *q++ = '0'; 157 break; 158 default: 159 *q++ = *cp; 160 } 161 } 162 *q++ = COMPONENT_SEP; 163 } 164 165 if (i > 0) 166 q--; /* Back up last component separator */ 167 *q++ = REALM_SEP; 168 169 cp = krb5_princ_realm(context, principal)->data; 170 length = krb5_princ_realm(context, principal)->length; 171 for (j=0; j < length; j++,cp++) { 172 switch (*cp) { 173 case COMPONENT_SEP: 174 case REALM_SEP: 175 case '\\': 176 *q++ = '\\'; 177 *q++ = *cp; 178 break; 179 case '\t': 180 *q++ = '\\'; 181 *q++ = 't'; 182 break; 183 case '\n': 184 *q++ = '\\'; 185 *q++ = 'n'; 186 break; 187 case '\b': 188 *q++ = '\\'; 189 *q++ = 'b'; 190 break; 191 case '\0': 192 *q++ = '\\'; 193 *q++ = '0'; 194 break; 195 default: 196 *q++ = *cp; 197 } 198 } 199 *q++ = '\0'; 200 201 return 0; 202 } 203 204 krb5_error_code KRB5_CALLCONV 205 krb5_unparse_name(krb5_context context, krb5_const_principal principal, register char **name) 206 { 207 if (name) /* name == NULL will return error from _ext */ 208 *name = NULL; 209 return(krb5_unparse_name_ext(context, principal, name, NULL)); 210 } 211 212