b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * This file and its contents are supplied under the terms of the
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * You may only use this file in accordance with the terms of version
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * 1.0 of the CDDL.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross *
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * A full copy of the text of the CDDL should have accompanied this
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * source. A copy of the CDDL is also available via the Internet at
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * http://www.illumos.org/license/CDDL.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <stdio.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <stdlib.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <stdarg.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <string.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <syslog.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <rpc/rpc.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <sys/uuid.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <smb/ntstatus.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <synch.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <thread.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <arpa/inet.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <uuid/uuid.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "idmapd.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "libadutils.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "dsgetdc.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "ads_priv.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossvoid adspriv_program_1(struct svc_req *, register SVCXPRT *);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon RossSVCXPRT *dcl_xprt = NULL;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossvoid
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossinit_dc_locator(void)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross int connmaxrec = 32 * 1024;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dcl_xprt = svc_door_create(adspriv_program_1,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross ADSPRIV_PROGRAM, ADSPRIV_V1, connmaxrec);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (dcl_xprt == NULL) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_ERR, "unable to create door RPC service");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (!svc_control(dcl_xprt, SVCSET_CONNMAXREC, &connmaxrec)) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_ERR, "unable to limit RPC request size");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossvoid
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossfini_dc_locator(void)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (dcl_xprt != NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross svc_destroy(dcl_xprt);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Functions called by the (generated) adspriv_srv.c
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/* ARGSUSED */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossbool_t
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossadspriv_null_1_svc(void *result, struct svc_req *rqstp)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (TRUE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/* ARGSUSED */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossbool_t
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossadspriv_forcerediscovery_1_svc(
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DsForceRediscoveryArgs args,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross int *res,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross struct svc_req *sreq)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* Ignoring args for now. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmap_cfg_force_rediscovery();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross *res = 0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (TRUE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/* ARGSUSED */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossbool_t
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossadspriv_getdcname_1_svc(
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DsGetDcNameArgs args,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DsGetDcNameRes *res,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross struct svc_req *sreq)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross uuid_t uuid;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross adspriv_dcinfo *dci;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmap_pg_config_t *pgcfg;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross ad_disc_ds_t *ds;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross char *s;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* Init */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memset(res, 0, sizeof (*res));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = 0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci = &res->DsGetDcNameRes_u.res0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (args.Flags & DS_FORCE_REDISCOVERY)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmap_cfg_force_rediscovery();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * We normally should wait if discovery is running.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Sort of mis-using the background flag as a way to
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * skip the wait, until we really do background disc.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((args.Flags & DS_BACKGROUND_ONLY) == 0) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross timespec_t tv = { 15, 0 };
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross int rc = 0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross int waited = 0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (_idmapdstate.addisc_st != 0)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmapdlog(LOG_DEBUG, "getdcname wait begin");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross while (_idmapdstate.addisc_st != 0) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross waited++;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = cond_reltimedwait(&_idmapdstate.addisc_cv,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross &_idmapdstate.addisc_lk, &tv);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (rc == ETIME)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross break;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (rc == ETIME) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* Caller will replace this with DC not found. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmapdlog(LOG_ERR, "getdcname timeout");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = NT_STATUS_CANT_WAIT;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (TRUE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (waited) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross idmapdlog(LOG_DEBUG, "getdcname wait done");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross RDLOCK_CONFIG();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross pgcfg = &_idmapdstate.cfg->pgcfg;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (pgcfg->domain_name == NULL) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = NT_STATUS_INVALID_SERVER_STATE;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross goto out;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (args.DomainName != NULL && args.DomainName[0] != '\0' &&
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross 0 != strcasecmp(args.DomainName, pgcfg->domain_name)) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * They asked for a specific domain not our primary,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * which is not supported (and not needed).
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = NT_STATUS_NO_SUCH_DOMAIN;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross goto out;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((ds = pgcfg->domain_controller) == NULL) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross goto out;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_DcName = strdup(ds->host);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_DcAddr = calloc(1, INET6_ADDRSTRLEN);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (dci->dci_DcAddr != NULL &&
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross ad_disc_getnameinfo(dci->dci_DcAddr, INET6_ADDRSTRLEN,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross &ds->addr) == 0)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_AddrType = DS_INET_ADDRESS;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((s = pgcfg->domain_guid) != NULL &&
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross 0 == uuid_parse(s, uuid)) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memcpy(dci->dci_guid, uuid, sizeof (uuid));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((s = pgcfg->domain_name) != NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_DomainName = strdup(s);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((s = pgcfg->forest_name) != NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_DnsForestName = strdup(s);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_Flags = ds->flags;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_DcSiteName = strdup(ds->site);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if ((s = pgcfg->site_name) != NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross dci->dci_ClientSiteName = strdup(s);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* Address in binary form too. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memcpy(&dci->dci_sockaddr,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross &ds->addr, ADSPRIV_SOCKADDR_LEN);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossout:
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross UNLOCK_CONFIG();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (TRUE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/* ARGSUSED */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossint
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossadspriv_program_1_freeresult(SVCXPRT *xprt, xdrproc_t fun, caddr_t res)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) xdr_free(fun, res);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (TRUE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}