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