smbd_krb5lookup.c revision b3700b074e637f8c6991b70754c88a2cfffb246b
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * This file and its contents are supplied under the terms of the
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Common Development and Distribution License ("CDDL"), version 1.0.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * You may only use this file in accordance with the terms of version
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * 1.0 of the CDDL.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * A full copy of the text of the CDDL should have accompanied this
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * source. A copy of the CDDL is also available via the Internet at
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * http://www.illumos.org/license/CDDL.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <stdio.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <stdlib.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <stdarg.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <string.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <syslog.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/types.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/errno.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/socket.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <netinet/in.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <sys/note.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include <smbsrv/libsmbns.h>
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include "smbd.h"
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#include "locate_plugin.h"
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/* osconf.h - sigh */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define KRB5_DEFAULT_PORT 88
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define DEFAULT_KADM5_PORT 749
83c4dfe9546fd839e7a52bca7e9920da918f916ejg#define DEFAULT_KPASSWD_PORT 464
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * This is an "override plugin" used by libkrb5. See:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c
83c4dfe9546fd839e7a52bca7e9920da918f916ejg *
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * The interface is based on:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * http://web.mit.edu/~kerberos/krb5-1.12/doc/plugindev/locate.html
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg/*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Called by krb5int_locate_server / override_locate_server
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejgkrb5_error_code
83c4dfe9546fd839e7a52bca7e9920da918f916ejg_krb5_override_service_locator(
83c4dfe9546fd839e7a52bca7e9920da918f916ejg void *arg0,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg enum locate_service_type svc,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg const char *realm,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int socktype,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int family,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int (*cbfunc)(void *, int, struct sockaddr *),
83c4dfe9546fd839e7a52bca7e9920da918f916ejg void *cbdata)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg{
83c4dfe9546fd839e7a52bca7e9920da918f916ejg _NOTE(ARGUNUSED(arg0))
83c4dfe9546fd839e7a52bca7e9920da918f916ejg smb_domainex_t dxi;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg int rc = KRB5_PLUGIN_NO_HANDLE;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg short port;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Is this a service we want to override?
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg switch (svc) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case locate_service_kdc:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case locate_service_master_kdc:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg port = htons(KRB5_DEFAULT_PORT);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case locate_service_kadmin:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg port = htons(DEFAULT_KADM5_PORT);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case locate_service_kpasswd:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg port = htons(DEFAULT_KPASSWD_PORT);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case locate_service_krb524:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg default:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rc);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * What's my domain? Note: have to get this in a way
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * that works while join domain is underway.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (!smb_domain_getinfo(&dxi)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg smbd_report("_krb5_override_service_locator "
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "failed getting domain info");
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (KRB5_ERR_HOST_REALM_UNKNOWN);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Is this a realm we want to override?
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (0 != strcasecmp(realm, dxi.d_primary.di_fqname)) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg syslog(LOG_DEBUG, "_krb5_override_service_locator, "
83c4dfe9546fd839e7a52bca7e9920da918f916ejg "realm=%s, fqdn=%s", realm, dxi.d_primary.di_fqname);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (rc);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Yes, this is our domain. Have a DC?
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (dxi.d_dci.dc_name[0] == '\0' ||
83c4dfe9546fd839e7a52bca7e9920da918f916ejg dxi.d_dci.dc_addr.a_family == 0)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (KRB5_REALM_CANT_RESOLVE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg switch (family) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case AF_UNSPEC:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break; /* OK */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case AF_INET:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case AF_INET6:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (family == dxi.d_dci.dc_addr.a_family)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break; /* OK */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /* else fallthrough */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg default:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg return (KRB5_ERR_NO_SERVICE);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /*
83c4dfe9546fd839e7a52bca7e9920da918f916ejg * Provide the service address we have.
83c4dfe9546fd839e7a52bca7e9920da918f916ejg */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg switch (dxi.d_dci.dc_addr.a_family) {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case AF_INET: {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg struct sockaddr_in sin;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) memset(&sin, 0, sizeof (sin));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sin.sin_family = AF_INET;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sin.sin_port = port;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) memcpy(&sin.sin_addr, &dxi.d_dci.dc_addr.a_ipv4,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sizeof (sin.sin_addr));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /* rc from cbfunc is special. */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rc)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rc = ENOMEM;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg case AF_INET6: {
83c4dfe9546fd839e7a52bca7e9920da918f916ejg struct sockaddr_in6 sin6;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) memset(&sin6, 0, sizeof (sin6));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sin6.sin6_family = AF_INET6;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sin6.sin6_port = port;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg (void) memcpy(&sin6.sin6_addr, &dxi.d_dci.dc_addr.a_ipv6,
83c4dfe9546fd839e7a52bca7e9920da918f916ejg sizeof (sin6.sin6_addr));
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin6);
83c4dfe9546fd839e7a52bca7e9920da918f916ejg /* rc from cbfunc is special. */
83c4dfe9546fd839e7a52bca7e9920da918f916ejg if (rc)
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rc = ENOMEM;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg break;
83c4dfe9546fd839e7a52bca7e9920da918f916ejg }
83c4dfe9546fd839e7a52bca7e9920da918f916ejg default:
83c4dfe9546fd839e7a52bca7e9920da918f916ejg rc = KRB5_ERR_NO_SERVICE;
break;
}
return (rc);
}