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 * MS-compatible Directory Server Discovery API, DsGetDC...()
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <stdlib.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <string.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <smb/nterror.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <smb/ntstatus.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <arpa/inet.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "dsgetdc.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include "ads_priv.h"
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <assert.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#define DSGETDC_VALID_FLAGS ( \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_FORCE_REDISCOVERY | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_DIRECTORY_SERVICE_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_DIRECTORY_SERVICE_PREFERRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_GC_SERVER_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_PDC_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_BACKGROUND_ONLY | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_IP_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_KDC_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_TIMESERV_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_WRITABLE_REQUIRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_GOOD_TIMESERV_PREFERRED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_AVOID_SELF | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_ONLY_LDAP_NEEDED | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_IS_FLAT_NAME | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_IS_DNS_NAME | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_RETURN_FLAT_NAME | \
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DS_RETURN_DNS_NAME)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossstatic struct timeval TIMEOUT = { 15, 0 };
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross/*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * The Windows version of this would return a single allocation,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * where any strings pointed to in the returned structure would be
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * stored in space following the top-level returned structure.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * This allows NetApiBufferFree() to be the same as free().
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross *
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * However, we don't have an easy way to do that right now, so
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * the dcinfo returned here will be free'd with DsFreeDcInfo().
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossuint32_t
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross_DsGetDcName(const char *ComputerName,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross const char *DomainName, const struct uuid *DomainGuid,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross const char *SiteName, uint32_t Flags,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DOMAIN_CONTROLLER_INFO **dcinfo)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DsGetDcNameArgs args;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DsGetDcNameRes res;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross CLIENT *clnt = NULL;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross enum clnt_stat clstat;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross *dcinfo = NULL;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memset(&args, 0, sizeof (args));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memset(&res, 0, sizeof (res));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Later check for over constrained optional args here,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * and return (ERROR_INVALID_PARAMETER);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (Flags & ~DSGETDC_VALID_FLAGS)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (ERROR_INVALID_FLAGS);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Call the ADS deamon.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross clnt = clnt_door_create(ADSPRIV_PROGRAM, ADSPRIV_V1, ADSPRIV_MAX_XFER);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (clnt == NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (RPC_S_NOT_LISTENING);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross args.ComputerName = (char *)ComputerName;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross args.DomainName = (char *)DomainName;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (DomainGuid != NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memcpy(&args.DomainGuid, DomainGuid,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross sizeof (args.DomainGuid));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross args.SiteName = (char *)SiteName;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross args.Flags = Flags;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross clstat = clnt_call(clnt, ADSPRIV_GetDcName,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (xdrproc_t)xdr_DsGetDcNameArgs, (caddr_t)&args,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (xdrproc_t)xdr_DsGetDcNameRes, (caddr_t)&res, TIMEOUT);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross clnt_destroy(clnt);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (clstat != RPC_SUCCESS)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (RPC_S_CALL_FAILED);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (res.status != 0)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (res.status);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross *dcinfo = malloc(sizeof (**dcinfo));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (*dcinfo == NULL)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (ERROR_NOT_ENOUGH_MEMORY);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * We have taken pains to make these two the same.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * DOMAIN_CONTROLLER_INFO / struct adspriv_dcinfo
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* LINTED E_TRUE_LOGICAL_EXPR */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross assert(sizeof (**dcinfo) == sizeof (res.DsGetDcNameRes_u.res0));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) memcpy(*dcinfo, &res.DsGetDcNameRes_u.res0, sizeof (**dcinfo));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * NB: Do NOT xdr_free the result, because we're
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * returning a copy of it to the caller.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (0);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossint
b3700b074e637f8c6991b70754c88a2cfffb246bGordon RossDsGetDcName(const char *ComputerName,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross const char *DomainName, const struct uuid *DomainGuid,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross const char *SiteName, uint32_t Flags,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross DOMAIN_CONTROLLER_INFO **dcinfo)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross uint32_t status;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross int rc;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = _DsGetDcName(ComputerName, DomainName, DomainGuid,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross SiteName, Flags, dcinfo);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross switch (status) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross case 0:
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = 0;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross break;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross case NT_STATUS_NO_SUCH_DOMAIN: /* Specified domain unknown */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross case NT_STATUS_CANT_WAIT: /* or gave up waiting. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross case NT_STATUS_INVALID_SERVER_STATE: /* not in domain mode. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = ERROR_NO_SUCH_DOMAIN;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross break;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross default:
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = ERROR_INTERNAL_ERROR;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross break;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (rc);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossvoid
b3700b074e637f8c6991b70754c88a2cfffb246bGordon RossDsFreeDcInfo(DOMAIN_CONTROLLER_INFO *dci)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (dci != NULL) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross xdr_free(xdr_DsGetDcNameRes, (char *)dci);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross free(dci);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross}