2
* Copyright (c) 1997-2007 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. 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.
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
35
* @page page_principal The principal handing functions.
37
* A Kerberos principal is a email address looking string that
38
* contains to parts separeted by a @. The later part is the kerbero
39
* realm the principal belongs to and the former is a list of 0 or
40
* more components. For example
43
host/hummel.it.su.se@SU.SE
47
* See the library functions here: @ref krb5_principal
50
#include "krb5_locl.h"
51
#ifdef HAVE_RES_SEARCH
54
#ifdef HAVE_ARPA_NAMESER_H
55
#include <arpa/nameser.h>
62
#define princ_num_comp(P) ((P)->name.name_string.len)
63
#define princ_type(P) ((P)->name.name_type)
64
#define princ_comp(P) ((P)->name.name_string.val)
65
#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
66
#define princ_realm(P) ((P)->realm)
69
* Frees a Kerberos principal allocated by the library with
70
* krb5_parse_name(), krb5_make_principal() or any other related
71
* principal functions.
73
* @param context A Kerberos context.
74
* @param p a principal to free.
76
* @return An krb5 error code, see krb5_get_error_message().
78
* @ingroup krb5_principal
83
void KRB5_LIB_FUNCTION
84
krb5_free_principal(krb5_context context,
93
void KRB5_LIB_FUNCTION
94
krb5_principal_set_type(krb5_context context,
95
krb5_principal principal,
98
princ_type(principal) = type;
101
int KRB5_LIB_FUNCTION
102
krb5_principal_get_type(krb5_context context,
103
krb5_const_principal principal)
105
return princ_type(principal);
108
const char* KRB5_LIB_FUNCTION
109
krb5_principal_get_realm(krb5_context context,
110
krb5_const_principal principal)
112
return princ_realm(principal);
115
const char* KRB5_LIB_FUNCTION
116
krb5_principal_get_comp_string(krb5_context context,
117
krb5_const_principal principal,
118
unsigned int component)
120
if(component >= princ_num_comp(principal))
122
return princ_ncomp(principal, component);
126
* Get number of component is principal.
128
* @param context Kerberos 5 context
129
* @param principal principal to query
130
* @return number of components in string
134
unsigned int KRB5_LIB_FUNCTION
135
krb5_principal_get_num_comp(krb5_context context,
136
krb5_const_principal principal)
138
return princ_num_comp(principal);
141
krb5_error_code KRB5_LIB_FUNCTION
142
krb5_parse_name_flags(krb5_context context,
145
krb5_principal *principal)
148
heim_general_string *comp;
149
heim_general_string realm = NULL;
161
int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
165
#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM)
167
if ((flags & RFLAGS) == RFLAGS) {
168
krb5_set_error_message(context, KRB5_ERR_NO_SERVICE,
169
N_("Can't require both realm and "
170
"no realm at the same time", ""));
171
return KRB5_ERR_NO_SERVICE;
175
/* count number of component,
176
* enterprise names only have one component
180
for(p = name; *p; p++){
183
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
184
N_("trailing \\ in principal name", ""));
185
return KRB5_PARSE_MALFORMED;
194
comp = calloc(ncomp, sizeof(*comp));
196
krb5_set_error_message(context, ENOMEM,
197
N_("malloc: out of memory", ""));
202
p = start = q = s = strdup(name);
205
krb5_set_error_message(context, ENOMEM,
206
N_("malloc: out of memory", ""));
222
ret = KRB5_PARSE_MALFORMED;
223
krb5_set_error_message(context, ret,
224
N_("trailing \\ in principal name", ""));
227
}else if(enterprise && first_at) {
230
}else if((c == '/' && !enterprise) || c == '@'){
232
ret = KRB5_PARSE_MALFORMED;
233
krb5_set_error_message(context, ret,
234
N_("part after realm in principal name", ""));
237
comp[n] = malloc(q - start + 1);
238
if (comp[n] == NULL) {
240
krb5_set_error_message(context, ret,
241
N_("malloc: out of memory", ""));
244
memcpy(comp[n], start, q - start);
245
comp[n][q - start] = 0;
253
if(got_realm && (c == '/' || c == '\0')) {
254
ret = KRB5_PARSE_MALFORMED;
255
krb5_set_error_message(context, ret,
256
N_("part after realm in principal name", ""));
262
if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
263
ret = KRB5_PARSE_MALFORMED;
264
krb5_set_error_message(context, ret,
265
N_("realm found in 'short' principal "
266
"expected to be without one", ""));
269
realm = malloc(q - start + 1);
272
krb5_set_error_message(context, ret,
273
N_("malloc: out of memory", ""));
276
memcpy(realm, start, q - start);
277
realm[q - start] = 0;
279
if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) {
280
ret = KRB5_PARSE_MALFORMED;
281
krb5_set_error_message(context, ret,
282
N_("realm NOT found in principal "
283
"expected to be with one", ""));
285
} else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
288
ret = krb5_get_default_realm (context, &realm);
293
comp[n] = malloc(q - start + 1);
294
if (comp[n] == NULL) {
296
krb5_set_error_message(context, ret,
297
N_("malloc: out of memory", ""));
300
memcpy(comp[n], start, q - start);
301
comp[n][q - start] = 0;
304
*principal = malloc(sizeof(**principal));
305
if (*principal == NULL) {
307
krb5_set_error_message(context, ret,
308
N_("malloc: out of memory", ""));
312
(*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL;
314
(*principal)->name.name_type = KRB5_NT_PRINCIPAL;
315
(*principal)->name.name_string.val = comp;
316
princ_num_comp(*principal) = n;
317
(*principal)->realm = realm;
330
krb5_error_code KRB5_LIB_FUNCTION
331
krb5_parse_name(krb5_context context,
333
krb5_principal *principal)
335
return krb5_parse_name_flags(context, name, 0, principal);
338
static const char quotable_chars[] = " \n\t\b\\/@";
339
static const char replace_chars[] = " ntb\\/@";
340
static const char nq_chars[] = " \\/@";
342
#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
345
quote_string(const char *s, char *out, size_t idx, size_t len, int display)
348
for(p = s; *p && idx < len; p++){
349
q = strchr(quotable_chars, *p);
351
add_char(out, idx, len, replace_chars[q - quotable_chars]);
353
add_char(out, idx, len, '\\');
354
add_char(out, idx, len, replace_chars[q - quotable_chars]);
356
add_char(out, idx, len, *p);
364
static krb5_error_code
365
unparse_name_fixed(krb5_context context,
366
krb5_const_principal principal,
373
int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
374
int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
375
int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
377
if (!no_realm && princ_realm(principal) == NULL) {
378
krb5_set_error_message(context, ERANGE,
379
N_("Realm missing from principal, "
380
"can't unparse", ""));
384
for(i = 0; i < princ_num_comp(principal); i++){
386
add_char(name, idx, len, '/');
387
idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
389
krb5_set_error_message(context, ERANGE,
390
N_("Out of space printing principal", ""));
394
/* add realm if different from default realm */
395
if(short_form && !no_realm) {
398
ret = krb5_get_default_realm(context, &r);
401
if(strcmp(princ_realm(principal), r) != 0)
405
if(!short_form && !no_realm) {
406
add_char(name, idx, len, '@');
407
idx = quote_string(princ_realm(principal), name, idx, len, display);
409
krb5_set_error_message(context, ERANGE,
410
N_("Out of space printing "
411
"realm of principal", ""));
418
krb5_error_code KRB5_LIB_FUNCTION
419
krb5_unparse_name_fixed(krb5_context context,
420
krb5_const_principal principal,
424
return unparse_name_fixed(context, principal, name, len, 0);
427
krb5_error_code KRB5_LIB_FUNCTION
428
krb5_unparse_name_fixed_short(krb5_context context,
429
krb5_const_principal principal,
433
return unparse_name_fixed(context, principal, name, len,
434
KRB5_PRINCIPAL_UNPARSE_SHORT);
437
krb5_error_code KRB5_LIB_FUNCTION
438
krb5_unparse_name_fixed_flags(krb5_context context,
439
krb5_const_principal principal,
444
return unparse_name_fixed(context, principal, name, len, flags);
447
static krb5_error_code
448
unparse_name(krb5_context context,
449
krb5_const_principal principal,
453
size_t len = 0, plen;
457
if (princ_realm(principal)) {
458
plen = strlen(princ_realm(principal));
460
if(strcspn(princ_realm(principal), quotable_chars) == plen)
466
for(i = 0; i < princ_num_comp(principal); i++){
467
plen = strlen(princ_ncomp(principal, i));
468
if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen)
477
krb5_set_error_message(context, ENOMEM,
478
N_("malloc: out of memory", ""));
481
ret = unparse_name_fixed(context, principal, *name, len, flags);
489
krb5_error_code KRB5_LIB_FUNCTION
490
krb5_unparse_name(krb5_context context,
491
krb5_const_principal principal,
494
return unparse_name(context, principal, name, 0);
497
krb5_error_code KRB5_LIB_FUNCTION
498
krb5_unparse_name_flags(krb5_context context,
499
krb5_const_principal principal,
503
return unparse_name(context, principal, name, flags);
506
krb5_error_code KRB5_LIB_FUNCTION
507
krb5_unparse_name_short(krb5_context context,
508
krb5_const_principal principal,
511
return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT);
514
#if 0 /* not implemented */
516
krb5_error_code KRB5_LIB_FUNCTION
517
krb5_unparse_name_ext(krb5_context context,
518
krb5_const_principal principal,
522
krb5_abortx(context, "unimplemented krb5_unparse_name_ext called");
527
krb5_realm * KRB5_LIB_FUNCTION
528
krb5_princ_realm(krb5_context context,
529
krb5_principal principal)
531
return &princ_realm(principal);
535
void KRB5_LIB_FUNCTION
536
krb5_princ_set_realm(krb5_context context,
537
krb5_principal principal,
540
princ_realm(principal) = *realm;
543
krb5_error_code KRB5_LIB_FUNCTION
544
krb5_principal_set_realm(krb5_context context,
545
krb5_principal principal,
546
krb5_const_realm realm)
548
if (princ_realm(principal))
549
free(princ_realm(principal));
551
princ_realm(principal) = strdup(realm);
552
if (princ_realm(principal) == NULL) {
553
krb5_set_error_message(context, ENOMEM,
554
N_("malloc: out of memory", ""));
561
krb5_error_code KRB5_LIB_FUNCTION
562
krb5_build_principal(krb5_context context,
563
krb5_principal *principal,
565
krb5_const_realm realm,
571
ret = krb5_build_principal_va(context, principal, rlen, realm, ap);
576
static krb5_error_code
577
append_component(krb5_context context, krb5_principal p,
581
heim_general_string *tmp;
582
size_t len = princ_num_comp(p);
584
tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp));
586
krb5_set_error_message(context, ENOMEM,
587
N_("malloc: out of memory", ""));
591
princ_ncomp(p, len) = malloc(comp_len + 1);
592
if (princ_ncomp(p, len) == NULL) {
593
krb5_set_error_message(context, ENOMEM,
594
N_("malloc: out of memory", ""));
597
memcpy (princ_ncomp(p, len), comp, comp_len);
598
princ_ncomp(p, len)[comp_len] = '\0';
604
va_ext_princ(krb5_context context, krb5_principal p, va_list ap)
609
len = va_arg(ap, int);
612
s = va_arg(ap, const char*);
613
append_component(context, p, s, len);
618
va_princ(krb5_context context, krb5_principal p, va_list ap)
622
s = va_arg(ap, const char*);
625
append_component(context, p, s, strlen(s));
630
static krb5_error_code
631
build_principal(krb5_context context,
632
krb5_principal *principal,
634
krb5_const_realm realm,
635
void (*func)(krb5_context, krb5_principal, va_list),
640
p = calloc(1, sizeof(*p));
642
krb5_set_error_message(context, ENOMEM,
643
N_("malloc: out of memory", ""));
646
princ_type(p) = KRB5_NT_PRINCIPAL;
648
princ_realm(p) = strdup(realm);
649
if(p->realm == NULL){
651
krb5_set_error_message(context, ENOMEM,
652
N_("malloc: out of memory", ""));
656
(*func)(context, p, ap);
661
krb5_error_code KRB5_LIB_FUNCTION
662
krb5_make_principal(krb5_context context,
663
krb5_principal *principal,
664
krb5_const_realm realm,
671
ret = krb5_get_default_realm(context, &r);
677
ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
684
krb5_error_code KRB5_LIB_FUNCTION
685
krb5_build_principal_va(krb5_context context,
686
krb5_principal *principal,
688
krb5_const_realm realm,
691
return build_principal(context, principal, rlen, realm, va_princ, ap);
694
krb5_error_code KRB5_LIB_FUNCTION
695
krb5_build_principal_va_ext(krb5_context context,
696
krb5_principal *principal,
698
krb5_const_realm realm,
701
return build_principal(context, principal, rlen, realm, va_ext_princ, ap);
705
krb5_error_code KRB5_LIB_FUNCTION
706
krb5_build_principal_ext(krb5_context context,
707
krb5_principal *principal,
709
krb5_const_realm realm,
715
ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap);
721
krb5_error_code KRB5_LIB_FUNCTION
722
krb5_copy_principal(krb5_context context,
723
krb5_const_principal inprinc,
724
krb5_principal *outprinc)
726
krb5_principal p = malloc(sizeof(*p));
728
krb5_set_error_message(context, ENOMEM,
729
N_("malloc: out of memory", ""));
732
if(copy_Principal(inprinc, p)) {
734
krb5_set_error_message(context, ENOMEM,
735
N_("malloc: out of memory", ""));
743
* return TRUE iff princ1 == princ2 (without considering the realm)
746
krb5_boolean KRB5_LIB_FUNCTION
747
krb5_principal_compare_any_realm(krb5_context context,
748
krb5_const_principal princ1,
749
krb5_const_principal princ2)
752
if(princ_num_comp(princ1) != princ_num_comp(princ2))
754
for(i = 0; i < princ_num_comp(princ1); i++){
755
if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0)
761
krb5_boolean KRB5_LIB_FUNCTION
762
_krb5_principal_compare_PrincipalName(krb5_context context,
763
krb5_const_principal princ1,
764
PrincipalName *princ2)
767
if (princ_num_comp(princ1) != princ2->name_string.len)
769
for(i = 0; i < princ_num_comp(princ1); i++){
770
if(strcmp(princ_ncomp(princ1, i), princ2->name_string.val[i]) != 0)
778
* return TRUE iff princ1 == princ2
781
krb5_boolean KRB5_LIB_FUNCTION
782
krb5_principal_compare(krb5_context context,
783
krb5_const_principal princ1,
784
krb5_const_principal princ2)
786
if(!krb5_realm_compare(context, princ1, princ2))
788
return krb5_principal_compare_any_realm(context, princ1, princ2);
792
* return TRUE iff realm(princ1) == realm(princ2)
795
krb5_boolean KRB5_LIB_FUNCTION
796
krb5_realm_compare(krb5_context context,
797
krb5_const_principal princ1,
798
krb5_const_principal princ2)
800
return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
804
* return TRUE iff princ matches pattern
807
krb5_boolean KRB5_LIB_FUNCTION
808
krb5_principal_match(krb5_context context,
809
krb5_const_principal princ,
810
krb5_const_principal pattern)
813
if(princ_num_comp(princ) != princ_num_comp(pattern))
815
if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0)
817
for(i = 0; i < princ_num_comp(princ); i++){
818
if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0)
825
static struct v4_name_convert {
828
} default_v4_name_convert[] = {
830
{ "hprop", "hprop" },
839
* return the converted instance name of `name' in `realm'.
840
* look in the configuration file and then in the default set above.
841
* return NULL if no conversion is appropriate.
845
get_name_conversion(krb5_context context, const char *realm, const char *name)
847
struct v4_name_convert *q;
850
p = krb5_config_get_string(context, NULL, "realms", realm,
851
"v4_name_convert", "host", name, NULL);
853
p = krb5_config_get_string(context, NULL, "libdefaults",
854
"v4_name_convert", "host", name, NULL);
858
/* XXX should be possible to override default list */
859
p = krb5_config_get_string(context, NULL,
868
p = krb5_config_get_string(context, NULL,
876
for(q = default_v4_name_convert; q->from; q++)
877
if(strcmp(q->from, name) == 0)
883
* convert the v4 principal `name.instance@realm' to a v5 principal in `princ'.
884
* if `resolve', use DNS.
885
* if `func', use that function for validating the conversion
888
krb5_error_code KRB5_LIB_FUNCTION
889
krb5_425_conv_principal_ext2(krb5_context context,
891
const char *instance,
893
krb5_boolean (*func)(krb5_context,
894
void *, krb5_principal),
896
krb5_boolean resolve,
897
krb5_principal *princ)
902
char host[MAXHOSTNAMELEN];
903
char local_hostname[MAXHOSTNAMELEN];
905
/* do the following: if the name is found in the
906
`v4_name_convert:host' part, is assumed to be a `host' type
907
principal, and the instance is looked up in the
908
`v4_instance_convert' part. if not found there the name is
909
(optionally) looked up as a hostname, and if that doesn't yield
910
anything, the `default_domain' is appended to the instance
915
if(instance[0] == 0){
919
p = get_name_conversion(context, realm, name);
923
p = krb5_config_get_string(context, NULL, "realms", realm,
924
"v4_instance_convert", instance, NULL);
927
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
928
if(func == NULL || (*func)(context, funcctx, pr)){
932
krb5_free_principal(context, pr);
934
krb5_clear_error_message (context);
935
return HEIM_ERR_V4_PRINC_NO_CONV;
938
krb5_boolean passed = FALSE;
943
r = dns_lookup(instance, "aaaa");
945
if (r->head && r->head->type == T_AAAA) {
946
inst = strdup(r->head->domain);
951
r = dns_lookup(instance, "a");
953
if(r->head && r->head->type == T_A) {
954
inst = strdup(r->head->domain);
961
struct addrinfo hints, *ai;
963
memset (&hints, 0, sizeof(hints));
964
hints.ai_flags = AI_CANONNAME;
965
ret = getaddrinfo(instance, NULL, &hints, &ai);
967
const struct addrinfo *a;
968
for (a = ai; a != NULL; a = a->ai_next) {
969
if (a->ai_canonname != NULL) {
970
inst = strdup (a->ai_canonname);
980
krb5_set_error_message(context, ENOMEM,
981
N_("malloc: out of memory", ""));
985
ret = krb5_make_principal(context, &pr, realm, name, inst,
989
if(func == NULL || (*func)(context, funcctx, pr)){
993
krb5_free_principal(context, pr);
998
snprintf(host, sizeof(host), "%s.%s", instance, realm);
1000
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
1001
if((*func)(context, funcctx, pr)){
1005
krb5_free_principal(context, pr);
1009
* if the instance is the first component of the local hostname,
1010
* the converted host should be the long hostname.
1014
gethostname (local_hostname, sizeof(local_hostname)) == 0 &&
1015
strncmp(instance, local_hostname, strlen(instance)) == 0 &&
1016
local_hostname[strlen(instance)] == '.') {
1017
strlcpy(host, local_hostname, sizeof(host));
1022
char **domains, **d;
1023
domains = krb5_config_get_strings(context, NULL, "realms", realm,
1024
"v4_domains", NULL);
1025
for(d = domains; d && *d; d++){
1026
snprintf(host, sizeof(host), "%s.%s", instance, *d);
1027
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
1028
if(func == NULL || (*func)(context, funcctx, pr)){
1030
krb5_config_free_strings(domains);
1033
krb5_free_principal(context, pr);
1035
krb5_config_free_strings(domains);
1039
p = krb5_config_get_string(context, NULL, "realms", realm,
1040
"default_domain", NULL);
1042
/* this should be an error, just faking a name is not good */
1043
krb5_clear_error_message (context);
1044
return HEIM_ERR_V4_PRINC_NO_CONV;
1049
snprintf(host, sizeof(host), "%s.%s", instance, p);
1051
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
1052
if(func == NULL || (*func)(context, funcctx, pr)){
1056
krb5_free_principal(context, pr);
1057
krb5_clear_error_message (context);
1058
return HEIM_ERR_V4_PRINC_NO_CONV;
1060
p = krb5_config_get_string(context, NULL,
1068
p = krb5_config_get_string(context, NULL,
1077
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
1078
if(func == NULL || (*func)(context, funcctx, pr)){
1082
krb5_free_principal(context, pr);
1083
krb5_clear_error_message (context);
1084
return HEIM_ERR_V4_PRINC_NO_CONV;
1088
convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal)
1090
krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx;
1091
return (*func)(conxtext, principal);
1094
krb5_error_code KRB5_LIB_FUNCTION
1095
krb5_425_conv_principal_ext(krb5_context context,
1097
const char *instance,
1099
krb5_boolean (*func)(krb5_context, krb5_principal),
1100
krb5_boolean resolve,
1101
krb5_principal *principal)
1103
return krb5_425_conv_principal_ext2(context,
1107
func ? convert_func : NULL,
1115
krb5_error_code KRB5_LIB_FUNCTION
1116
krb5_425_conv_principal(krb5_context context,
1118
const char *instance,
1120
krb5_principal *princ)
1122
krb5_boolean resolve = krb5_config_get_bool(context,
1125
"v4_instance_resolve",
1128
return krb5_425_conv_principal_ext(context, name, instance, realm,
1129
NULL, resolve, princ);
1134
check_list(const krb5_config_binding *l, const char *name, const char **out)
1137
if (l->type != krb5_config_string)
1139
if(strcmp(name, l->u.string) == 0) {
1149
name_convert(krb5_context context, const char *name, const char *realm,
1152
const krb5_config_binding *l;
1153
l = krb5_config_get_list (context,
1160
if(l && check_list(l, name, out))
1161
return KRB5_NT_SRV_HST;
1162
l = krb5_config_get_list (context,
1168
if(l && check_list(l, name, out))
1169
return KRB5_NT_SRV_HST;
1170
l = krb5_config_get_list (context,
1177
if(l && check_list(l, name, out))
1178
return KRB5_NT_UNKNOWN;
1179
l = krb5_config_get_list (context,
1185
if(l && check_list(l, name, out))
1186
return KRB5_NT_UNKNOWN;
1188
/* didn't find it in config file, try built-in list */
1190
struct v4_name_convert *q;
1191
for(q = default_v4_name_convert; q->from; q++) {
1192
if(strcmp(name, q->to) == 0) {
1194
return KRB5_NT_SRV_HST;
1202
* convert the v5 principal in `principal' into a v4 corresponding one
1203
* in `name, instance, realm'
1204
* this is limited interface since there's no length given for these
1205
* three parameters. They have to be 40 bytes each (ANAME_SZ).
1208
krb5_error_code KRB5_LIB_FUNCTION
1209
krb5_524_conv_principal(krb5_context context,
1210
const krb5_principal principal,
1215
const char *n, *i, *r;
1217
int type = princ_type(principal);
1218
const int aname_sz = 40;
1220
r = principal->realm;
1222
switch(principal->name.name_string.len){
1224
n = principal->name.name_string.val[0];
1228
n = principal->name.name_string.val[0];
1229
i = principal->name.name_string.val[1];
1232
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1233
N_("cannot convert a %d "
1234
"component principal", ""),
1235
principal->name.name_string.len);
1236
return KRB5_PARSE_MALFORMED;
1241
int t = name_convert(context, n, r, &tmp);
1248
if(type == KRB5_NT_SRV_HST){
1251
strlcpy (tmpinst, i, sizeof(tmpinst));
1252
p = strchr(tmpinst, '.');
1258
if (strlcpy (name, n, aname_sz) >= aname_sz) {
1259
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1260
N_("too long name component to convert", ""));
1261
return KRB5_PARSE_MALFORMED;
1263
if (strlcpy (instance, i, aname_sz) >= aname_sz) {
1264
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1265
N_("too long instance component to convert", ""));
1266
return KRB5_PARSE_MALFORMED;
1268
if (strlcpy (realm, r, aname_sz) >= aname_sz) {
1269
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1270
N_("too long realm component to convert", ""));
1271
return KRB5_PARSE_MALFORMED;
1277
* Create a principal for the service running on hostname. If
1278
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
1279
* some other service), this is potentially insecure.
1281
* @param context A Kerberos context.
1282
* @param hostname hostname to use
1283
* @param sname Service name to use
1284
* @param type name type of pricipal, use KRB5_NT_SRV_HST or KRB5_NT_UNKNOWN.
1285
* @param ret_princ return principal, free with krb5_free_principal().
1287
* @return An krb5 error code, see krb5_get_error_message().
1289
* @ingroup krb5_principal
1292
krb5_error_code KRB5_LIB_FUNCTION
1293
krb5_sname_to_principal (krb5_context context,
1294
const char *hostname,
1297
krb5_principal *ret_princ)
1299
krb5_error_code ret;
1300
char localhost[MAXHOSTNAMELEN];
1301
char **realms, *host = NULL;
1303
if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) {
1304
krb5_set_error_message(context, KRB5_SNAME_UNSUPP_NAMETYPE,
1305
N_("unsupported name type %d", ""),
1307
return KRB5_SNAME_UNSUPP_NAMETYPE;
1309
if(hostname == NULL) {
1310
ret = gethostname(localhost, sizeof(localhost) - 1);
1313
krb5_set_error_message(context, ret,
1314
N_("Failed to get local hostname", ""));
1317
localhost[sizeof(localhost) - 1] = '\0';
1318
hostname = localhost;
1322
if(type == KRB5_NT_SRV_HST) {
1323
ret = krb5_expand_hostname_realms (context, hostname,
1330
ret = krb5_get_host_realm(context, hostname, &realms);
1335
ret = krb5_make_principal(context, ret_princ, realms[0], sname,
1339
krb5_free_host_realm(context, realms);
1343
static const struct {
1347
{ "UNKNOWN", KRB5_NT_UNKNOWN },
1348
{ "PRINCIPAL", KRB5_NT_PRINCIPAL },
1349
{ "SRV_INST", KRB5_NT_SRV_INST },
1350
{ "SRV_HST", KRB5_NT_SRV_HST },
1351
{ "SRV_XHST", KRB5_NT_SRV_XHST },
1352
{ "UID", KRB5_NT_UID },
1353
{ "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
1354
{ "SMTP_NAME", KRB5_NT_SMTP_NAME },
1355
{ "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
1356
{ "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
1357
{ "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
1358
{ "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
1363
krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
1367
for(i = 0; nametypes[i].type; i++) {
1368
if (strcasecmp(nametypes[i].type, str) == 0) {
1369
*nametype = nametypes[i].value;
1373
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1374
N_("Failed to find name type %s", ""), str);
1375
return KRB5_PARSE_MALFORMED;