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 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * lib/kadm/str_conv.c 28 * 29 * Copyright 1995 by the Massachusetts Institute of Technology. 30 * All Rights Reserved. 31 * 32 * Export of this software from the United States of America may 33 * require a specific license from the United States Government. 34 * It is the responsibility of any person or organization contemplating 35 * export to obtain such a license before exporting. 36 * 37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 38 * distribute this software and its documentation for any purpose and 39 * without fee is hereby granted, provided that the above copyright 40 * notice appear in all copies and that both that copyright notice and 41 * this permission notice appear in supporting documentation, and that 42 * the name of M.I.T. not be used in advertising or publicity pertaining 43 * to distribution of the software without specific, written prior 44 * permission. Furthermore if you modify this software you must label 45 * your software as modified software and not distribute it in such a 46 * fashion that it might be confused with the original M.I.T. software. 47 * M.I.T. makes no representations about the suitability of 48 * this software for any purpose. It is provided "as is" without express 49 * or implied warranty. 50 * 51 */ 52 53 /* 54 * str_conv.c - Convert between strings and Kerberos internal data. 55 */ 56 57 /* 58 * Table of contents: 59 * 60 * String decoding: 61 * ---------------- 62 * krb5_string_to_flags() - Convert string to krb5_flags. 63 * 64 * String encoding: 65 * ---------------- 66 * krb5_flags_to_string() - Convert krb5_flags to string. 67 */ 68 69 #include "k5-int.h" 70 #include "admin_internal.h" 71 72 /* 73 * Local data structures. 74 */ 75 struct flags_lookup_entry { 76 krb5_flags fl_flags; /* Flag */ 77 krb5_boolean fl_sense; /* Sense of the flag */ 78 const char * fl_specifier; /* How to recognize it */ 79 const char * fl_output; /* How to spit it out */ 80 }; 81 82 /* 83 * Local strings 84 */ 85 86 static const char default_tupleseps[] = ", \t"; 87 static const char default_ksaltseps[] = ":."; 88 89 /* Keytype strings */ 90 /* Flags strings */ 91 static const char flags_pdate_in[] = "postdateable"; 92 static const char flags_fwd_in[] = "forwardable"; 93 static const char flags_tgtbased_in[] = "tgt-based"; 94 static const char flags_renew_in[] = "renewable"; 95 static const char flags_proxy_in[] = "proxiable"; 96 static const char flags_dup_skey_in[] = "dup-skey"; 97 static const char flags_tickets_in[] = "allow-tickets"; 98 static const char flags_preauth_in[] = "preauth"; 99 static const char flags_hwauth_in[] = "hwauth"; 100 static const char flags_pwchange_in[] = "pwchange"; 101 static const char flags_service_in[] = "service"; 102 static const char flags_pwsvc_in[] = "pwservice"; 103 static const char flags_md5_in[] = "md5"; 104 static const char flags_pdate_out[] = "Not Postdateable"; 105 static const char flags_fwd_out[] = "Not Forwardable"; 106 static const char flags_tgtbased_out[] = "No TGT-based requests"; 107 static const char flags_renew_out[] = "Not renewable"; 108 static const char flags_proxy_out[] = "Not proxiable"; 109 static const char flags_dup_skey_out[] = "No DUP_SKEY requests"; 110 static const char flags_tickets_out[] = "All Tickets Disallowed"; 111 static const char flags_preauth_out[] = "Preauthorization required"; 112 static const char flags_hwauth_out[] = "HW Authorization required"; 113 static const char flags_pwchange_out[] = "Password Change required"; 114 static const char flags_service_out[] = "Service Disabled"; 115 static const char flags_pwsvc_out[] = "Password Changing Service"; 116 static const char flags_md5_out[] = "RSA-MD5 supported"; 117 static const char flags_default_neg[] = "-"; 118 static const char flags_default_sep[] = " "; 119 120 /* 121 * Lookup tables. 122 */ 123 124 static const struct flags_lookup_entry flags_table[] = { 125 /* flag sense input specifier output string */ 126 /*----------------------------- ------- ------------------ ------------------*/ 127 { KRB5_KDB_DISALLOW_POSTDATED, 0, flags_pdate_in, flags_pdate_out }, 128 { KRB5_KDB_DISALLOW_FORWARDABLE,0, flags_fwd_in, flags_fwd_out }, 129 { KRB5_KDB_DISALLOW_TGT_BASED, 0, flags_tgtbased_in, flags_tgtbased_out}, 130 { KRB5_KDB_DISALLOW_RENEWABLE, 0, flags_renew_in, flags_renew_out }, 131 { KRB5_KDB_DISALLOW_PROXIABLE, 0, flags_proxy_in, flags_proxy_out }, 132 { KRB5_KDB_DISALLOW_DUP_SKEY, 0, flags_dup_skey_in, flags_dup_skey_out}, 133 { KRB5_KDB_DISALLOW_ALL_TIX, 0, flags_tickets_in, flags_tickets_out }, 134 { KRB5_KDB_REQUIRES_PRE_AUTH, 1, flags_preauth_in, flags_preauth_out }, 135 { KRB5_KDB_REQUIRES_HW_AUTH, 1, flags_hwauth_in, flags_hwauth_out }, 136 { KRB5_KDB_REQUIRES_PWCHANGE, 1, flags_pwchange_in, flags_pwchange_out}, 137 { KRB5_KDB_DISALLOW_SVR, 0, flags_service_in, flags_service_out }, 138 { KRB5_KDB_PWCHANGE_SERVICE, 1, flags_pwsvc_in, flags_pwsvc_out }, 139 { KRB5_KDB_SUPPORT_DESMD5, 1, flags_md5_in, flags_md5_out } 140 }; 141 static const int flags_table_nents = sizeof(flags_table)/ 142 sizeof(flags_table[0]); 143 144 145 krb5_error_code 146 krb5_string_to_flags(string, positive, negative, flagsp) 147 char * string; 148 const char * positive; 149 const char * negative; 150 krb5_flags * flagsp; 151 { 152 int i; 153 int found; 154 const char *neg; 155 size_t nsize, psize; 156 int cpos; 157 int sense; 158 159 found = 0; 160 /* We need to have a way to negate it. */ 161 neg = (negative) ? negative : flags_default_neg; 162 nsize = strlen(neg); 163 psize = (positive) ? strlen(positive) : 0; 164 165 cpos = 0; 166 sense = 1; 167 /* First check for positive or negative sense */ 168 if (!strncasecmp(neg, string, nsize)) { 169 sense = 0; 170 cpos += (int) nsize; 171 } 172 else if (psize && !strncasecmp(positive, string, psize)) { 173 cpos += (int) psize; 174 } 175 176 for (i=0; i<flags_table_nents; i++) { 177 if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) { 178 found = 1; 179 if (sense == (int) flags_table[i].fl_sense) 180 *flagsp |= flags_table[i].fl_flags; 181 else 182 *flagsp &= ~flags_table[i].fl_flags; 183 184 break; 185 } 186 } 187 return((found) ? 0 : EINVAL); 188 } 189 190 krb5_error_code 191 krb5_flags_to_string(flags, sep, buffer, buflen) 192 krb5_flags flags; 193 const char * sep; 194 char * buffer; 195 size_t buflen; 196 { 197 int i; 198 krb5_flags pflags; 199 const char *sepstring; 200 char *op; 201 int initial; 202 krb5_error_code retval; 203 204 retval = 0; 205 op = buffer; 206 pflags = 0; 207 initial = 1; 208 sepstring = (sep) ? sep : flags_default_sep; 209 /* Blast through the table matching all we can */ 210 for (i=0; i<flags_table_nents; i++) { 211 if (flags & flags_table[i].fl_flags) { 212 /* Found a match, see if it'll fit into the output buffer */ 213 if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) < 214 (buffer + buflen)) { 215 if (!initial) { 216 strcpy(op, sep); 217 op += strlen(sep); 218 } 219 initial = 0; 220 strcpy(op, flags_table[i].fl_output); 221 op += strlen(flags_table[i].fl_output); 222 } 223 else { 224 retval = ENOMEM; 225 break; 226 } 227 /* Keep track of what we matched */ 228 pflags |= flags_table[i].fl_flags; 229 } 230 } 231 if (!retval) { 232 /* See if there's any leftovers */ 233 if (flags & ~pflags) 234 retval = EINVAL; 235 else if (initial) 236 *buffer = '\0'; 237 } 238 return(retval); 239 } 240 241 krb5_error_code 242 krb5_input_flag_to_string(flag, buffer, buflen) 243 int flag; 244 char * buffer; 245 size_t buflen; 246 { 247 if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */ 248 if(strlen(flags_table[flag].fl_specifier) > buflen) return ENOMEM; 249 strcpy(buffer, flags_table[flag].fl_specifier); 250 return 0; 251 } 252 253 /* 254 * krb5_keysalt_is_present() - Determine if a key/salt pair is present 255 * in a list of key/salt tuples. 256 * 257 * Salttype may be negative to indicate a search for only a enctype. 258 */ 259 krb5_boolean 260 krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype) 261 krb5_key_salt_tuple *ksaltlist; 262 krb5_int32 nksalts; 263 krb5_enctype enctype; 264 krb5_int32 salttype; 265 { 266 krb5_boolean foundit; 267 int i; 268 269 foundit = 0; 270 if (ksaltlist) { 271 for (i=0; i<nksalts; i++) { 272 if ((ksaltlist[i].ks_enctype == enctype) && 273 ((ksaltlist[i].ks_salttype == salttype) || 274 (salttype < 0))) { 275 foundit = 1; 276 break; 277 } 278 } 279 } 280 return(foundit); 281 } 282 283 /* 284 * krb5_string_to_keysalts() - Convert a string representation to a list 285 * of key/salt tuples. 286 */ 287 krb5_error_code 288 krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp) 289 char *string; 290 const char *tupleseps; 291 const char *ksaltseps; 292 krb5_boolean dups; 293 krb5_key_salt_tuple **ksaltp; 294 krb5_int32 *nksaltp; 295 { 296 krb5_error_code kret; 297 char *kp, *sp, *ep; 298 char sepchar, trailchar; 299 krb5_enctype ktype; 300 krb5_int32 stype; 301 krb5_key_salt_tuple *savep; 302 const char *tseplist; 303 const char *ksseplist; 304 const char *septmp; 305 size_t len; 306 307 kret = 0; 308 kp = string; 309 tseplist = (tupleseps) ? tupleseps : default_tupleseps; 310 ksseplist = (ksaltseps) ? ksaltseps : default_ksaltseps; 311 while (kp) { 312 /* Attempt to find a separator */ 313 ep = (char *) NULL; 314 if (*tseplist) { 315 septmp = tseplist; 316 for (ep = strchr(kp, (int) *septmp); 317 *(++septmp) && !ep; 318 ep = strchr(kp, (int) *septmp)); 319 } 320 321 if (ep) { 322 trailchar = *ep; 323 *ep = '\0'; 324 ep++; 325 } 326 /* 327 * kp points to something (hopefully) of the form: 328 * <enctype><ksseplist><salttype> 329 * or 330 * <enctype> 331 */ 332 sp = (char *) NULL; 333 /* Attempt to find a separator */ 334 septmp = ksseplist; 335 for (sp = strchr(kp, (int) *septmp); 336 *(++septmp) && !sp; 337 sp = strchr(kp, (int)*septmp)); 338 339 if (sp) { 340 /* Separate enctype from salttype */ 341 sepchar = *sp; 342 *sp = '\0'; 343 sp++; 344 } 345 else 346 stype = -1; 347 348 /* 349 * Attempt to parse enctype and salttype. If we parse well 350 * then make sure that it specifies a unique key/salt combo 351 */ 352 if (!(kret = krb5_string_to_enctype(kp, &ktype)) && 353 (!sp || !(kret = krb5_string_to_salttype(sp, &stype))) && 354 (dups || 355 !krb5_keysalt_is_present(*ksaltp, *nksaltp, ktype, stype))) { 356 357 /* Squirrel away old keysalt array */ 358 savep = *ksaltp; 359 len = (size_t) *nksaltp; 360 361 /* Get new keysalt array */ 362 if (*ksaltp = (krb5_key_salt_tuple *) 363 malloc((len + 1) * sizeof(krb5_key_salt_tuple))) { 364 365 /* Copy old keysalt if appropriate */ 366 if (savep) { 367 memcpy(*ksaltp, savep, 368 len * sizeof(krb5_key_salt_tuple)); 369 krb5_xfree(savep); 370 } 371 372 /* Save our values */ 373 (*ksaltp)[(*nksaltp)].ks_enctype = ktype; 374 (*ksaltp)[(*nksaltp)].ks_salttype = stype; 375 (*nksaltp)++; 376 } 377 else { 378 *ksaltp = savep; 379 break; 380 } 381 } 382 /* 383 * Solaris Kerberos 384 * If the string did not yield a valid enctype/keysalt 385 * just ignore it and continue on. MIT kerberos stops 386 * searching when if finds an unknown string. 387 */ 388 if (sp) 389 sp[-1] = sepchar; 390 if (ep) 391 ep[-1] = trailchar; 392 kp = ep; 393 394 /* Skip over extra separators - like spaces */ 395 if (kp && *tseplist) { 396 septmp = tseplist; 397 while(*septmp && *kp) { 398 if(*septmp == *kp) { 399 /* Increment string - reset separator list */ 400 kp++; 401 septmp = tseplist; 402 } else { 403 septmp++; 404 } 405 } 406 if (!*kp) kp = NULL; 407 } 408 } /* while kp */ 409 return(kret); 410 } 411 412 /* 413 * krb5_keysalt_iterate() - Do something for each unique key/salt 414 * combination. 415 * 416 * If ignoresalt set, then salttype is ignored. 417 */ 418 krb5_error_code 419 krb5_keysalt_iterate(ksaltlist, nksalt, ignoresalt, iterator, arg) 420 krb5_key_salt_tuple *ksaltlist; 421 krb5_int32 nksalt; 422 krb5_boolean ignoresalt; 423 krb5_error_code (*iterator) KRB5_NPROTOTYPE((krb5_key_salt_tuple *, 424 krb5_pointer)); 425 krb5_pointer arg; 426 { 427 int i; 428 krb5_error_code kret; 429 krb5_key_salt_tuple scratch; 430 431 kret = 0; 432 for (i=0; i<nksalt; i++) { 433 scratch.ks_enctype = ksaltlist[i].ks_enctype; 434 scratch.ks_salttype = (ignoresalt) ? -1 : ksaltlist[i].ks_salttype; 435 if (!krb5_keysalt_is_present(ksaltlist, 436 i, 437 scratch.ks_enctype, 438 scratch.ks_salttype)) { 439 if (kret = (*iterator)(&scratch, arg)) 440 break; 441 } 442 } 443 return(kret); 444 } 445