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 #include <stdio.h>
18*b3700b07SGordon Ross #include <stdlib.h>
19*b3700b07SGordon Ross #include <stdarg.h>
20*b3700b07SGordon Ross #include <string.h>
21*b3700b07SGordon Ross #include <syslog.h>
22*b3700b07SGordon Ross #include <rpc/rpc.h>
23*b3700b07SGordon Ross #include <sys/uuid.h>
24*b3700b07SGordon Ross #include <smb/ntstatus.h>
25*b3700b07SGordon Ross #include <synch.h>
26*b3700b07SGordon Ross #include <thread.h>
27*b3700b07SGordon Ross #include <arpa/inet.h>
28*b3700b07SGordon Ross #include <uuid/uuid.h>
29*b3700b07SGordon Ross 
30*b3700b07SGordon Ross #include "idmapd.h"
31*b3700b07SGordon Ross #include "libadutils.h"
32*b3700b07SGordon Ross #include "dsgetdc.h"
33*b3700b07SGordon Ross #include "ads_priv.h"
34*b3700b07SGordon Ross 
35*b3700b07SGordon Ross void adspriv_program_1(struct svc_req *, register SVCXPRT *);
36*b3700b07SGordon Ross 
37*b3700b07SGordon Ross SVCXPRT *dcl_xprt = NULL;
38*b3700b07SGordon Ross 
39*b3700b07SGordon Ross void
40*b3700b07SGordon Ross init_dc_locator(void)
41*b3700b07SGordon Ross {
42*b3700b07SGordon Ross 	int	connmaxrec = 32 * 1024;
43*b3700b07SGordon Ross 
44*b3700b07SGordon Ross 	dcl_xprt = svc_door_create(adspriv_program_1,
45*b3700b07SGordon Ross 	    ADSPRIV_PROGRAM, ADSPRIV_V1, connmaxrec);
46*b3700b07SGordon Ross 	if (dcl_xprt == NULL) {
47*b3700b07SGordon Ross 		syslog(LOG_ERR, "unable to create door RPC service");
48*b3700b07SGordon Ross 		return;
49*b3700b07SGordon Ross 	}
50*b3700b07SGordon Ross 
51*b3700b07SGordon Ross 	if (!svc_control(dcl_xprt, SVCSET_CONNMAXREC, &connmaxrec)) {
52*b3700b07SGordon Ross 		syslog(LOG_ERR, "unable to limit RPC request size");
53*b3700b07SGordon Ross 	}
54*b3700b07SGordon Ross }
55*b3700b07SGordon Ross 
56*b3700b07SGordon Ross void
57*b3700b07SGordon Ross fini_dc_locator(void)
58*b3700b07SGordon Ross {
59*b3700b07SGordon Ross 	if (dcl_xprt != NULL)
60*b3700b07SGordon Ross 		svc_destroy(dcl_xprt);
61*b3700b07SGordon Ross }
62*b3700b07SGordon Ross 
63*b3700b07SGordon Ross /*
64*b3700b07SGordon Ross  * Functions called by the (generated) adspriv_srv.c
65*b3700b07SGordon Ross  */
66*b3700b07SGordon Ross 
67*b3700b07SGordon Ross /* ARGSUSED */
68*b3700b07SGordon Ross bool_t
69*b3700b07SGordon Ross adspriv_null_1_svc(void *result, struct svc_req *rqstp)
70*b3700b07SGordon Ross {
71*b3700b07SGordon Ross 	return (TRUE);
72*b3700b07SGordon Ross }
73*b3700b07SGordon Ross 
74*b3700b07SGordon Ross /* ARGSUSED */
75*b3700b07SGordon Ross bool_t
76*b3700b07SGordon Ross adspriv_forcerediscovery_1_svc(
77*b3700b07SGordon Ross 	DsForceRediscoveryArgs args,
78*b3700b07SGordon Ross 	int *res,
79*b3700b07SGordon Ross 	struct svc_req *sreq)
80*b3700b07SGordon Ross {
81*b3700b07SGordon Ross 	/* Ignoring args for now. */
82*b3700b07SGordon Ross 
83*b3700b07SGordon Ross 	idmap_cfg_force_rediscovery();
84*b3700b07SGordon Ross 	*res = 0;
85*b3700b07SGordon Ross 
86*b3700b07SGordon Ross 	return (TRUE);
87*b3700b07SGordon Ross }
88*b3700b07SGordon Ross 
89*b3700b07SGordon Ross 
90*b3700b07SGordon Ross /* ARGSUSED */
91*b3700b07SGordon Ross bool_t
92*b3700b07SGordon Ross adspriv_getdcname_1_svc(
93*b3700b07SGordon Ross 	DsGetDcNameArgs args,
94*b3700b07SGordon Ross 	DsGetDcNameRes *res,
95*b3700b07SGordon Ross 	struct svc_req *sreq)
96*b3700b07SGordon Ross {
97*b3700b07SGordon Ross 	uuid_t uuid;
98*b3700b07SGordon Ross 	adspriv_dcinfo *dci;
99*b3700b07SGordon Ross 	idmap_pg_config_t *pgcfg;
100*b3700b07SGordon Ross 	ad_disc_ds_t *ds;
101*b3700b07SGordon Ross 	char *s;
102*b3700b07SGordon Ross 
103*b3700b07SGordon Ross 	/* Init */
104*b3700b07SGordon Ross 	(void) memset(res, 0, sizeof (*res));
105*b3700b07SGordon Ross 	res->status = 0;
106*b3700b07SGordon Ross 	dci = &res->DsGetDcNameRes_u.res0;
107*b3700b07SGordon Ross 
108*b3700b07SGordon Ross 	if (args.Flags & DS_FORCE_REDISCOVERY)
109*b3700b07SGordon Ross 		idmap_cfg_force_rediscovery();
110*b3700b07SGordon Ross 
111*b3700b07SGordon Ross 	/*
112*b3700b07SGordon Ross 	 * We normally should wait if discovery is running.
113*b3700b07SGordon Ross 	 * Sort of mis-using the background flag as a way to
114*b3700b07SGordon Ross 	 * skip the wait, until we really do background disc.
115*b3700b07SGordon Ross 	 */
116*b3700b07SGordon Ross 	if ((args.Flags & DS_BACKGROUND_ONLY) == 0) {
117*b3700b07SGordon Ross 		timespec_t tv = { 15, 0 };
118*b3700b07SGordon Ross 		int rc = 0;
119*b3700b07SGordon Ross 		int waited = 0;
120*b3700b07SGordon Ross 
121*b3700b07SGordon Ross 		(void) mutex_lock(&_idmapdstate.addisc_lk);
122*b3700b07SGordon Ross 
123*b3700b07SGordon Ross 		if (_idmapdstate.addisc_st != 0)
124*b3700b07SGordon Ross 			idmapdlog(LOG_DEBUG, "getdcname wait begin");
125*b3700b07SGordon Ross 
126*b3700b07SGordon Ross 		while (_idmapdstate.addisc_st != 0) {
127*b3700b07SGordon Ross 			waited++;
128*b3700b07SGordon Ross 			rc = cond_reltimedwait(&_idmapdstate.addisc_cv,
129*b3700b07SGordon Ross 			    &_idmapdstate.addisc_lk, &tv);
130*b3700b07SGordon Ross 			if (rc == ETIME)
131*b3700b07SGordon Ross 				break;
132*b3700b07SGordon Ross 		}
133*b3700b07SGordon Ross 		(void) mutex_unlock(&_idmapdstate.addisc_lk);
134*b3700b07SGordon Ross 
135*b3700b07SGordon Ross 		if (rc == ETIME) {
136*b3700b07SGordon Ross 			/* Caller will replace this with DC not found. */
137*b3700b07SGordon Ross 			idmapdlog(LOG_ERR, "getdcname timeout");
138*b3700b07SGordon Ross 			res->status = NT_STATUS_CANT_WAIT;
139*b3700b07SGordon Ross 			return (TRUE);
140*b3700b07SGordon Ross 		}
141*b3700b07SGordon Ross 		if (waited) {
142*b3700b07SGordon Ross 			idmapdlog(LOG_DEBUG, "getdcname wait done");
143*b3700b07SGordon Ross 		}
144*b3700b07SGordon Ross 	}
145*b3700b07SGordon Ross 
146*b3700b07SGordon Ross 	RDLOCK_CONFIG();
147*b3700b07SGordon Ross 	pgcfg = &_idmapdstate.cfg->pgcfg;
148*b3700b07SGordon Ross 
149*b3700b07SGordon Ross 	if (pgcfg->domain_name == NULL) {
150*b3700b07SGordon Ross 		res->status = NT_STATUS_INVALID_SERVER_STATE;
151*b3700b07SGordon Ross 		goto out;
152*b3700b07SGordon Ross 	}
153*b3700b07SGordon Ross 
154*b3700b07SGordon Ross 	if (args.DomainName != NULL && args.DomainName[0] != '\0' &&
155*b3700b07SGordon Ross 	    0 != strcasecmp(args.DomainName, pgcfg->domain_name)) {
156*b3700b07SGordon Ross 		/*
157*b3700b07SGordon Ross 		 * They asked for a specific domain not our primary,
158*b3700b07SGordon Ross 		 * which is not supported (and not needed).
159*b3700b07SGordon Ross 		 */
160*b3700b07SGordon Ross 		res->status = NT_STATUS_NO_SUCH_DOMAIN;
161*b3700b07SGordon Ross 		goto out;
162*b3700b07SGordon Ross 	}
163*b3700b07SGordon Ross 
164*b3700b07SGordon Ross 	if ((ds = pgcfg->domain_controller) == NULL) {
165*b3700b07SGordon Ross 		res->status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
166*b3700b07SGordon Ross 		goto out;
167*b3700b07SGordon Ross 	}
168*b3700b07SGordon Ross 
169*b3700b07SGordon Ross 	dci->dci_DcName = strdup(ds->host);
170*b3700b07SGordon Ross 
171*b3700b07SGordon Ross 	dci->dci_DcAddr = calloc(1, INET6_ADDRSTRLEN);
172*b3700b07SGordon Ross 	if (dci->dci_DcAddr != NULL &&
173*b3700b07SGordon Ross 	    ad_disc_getnameinfo(dci->dci_DcAddr, INET6_ADDRSTRLEN,
174*b3700b07SGordon Ross 	    &ds->addr) == 0)
175*b3700b07SGordon Ross 		dci->dci_AddrType = DS_INET_ADDRESS;
176*b3700b07SGordon Ross 
177*b3700b07SGordon Ross 	if ((s = pgcfg->domain_guid) != NULL &&
178*b3700b07SGordon Ross 	    0 == uuid_parse(s, uuid)) {
179*b3700b07SGordon Ross 		(void) memcpy(dci->dci_guid, uuid, sizeof (uuid));
180*b3700b07SGordon Ross 	}
181*b3700b07SGordon Ross 
182*b3700b07SGordon Ross 	if ((s = pgcfg->domain_name) != NULL)
183*b3700b07SGordon Ross 		dci->dci_DomainName = strdup(s);
184*b3700b07SGordon Ross 
185*b3700b07SGordon Ross 	if ((s = pgcfg->forest_name) != NULL)
186*b3700b07SGordon Ross 		dci->dci_DnsForestName = strdup(s);
187*b3700b07SGordon Ross 
188*b3700b07SGordon Ross 	dci->dci_Flags = ds->flags;
189*b3700b07SGordon Ross 	dci->dci_DcSiteName = strdup(ds->site);
190*b3700b07SGordon Ross 
191*b3700b07SGordon Ross 	if ((s = pgcfg->site_name) != NULL)
192*b3700b07SGordon Ross 		dci->dci_ClientSiteName = strdup(s);
193*b3700b07SGordon Ross 
194*b3700b07SGordon Ross 	/* Address in binary form too. */
195*b3700b07SGordon Ross 	(void) memcpy(&dci->dci_sockaddr,
196*b3700b07SGordon Ross 	    &ds->addr, ADSPRIV_SOCKADDR_LEN);
197*b3700b07SGordon Ross 
198*b3700b07SGordon Ross out:
199*b3700b07SGordon Ross 	UNLOCK_CONFIG();
200*b3700b07SGordon Ross 
201*b3700b07SGordon Ross 	return (TRUE);
202*b3700b07SGordon Ross }
203*b3700b07SGordon Ross 
204*b3700b07SGordon Ross /* ARGSUSED */
205*b3700b07SGordon Ross int
206*b3700b07SGordon Ross adspriv_program_1_freeresult(SVCXPRT *xprt, xdrproc_t fun, caddr_t res)
207*b3700b07SGordon Ross {
208*b3700b07SGordon Ross 	(void) xdr_free(fun, res);
209*b3700b07SGordon Ross 	return (TRUE);
210*b3700b07SGordon Ross }
211