1 /* 2 * Copyright 2006 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 #include "adm_proto.h" 72 73 /* 74 * Local data structures. 75 */ 76 struct flags_lookup_entry { 77 krb5_flags fl_flags; /* Flag */ 78 krb5_boolean fl_sense; /* Sense of the flag */ 79 const char * fl_specifier; /* How to recognize it */ 80 const char * fl_output; /* How to spit it out */ 81 }; 82 83 /* 84 * Local strings 85 */ 86 87 static const char default_tupleseps[] = ", \t"; 88 static const char default_ksaltseps[] = ":."; 89 90 /* Keytype strings */ 91 /* Flags strings */ 92 static const char flags_pdate_in[] = "postdateable"; 93 static const char flags_fwd_in[] = "forwardable"; 94 static const char flags_tgtbased_in[] = "tgt-based"; 95 static const char flags_renew_in[] = "renewable"; 96 static const char flags_proxy_in[] = "proxiable"; 97 static const char flags_dup_skey_in[] = "dup-skey"; 98 static const char flags_tickets_in[] = "allow-tickets"; 99 static const char flags_preauth_in[] = "preauth"; 100 static const char flags_hwauth_in[] = "hwauth"; 101 static const char flags_pwchange_in[] = "pwchange"; 102 static const char flags_service_in[] = "service"; 103 static const char flags_pwsvc_in[] = "pwservice"; 104 static const char flags_md5_in[] = "md5"; 105 static const char flags_pdate_out[] = "Not Postdateable"; 106 static const char flags_fwd_out[] = "Not Forwardable"; 107 static const char flags_tgtbased_out[] = "No TGT-based requests"; 108 static const char flags_renew_out[] = "Not renewable"; 109 static const char flags_proxy_out[] = "Not proxiable"; 110 static const char flags_dup_skey_out[] = "No DUP_SKEY requests"; 111 static const char flags_tickets_out[] = "All Tickets Disallowed"; 112 static const char flags_preauth_out[] = "Preauthorization required"; 113 static const char flags_hwauth_out[] = "HW Authorization required"; 114 static const char flags_pwchange_out[] = "Password Change required"; 115 static const char flags_service_out[] = "Service Disabled"; 116 static const char flags_pwsvc_out[] = "Password Changing Service"; 117 static const char flags_md5_out[] = "RSA-MD5 supported"; 118 static const char flags_default_neg[] = "-"; 119 static const char flags_default_sep[] = " "; 120 121 /* 122 * Lookup tables. 123 */ 124 125 static const struct flags_lookup_entry flags_table[] = { 126 /* flag sense input specifier output string */ 127 /*----------------------------- ------- ------------------ ------------------*/ 128 { KRB5_KDB_DISALLOW_POSTDATED, 0, flags_pdate_in, flags_pdate_out }, 129 { KRB5_KDB_DISALLOW_FORWARDABLE,0, flags_fwd_in, flags_fwd_out }, 130 { KRB5_KDB_DISALLOW_TGT_BASED, 0, flags_tgtbased_in, flags_tgtbased_out}, 131 { KRB5_KDB_DISALLOW_RENEWABLE, 0, flags_renew_in, flags_renew_out }, 132 { KRB5_KDB_DISALLOW_PROXIABLE, 0, flags_proxy_in, flags_proxy_out }, 133 { KRB5_KDB_DISALLOW_DUP_SKEY, 0, flags_dup_skey_in, flags_dup_skey_out}, 134 { KRB5_KDB_DISALLOW_ALL_TIX, 0, flags_tickets_in, flags_tickets_out }, 135 { KRB5_KDB_REQUIRES_PRE_AUTH, 1, flags_preauth_in, flags_preauth_out }, 136 { KRB5_KDB_REQUIRES_HW_AUTH, 1, flags_hwauth_in, flags_hwauth_out }, 137 { KRB5_KDB_REQUIRES_PWCHANGE, 1, flags_pwchange_in, flags_pwchange_out}, 138 { KRB5_KDB_DISALLOW_SVR, 0, flags_service_in, flags_service_out }, 139 { KRB5_KDB_PWCHANGE_SERVICE, 1, flags_pwsvc_in, flags_pwsvc_out }, 140 { KRB5_KDB_SUPPORT_DESMD5, 1, flags_md5_in, flags_md5_out } 141 }; 142 static const int flags_table_nents = sizeof(flags_table)/ 143 sizeof(flags_table[0]); 144 145 146 krb5_error_code 147 krb5_string_to_flags(string, positive, negative, flagsp) 148 char * string; 149 const char * positive; 150 const char * negative; 151 krb5_flags * flagsp; 152 { 153 int i; 154 int found; 155 const char *neg; 156 size_t nsize, psize; 157 int cpos; 158 int sense; 159 160 found = 0; 161 /* We need to have a way to negate it. */ 162 neg = (negative) ? negative : flags_default_neg; 163 nsize = strlen(neg); 164 psize = (positive) ? strlen(positive) : 0; 165 166 cpos = 0; 167 sense = 1; 168 /* First check for positive or negative sense */ 169 if (!strncasecmp(neg, string, nsize)) { 170 sense = 0; 171 cpos += (int) nsize; 172 } 173 else if (psize && !strncasecmp(positive, string, psize)) { 174 cpos += (int) psize; 175 } 176 177 for (i=0; i<flags_table_nents; i++) { 178 if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) { 179 found = 1; 180 if (sense == (int) flags_table[i].fl_sense) 181 *flagsp |= flags_table[i].fl_flags; 182 else 183 *flagsp &= ~flags_table[i].fl_flags; 184 185 break; 186 } 187 } 188 return((found) ? 0 : EINVAL); 189 } 190 191 krb5_error_code 192 krb5_flags_to_string(flags, sep, buffer, buflen) 193 krb5_flags flags; 194 const char * sep; 195 char * buffer; 196 size_t buflen; 197 { 198 int i; 199 krb5_flags pflags; 200 const char *sepstring; 201 char *op; 202 int initial; 203 krb5_error_code retval; 204 205 retval = 0; 206 op = buffer; 207 pflags = 0; 208 initial = 1; 209 sepstring = (sep) ? sep : flags_default_sep; 210 /* Blast through the table matching all we can */ 211 for (i=0; i<flags_table_nents; i++) { 212 if (flags & flags_table[i].fl_flags) { 213 /* Found a match, see if it'll fit into the output buffer */ 214 if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) < 215 (buffer + buflen)) { 216 if (!initial) { 217 strcpy(op, sep); 218 op += strlen(sep); 219 } 220 initial = 0; 221 strcpy(op, flags_table[i].fl_output); 222 op += strlen(flags_table[i].fl_output); 223 } 224 else { 225 retval = ENOMEM; 226 break; 227 } 228 /* Keep track of what we matched */ 229 pflags |= flags_table[i].fl_flags; 230 } 231 } 232 if (!retval) { 233 /* See if there's any leftovers */ 234 if (flags & ~pflags) 235 retval = EINVAL; 236 else if (initial) 237 *buffer = '\0'; 238 } 239 return(retval); 240 } 241 242 krb5_error_code 243 krb5_input_flag_to_string(flag, buffer, buflen) 244 int flag; 245 char * buffer; 246 size_t buflen; 247 { 248 if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */ 249 if(strlen(flags_table[flag].fl_specifier) > buflen) return ENOMEM; 250 strcpy(buffer, flags_table[flag].fl_specifier); 251 return 0; 252 } 253 254 /* 255 * krb5_keysalt_is_present() - Determine if a key/salt pair is present 256 * in a list of key/salt tuples. 257 * 258 * Salttype may be negative to indicate a search for only a enctype. 259 */ 260 krb5_boolean 261 krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype) 262 krb5_key_salt_tuple *ksaltlist; 263 krb5_int32 nksalts; 264 krb5_enctype enctype; 265 krb5_int32 salttype; 266 { 267 krb5_boolean foundit; 268 int i; 269 270 foundit = 0; 271 if (ksaltlist) { 272 for (i=0; i<nksalts; i++) { 273 if ((ksaltlist[i].ks_enctype == enctype) && 274 ((ksaltlist[i].ks_salttype == salttype) || 275 (salttype < 0))) { 276 foundit = 1; 277 break; 278 } 279 } 280 } 281 return(foundit); 282 } 283 284 /* 285 * krb5_string_to_keysalts() - Convert a string representation to a list 286 * of key/salt tuples. 287 */ 288 krb5_error_code 289 krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp) 290 char *string; 291 const char *tupleseps; 292 const char *ksaltseps; 293 krb5_boolean dups; 294 krb5_key_salt_tuple **ksaltp; 295 krb5_int32 *nksaltp; 296 { 297 krb5_error_code kret; 298 char *kp, *sp, *ep; 299 char sepchar, trailchar; 300 krb5_enctype ktype; 301 krb5_int32 stype; 302 krb5_key_salt_tuple *savep; 303 const char *tseplist; 304 const char *ksseplist; 305 const char *septmp; 306 size_t len; 307 308 kret = 0; 309 kp = string; 310 tseplist = (tupleseps) ? tupleseps : default_tupleseps; 311 ksseplist = (ksaltseps) ? ksaltseps : default_ksaltseps; 312 while (kp) { 313 /* Attempt to find a separator */ 314 ep = (char *) NULL; 315 if (*tseplist) { 316 septmp = tseplist; 317 for (ep = strchr(kp, (int) *septmp); 318 *(++septmp) && !ep; 319 ep = strchr(kp, (int) *septmp)); 320 } 321 322 if (ep) { 323 trailchar = *ep; 324 *ep = '\0'; 325 ep++; 326 } 327 /* 328 * kp points to something (hopefully) of the form: 329 * <enctype><ksseplist><salttype> 330 * or 331 * <enctype> 332 */ 333 sp = (char *) NULL; 334 /* Attempt to find a separator */ 335 septmp = ksseplist; 336 for (sp = strchr(kp, (int) *septmp); 337 *(++septmp) && !sp; 338 sp = strchr(kp, (int)*septmp)); 339 340 if (sp) { 341 /* Separate enctype from salttype */ 342 sepchar = *sp; 343 *sp = '\0'; 344 sp++; 345 } 346 else 347 stype = -1; 348 349 /* 350 * Attempt to parse enctype and salttype. If we parse well 351 * then make sure that it specifies a unique key/salt combo 352 */ 353 if (!(kret = krb5_string_to_enctype(kp, &ktype)) && 354 (!sp || !(kret = krb5_string_to_salttype(sp, &stype))) && 355 (dups || 356 !krb5_keysalt_is_present(*ksaltp, *nksaltp, ktype, stype))) { 357 358 /* Squirrel away old keysalt array */ 359 savep = *ksaltp; 360 len = (size_t) *nksaltp; 361 362 /* Get new keysalt array */ 363 *ksaltp = (krb5_key_salt_tuple *) 364 malloc((len + 1) * sizeof(krb5_key_salt_tuple)); 365 if (*ksaltp) { 366 367 /* Copy old keysalt if appropriate */ 368 if (savep) { 369 memcpy(*ksaltp, savep, 370 len * sizeof(krb5_key_salt_tuple)); 371 krb5_xfree(savep); 372 } 373 374 /* Save our values */ 375 (*ksaltp)[(*nksaltp)].ks_enctype = ktype; 376 (*ksaltp)[(*nksaltp)].ks_salttype = stype; 377 (*nksaltp)++; 378 } 379 else { 380 *ksaltp = savep; 381 break; 382 } 383 } 384 /* 385 * Solaris Kerberos 386 * If the string did not yield a valid enctype/keysalt 387 * just ignore it and continue on. MIT kerberos stops 388 * searching when if finds an unknown string. 389 */ 390 if (sp) 391 sp[-1] = sepchar; 392 if (ep) 393 ep[-1] = trailchar; 394 kp = ep; 395 396 /* Skip over extra separators - like spaces */ 397 if (kp && *tseplist) { 398 septmp = tseplist; 399 while(*septmp && *kp) { 400 if(*septmp == *kp) { 401 /* Increment string - reset separator list */ 402 kp++; 403 septmp = tseplist; 404 } else { 405 septmp++; 406 } 407 } 408 if (!*kp) kp = NULL; 409 } 410 } /* while kp */ 411 return(kret); 412 } 413 414 /* 415 * krb5_keysalt_iterate() - Do something for each unique key/salt 416 * combination. 417 * 418 * If ignoresalt set, then salttype is ignored. 419 */ 420 krb5_error_code 421 krb5_keysalt_iterate(ksaltlist, nksalt, ignoresalt, iterator, arg) 422 krb5_key_salt_tuple *ksaltlist; 423 krb5_int32 nksalt; 424 krb5_boolean ignoresalt; 425 krb5_error_code (*iterator) (krb5_key_salt_tuple *, krb5_pointer); 426 krb5_pointer arg; 427 { 428 int i; 429 krb5_error_code kret; 430 krb5_key_salt_tuple scratch; 431 432 kret = 0; 433 for (i=0; i<nksalt; i++) { 434 scratch.ks_enctype = ksaltlist[i].ks_enctype; 435 scratch.ks_salttype = (ignoresalt) ? -1 : ksaltlist[i].ks_salttype; 436 if (!krb5_keysalt_is_present(ksaltlist, 437 i, 438 scratch.ks_enctype, 439 scratch.ks_salttype)) { 440 kret = (*iterator)(&scratch, arg); 441 if (kret) 442 break; 443 } 444 } 445 return(kret); 446 } 447