2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
5 * lib/krb5/os/sn2princ.c
7 * Copyright 1991,2002 by the Massachusetts Institute of Technology.
10 * Export of this software from the United States of America may
11 * require a specific license from the United States Government.
12 * It is the responsibility of any person or organization contemplating
13 * export to obtain such a license before exporting.
15 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
16 * distribute this software and its documentation for any purpose and
17 * without fee is hereby granted, provided that the above copyright
18 * notice appear in all copies and that both that copyright notice and
19 * this permission notice appear in supporting documentation, and that
20 * the name of M.I.T. not be used in advertising or publicity pertaining
21 * to distribution of the software without specific, written prior
22 * permission. Furthermore if you modify this software you must label
23 * your software as modified software and not distribute it in such a
24 * fashion that it might be confused with the original M.I.T. software.
25 * M.I.T. makes no representations about the suitability of
26 * this software for any purpose. It is provided "as is" without express
27 * or implied warranty.
30 * Convert a hostname and service name to a principal in the "standard"
36 #include "fake-addrinfo.h"
38 #ifdef HAVE_SYS_PARAM_H
39 #include <sys/param.h>
44 #if !defined(DEFAULT_RDNS_LOOKUP)
45 /* Solaris Kerberos */
46 #define DEFAULT_RDNS_LOOKUP 0
51 * The following prototypes are needed because these are
52 * private interfaces that do not have prototypes in any .h
54 extern struct hostent
*res_getipnodebyname(const char *, int, int, int *);
55 extern struct hostent
*res_getipnodebyaddr(const void *, size_t, int, int *);
56 extern void res_freehostent(struct hostent
*);
59 maybe_use_reverse_dns (krb5_context context
, int defalt
)
65 code
= profile_get_string(context
->profile
, "libdefaults",
66 "rdns", 0, 0, &value
);
73 use_rdns
= _krb5_conf_boolean(value
);
74 profile_release_string(value
);
81 * Note, krb5_sname_to_principal() allocates memory for ret_princ. Be sure to
82 * use krb5_free_principal() on ret_princ to free it when done referencing it.
84 krb5_error_code KRB5_CALLCONV
85 krb5_sname_to_principal(krb5_context context
, const char *hostname
, const char *sname
, krb5_int32 type
, krb5_principal
*ret_princ
)
87 char **hrealms
, *realm
, *remote_host
;
88 krb5_error_code retval
;
90 char localname
[MAXHOSTNAMELEN
];
91 /* Solaris Kerberos */
92 KRB5_LOG0(KRB5_INFO
, "krb5_sname_to_principal() start");
93 #ifdef DEBUG_REFERRALS
94 printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname
,sname
,type
);
95 printf(" name types: 0=unknown, 3=srv_host\n");
97 if ((type
== KRB5_NT_UNKNOWN
) ||
98 (type
== KRB5_NT_SRV_HST
)) {
100 /* if hostname is NULL, use local hostname */
102 if (gethostname(localname
, MAXHOSTNAMELEN
)) {
103 /* Solaris Kerberos */
104 KRB5_LOG0(KRB5_ERR
, "krb5_sname_to_principal()"
105 " gethostname failed");
108 hostname
= localname
;
111 /* if sname is NULL, use "host" */
115 /* copy the hostname into non-volatile storage */
117 if (type
== KRB5_NT_SRV_HST
) {
118 /* Solaris Kerberos */
119 struct hostent
*hp
= NULL
;
120 struct hostent
*hp2
= NULL
;
124 /* Note that the old code would accept numeric addresses,
125 and if the gethostbyaddr step could convert them to
126 real hostnames, you could actually get reasonable
127 results. If the mapping failed, you'd get dotted
128 triples as realm names. *sigh*
130 The latter has been fixed in hst_realm.c, but we should
131 keep supporting numeric addresses if they do have
132 hostnames associated. */
135 * Solaris kerberos: using res_getipnodebyname() to force dns name
136 * resolution. Note, res_getaddrinfo() isn't exported by libreolv
137 * so we use res_getipnodebyname() (MIT uses getaddrinfo()).
139 KRB5_LOG(KRB5_INFO
, "krb5_sname_to_principal() hostname %s",
142 addr_family
= AF_INET
;
143 try_getipnodebyname_again
:
144 hp
= res_getipnodebyname(hostname
, addr_family
, 0, &err
);
146 #ifdef DEBUG_REFERRALS
147 printf("sname_to_princ: probably punting due to bad hostname of %s\n",hostname
);
149 if (addr_family
== AF_INET
) {
150 KRB5_LOG(KRB5_INFO
, "krb5_sname_to_principal()"
151 " can't get AF_INET addr, err = %d", err
);
152 /* Just in case it's an IPv6-only name. */
153 addr_family
= AF_INET6
;
154 goto try_getipnodebyname_again
;
156 KRB5_LOG(KRB5_ERR
, "krb5_sname_to_principal()"
157 " can't get AF_INET or AF_INET6 addr,"
160 krb5_set_error_message(context
, KRB5_ERR_BAD_HOSTNAME
,
161 dgettext(TEXT_DOMAIN
,
162 "Hostname cannot be canonicalized for '%s': %s"),
163 hostname
, strerror(err
));
164 return KRB5_ERR_BAD_HOSTNAME
;
166 remote_host
= strdup(hp
? hp
->h_name
: hostname
);
173 if (maybe_use_reverse_dns(context
, DEFAULT_RDNS_LOOKUP
)) {
175 * Do a reverse resolution to get the full name, just in
176 * case there's some funny business going on. If there
177 * isn't an in-addr record, give up.
179 /* XXX: This is *so* bogus. There are several cases where
180 this won't get us the canonical name of the host, but
181 this is what we've trained people to expect. We'll
182 probably fix it at some point, but let's try to
183 preserve the current behavior and only shake things up
184 once when it comes time to fix this lossage. */
185 hp2
= res_getipnodebyaddr(hp
->h_addr
, hp
->h_length
,
186 hp
->h_addrtype
, &err
);
190 remote_host
= strdup(hp2
->h_name
);
192 res_freehostent(hp2
);
197 KRB5_LOG(KRB5_INFO
, "krb5_sname_to_principal() remote_host %s",
207 res_freehostent(hp2
);
210 } else /* type == KRB5_NT_UNKNOWN */ {
211 remote_host
= strdup(hostname
);
215 #ifdef DEBUG_REFERRALS
216 printf("sname_to_princ: hostname <%s> after rdns processing\n",remote_host
);
219 if (type
== KRB5_NT_SRV_HST
)
220 for (cp
= remote_host
; *cp
; cp
++)
221 if (isupper((unsigned char) (*cp
)))
222 *cp
= tolower((unsigned char) (*cp
));
225 * Windows NT5's broken resolver gratuitously tacks on a
226 * trailing period to the hostname (at least it does in
227 * Beta2). Find and remove it.
229 if (remote_host
[0]) {
230 cp
= remote_host
+ strlen(remote_host
)-1;
236 if ((retval
= krb5_get_host_realm(context
, remote_host
, &hrealms
))) {
241 #ifdef DEBUG_REFERRALS
242 printf("sname_to_princ: realm <%s> after krb5_get_host_realm\n",hrealms
[0]);
246 /* Solaris Kerberos */
247 krb5_set_error_message(context
, KRB5_ERR_HOST_REALM_UNKNOWN
,
248 dgettext(TEXT_DOMAIN
,
249 "Cannot determine realm for host: host is '%s'"),
250 remote_host
? remote_host
: "unknown");
254 return KRB5_ERR_HOST_REALM_UNKNOWN
;
258 retval
= krb5_build_principal(context
, ret_princ
, strlen(realm
),
259 realm
, sname
, remote_host
,
263 krb5_princ_type(context
, *ret_princ
) = type
;
265 #ifdef DEBUG_REFERRALS
266 printf("krb5_sname_to_principal returning\n");
267 printf("realm: <%s>, sname: <%s>, remote_host: <%s>\n",
268 realm
,sname
,remote_host
);
269 krb5int_dbgref_dump_principal("krb5_sname_to_principal",*ret_princ
);
274 krb5_free_host_realm(context
, hrealms
);
277 return KRB5_SNAME_UNSUPP_NAMETYPE
;