dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / smbsrv / smbd / smbd_krb5lookup.c
blobaf98b15b1b46a61bb83dc60f2d0e094ed18a24d0
1 /*
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
5 * 1.0 of the CDDL.
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.
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #include <string.h>
20 #include <syslog.h>
22 #include <sys/types.h>
23 #include <sys/errno.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <sys/note.h>
28 #include <smbsrv/libsmbns.h>
30 #include "smbd.h"
31 #include "locate_plugin.h"
33 /* osconf.h - sigh */
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
50 krb5_error_code
51 _krb5_override_service_locator(
52 void *arg0,
53 enum locate_service_type svc,
54 const char *realm,
55 int socktype,
56 int family,
57 int (*cbfunc)(void *, int, struct sockaddr *),
58 void *cbdata)
60 _NOTE(ARGUNUSED(arg0))
61 smb_domainex_t dxi;
62 int rc = KRB5_PLUGIN_NO_HANDLE;
63 short port;
66 * Is this a service we want to override?
68 switch (svc) {
69 case locate_service_kdc:
70 case locate_service_master_kdc:
71 port = htons(KRB5_DEFAULT_PORT);
72 break;
73 case locate_service_kadmin:
74 port = htons(DEFAULT_KADM5_PORT);
75 break;
76 case locate_service_kpasswd:
77 port = htons(DEFAULT_KPASSWD_PORT);
78 break;
79 case locate_service_krb524:
80 default:
81 return (rc);
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);
100 return (rc);
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);
110 switch (family) {
111 case AF_UNSPEC:
112 break; /* OK */
113 case AF_INET:
114 case AF_INET6:
115 if (family == dxi.d_dci.dc_addr.a_family)
116 break; /* OK */
117 /* else fallthrough */
118 default:
119 return (KRB5_ERR_NO_SERVICE);
123 * Provide the service address we have.
125 switch (dxi.d_dci.dc_addr.a_family) {
126 case AF_INET: {
127 struct sockaddr_in sin;
128 (void) memset(&sin, 0, sizeof (sin));
129 sin.sin_family = AF_INET;
130 sin.sin_port = port;
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. */
135 if (rc)
136 rc = ENOMEM;
137 break;
139 case AF_INET6: {
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. */
148 if (rc)
149 rc = ENOMEM;
150 break;
152 default:
153 rc = KRB5_ERR_NO_SERVICE;
154 break;
157 return (rc);