17c478bd9Sstevel@tonic-gate /*
25e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate /*
57c478bd9Sstevel@tonic-gate * lib/krb5/os/sn2princ.c
67c478bd9Sstevel@tonic-gate *
7505d05c7Sgtb * Copyright 1991,2002 by the Massachusetts Institute of Technology.
87c478bd9Sstevel@tonic-gate * All Rights Reserved.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
117c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
127c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
137c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
1455fea89dSDan Cross *
157c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
167c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
177c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
187c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
197c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
207c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
217c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
227c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
237c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
247c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
257c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
267c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
277c478bd9Sstevel@tonic-gate * or implied warranty.
2855fea89dSDan Cross *
297c478bd9Sstevel@tonic-gate *
307c478bd9Sstevel@tonic-gate * Convert a hostname and service name to a principal in the "standard"
317c478bd9Sstevel@tonic-gate * form.
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
34159d09a2SMark Phalan #include "k5-int.h"
35159d09a2SMark Phalan #include "os-proto.h"
36505d05c7Sgtb #include "fake-addrinfo.h"
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate #ifdef HAVE_SYS_PARAM_H
397c478bd9Sstevel@tonic-gate #include <sys/param.h>
407c478bd9Sstevel@tonic-gate #endif
415e01956fSGlenn Barry #include <locale.h>
425e01956fSGlenn Barry #include <syslog.h>
437c478bd9Sstevel@tonic-gate
44159d09a2SMark Phalan #if !defined(DEFAULT_RDNS_LOOKUP)
45159d09a2SMark Phalan /* Solaris Kerberos */
46159d09a2SMark Phalan #define DEFAULT_RDNS_LOOKUP 0
47159d09a2SMark Phalan #endif
48159d09a2SMark Phalan
49fe598cdcSmp /*
50fe598cdcSmp * Solaris Kerberos:
51fe598cdcSmp * The following prototypes are needed because these are
527c478bd9Sstevel@tonic-gate * private interfaces that do not have prototypes in any .h
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate extern struct hostent *res_getipnodebyname(const char *, int, int, int *);
557c478bd9Sstevel@tonic-gate extern struct hostent *res_getipnodebyaddr(const void *, size_t, int, int *);
567c478bd9Sstevel@tonic-gate extern void res_freehostent(struct hostent *);
577c478bd9Sstevel@tonic-gate
58159d09a2SMark Phalan static int
maybe_use_reverse_dns(krb5_context context,int def_val)59*9b622488SToomas Soome maybe_use_reverse_dns (krb5_context context, int def_val)
60159d09a2SMark Phalan {
61159d09a2SMark Phalan krb5_error_code code;
62159d09a2SMark Phalan char * value = NULL;
63159d09a2SMark Phalan int use_rdns = 0;
64159d09a2SMark Phalan
65159d09a2SMark Phalan code = profile_get_string(context->profile, "libdefaults",
66159d09a2SMark Phalan "rdns", 0, 0, &value);
67159d09a2SMark Phalan if (code)
68*9b622488SToomas Soome return def_val;
69159d09a2SMark Phalan
70159d09a2SMark Phalan if (value == 0)
71*9b622488SToomas Soome return def_val;
72159d09a2SMark Phalan
73159d09a2SMark Phalan use_rdns = _krb5_conf_boolean(value);
74159d09a2SMark Phalan profile_release_string(value);
75159d09a2SMark Phalan return use_rdns;
76159d09a2SMark Phalan }
77159d09a2SMark Phalan
78159d09a2SMark Phalan
797c478bd9Sstevel@tonic-gate /*
80159d09a2SMark Phalan * Solaris Kerberos:
817c478bd9Sstevel@tonic-gate * Note, krb5_sname_to_principal() allocates memory for ret_princ. Be sure to
827c478bd9Sstevel@tonic-gate * use krb5_free_principal() on ret_princ to free it when done referencing it.
837c478bd9Sstevel@tonic-gate */
84159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_sname_to_principal(krb5_context context,const char * hostname,const char * sname,krb5_int32 type,krb5_principal * ret_princ)85505d05c7Sgtb krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate char **hrealms, *realm, *remote_host;
887c478bd9Sstevel@tonic-gate krb5_error_code retval;
897c478bd9Sstevel@tonic-gate register char *cp;
907c478bd9Sstevel@tonic-gate char localname[MAXHOSTNAMELEN];
91159d09a2SMark Phalan /* Solaris Kerberos */
92159d09a2SMark Phalan KRB5_LOG0(KRB5_INFO, "krb5_sname_to_principal() start");
93fe598cdcSmp #ifdef DEBUG_REFERRALS
94fe598cdcSmp printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname,sname,type);
95fe598cdcSmp printf(" name types: 0=unknown, 3=srv_host\n");
96fe598cdcSmp #endif
977c478bd9Sstevel@tonic-gate if ((type == KRB5_NT_UNKNOWN) ||
987c478bd9Sstevel@tonic-gate (type == KRB5_NT_SRV_HST)) {
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate /* if hostname is NULL, use local hostname */
1017c478bd9Sstevel@tonic-gate if (! hostname) {
1027c478bd9Sstevel@tonic-gate if (gethostname(localname, MAXHOSTNAMELEN)) {
103159d09a2SMark Phalan /* Solaris Kerberos */
1047c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_ERR, "krb5_sname_to_principal()"
1057c478bd9Sstevel@tonic-gate " gethostname failed");
1067c478bd9Sstevel@tonic-gate return SOCKET_ERRNO;
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate hostname = localname;
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate /* if sname is NULL, use "host" */
1127c478bd9Sstevel@tonic-gate if (! sname)
1137c478bd9Sstevel@tonic-gate sname = "host";
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /* copy the hostname into non-volatile storage */
116159d09a2SMark Phalan
1177c478bd9Sstevel@tonic-gate if (type == KRB5_NT_SRV_HST) {
118159d09a2SMark Phalan /* Solaris Kerberos */
119159d09a2SMark Phalan struct hostent *hp = NULL;
120159d09a2SMark Phalan struct hostent *hp2 = NULL;
121159d09a2SMark Phalan int err;
122159d09a2SMark Phalan int addr_family;
123159d09a2SMark Phalan
124159d09a2SMark Phalan /* Note that the old code would accept numeric addresses,
125159d09a2SMark Phalan and if the gethostbyaddr step could convert them to
126159d09a2SMark Phalan real hostnames, you could actually get reasonable
127159d09a2SMark Phalan results. If the mapping failed, you'd get dotted
128159d09a2SMark Phalan triples as realm names. *sigh*
129159d09a2SMark Phalan
130159d09a2SMark Phalan The latter has been fixed in hst_realm.c, but we should
131159d09a2SMark Phalan keep supporting numeric addresses if they do have
132159d09a2SMark Phalan hostnames associated. */
133159d09a2SMark Phalan
134159d09a2SMark Phalan /*
135159d09a2SMark Phalan * Solaris kerberos: using res_getipnodebyname() to force dns name
136159d09a2SMark Phalan * resolution. Note, res_getaddrinfo() isn't exported by libreolv
137159d09a2SMark Phalan * so we use res_getipnodebyname() (MIT uses getaddrinfo()).
138159d09a2SMark Phalan */
139159d09a2SMark Phalan KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal() hostname %s",
140159d09a2SMark Phalan hostname);
141159d09a2SMark Phalan
142159d09a2SMark Phalan addr_family = AF_INET;
143159d09a2SMark Phalan try_getipnodebyname_again:
144159d09a2SMark Phalan hp = res_getipnodebyname(hostname, addr_family, 0, &err);
145159d09a2SMark Phalan if (!hp) {
146159d09a2SMark Phalan #ifdef DEBUG_REFERRALS
147159d09a2SMark Phalan printf("sname_to_princ: probably punting due to bad hostname of %s\n",hostname);
1487c478bd9Sstevel@tonic-gate #endif
149159d09a2SMark Phalan if (addr_family == AF_INET) {
150159d09a2SMark Phalan KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal()"
151159d09a2SMark Phalan " can't get AF_INET addr, err = %d", err);
152159d09a2SMark Phalan /* Just in case it's an IPv6-only name. */
153159d09a2SMark Phalan addr_family = AF_INET6;
154159d09a2SMark Phalan goto try_getipnodebyname_again;
155159d09a2SMark Phalan }
156159d09a2SMark Phalan KRB5_LOG(KRB5_ERR, "krb5_sname_to_principal()"
157159d09a2SMark Phalan " can't get AF_INET or AF_INET6 addr,"
158159d09a2SMark Phalan " err = %d", err);
1595e01956fSGlenn Barry
1605e01956fSGlenn Barry krb5_set_error_message(context, KRB5_ERR_BAD_HOSTNAME,
1615e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
1625e01956fSGlenn Barry "Hostname cannot be canonicalized for '%s': %s"),
1635e01956fSGlenn Barry hostname, strerror(err));
164159d09a2SMark Phalan return KRB5_ERR_BAD_HOSTNAME;
165159d09a2SMark Phalan }
166159d09a2SMark Phalan remote_host = strdup(hp ? hp->h_name : hostname);
167159d09a2SMark Phalan if (!remote_host) {
168159d09a2SMark Phalan if (hp != NULL)
169159d09a2SMark Phalan res_freehostent(hp);
170159d09a2SMark Phalan return ENOMEM;
171159d09a2SMark Phalan }
172159d09a2SMark Phalan
173159d09a2SMark Phalan if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
174159d09a2SMark Phalan /*
175159d09a2SMark Phalan * Do a reverse resolution to get the full name, just in
176159d09a2SMark Phalan * case there's some funny business going on. If there
177159d09a2SMark Phalan * isn't an in-addr record, give up.
178159d09a2SMark Phalan */
179159d09a2SMark Phalan /* XXX: This is *so* bogus. There are several cases where
180159d09a2SMark Phalan this won't get us the canonical name of the host, but
181159d09a2SMark Phalan this is what we've trained people to expect. We'll
182159d09a2SMark Phalan probably fix it at some point, but let's try to
183159d09a2SMark Phalan preserve the current behavior and only shake things up
184159d09a2SMark Phalan once when it comes time to fix this lossage. */
185159d09a2SMark Phalan hp2 = res_getipnodebyaddr(hp->h_addr, hp->h_length,
186159d09a2SMark Phalan hp->h_addrtype, &err);
187159d09a2SMark Phalan
188159d09a2SMark Phalan if (hp2 != NULL) {
189159d09a2SMark Phalan free(remote_host);
190159d09a2SMark Phalan remote_host = strdup(hp2->h_name);
191159d09a2SMark Phalan if (!remote_host) {
192159d09a2SMark Phalan res_freehostent(hp2);
193159d09a2SMark Phalan if (hp != NULL)
194159d09a2SMark Phalan res_freehostent(hp);
195159d09a2SMark Phalan return ENOMEM;
196159d09a2SMark Phalan }
197159d09a2SMark Phalan KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal() remote_host %s",
198159d09a2SMark Phalan remote_host);
199159d09a2SMark Phalan }
200159d09a2SMark Phalan }
201159d09a2SMark Phalan
202159d09a2SMark Phalan if (hp != NULL) {
203159d09a2SMark Phalan res_freehostent(hp);
204159d09a2SMark Phalan }
205159d09a2SMark Phalan
206159d09a2SMark Phalan if (hp2 != NULL) {
207159d09a2SMark Phalan res_freehostent(hp2);
208159d09a2SMark Phalan }
209159d09a2SMark Phalan
2107c478bd9Sstevel@tonic-gate } else /* type == KRB5_NT_UNKNOWN */ {
211159d09a2SMark Phalan remote_host = strdup(hostname);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate if (!remote_host)
2147c478bd9Sstevel@tonic-gate return ENOMEM;
215fe598cdcSmp #ifdef DEBUG_REFERRALS
216fe598cdcSmp printf("sname_to_princ: hostname <%s> after rdns processing\n",remote_host);
217fe598cdcSmp #endif
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if (type == KRB5_NT_SRV_HST)
2207c478bd9Sstevel@tonic-gate for (cp = remote_host; *cp; cp++)
221159d09a2SMark Phalan if (isupper((unsigned char) (*cp)))
222159d09a2SMark Phalan *cp = tolower((unsigned char) (*cp));
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate /*
2257c478bd9Sstevel@tonic-gate * Windows NT5's broken resolver gratuitously tacks on a
2267c478bd9Sstevel@tonic-gate * trailing period to the hostname (at least it does in
2277c478bd9Sstevel@tonic-gate * Beta2). Find and remove it.
2287c478bd9Sstevel@tonic-gate */
2297c478bd9Sstevel@tonic-gate if (remote_host[0]) {
230159d09a2SMark Phalan cp = remote_host + strlen(remote_host)-1;
231159d09a2SMark Phalan if (*cp == '.')
232159d09a2SMark Phalan *cp = 0;
2337c478bd9Sstevel@tonic-gate }
23455fea89dSDan Cross
235159d09a2SMark Phalan
236159d09a2SMark Phalan if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) {
2377c478bd9Sstevel@tonic-gate free(remote_host);
2387c478bd9Sstevel@tonic-gate return retval;
2397c478bd9Sstevel@tonic-gate }
240fe598cdcSmp
241fe598cdcSmp #ifdef DEBUG_REFERRALS
242fe598cdcSmp printf("sname_to_princ: realm <%s> after krb5_get_host_realm\n",hrealms[0]);
243fe598cdcSmp #endif
244fe598cdcSmp
2457c478bd9Sstevel@tonic-gate if (!hrealms[0]) {
2465e01956fSGlenn Barry /* Solaris Kerberos */
2475e01956fSGlenn Barry krb5_set_error_message(context, KRB5_ERR_HOST_REALM_UNKNOWN,
2485e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
2495e01956fSGlenn Barry "Cannot determine realm for host: host is '%s'"),
2505e01956fSGlenn Barry remote_host ? remote_host : "unknown");
2515e01956fSGlenn Barry
2527c478bd9Sstevel@tonic-gate free(remote_host);
2537c478bd9Sstevel@tonic-gate krb5_xfree(hrealms);
2547c478bd9Sstevel@tonic-gate return KRB5_ERR_HOST_REALM_UNKNOWN;
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate realm = hrealms[0];
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate retval = krb5_build_principal(context, ret_princ, strlen(realm),
2597c478bd9Sstevel@tonic-gate realm, sname, remote_host,
2607c478bd9Sstevel@tonic-gate (char *)0);
2617c478bd9Sstevel@tonic-gate
262bb294766SMark Phalan if (retval == 0)
263bb294766SMark Phalan krb5_princ_type(context, *ret_princ) = type;
2647c478bd9Sstevel@tonic-gate
265fe598cdcSmp #ifdef DEBUG_REFERRALS
266fe598cdcSmp printf("krb5_sname_to_principal returning\n");
267fe598cdcSmp printf("realm: <%s>, sname: <%s>, remote_host: <%s>\n",
268fe598cdcSmp realm,sname,remote_host);
269fe598cdcSmp krb5int_dbgref_dump_principal("krb5_sname_to_principal",*ret_princ);
270fe598cdcSmp #endif
271fe598cdcSmp
2727c478bd9Sstevel@tonic-gate free(remote_host);
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate krb5_free_host_realm(context, hrealms);
2757c478bd9Sstevel@tonic-gate return retval;
2767c478bd9Sstevel@tonic-gate } else {
2777c478bd9Sstevel@tonic-gate return KRB5_SNAME_UNSUPP_NAMETYPE;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
281