1 /* 2 * Copyright (c) 1997-1999 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "krb5_locl.h" 35 #ifdef HAVE_RES_SEARCH 36 #define USE_RESOLVER 37 #endif 38 #ifdef HAVE_ARPA_NAMESER_H 39 #include <arpa/nameser.h> 40 #endif 41 #include "resolve.h" 42 43 RCSID("$Id: principal.c,v 1.57 2000/01/08 08:08:03 assar Exp $"); 44 45 #define princ_num_comp(P) ((P)->name.name_string.len) 46 #define princ_type(P) ((P)->name.name_type) 47 #define princ_comp(P) ((P)->name.name_string.val) 48 #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) 49 #define princ_realm(P) ((P)->realm) 50 51 void 52 krb5_free_principal(krb5_context context, 53 krb5_principal p) 54 { 55 if(p){ 56 free_Principal(p); 57 free(p); 58 } 59 } 60 61 krb5_error_code 62 krb5_parse_name(krb5_context context, 63 const char *name, 64 krb5_principal *principal) 65 { 66 krb5_error_code ret; 67 general_string *comp; 68 general_string realm; 69 int ncomp; 70 71 char *p; 72 char *q; 73 char *s; 74 char *start; 75 76 int n; 77 char c; 78 int got_realm = 0; 79 80 /* count number of component */ 81 ncomp = 1; 82 for(p = (char*)name; *p; p++){ 83 if(*p=='\\'){ 84 if(!p[1]) 85 return KRB5_PARSE_MALFORMED; 86 p++; 87 } else if(*p == '/') 88 ncomp++; 89 } 90 comp = calloc(ncomp, sizeof(*comp)); 91 if (comp == NULL) 92 return ENOMEM; 93 94 n = 0; 95 start = q = p = s = strdup(name); 96 if (start == NULL) { 97 free (comp); 98 return ENOMEM; 99 } 100 while(*p){ 101 c = *p++; 102 if(c == '\\'){ 103 c = *p++; 104 if(c == 'n') 105 c = '\n'; 106 else if(c == 't') 107 c = '\t'; 108 else if(c == 'b') 109 c = '\b'; 110 else if(c == '0') 111 c = '\0'; 112 }else if(c == '/' || c == '@'){ 113 if(got_realm){ 114 ret = KRB5_PARSE_MALFORMED; 115 goto exit; 116 }else{ 117 comp[n] = malloc(q - start + 1); 118 if (comp[n] == NULL) { 119 ret = ENOMEM; 120 goto exit; 121 } 122 strncpy(comp[n], start, q - start); 123 comp[n][q - start] = 0; 124 n++; 125 } 126 if(c == '@') 127 got_realm = 1; 128 start = q; 129 continue; 130 } 131 if(got_realm && (c == ':' || c == '/' || c == '\0')) { 132 ret = KRB5_PARSE_MALFORMED; 133 goto exit; 134 } 135 *q++ = c; 136 } 137 if(got_realm){ 138 realm = malloc(q - start + 1); 139 if (realm == NULL) { 140 ret = ENOMEM; 141 goto exit; 142 } 143 strncpy(realm, start, q - start); 144 realm[q - start] = 0; 145 }else{ 146 ret = krb5_get_default_realm (context, &realm); 147 if (ret) 148 goto exit; 149 150 comp[n] = malloc(q - start + 1); 151 if (comp[n] == NULL) { 152 ret = ENOMEM; 153 goto exit; 154 } 155 strncpy(comp[n], start, q - start); 156 comp[n][q - start] = 0; 157 n++; 158 } 159 *principal = malloc(sizeof(**principal)); 160 if (*principal == NULL) { 161 ret = ENOMEM; 162 goto exit; 163 } 164 (*principal)->name.name_type = KRB5_NT_PRINCIPAL; 165 (*principal)->name.name_string.val = comp; 166 princ_num_comp(*principal) = n; 167 (*principal)->realm = realm; 168 free(s); 169 return 0; 170 exit: 171 while(n>0){ 172 free(comp[--n]); 173 } 174 free(comp); 175 free(s); 176 return ret; 177 } 178 179 static const char quotable_chars[] = "\n\t\b\\/@"; 180 static const char replace_chars[] = "ntb\\/@"; 181 182 #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); 183 184 static size_t 185 quote_string(const char *s, char *out, size_t index, size_t len) 186 { 187 const char *p, *q; 188 for(p = s; *p && index < len; p++){ 189 if((q = strchr(quotable_chars, *p))){ 190 add_char(out, index, len, '\\'); 191 add_char(out, index, len, replace_chars[q - quotable_chars]); 192 }else 193 add_char(out, index, len, *p); 194 } 195 if(index < len) 196 out[index] = '\0'; 197 return index; 198 } 199 200 201 static krb5_error_code 202 unparse_name_fixed(krb5_context context, 203 krb5_const_principal principal, 204 char *name, 205 size_t len, 206 krb5_boolean short_form) 207 { 208 size_t index = 0; 209 int i; 210 for(i = 0; i < princ_num_comp(principal); i++){ 211 if(i) 212 add_char(name, index, len, '/'); 213 index = quote_string(princ_ncomp(principal, i), name, index, len); 214 if(index == len) 215 return ERANGE; 216 } 217 /* add realm if different from default realm */ 218 if(short_form) { 219 krb5_realm r; 220 krb5_error_code ret; 221 ret = krb5_get_default_realm(context, &r); 222 if(ret) 223 return ret; 224 if(strcmp(princ_realm(principal), r) != 0) 225 short_form = 0; 226 free(r); 227 } 228 if(!short_form) { 229 add_char(name, index, len, '@'); 230 index = quote_string(princ_realm(principal), name, index, len); 231 if(index == len) 232 return ERANGE; 233 } 234 return 0; 235 } 236 237 krb5_error_code 238 krb5_unparse_name_fixed(krb5_context context, 239 krb5_const_principal principal, 240 char *name, 241 size_t len) 242 { 243 return unparse_name_fixed(context, principal, name, len, FALSE); 244 } 245 246 krb5_error_code 247 krb5_unparse_name_fixed_short(krb5_context context, 248 krb5_const_principal principal, 249 char *name, 250 size_t len) 251 { 252 return unparse_name_fixed(context, principal, name, len, TRUE); 253 } 254 255 static krb5_error_code 256 unparse_name(krb5_context context, 257 krb5_const_principal principal, 258 char **name, 259 krb5_boolean short_flag) 260 { 261 size_t len = 0, plen; 262 int i; 263 krb5_error_code ret; 264 /* count length */ 265 plen = strlen(princ_realm(principal)); 266 if(strcspn(princ_realm(principal), quotable_chars) == plen) 267 len += plen; 268 else 269 len += 2*plen; 270 len++; 271 for(i = 0; i < princ_num_comp(principal); i++){ 272 plen = strlen(princ_ncomp(principal, i)); 273 if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) 274 len += plen; 275 else 276 len += 2*plen; 277 len++; 278 } 279 *name = malloc(len); 280 if(len != 0 && *name == NULL) 281 return ENOMEM; 282 ret = unparse_name_fixed(context, principal, *name, len, short_flag); 283 if(ret) 284 free(*name); 285 return ret; 286 } 287 288 krb5_error_code 289 krb5_unparse_name(krb5_context context, 290 krb5_const_principal principal, 291 char **name) 292 { 293 return unparse_name(context, principal, name, FALSE); 294 } 295 296 krb5_error_code 297 krb5_unparse_name_short(krb5_context context, 298 krb5_const_principal principal, 299 char **name) 300 { 301 return unparse_name(context, principal, name, TRUE); 302 } 303 304 #if 0 /* not implemented */ 305 306 krb5_error_code 307 krb5_unparse_name_ext(krb5_context context, 308 krb5_const_principal principal, 309 char **name, 310 size_t *size) 311 { 312 krb5_abortx(context, "unimplemented krb5_unparse_name_ext called"); 313 } 314 315 #endif 316 317 krb5_realm* 318 krb5_princ_realm(krb5_context context, 319 krb5_principal principal) 320 { 321 return &princ_realm(principal); 322 } 323 324 325 void 326 krb5_princ_set_realm(krb5_context context, 327 krb5_principal principal, 328 krb5_realm *realm) 329 { 330 princ_realm(principal) = *realm; 331 } 332 333 334 krb5_error_code 335 krb5_build_principal(krb5_context context, 336 krb5_principal *principal, 337 int rlen, 338 krb5_const_realm realm, 339 ...) 340 { 341 krb5_error_code ret; 342 va_list ap; 343 va_start(ap, realm); 344 ret = krb5_build_principal_va(context, principal, rlen, realm, ap); 345 va_end(ap); 346 return ret; 347 } 348 349 static krb5_error_code 350 append_component(krb5_context context, krb5_principal p, 351 general_string comp, 352 size_t comp_len) 353 { 354 general_string *tmp; 355 size_t len = princ_num_comp(p); 356 tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); 357 if(tmp == NULL) 358 return ENOMEM; 359 princ_comp(p) = tmp; 360 princ_ncomp(p, len) = malloc(comp_len + 1); 361 memcpy (princ_ncomp(p, len), comp, comp_len); 362 princ_ncomp(p, len)[comp_len] = '\0'; 363 princ_num_comp(p)++; 364 return 0; 365 } 366 367 static void 368 va_ext_princ(krb5_context context, krb5_principal p, va_list ap) 369 { 370 while(1){ 371 char *s; 372 int len; 373 len = va_arg(ap, int); 374 if(len == 0) 375 break; 376 s = va_arg(ap, char*); 377 append_component(context, p, s, len); 378 } 379 } 380 381 static void 382 va_princ(krb5_context context, krb5_principal p, va_list ap) 383 { 384 while(1){ 385 char *s; 386 s = va_arg(ap, char*); 387 if(s == NULL) 388 break; 389 append_component(context, p, s, strlen(s)); 390 } 391 } 392 393 394 static krb5_error_code 395 build_principal(krb5_context context, 396 krb5_principal *principal, 397 int rlen, 398 krb5_const_realm realm, 399 void (*func)(krb5_context, krb5_principal, va_list), 400 va_list ap) 401 { 402 krb5_principal p; 403 404 p = calloc(1, sizeof(*p)); 405 if (p == NULL) 406 return ENOMEM; 407 princ_type(p) = KRB5_NT_PRINCIPAL; 408 409 princ_realm(p) = strdup(realm); 410 if(p->realm == NULL){ 411 free(p); 412 return ENOMEM; 413 } 414 415 (*func)(context, p, ap); 416 *principal = p; 417 return 0; 418 } 419 420 krb5_error_code 421 krb5_make_principal(krb5_context context, 422 krb5_principal *principal, 423 krb5_const_realm realm, 424 ...) 425 { 426 krb5_error_code ret; 427 krb5_realm r = NULL; 428 va_list ap; 429 if(realm == NULL) { 430 ret = krb5_get_default_realm(context, &r); 431 if(ret) 432 return ret; 433 realm = r; 434 } 435 va_start(ap, realm); 436 ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); 437 va_end(ap); 438 if(r) 439 free(r); 440 return ret; 441 } 442 443 krb5_error_code 444 krb5_build_principal_va(krb5_context context, 445 krb5_principal *principal, 446 int rlen, 447 krb5_const_realm realm, 448 va_list ap) 449 { 450 return build_principal(context, principal, rlen, realm, va_princ, ap); 451 } 452 453 krb5_error_code 454 krb5_build_principal_va_ext(krb5_context context, 455 krb5_principal *principal, 456 int rlen, 457 krb5_const_realm realm, 458 va_list ap) 459 { 460 return build_principal(context, principal, rlen, realm, va_ext_princ, ap); 461 } 462 463 464 krb5_error_code 465 krb5_build_principal_ext(krb5_context context, 466 krb5_principal *principal, 467 int rlen, 468 krb5_const_realm realm, 469 ...) 470 { 471 krb5_error_code ret; 472 va_list ap; 473 va_start(ap, realm); 474 ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap); 475 va_end(ap); 476 return ret; 477 } 478 479 480 krb5_error_code 481 krb5_copy_principal(krb5_context context, 482 krb5_const_principal inprinc, 483 krb5_principal *outprinc) 484 { 485 krb5_principal p = malloc(sizeof(*p)); 486 if (p == NULL) 487 return ENOMEM; 488 if(copy_Principal(inprinc, p)) 489 return ENOMEM; 490 *outprinc = p; 491 return 0; 492 } 493 494 495 krb5_boolean 496 krb5_principal_compare_any_realm(krb5_context context, 497 krb5_const_principal princ1, 498 krb5_const_principal princ2) 499 { 500 int i; 501 if(princ_num_comp(princ1) != princ_num_comp(princ2)) 502 return FALSE; 503 for(i = 0; i < princ_num_comp(princ1); i++){ 504 if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0) 505 return FALSE; 506 } 507 return TRUE; 508 } 509 510 krb5_boolean 511 krb5_principal_compare(krb5_context context, 512 krb5_const_principal princ1, 513 krb5_const_principal princ2) 514 { 515 if(!krb5_realm_compare(context, princ1, princ2)) 516 return FALSE; 517 return krb5_principal_compare_any_realm(context, princ1, princ2); 518 } 519 520 521 krb5_boolean 522 krb5_realm_compare(krb5_context context, 523 krb5_const_principal princ1, 524 krb5_const_principal princ2) 525 { 526 return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; 527 } 528 529 struct v4_name_convert { 530 const char *from; 531 const char *to; 532 } default_v4_name_convert[] = { 533 { "ftp", "ftp" }, 534 { "hprop", "hprop" }, 535 { "pop", "pop" }, 536 { "rcmd", "host" }, 537 { NULL, NULL } 538 }; 539 540 static const char* 541 get_name_conversion(krb5_context context, const char *realm, const char *name) 542 { 543 struct v4_name_convert *q; 544 const char *p; 545 p = krb5_config_get_string(context, NULL, "realms", realm, 546 "v4_name_convert", "host", name, NULL); 547 if(p == NULL) 548 p = krb5_config_get_string(context, NULL, "libdefaults", 549 "v4_name_convert", "host", name, NULL); 550 if(p) 551 return p; 552 553 /* XXX should be possible to override default list */ 554 p = krb5_config_get_string(context, NULL, 555 "realms", 556 realm, 557 "v4_name_convert", 558 "plain", 559 name, 560 NULL); 561 if(p) 562 return NULL; 563 p = krb5_config_get_string(context, NULL, 564 "libdefaults", 565 "v4_name_convert", 566 "plain", 567 name, 568 NULL); 569 if(p) 570 return NULL; 571 for(q = default_v4_name_convert; q->from; q++) 572 if(strcmp(q->from, name) == 0) 573 return q->to; 574 return NULL; 575 } 576 577 krb5_error_code 578 krb5_425_conv_principal_ext(krb5_context context, 579 const char *name, 580 const char *instance, 581 const char *realm, 582 krb5_boolean (*func)(krb5_context, krb5_principal), 583 krb5_boolean resolve, 584 krb5_principal *princ) 585 { 586 const char *p; 587 krb5_error_code ret; 588 krb5_principal pr; 589 char host[128]; 590 591 /* do the following: if the name is found in the 592 `v4_name_convert:host' part, is is assumed to be a `host' type 593 principal, and the instance is looked up in the 594 `v4_instance_convert' part. if not found there the name is 595 (optionally) looked up as a hostname, and if that doesn't yield 596 anything, the `default_domain' is appended to the instance 597 */ 598 599 if(instance == NULL) 600 goto no_host; 601 if(instance[0] == 0){ 602 instance = NULL; 603 goto no_host; 604 } 605 p = get_name_conversion(context, realm, name); 606 if(p == NULL) 607 goto no_host; 608 name = p; 609 p = krb5_config_get_string(context, NULL, "realms", realm, 610 "v4_instance_convert", instance, NULL); 611 if(p){ 612 instance = p; 613 ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 614 if(func == NULL || (*func)(context, pr)){ 615 *princ = pr; 616 return 0; 617 } 618 krb5_free_principal(context, pr); 619 *princ = NULL; 620 return HEIM_ERR_V4_PRINC_NO_CONV; 621 } 622 if(resolve){ 623 const char *inst = NULL; 624 #ifdef USE_RESOLVER 625 struct dns_reply *r; 626 r = dns_lookup(instance, "a"); 627 if(r && r->head && r->head->type == T_A) 628 inst = r->head->domain; 629 #else 630 struct hostent *hp = roken_gethostbyname(instance); 631 if(hp) 632 inst = hp->h_name; 633 #endif 634 if(inst) { 635 ret = krb5_make_principal(context, &pr, realm, name, inst, NULL); 636 if(ret == 0) { 637 if(func == NULL || (*func)(context, pr)){ 638 *princ = pr; 639 #ifdef USE_RESOLVER 640 dns_free_data(r); 641 #endif 642 return 0; 643 } 644 krb5_free_principal(context, pr); 645 } 646 } 647 #ifdef USE_RESOLVER 648 if(r) 649 dns_free_data(r); 650 #endif 651 } 652 { 653 char **domains, **d; 654 domains = krb5_config_get_strings(context, NULL, "realms", realm, 655 "v4_domains", NULL); 656 for(d = domains; d && *d; d++){ 657 snprintf(host, sizeof(host), "%s.%s", instance, *d); 658 ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 659 if(func == NULL || (*func)(context, pr)){ 660 *princ = pr; 661 krb5_config_free_strings(domains); 662 return 0; 663 } 664 krb5_free_principal(context, pr); 665 } 666 krb5_config_free_strings(domains); 667 } 668 669 670 p = krb5_config_get_string(context, NULL, "realms", realm, 671 "default_domain", NULL); 672 if(p == NULL){ 673 /* should this be an error or should it silently 674 succeed? */ 675 return HEIM_ERR_V4_PRINC_NO_CONV; 676 } 677 678 if (*p == '.') 679 ++p; 680 snprintf(host, sizeof(host), "%s.%s", instance, p); 681 ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 682 if(func == NULL || (*func)(context, pr)){ 683 *princ = pr; 684 return 0; 685 } 686 krb5_free_principal(context, pr); 687 return HEIM_ERR_V4_PRINC_NO_CONV; 688 no_host: 689 p = krb5_config_get_string(context, NULL, 690 "realms", 691 realm, 692 "v4_name_convert", 693 "plain", 694 name, 695 NULL); 696 if(p == NULL) 697 p = krb5_config_get_string(context, NULL, 698 "libdefaults", 699 "v4_name_convert", 700 "plain", 701 name, 702 NULL); 703 if(p) 704 name = p; 705 706 ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 707 if(func == NULL || (*func)(context, pr)){ 708 *princ = pr; 709 return 0; 710 } 711 krb5_free_principal(context, pr); 712 return HEIM_ERR_V4_PRINC_NO_CONV; 713 } 714 715 krb5_error_code 716 krb5_425_conv_principal(krb5_context context, 717 const char *name, 718 const char *instance, 719 const char *realm, 720 krb5_principal *princ) 721 { 722 krb5_boolean resolve = krb5_config_get_bool(context, 723 NULL, 724 "libdefaults", 725 "v4_instance_resolve", 726 NULL); 727 728 return krb5_425_conv_principal_ext(context, name, instance, realm, 729 NULL, resolve, princ); 730 } 731 732 733 static int 734 check_list(const krb5_config_binding *l, const char *name, const char **out) 735 { 736 while(l){ 737 if (l->type != krb5_config_string) 738 continue; 739 if(strcmp(name, l->u.string) == 0) { 740 *out = l->name; 741 return 1; 742 } 743 l = l->next; 744 } 745 return 0; 746 } 747 748 static int 749 name_convert(krb5_context context, const char *name, const char *realm, 750 const char **out) 751 { 752 const krb5_config_binding *l; 753 l = krb5_config_get_list (context, 754 NULL, 755 "realms", 756 realm, 757 "v4_name_convert", 758 "host", 759 NULL); 760 if(l && check_list(l, name, out)) 761 return KRB5_NT_SRV_HST; 762 l = krb5_config_get_list (context, 763 NULL, 764 "libdefaults", 765 "v4_name_convert", 766 "host", 767 NULL); 768 if(l && check_list(l, name, out)) 769 return KRB5_NT_SRV_HST; 770 l = krb5_config_get_list (context, 771 NULL, 772 "realms", 773 realm, 774 "v4_name_convert", 775 "plain", 776 NULL); 777 if(l && check_list(l, name, out)) 778 return KRB5_NT_UNKNOWN; 779 l = krb5_config_get_list (context, 780 NULL, 781 "libdefaults", 782 "v4_name_convert", 783 "host", 784 NULL); 785 if(l && check_list(l, name, out)) 786 return KRB5_NT_UNKNOWN; 787 788 /* didn't find it in config file, try built-in list */ 789 { 790 struct v4_name_convert *q; 791 for(q = default_v4_name_convert; q->from; q++) { 792 if(strcmp(name, q->to) == 0) { 793 *out = q->from; 794 return KRB5_NT_SRV_HST; 795 } 796 } 797 } 798 return -1; 799 } 800 801 krb5_error_code 802 krb5_524_conv_principal(krb5_context context, 803 const krb5_principal principal, 804 char *name, 805 char *instance, 806 char *realm) 807 { 808 const char *n, *i, *r; 809 char tmpinst[40]; 810 int type = princ_type(principal); 811 812 r = principal->realm; 813 814 switch(principal->name.name_string.len){ 815 case 1: 816 n = principal->name.name_string.val[0]; 817 i = ""; 818 break; 819 case 2: 820 n = principal->name.name_string.val[0]; 821 i = principal->name.name_string.val[1]; 822 break; 823 default: 824 return KRB5_PARSE_MALFORMED; 825 } 826 827 { 828 const char *tmp; 829 int t = name_convert(context, n, r, &tmp); 830 if(t >= 0) { 831 type = t; 832 n = tmp; 833 } 834 } 835 836 if(type == KRB5_NT_SRV_HST){ 837 char *p; 838 strncpy(tmpinst, i, sizeof(tmpinst)); 839 tmpinst[sizeof(tmpinst) - 1] = 0; 840 p = strchr(tmpinst, '.'); 841 if(p) *p = 0; 842 i = tmpinst; 843 } 844 845 if(strlen(r) >= 40) 846 return KRB5_PARSE_MALFORMED; 847 if(strlen(n) >= 40) 848 return KRB5_PARSE_MALFORMED; 849 if(strlen(i) >= 40) 850 return KRB5_PARSE_MALFORMED; 851 strcpy(realm, r); 852 strcpy(name, n); 853 strcpy(instance, i); 854 return 0; 855 } 856 857 /* 858 * Create a principal in `ret_princ' for the service `sname' running 859 * on host `hostname'. 860 */ 861 862 krb5_error_code 863 krb5_sname_to_principal (krb5_context context, 864 const char *hostname, 865 const char *sname, 866 int32_t type, 867 krb5_principal *ret_princ) 868 { 869 krb5_error_code ret; 870 char localhost[128]; 871 char **realms, *host = NULL; 872 873 if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) 874 return KRB5_SNAME_UNSUPP_NAMETYPE; 875 if(hostname == NULL) { 876 gethostname(localhost, sizeof(localhost)); 877 hostname = localhost; 878 } 879 if(sname == NULL) 880 sname = "host"; 881 if(type == KRB5_NT_SRV_HST) { 882 ret = krb5_expand_hostname (context, hostname, &host); 883 if (ret) 884 return ret; 885 strlwr(host); 886 hostname = host; 887 } 888 ret = krb5_get_host_realm(context, hostname, &realms); 889 if(ret) 890 return ret; 891 892 ret = krb5_make_principal(context, ret_princ, realms[0], sname, 893 hostname, NULL); 894 if(host) 895 free(host); 896 krb5_free_host_realm(context, realms); 897 return ret; 898 } 899