1*b3700b07SGordon Ross /*
2*b3700b07SGordon Ross * This file and its contents are supplied under the terms of the
3*b3700b07SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
4*b3700b07SGordon Ross * You may only use this file in accordance with the terms of version
5*b3700b07SGordon Ross * 1.0 of the CDDL.
6*b3700b07SGordon Ross *
7*b3700b07SGordon Ross * A full copy of the text of the CDDL should have accompanied this
8*b3700b07SGordon Ross * source. A copy of the CDDL is also available via the Internet at
9*b3700b07SGordon Ross * http://www.illumos.org/license/CDDL.
10*b3700b07SGordon Ross */
11*b3700b07SGordon Ross
12*b3700b07SGordon Ross /*
13*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
14*b3700b07SGordon Ross */
15*b3700b07SGordon Ross
16*b3700b07SGordon Ross /*
17*b3700b07SGordon Ross * MS-compatible Directory Server Discovery API, DsGetDC...()
18*b3700b07SGordon Ross */
19*b3700b07SGordon Ross
20*b3700b07SGordon Ross #include <stdlib.h>
21*b3700b07SGordon Ross #include <string.h>
22*b3700b07SGordon Ross #include <smb/nterror.h>
23*b3700b07SGordon Ross #include <smb/ntstatus.h>
24*b3700b07SGordon Ross #include <arpa/inet.h>
25*b3700b07SGordon Ross #include "dsgetdc.h"
26*b3700b07SGordon Ross #include "ads_priv.h"
27*b3700b07SGordon Ross #include <assert.h>
28*b3700b07SGordon Ross
29*b3700b07SGordon Ross #define DSGETDC_VALID_FLAGS ( \
30*b3700b07SGordon Ross DS_FORCE_REDISCOVERY | \
31*b3700b07SGordon Ross DS_DIRECTORY_SERVICE_REQUIRED | \
32*b3700b07SGordon Ross DS_DIRECTORY_SERVICE_PREFERRED | \
33*b3700b07SGordon Ross DS_GC_SERVER_REQUIRED | \
34*b3700b07SGordon Ross DS_PDC_REQUIRED | \
35*b3700b07SGordon Ross DS_BACKGROUND_ONLY | \
36*b3700b07SGordon Ross DS_IP_REQUIRED | \
37*b3700b07SGordon Ross DS_KDC_REQUIRED | \
38*b3700b07SGordon Ross DS_TIMESERV_REQUIRED | \
39*b3700b07SGordon Ross DS_WRITABLE_REQUIRED | \
40*b3700b07SGordon Ross DS_GOOD_TIMESERV_PREFERRED | \
41*b3700b07SGordon Ross DS_AVOID_SELF | \
42*b3700b07SGordon Ross DS_ONLY_LDAP_NEEDED | \
43*b3700b07SGordon Ross DS_IS_FLAT_NAME | \
44*b3700b07SGordon Ross DS_IS_DNS_NAME | \
45*b3700b07SGordon Ross DS_RETURN_FLAT_NAME | \
46*b3700b07SGordon Ross DS_RETURN_DNS_NAME)
47*b3700b07SGordon Ross
48*b3700b07SGordon Ross static struct timeval TIMEOUT = { 15, 0 };
49*b3700b07SGordon Ross
50*b3700b07SGordon Ross /*
51*b3700b07SGordon Ross * The Windows version of this would return a single allocation,
52*b3700b07SGordon Ross * where any strings pointed to in the returned structure would be
53*b3700b07SGordon Ross * stored in space following the top-level returned structure.
54*b3700b07SGordon Ross * This allows NetApiBufferFree() to be the same as free().
55*b3700b07SGordon Ross *
56*b3700b07SGordon Ross * However, we don't have an easy way to do that right now, so
57*b3700b07SGordon Ross * the dcinfo returned here will be free'd with DsFreeDcInfo().
58*b3700b07SGordon Ross */
59*b3700b07SGordon Ross uint32_t
_DsGetDcName(const char * ComputerName,const char * DomainName,const struct uuid * DomainGuid,const char * SiteName,uint32_t Flags,DOMAIN_CONTROLLER_INFO ** dcinfo)60*b3700b07SGordon Ross _DsGetDcName(const char *ComputerName,
61*b3700b07SGordon Ross const char *DomainName, const struct uuid *DomainGuid,
62*b3700b07SGordon Ross const char *SiteName, uint32_t Flags,
63*b3700b07SGordon Ross DOMAIN_CONTROLLER_INFO **dcinfo)
64*b3700b07SGordon Ross {
65*b3700b07SGordon Ross DsGetDcNameArgs args;
66*b3700b07SGordon Ross DsGetDcNameRes res;
67*b3700b07SGordon Ross CLIENT *clnt = NULL;
68*b3700b07SGordon Ross enum clnt_stat clstat;
69*b3700b07SGordon Ross
70*b3700b07SGordon Ross *dcinfo = NULL;
71*b3700b07SGordon Ross (void) memset(&args, 0, sizeof (args));
72*b3700b07SGordon Ross (void) memset(&res, 0, sizeof (res));
73*b3700b07SGordon Ross
74*b3700b07SGordon Ross /*
75*b3700b07SGordon Ross * Later check for over constrained optional args here,
76*b3700b07SGordon Ross * and return (ERROR_INVALID_PARAMETER);
77*b3700b07SGordon Ross */
78*b3700b07SGordon Ross
79*b3700b07SGordon Ross if (Flags & ~DSGETDC_VALID_FLAGS)
80*b3700b07SGordon Ross return (ERROR_INVALID_FLAGS);
81*b3700b07SGordon Ross
82*b3700b07SGordon Ross /*
83*b3700b07SGordon Ross * Call the ADS deamon.
84*b3700b07SGordon Ross */
85*b3700b07SGordon Ross clnt = clnt_door_create(ADSPRIV_PROGRAM, ADSPRIV_V1, ADSPRIV_MAX_XFER);
86*b3700b07SGordon Ross if (clnt == NULL)
87*b3700b07SGordon Ross return (RPC_S_NOT_LISTENING);
88*b3700b07SGordon Ross
89*b3700b07SGordon Ross args.ComputerName = (char *)ComputerName;
90*b3700b07SGordon Ross args.DomainName = (char *)DomainName;
91*b3700b07SGordon Ross if (DomainGuid != NULL)
92*b3700b07SGordon Ross (void) memcpy(&args.DomainGuid, DomainGuid,
93*b3700b07SGordon Ross sizeof (args.DomainGuid));
94*b3700b07SGordon Ross args.SiteName = (char *)SiteName;
95*b3700b07SGordon Ross args.Flags = Flags;
96*b3700b07SGordon Ross
97*b3700b07SGordon Ross clstat = clnt_call(clnt, ADSPRIV_GetDcName,
98*b3700b07SGordon Ross (xdrproc_t)xdr_DsGetDcNameArgs, (caddr_t)&args,
99*b3700b07SGordon Ross (xdrproc_t)xdr_DsGetDcNameRes, (caddr_t)&res, TIMEOUT);
100*b3700b07SGordon Ross
101*b3700b07SGordon Ross clnt_destroy(clnt);
102*b3700b07SGordon Ross if (clstat != RPC_SUCCESS)
103*b3700b07SGordon Ross return (RPC_S_CALL_FAILED);
104*b3700b07SGordon Ross if (res.status != 0)
105*b3700b07SGordon Ross return (res.status);
106*b3700b07SGordon Ross
107*b3700b07SGordon Ross *dcinfo = malloc(sizeof (**dcinfo));
108*b3700b07SGordon Ross if (*dcinfo == NULL)
109*b3700b07SGordon Ross return (ERROR_NOT_ENOUGH_MEMORY);
110*b3700b07SGordon Ross
111*b3700b07SGordon Ross /*
112*b3700b07SGordon Ross * We have taken pains to make these two the same.
113*b3700b07SGordon Ross * DOMAIN_CONTROLLER_INFO / struct adspriv_dcinfo
114*b3700b07SGordon Ross */
115*b3700b07SGordon Ross /* LINTED E_TRUE_LOGICAL_EXPR */
116*b3700b07SGordon Ross assert(sizeof (**dcinfo) == sizeof (res.DsGetDcNameRes_u.res0));
117*b3700b07SGordon Ross (void) memcpy(*dcinfo, &res.DsGetDcNameRes_u.res0, sizeof (**dcinfo));
118*b3700b07SGordon Ross
119*b3700b07SGordon Ross /*
120*b3700b07SGordon Ross * NB: Do NOT xdr_free the result, because we're
121*b3700b07SGordon Ross * returning a copy of it to the caller.
122*b3700b07SGordon Ross */
123*b3700b07SGordon Ross return (0);
124*b3700b07SGordon Ross }
125*b3700b07SGordon Ross
126*b3700b07SGordon Ross int
DsGetDcName(const char * ComputerName,const char * DomainName,const struct uuid * DomainGuid,const char * SiteName,uint32_t Flags,DOMAIN_CONTROLLER_INFO ** dcinfo)127*b3700b07SGordon Ross DsGetDcName(const char *ComputerName,
128*b3700b07SGordon Ross const char *DomainName, const struct uuid *DomainGuid,
129*b3700b07SGordon Ross const char *SiteName, uint32_t Flags,
130*b3700b07SGordon Ross DOMAIN_CONTROLLER_INFO **dcinfo)
131*b3700b07SGordon Ross {
132*b3700b07SGordon Ross uint32_t status;
133*b3700b07SGordon Ross int rc;
134*b3700b07SGordon Ross
135*b3700b07SGordon Ross status = _DsGetDcName(ComputerName, DomainName, DomainGuid,
136*b3700b07SGordon Ross SiteName, Flags, dcinfo);
137*b3700b07SGordon Ross
138*b3700b07SGordon Ross switch (status) {
139*b3700b07SGordon Ross case 0:
140*b3700b07SGordon Ross rc = 0;
141*b3700b07SGordon Ross break;
142*b3700b07SGordon Ross case NT_STATUS_NO_SUCH_DOMAIN: /* Specified domain unknown */
143*b3700b07SGordon Ross case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
144*b3700b07SGordon Ross case NT_STATUS_CANT_WAIT: /* or gave up waiting. */
145*b3700b07SGordon Ross case NT_STATUS_INVALID_SERVER_STATE: /* not in domain mode. */
146*b3700b07SGordon Ross rc = ERROR_NO_SUCH_DOMAIN;
147*b3700b07SGordon Ross break;
148*b3700b07SGordon Ross default:
149*b3700b07SGordon Ross rc = ERROR_INTERNAL_ERROR;
150*b3700b07SGordon Ross break;
151*b3700b07SGordon Ross }
152*b3700b07SGordon Ross return (rc);
153*b3700b07SGordon Ross }
154*b3700b07SGordon Ross
155*b3700b07SGordon Ross void
DsFreeDcInfo(DOMAIN_CONTROLLER_INFO * dci)156*b3700b07SGordon Ross DsFreeDcInfo(DOMAIN_CONTROLLER_INFO *dci)
157*b3700b07SGordon Ross {
158*b3700b07SGordon Ross if (dci != NULL) {
159*b3700b07SGordon Ross xdr_free(xdr_DsGetDcNameRes, (char *)dci);
160*b3700b07SGordon Ross free(dci);
161*b3700b07SGordon Ross }
162*b3700b07SGordon Ross }
163