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