1 /* 2 * Copyright (c) 1997-2000 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.63 2000/02/07 03:19:05 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 memcpy(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 memcpy(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 memcpy(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 const char *comp, 352 size_t comp_len) 353 { 354 general_string *tmp; 355 size_t len = princ_num_comp(p); 356 357 tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); 358 if(tmp == NULL) 359 return ENOMEM; 360 princ_comp(p) = tmp; 361 princ_ncomp(p, len) = malloc(comp_len + 1); 362 if (princ_ncomp(p, len) == NULL) 363 return ENOMEM; 364 memcpy (princ_ncomp(p, len), comp, comp_len); 365 princ_ncomp(p, len)[comp_len] = '\0'; 366 princ_num_comp(p)++; 367 return 0; 368 } 369 370 static void 371 va_ext_princ(krb5_context context, krb5_principal p, va_list ap) 372 { 373 while(1){ 374 const char *s; 375 int len; 376 len = va_arg(ap, int); 377 if(len == 0) 378 break; 379 s = va_arg(ap, const char*); 380 append_component(context, p, s, len); 381 } 382 } 383 384 static void 385 va_princ(krb5_context context, krb5_principal p, va_list ap) 386 { 387 while(1){ 388 const char *s; 389 s = va_arg(ap, const char*); 390 if(s == NULL) 391 break; 392 append_component(context, p, s, strlen(s)); 393 } 394 } 395 396 397 static krb5_error_code 398 build_principal(krb5_context context, 399 krb5_principal *principal, 400 int rlen, 401 krb5_const_realm realm, 402 void (*func)(krb5_context, krb5_principal, va_list), 403 va_list ap) 404 { 405 krb5_principal p; 406 407 p = calloc(1, sizeof(*p)); 408 if (p == NULL) 409 return ENOMEM; 410 princ_type(p) = KRB5_NT_PRINCIPAL; 411 412 princ_realm(p) = strdup(realm); 413 if(p->realm == NULL){ 414 free(p); 415 return ENOMEM; 416 } 417 418 (*func)(context, p, ap); 419 *principal = p; 420 return 0; 421 } 422 423 krb5_error_code 424 krb5_make_principal(krb5_context context, 425 krb5_principal *principal, 426 krb5_const_realm realm, 427 ...) 428 { 429 krb5_error_code ret; 430 krb5_realm r = NULL; 431 va_list ap; 432 if(realm == NULL) { 433 ret = krb5_get_default_realm(context, &r); 434 if(ret) 435 return ret; 436 realm = r; 437 } 438 va_start(ap, realm); 439 ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); 440 va_end(ap); 441 if(r) 442 free(r); 443 return ret; 444 } 445 446 krb5_error_code 447 krb5_build_principal_va(krb5_context context, 448 krb5_principal *principal, 449 int rlen, 450 krb5_const_realm realm, 451 va_list ap) 452 { 453 return build_principal(context, principal, rlen, realm, va_princ, ap); 454 } 455 456 krb5_error_code 457 krb5_build_principal_va_ext(krb5_context context, 458 krb5_principal *principal, 459 int rlen, 460 krb5_const_realm realm, 461 va_list ap) 462 { 463 return build_principal(context, principal, rlen, realm, va_ext_princ, ap); 464 } 465 466 467 krb5_error_code 468 krb5_build_principal_ext(krb5_context context, 469 krb5_principal *principal, 470 int rlen, 471 krb5_const_realm realm, 472 ...) 473 { 474 krb5_error_code ret; 475 va_list ap; 476 va_start(ap, realm); 477 ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap); 478 va_end(ap); 479 return ret; 480 } 481 482 483 krb5_error_code 484 krb5_copy_principal(krb5_context context, 485 krb5_const_principal inprinc, 486 krb5_principal *outprinc) 487 { 488 krb5_principal p = malloc(sizeof(*p)); 489 if (p == NULL) 490 return ENOMEM; 491 if(copy_Principal(inprinc, p)) 492 return ENOMEM; 493 *outprinc = p; 494 return 0; 495 } 496 497 498 krb5_boolean 499 krb5_principal_compare_any_realm(krb5_context context, 500 krb5_const_principal princ1, 501 krb5_const_principal princ2) 502 { 503 int i; 504 if(princ_num_comp(princ1) != princ_num_comp(princ2)) 505 return FALSE; 506 for(i = 0; i < princ_num_comp(princ1); i++){ 507 if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0) 508 return FALSE; 509 } 510 return TRUE; 511 } 512 513 krb5_boolean 514 krb5_principal_compare(krb5_context context, 515 krb5_const_principal princ1, 516 krb5_const_principal princ2) 517 { 518 if(!krb5_realm_compare(context, princ1, princ2)) 519 return FALSE; 520 return krb5_principal_compare_any_realm(context, princ1, princ2); 521 } 522 523 524 krb5_boolean 525 krb5_realm_compare(krb5_context context, 526 krb5_const_principal princ1, 527 krb5_const_principal princ2) 528 { 529 return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; 530 } 531 532 struct v4_name_convert { 533 const char *from; 534 const char *to; 535 } default_v4_name_convert[] = { 536 { "ftp", "ftp" }, 537 { "hprop", "hprop" }, 538 { "pop", "pop" }, 539 { "rcmd", "host" }, 540 { NULL, NULL } 541 }; 542 543 static const char* 544 get_name_conversion(krb5_context context, const char *realm, const char *name) 545 { 546 struct v4_name_convert *q; 547 const char *p; 548 p = krb5_config_get_string(context, NULL, "realms", realm, 549 "v4_name_convert", "host", name, NULL); 550 if(p == NULL) 551 p = krb5_config_get_string(context, NULL, "libdefaults", 552 "v4_name_convert", "host", name, NULL); 553 if(p) 554 return p; 555 556 /* XXX should be possible to override default list */ 557 p = krb5_config_get_string(context, NULL, 558 "realms", 559 realm, 560 "v4_name_convert", 561 "plain", 562 name, 563 NULL); 564 if(p) 565 return NULL; 566 p = krb5_config_get_string(context, NULL, 567 "libdefaults", 568 "v4_name_convert", 569 "plain", 570 name, 571 NULL); 572 if(p) 573 return NULL; 574 for(q = default_v4_name_convert; q->from; q++) 575 if(strcmp(q->from, name) == 0) 576 return q->to; 577 return NULL; 578 } 579 580 krb5_error_code 581 krb5_425_conv_principal_ext(krb5_context context, 582 const char *name, 583 const char *instance, 584 const char *realm, 585 krb5_boolean (*func)(krb5_context, krb5_principal), 586 krb5_boolean resolve, 587 krb5_principal *princ) 588 { 589 const char *p; 590 krb5_error_code ret; 591 krb5_principal pr; 592 char host[128]; 593 594 /* do the following: if the name is found in the 595 `v4_name_convert:host' part, is is assumed to be a `host' type 596 principal, and the instance is looked up in the 597 `v4_instance_convert' part. if not found there the name is 598 (optionally) looked up as a hostname, and if that doesn't yield 599 anything, the `default_domain' is appended to the instance 600 */ 601 602 if(instance == NULL) 603 goto no_host; 604 if(instance[0] == 0){ 605 instance = NULL; 606 goto no_host; 607 } 608 p = get_name_conversion(context, realm, name); 609 if(p == NULL) 610 goto no_host; 611 name = p; 612 p = krb5_config_get_string(context, NULL, "realms", realm, 613 "v4_instance_convert", instance, NULL); 614 if(p){ 615 instance = p; 616 ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 617 if(func == NULL || (*func)(context, pr)){ 618 *princ = pr; 619 return 0; 620 } 621 krb5_free_principal(context, pr); 622 *princ = NULL; 623 return HEIM_ERR_V4_PRINC_NO_CONV; 624 } 625 if(resolve){ 626 const char *inst = NULL; 627 #ifdef USE_RESOLVER 628 struct dns_reply *r; 629 r = dns_lookup(instance, "a"); 630 if(r && r->head && r->head->type == T_A) 631 inst = r->head->domain; 632 #else 633 struct hostent *hp = roken_gethostbyname(instance); 634 if(hp) 635 inst = hp->h_name; 636 #endif 637 if(inst) { 638 ret = krb5_make_principal(context, &pr, realm, name, inst, NULL); 639 if(ret == 0) { 640 if(func == NULL || (*func)(context, pr)){ 641 *princ = pr; 642 #ifdef USE_RESOLVER 643 dns_free_data(r); 644 #endif 645 return 0; 646 } 647 krb5_free_principal(context, pr); 648 } 649 } 650 #ifdef USE_RESOLVER 651 if(r) 652 dns_free_data(r); 653 #endif 654 } 655 { 656 char **domains, **d; 657 domains = krb5_config_get_strings(context, NULL, "realms", realm, 658 "v4_domains", NULL); 659 for(d = domains; d && *d; d++){ 660 snprintf(host, sizeof(host), "%s.%s", instance, *d); 661 ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 662 if(func == NULL || (*func)(context, pr)){ 663 *princ = pr; 664 krb5_config_free_strings(domains); 665 return 0; 666 } 667 krb5_free_principal(context, pr); 668 } 669 krb5_config_free_strings(domains); 670 } 671 672 673 p = krb5_config_get_string(context, NULL, "realms", realm, 674 "default_domain", NULL); 675 if(p == NULL){ 676 /* should this be an error or should it silently 677 succeed? */ 678 return HEIM_ERR_V4_PRINC_NO_CONV; 679 } 680 681 if (*p == '.') 682 ++p; 683 snprintf(host, sizeof(host), "%s.%s", instance, p); 684 ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 685 if(func == NULL || (*func)(context, pr)){ 686 *princ = pr; 687 return 0; 688 } 689 krb5_free_principal(context, pr); 690 return HEIM_ERR_V4_PRINC_NO_CONV; 691 no_host: 692 p = krb5_config_get_string(context, NULL, 693 "realms", 694 realm, 695 "v4_name_convert", 696 "plain", 697 name, 698 NULL); 699 if(p == NULL) 700 p = krb5_config_get_string(context, NULL, 701 "libdefaults", 702 "v4_name_convert", 703 "plain", 704 name, 705 NULL); 706 if(p) 707 name = p; 708 709 ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 710 if(func == NULL || (*func)(context, pr)){ 711 *princ = pr; 712 return 0; 713 } 714 krb5_free_principal(context, pr); 715 return HEIM_ERR_V4_PRINC_NO_CONV; 716 } 717 718 krb5_error_code 719 krb5_425_conv_principal(krb5_context context, 720 const char *name, 721 const char *instance, 722 const char *realm, 723 krb5_principal *princ) 724 { 725 krb5_boolean resolve = krb5_config_get_bool(context, 726 NULL, 727 "libdefaults", 728 "v4_instance_resolve", 729 NULL); 730 731 return krb5_425_conv_principal_ext(context, name, instance, realm, 732 NULL, resolve, princ); 733 } 734 735 736 static int 737 check_list(const krb5_config_binding *l, const char *name, const char **out) 738 { 739 while(l){ 740 if (l->type != krb5_config_string) 741 continue; 742 if(strcmp(name, l->u.string) == 0) { 743 *out = l->name; 744 return 1; 745 } 746 l = l->next; 747 } 748 return 0; 749 } 750 751 static int 752 name_convert(krb5_context context, const char *name, const char *realm, 753 const char **out) 754 { 755 const krb5_config_binding *l; 756 l = krb5_config_get_list (context, 757 NULL, 758 "realms", 759 realm, 760 "v4_name_convert", 761 "host", 762 NULL); 763 if(l && check_list(l, name, out)) 764 return KRB5_NT_SRV_HST; 765 l = krb5_config_get_list (context, 766 NULL, 767 "libdefaults", 768 "v4_name_convert", 769 "host", 770 NULL); 771 if(l && check_list(l, name, out)) 772 return KRB5_NT_SRV_HST; 773 l = krb5_config_get_list (context, 774 NULL, 775 "realms", 776 realm, 777 "v4_name_convert", 778 "plain", 779 NULL); 780 if(l && check_list(l, name, out)) 781 return KRB5_NT_UNKNOWN; 782 l = krb5_config_get_list (context, 783 NULL, 784 "libdefaults", 785 "v4_name_convert", 786 "host", 787 NULL); 788 if(l && check_list(l, name, out)) 789 return KRB5_NT_UNKNOWN; 790 791 /* didn't find it in config file, try built-in list */ 792 { 793 struct v4_name_convert *q; 794 for(q = default_v4_name_convert; q->from; q++) { 795 if(strcmp(name, q->to) == 0) { 796 *out = q->from; 797 return KRB5_NT_SRV_HST; 798 } 799 } 800 } 801 return -1; 802 } 803 804 krb5_error_code 805 krb5_524_conv_principal(krb5_context context, 806 const krb5_principal principal, 807 char *name, 808 char *instance, 809 char *realm) 810 { 811 const char *n, *i, *r; 812 char tmpinst[40]; 813 int type = princ_type(principal); 814 815 r = principal->realm; 816 817 switch(principal->name.name_string.len){ 818 case 1: 819 n = principal->name.name_string.val[0]; 820 i = ""; 821 break; 822 case 2: 823 n = principal->name.name_string.val[0]; 824 i = principal->name.name_string.val[1]; 825 break; 826 default: 827 return KRB5_PARSE_MALFORMED; 828 } 829 830 { 831 const char *tmp; 832 int t = name_convert(context, n, r, &tmp); 833 if(t >= 0) { 834 type = t; 835 n = tmp; 836 } 837 } 838 839 if(type == KRB5_NT_SRV_HST){ 840 char *p; 841 842 strlcpy (tmpinst, i, sizeof(tmpinst)); 843 p = strchr(tmpinst, '.'); 844 if(p) 845 *p = 0; 846 i = tmpinst; 847 } 848 849 if(strlen(r) >= 40) 850 return KRB5_PARSE_MALFORMED; 851 if(strlen(n) >= 40) 852 return KRB5_PARSE_MALFORMED; 853 if(strlen(i) >= 40) 854 return KRB5_PARSE_MALFORMED; 855 strcpy(realm, r); 856 strcpy(name, n); 857 strcpy(instance, i); 858 return 0; 859 } 860 861 /* 862 * Create a principal in `ret_princ' for the service `sname' running 863 * on host `hostname'. */ 864 865 krb5_error_code 866 krb5_sname_to_principal (krb5_context context, 867 const char *hostname, 868 const char *sname, 869 int32_t type, 870 krb5_principal *ret_princ) 871 { 872 krb5_error_code ret; 873 char localhost[128]; 874 char **realms, *host = NULL; 875 876 if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) 877 return KRB5_SNAME_UNSUPP_NAMETYPE; 878 if(hostname == NULL) { 879 gethostname(localhost, sizeof(localhost)); 880 hostname = localhost; 881 } 882 if(sname == NULL) 883 sname = "host"; 884 if(type == KRB5_NT_SRV_HST) { 885 ret = krb5_expand_hostname_realms (context, hostname, 886 &host, &realms); 887 if (ret) 888 return ret; 889 strlwr(host); 890 hostname = host; 891 } else { 892 ret = krb5_get_host_realm(context, hostname, &realms); 893 if(ret) 894 return ret; 895 } 896 897 ret = krb5_make_principal(context, ret_princ, realms[0], sname, 898 hostname, NULL); 899 if(host) 900 free(host); 901 krb5_free_host_realm(context, realms); 902 return ret; 903 } 904