2 * Copyright (c) 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include "krb5_locl.h"
43 /* Public principal handling functions */
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)
52 krb5_free_principal(krb5_context context
,
62 krb5_parse_name(krb5_context context
,
64 krb5_principal
*principal
)
80 /* count number of component */
82 for(p
= (char*)name
; *p
; p
++){
85 return KRB5_PARSE_MALFORMED
;
90 comp
= calloc(ncomp
, sizeof(*comp
));
93 start
= q
= p
= s
= strdup(name
);
106 }else if(c
== '/' || c
== '@'){
114 return KRB5_PARSE_MALFORMED
;
116 comp
[n
] = malloc(q
- start
+ 1);
117 strncpy(comp
[n
], start
, q
- start
);
118 comp
[n
][q
- start
] = 0;
126 if(got_realm
&& (c
== ':' || c
== '/' || c
== '\0'))
131 realm
= malloc(q
- start
+ 1);
132 strncpy(realm
, start
, q
- start
);
133 realm
[q
- start
] = 0;
135 krb5_get_default_realm (context
, &realm
);
137 comp
[n
] = malloc(q
- start
+ 1);
138 strncpy(comp
[n
], start
, q
- start
);
139 comp
[n
][q
- start
] = 0;
142 *principal
= malloc(sizeof(**principal
));
143 (*principal
)->name
.name_type
= KRB5_NT_PRINCIPAL
;
144 (*principal
)->name
.name_string
.val
= comp
;
145 princ_num_comp(*principal
) = n
;
146 (*principal
)->realm
= realm
;
152 quote_string(char *s
, char **out
)
177 tmp
= realloc(tmp
, len
+ 2);
183 tmp
= realloc(tmp
, len
+ 1);
188 tmp
= realloc(tmp
, len
+ 1);
196 krb5_unparse_name(krb5_context context
,
197 krb5_principal principal
,
203 int ncomp
= princ_num_comp(principal
);
205 for (i
= 0; i
< ncomp
; i
++){
207 s
= realloc(s
, len
+ 2);
211 len
= quote_string(princ_ncomp(principal
, i
), &s
);
213 s
= realloc(s
, len
+ 2);
216 len
= quote_string(princ_realm(principal
), &s
);
222 #if 0 /* not implemented */
225 krb5_unparse_name_ext(krb5_context context
,
226 krb5_const_principal principal
,
230 fprintf(stderr
, "krb5_unparse_name_ext: not implemented\n");
237 krb5_princ_realm(krb5_context context
,
238 krb5_principal principal
)
240 return &princ_realm(principal
);
245 krb5_princ_set_realm(krb5_context context
,
246 krb5_principal principal
,
249 princ_realm(principal
) = *realm
;
254 krb5_build_principal(krb5_context context
,
255 krb5_principal
*principal
,
257 krb5_const_realm realm
,
263 ret
= krb5_build_principal_va(context
, principal
, rlen
, realm
, ap
);
268 static krb5_error_code
269 append_component(krb5_context context
, krb5_principal p
,
274 size_t len
= princ_num_comp(p
);
275 tmp
= realloc(princ_comp(p
), (len
+ 1) * sizeof(*tmp
));
279 princ_ncomp(p
, len
) = malloc(comp_len
+ 1);
280 memcpy (princ_ncomp(p
, len
), comp
, comp_len
);
281 princ_ncomp(p
, len
)[comp_len
] = '\0';
287 va_ext_princ(krb5_context context
, krb5_principal p
, va_list ap
)
292 len
= va_arg(ap
, int);
295 s
= va_arg(ap
, char*);
296 append_component(context
, p
, s
, len
);
301 va_princ(krb5_context context
, krb5_principal p
, va_list ap
)
305 s
= va_arg(ap
, char*);
308 append_component(context
, p
, s
, strlen(s
));
313 static krb5_error_code
314 build_principal(krb5_context context
,
315 krb5_principal
*principal
,
317 krb5_const_realm realm
,
318 void (*func
)(krb5_context
, krb5_principal
, va_list),
323 p
= calloc(1, sizeof(*p
));
326 princ_type(p
) = KRB5_NT_PRINCIPAL
;
328 princ_realm(p
) = strdup(realm
);
329 if(p
->realm
== NULL
){
334 (*func
)(context
, p
, ap
);
340 krb5_make_principal(krb5_context context
,
341 krb5_principal
*principal
,
342 krb5_const_realm realm
,
349 ret
= krb5_get_default_realm(context
, &r
);
355 ret
= krb5_build_principal_va(context
, principal
, strlen(realm
), realm
, ap
);
363 krb5_build_principal_va(krb5_context context
,
364 krb5_principal
*principal
,
366 krb5_const_realm realm
,
369 return build_principal(context
, principal
, rlen
, realm
, va_princ
, ap
);
373 krb5_build_principal_va_ext(krb5_context context
,
374 krb5_principal
*principal
,
376 krb5_const_realm realm
,
379 return build_principal(context
, principal
, rlen
, realm
, va_ext_princ
, ap
);
384 krb5_build_principal_ext(krb5_context context
,
385 krb5_principal
*principal
,
387 krb5_const_realm realm
,
393 ret
= krb5_build_principal_va_ext(context
, principal
, rlen
, realm
, ap
);
400 krb5_copy_principal(krb5_context context
,
401 krb5_const_principal inprinc
,
402 krb5_principal
*outprinc
)
404 krb5_principal p
= malloc(sizeof(*p
));
407 copy_Principal(inprinc
, p
);
414 krb5_principal_compare_any_realm(krb5_context context
,
415 krb5_const_principal princ1
,
416 krb5_const_principal princ2
)
419 if(princ_num_comp(princ1
) != princ_num_comp(princ2
))
421 for(i
= 0; i
< princ_num_comp(princ1
); i
++){
422 if(strcmp(princ_ncomp(princ1
, i
), princ_ncomp(princ2
, i
)) != 0)
429 krb5_principal_compare(krb5_context context
,
430 krb5_const_principal princ1
,
431 krb5_const_principal princ2
)
433 if(!krb5_realm_compare(context
, princ1
, princ2
))
435 return krb5_principal_compare_any_realm(context
, princ1
, princ2
);
440 krb5_realm_compare(krb5_context context
,
441 krb5_const_principal princ1
,
442 krb5_const_principal princ2
)
444 return strcmp(princ_realm(princ1
), princ_realm(princ2
)) == 0;
448 krb5_425_conv_principal_ext(krb5_context context
,
450 const char *instance
,
452 krb5_boolean (*func
)(krb5_context
, krb5_principal
),
453 krb5_boolean resolve
,
454 krb5_principal
*princ
)
461 /* do the following: if the name is found in the
462 `v4_name_convert:host' part, is is assumed to be a `host' type
463 principal, and the instance is looked up in the
464 `v4_instance_convert' part. if not found there the name is
465 (optionally) looked up as a hostname, and if that doesn't yield
466 anything, the `default_domain' is appended to the instance
471 if(instance
[0] == 0){
475 p
= krb5_config_get_string(context
->cf
, "realms", realm
,
476 "v4_name_convert", "host", name
, NULL
);
478 p
= krb5_config_get_string(context
->cf
, "libdefaults",
479 "v4_name_convert", "host", name
, NULL
);
483 p
= krb5_config_get_string(context
->cf
, "realms", realm
,
484 "v4_instance_convert", instance
, NULL
);
487 ret
= krb5_make_principal(context
, &pr
, realm
, name
, instance
, NULL
);
488 if(func
== NULL
|| (*func
)(context
, pr
)){
492 krb5_free_principal(context
, pr
);
494 return HEIM_ERR_V4_PRINC_NO_CONV
;
497 struct hostent
*hp
= gethostbyname(instance
);
499 instance
= hp
->h_name
;
500 ret
= krb5_make_principal(context
, &pr
,
501 realm
, name
, instance
, NULL
);
502 if(func
== NULL
|| (*func
)(context
, pr
)){
506 krb5_free_principal(context
, pr
);
511 domains
= krb5_config_get_strings(context
->cf
, "realms", realm
,
513 for(d
= domains
; d
&& *d
; d
++){
514 snprintf(host
, sizeof(host
), "%s.%s", instance
, *d
);
515 ret
= krb5_make_principal(context
, &pr
, realm
, name
, host
, NULL
);
516 if(func
== NULL
|| (*func
)(context
, pr
)){
518 krb5_config_free_strings(domains
);
521 krb5_free_principal(context
, pr
);
523 krb5_config_free_strings(domains
);
527 p
= krb5_config_get_string(context
->cf
, "realms", realm
,
528 "default_domain", NULL
);
530 /* should this be an error or should it silently
532 return HEIM_ERR_V4_PRINC_NO_CONV
;
535 snprintf(host
, sizeof(host
), "%s.%s", instance
, p
);
536 ret
= krb5_make_principal(context
, &pr
, realm
, name
, host
, NULL
);
537 if(func
== NULL
|| (*func
)(context
, pr
)){
541 krb5_free_principal(context
, pr
);
542 return HEIM_ERR_V4_PRINC_NO_CONV
;
544 p
= krb5_config_get_string(context
->cf
,
552 p
= krb5_config_get_string(context
->cf
,
561 ret
= krb5_make_principal(context
, &pr
, realm
, name
, instance
, NULL
);
562 if(func
== NULL
|| (*func
)(context
, pr
)){
566 krb5_free_principal(context
, pr
);
567 return HEIM_ERR_V4_PRINC_NO_CONV
;
571 krb5_425_conv_principal(krb5_context context
,
573 const char *instance
,
575 krb5_principal
*princ
)
577 krb5_boolean resolve
= krb5_config_get_bool(context
->cf
,
579 "v4_instance_resolve",
582 return krb5_425_conv_principal_ext(context
, name
, instance
, realm
,
583 NULL
, resolve
, princ
);
588 name_convert(krb5_context context
, const char *name
, const char *realm
,
591 const krb5_config_binding
*l
;
592 l
= krb5_config_get_list (context
->cf
,
599 l
= krb5_config_get_list (context
->cf
,
606 if (l
->type
!= krb5_config_string
)
608 if(strcmp(name
, l
->u
.string
) == 0)
616 krb5_524_conv_principal(krb5_context context
,
617 const krb5_principal principal
,
624 int type
= princ_type(principal
);
626 r
= principal
->realm
;
628 switch(principal
->name
.name_string
.len
){
630 n
= principal
->name
.name_string
.val
[0];
634 n
= principal
->name
.name_string
.val
[0];
635 i
= principal
->name
.name_string
.val
[1];
638 return KRB5_PARSE_MALFORMED
;
642 char *tmp
= name_convert(context
, n
, r
, "host");
644 type
= KRB5_NT_SRV_HST
;
647 tmp
= name_convert(context
, n
, r
, "plain");
649 type
= KRB5_NT_UNKNOWN
;
655 if(type
== KRB5_NT_SRV_HST
){
657 strncpy(tmpinst
, i
, sizeof(tmpinst
));
658 tmpinst
[sizeof(tmpinst
) - 1] = 0;
659 p
= strchr(tmpinst
, '.');
665 return KRB5_PARSE_MALFORMED
;
667 return KRB5_PARSE_MALFORMED
;
669 return KRB5_PARSE_MALFORMED
;
679 krb5_sname_to_principal (krb5_context context
,
680 const char *hostname
,
683 krb5_principal
*ret_princ
)
687 char **realms
, *host
= NULL
;
689 if(type
!= KRB5_NT_SRV_HST
&& type
!= KRB5_NT_UNKNOWN
)
690 return KRB5_SNAME_UNSUPP_NAMETYPE
;
691 if(hostname
== NULL
){
692 gethostname(localhost
, sizeof(localhost
));
693 hostname
= localhost
;
697 if(type
== KRB5_NT_SRV_HST
){
699 hp
= gethostbyname(hostname
);
701 hostname
= hp
->h_name
;
703 if(type
== KRB5_NT_SRV_HST
){
704 host
= strdup(hostname
);
711 ret
= krb5_get_host_realm(context
, hostname
, &realms
);
714 ret
= krb5_make_principal(context
, ret_princ
, realms
[0], sname
,
718 krb5_free_host_realm(context
, realms
);