2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
22 #include <sys/types.h>
23 #include <sys/errno.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
28 #include <smbsrv/libsmbns.h>
31 #include "locate_plugin.h"
34 #define KRB5_DEFAULT_PORT 88
35 #define DEFAULT_KADM5_PORT 749
36 #define DEFAULT_KPASSWD_PORT 464
39 * This is an "override plugin" used by libkrb5. See:
40 * lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c
42 * The interface is based on:
43 * http://web.mit.edu/~kerberos/krb5-1.12/doc/plugindev/locate.html
47 * Called by krb5int_locate_server / override_locate_server
51 _krb5_override_service_locator(
53 enum locate_service_type svc
,
57 int (*cbfunc
)(void *, int, struct sockaddr
*),
60 _NOTE(ARGUNUSED(arg0
))
62 int rc
= KRB5_PLUGIN_NO_HANDLE
;
66 * Is this a service we want to override?
69 case locate_service_kdc
:
70 case locate_service_master_kdc
:
71 port
= htons(KRB5_DEFAULT_PORT
);
73 case locate_service_kadmin
:
74 port
= htons(DEFAULT_KADM5_PORT
);
76 case locate_service_kpasswd
:
77 port
= htons(DEFAULT_KPASSWD_PORT
);
79 case locate_service_krb524
:
85 * What's my domain? Note: have to get this in a way
86 * that works while join domain is underway.
88 if (!smb_domain_getinfo(&dxi
)) {
89 smbd_report("_krb5_override_service_locator "
90 "failed getting domain info");
91 return (KRB5_ERR_HOST_REALM_UNKNOWN
);
95 * Is this a realm we want to override?
97 if (0 != strcasecmp(realm
, dxi
.d_primary
.di_fqname
)) {
98 syslog(LOG_DEBUG
, "_krb5_override_service_locator, "
99 "realm=%s, fqdn=%s", realm
, dxi
.d_primary
.di_fqname
);
104 * Yes, this is our domain. Have a DC?
106 if (dxi
.d_dci
.dc_name
[0] == '\0' ||
107 dxi
.d_dci
.dc_addr
.a_family
== 0)
108 return (KRB5_REALM_CANT_RESOLVE
);
115 if (family
== dxi
.d_dci
.dc_addr
.a_family
)
117 /* else fallthrough */
119 return (KRB5_ERR_NO_SERVICE
);
123 * Provide the service address we have.
125 switch (dxi
.d_dci
.dc_addr
.a_family
) {
127 struct sockaddr_in sin
;
128 (void) memset(&sin
, 0, sizeof (sin
));
129 sin
.sin_family
= AF_INET
;
131 (void) memcpy(&sin
.sin_addr
, &dxi
.d_dci
.dc_addr
.a_ipv4
,
132 sizeof (sin
.sin_addr
));
133 rc
= cbfunc(cbdata
, socktype
, (struct sockaddr
*)&sin
);
134 /* rc from cbfunc is special. */
140 struct sockaddr_in6 sin6
;
141 (void) memset(&sin6
, 0, sizeof (sin6
));
142 sin6
.sin6_family
= AF_INET6
;
143 sin6
.sin6_port
= port
;
144 (void) memcpy(&sin6
.sin6_addr
, &dxi
.d_dci
.dc_addr
.a_ipv6
,
145 sizeof (sin6
.sin6_addr
));
146 rc
= cbfunc(cbdata
, socktype
, (struct sockaddr
*)&sin6
);
147 /* rc from cbfunc is special. */
153 rc
= KRB5_ERR_NO_SERVICE
;