1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25%#if	defined(_KERNEL)
26%#include <sys/nvpair.h>
27%#else
28%#include <libnvpair.h>
29%#endif
30
31/*
32 * XDR support for nvlist_t.  libnvpair includes support for serializing
33 * an nvlist, but does not include any direct XDR plug-in support.  Support
34 * is made trickier by the fact that on read xdr_pointer() wants to allocate
35 * structures on its own, even when there's a custom xdr_*() function for
36 * the structure.  nvlist_unpack *also* wants to allocate the nvlist_t,
37 * and it seems wrong to burn sizeof(nvlist_t) into the program binary.
38 *
39 * Another possibility is to use opaque<> in this declaration, but that
40 * requires moving part of the encoding (the interaction with nvlist_pack
41 * and nvlist_unpack) out into the application, instead of keeping it
42 * all encapsulated in this layer.
43 *
44 * The resolution here is to put an nvlist_t * into a new typedef, and have
45 * *that* typedef have a custom xdr_*() function.  xdr allocates space for
46 * the pointer, but leaves all initialization of it nvlist_t *) to the
47 * custom function.
48 */
49#if	defined(RPC_HDR)
50%typedef nvlist_t *nvlist_t_ptr;
51#endif
52
53#if	defined(RPC_XDR)
54%#if	!defined(_KERNEL)
55%#include <string.h>
56%#include <stdio.h>
57%#endif
58%
59%bool_t
60%xdr_nvlist_t_ptr(XDR *xdrs, nvlist_t_ptr *n)
61%{
62%	char *buf;
63%	u_int len;
64%	bool_t ret;
65%	int err;
66%	size_t	sz;
67%	bool_t	present;
68%
69%	switch (xdrs->x_op) {
70%	case XDR_DECODE:
71%		if (!xdr_bool(xdrs, &present))
72%			return (FALSE);
73%		if (!present) {
74%			*n = NULL;
75%			return (TRUE);
76%		}
77%		buf = NULL;
78%		if (!xdr_bytes(xdrs, &buf, &len, ~0))
79%			return (FALSE);
80%
81%		err = nvlist_unpack(buf, (size_t)len, n, 0);
82%#if	defined(_KERNEL)
83%		kmem_free(buf, len);
84%#else
85%		free(buf);
86%#endif
87%
88%		if (err != 0) {
89%#if	!defined(_KERNEL)
90%			fprintf(stderr, "xdr_nvlist_t unpack:  %s\n",
91%			    strerror(err));
92%#endif
93%			return (FALSE);
94%		}
95%		return (TRUE);
96%
97%	case XDR_ENCODE:
98%		present = (*n != NULL);
99%		if (!xdr_bool(xdrs, &present))
100%			return (FALSE);
101%		if (!present)
102%			return (TRUE);
103%		buf = NULL;
104%		err = nvlist_pack(*n, &buf, &sz, NV_ENCODE_XDR, 0);
105%		if (err != 0) {
106%#if	!defined(_KERNEL)
107%			fprintf(stderr, "xdr_nvlist_t pack:  %s\n",
108%			    strerror(err));
109%#endif
110%			return (FALSE);
111%		}
112%
113%		/* nvlist_pack() and xdr_bytes() want different types */
114%		len = (u_int) sz;
115%
116%		ret = xdr_bytes(xdrs, &buf, &len, ~0);
117%#if	defined(_KERNEL)
118%		kmem_free(buf, len);
119%#else
120%		free(buf);
121%#endif
122%
123%		return (ret);
124%
125%	case XDR_FREE:
126%		if (*n != NULL) {
127%			nvlist_free(*n);
128%			*n = NULL;
129%		}
130%		return (TRUE);
131%
132%	default:
133%		return (FALSE);
134%	}
135%}
136#endif
137
138/* opaque type to support non-ASCII strings */
139typedef	string	idmap_utf8str<>;
140typedef	idmap_utf8str	idmap_utf8str_list<>;
141
142/* Return status */
143typedef int idmap_retcode;
144
145/* Identity types */
146enum idmap_id_type {
147	IDMAP_NONE = 0,
148	IDMAP_UID = 1,
149	IDMAP_GID,
150	IDMAP_SID,
151	IDMAP_USID,
152	IDMAP_GSID,
153	IDMAP_POSIXID
154};
155
156/* The type of ID mapping */
157enum idmap_map_type {
158	IDMAP_MAP_TYPE_UNKNOWN = 0,
159	IDMAP_MAP_TYPE_DS_AD,
160	IDMAP_MAP_TYPE_DS_NLDAP,
161	IDMAP_MAP_TYPE_RULE_BASED,
162	IDMAP_MAP_TYPE_EPHEMERAL,
163	IDMAP_MAP_TYPE_LOCAL_SID,
164	IDMAP_MAP_TYPE_KNOWN_SID,
165	IDMAP_MAP_TYPE_IDMU
166};
167
168
169/* Source of ID mapping */
170enum idmap_map_src {
171	IDMAP_MAP_SRC_UNKNOWN = 0,
172	IDMAP_MAP_SRC_NEW,
173	IDMAP_MAP_SRC_CACHE,
174	IDMAP_MAP_SRC_HARD_CODED,
175	IDMAP_MAP_SRC_ALGORITHMIC
176};
177
178
179/* SID */
180struct idmap_sid {
181	string		prefix<>;
182	uint32_t	rid;
183};
184
185/* Identity (sid-posix) */
186union idmap_id switch(idmap_id_type idtype) {
187	case IDMAP_UID: uint32_t uid;
188	case IDMAP_GID: uint32_t gid;
189	case IDMAP_SID: idmap_sid sid;
190	case IDMAP_USID: idmap_sid usid;
191	case IDMAP_GSID: idmap_sid gsid;
192	case IDMAP_NONE: void;
193	case IDMAP_POSIXID: void;
194};
195
196
197/* Name-based mapping rules */
198struct idmap_namerule {
199	bool		is_user;
200	bool		is_wuser;
201	int		direction;
202	idmap_utf8str	windomain;
203	idmap_utf8str	winname;
204	idmap_utf8str	unixname;
205	bool		is_nt4;
206};
207struct idmap_namerules_res {
208	idmap_retcode	retcode;
209	uint64_t	lastrowid;
210	idmap_namerule	rules<>;
211};
212
213/* How ID is mapped */
214struct idmap_how_ds_based {
215	idmap_utf8str	dn;
216	idmap_utf8str	attr;
217	idmap_utf8str	value;
218};
219
220union idmap_how switch(idmap_map_type map_type) {
221	case IDMAP_MAP_TYPE_UNKNOWN: void;
222	case IDMAP_MAP_TYPE_DS_AD: idmap_how_ds_based ad;
223	case IDMAP_MAP_TYPE_DS_NLDAP: idmap_how_ds_based nldap;
224	case IDMAP_MAP_TYPE_RULE_BASED: idmap_namerule rule;
225	case IDMAP_MAP_TYPE_EPHEMERAL: void;
226	case IDMAP_MAP_TYPE_LOCAL_SID: void;
227	case IDMAP_MAP_TYPE_KNOWN_SID: void;
228	case IDMAP_MAP_TYPE_IDMU: idmap_how_ds_based idmu;
229};
230
231struct idmap_info {
232	idmap_map_src	src;
233	idmap_how	how;
234	nvlist_t_ptr	trace;
235};
236
237
238/* Id result */
239struct idmap_id_res {
240	idmap_retcode	retcode;
241	idmap_id	id;
242	int		direction;
243	idmap_info	info;
244};
245struct idmap_ids_res {
246	idmap_retcode	retcode;
247	idmap_id_res	ids<>;
248};
249
250
251/*
252 * Flag supported by mapping requests
253 */
254
255/* Don't allocate a new value for the mapping */
256const IDMAP_REQ_FLG_NO_NEW_ID_ALLOC	= 0x00000001;
257
258/* Validate the given identity before mapping */
259const IDMAP_REQ_FLG_VALIDATE		= 0x00000002;
260
261/* Avoid name service lookups to prevent looping */
262const IDMAP_REQ_FLG_NO_NAMESERVICE	= 0x00000004;
263
264/* Request how a mapping was formed */
265const IDMAP_REQ_FLG_MAPPING_INFO	= 0x00000008;
266
267/*
268 * This libidmap only flag is defined in idmap.h
269 * It enables use of the libidmap cache
270 * const IDMAP_REQ_FLG_USE_CACHE	= 0x00000010;
271 */
272
273/* Request mapping for well-known or local SIDs only */
274const IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY	= 0x00000020;
275
276/* Request trace of mapping process */
277const IDMAP_REQ_FLG_TRACE	= 0x00000040;
278
279
280/*
281 * Mapping direction definitions
282 */
283const IDMAP_DIRECTION_UNDEF =	-1;	/* not defined */
284const IDMAP_DIRECTION_BI =	0;	/* bi-directional */
285const IDMAP_DIRECTION_W2U =	1;	/* windows to unix only */
286const IDMAP_DIRECTION_U2W =	2;	/* unix to windows only */
287
288
289/* Identity mappings (sid-posix) */
290struct idmap_mapping {
291	int32_t		flag;
292	int		direction;
293	idmap_id	id1;
294	idmap_utf8str	id1domain;
295	idmap_utf8str	id1name;
296	idmap_id	id2;
297	idmap_utf8str	id2domain;
298	idmap_utf8str	id2name;
299	idmap_info	info;
300};
301
302typedef idmap_mapping	idmap_mapping_batch<>;
303
304#ifndef IDMAP_XDR_MAPPING_ONLY
305struct idmap_mappings_res {
306	idmap_retcode		retcode;
307	uint64_t		lastrowid;
308	idmap_mapping		mappings<>;
309};
310
311
312/* Update result */
313struct idmap_update_res {
314	idmap_retcode	retcode;
315	int64_t	error_index;
316	idmap_namerule	error_rule;
317	idmap_namerule	conflict_rule;
318};
319
320/* Update requests */
321enum idmap_opnum {
322	OP_NONE = 0,
323	OP_ADD_NAMERULE = 1,
324	OP_RM_NAMERULE = 2,
325	OP_FLUSH_NAMERULES = 3
326};
327union idmap_update_op switch(idmap_opnum opnum) {
328	case OP_ADD_NAMERULE:
329	case OP_RM_NAMERULE:
330		idmap_namerule rule;
331	default:
332		void;
333};
334typedef idmap_update_op idmap_update_batch<>;
335
336const AD_DISC_MAXHOSTNAME = 256;
337
338struct idmap_ad_disc_ds_t {
339	int	port;
340	int	priority;
341	int	weight;
342	char	host[AD_DISC_MAXHOSTNAME];
343};
344
345
346/* get-prop, set-prop */
347enum idmap_prop_type {
348	PROP_UNKNOWN = 0,
349	PROP_LIST_SIZE_LIMIT = 1,
350	PROP_DEFAULT_DOMAIN = 2,	/* default domain name */
351	PROP_DOMAIN_NAME = 3,		/* AD domain name */
352	PROP_MACHINE_SID = 4,		/* machine sid */
353	PROP_DOMAIN_CONTROLLER = 5,	/* domain controller hosts */
354	PROP_FOREST_NAME = 6,		/* forest name */
355	PROP_SITE_NAME = 7,		/* site name */
356	PROP_GLOBAL_CATALOG = 8,	/* global catalog hosts */
357	PROP_AD_UNIXUSER_ATTR = 9,
358	PROP_AD_UNIXGROUP_ATTR = 10,
359	PROP_NLDAP_WINNAME_ATTR = 11,
360	PROP_DIRECTORY_BASED_MAPPING = 12
361};
362
363union idmap_prop_val switch(idmap_prop_type prop) {
364	case PROP_LIST_SIZE_LIMIT:
365		uint64_t intval;
366	case PROP_DEFAULT_DOMAIN:
367	case PROP_DOMAIN_NAME:
368	case PROP_MACHINE_SID:
369	case PROP_FOREST_NAME:
370	case PROP_SITE_NAME:
371	case PROP_AD_UNIXUSER_ATTR:
372	case PROP_AD_UNIXGROUP_ATTR:
373	case PROP_NLDAP_WINNAME_ATTR:
374	case PROP_DIRECTORY_BASED_MAPPING:
375		idmap_utf8str utf8val;
376	case PROP_DOMAIN_CONTROLLER:
377	case PROP_GLOBAL_CATALOG:
378		idmap_ad_disc_ds_t dsval;
379	default:
380		void;
381};
382
383struct idmap_prop_res {
384	idmap_retcode	retcode;
385	idmap_prop_val	value;
386	bool		auto_discovered;
387};
388
389enum idmap_flush_op {
390	IDMAP_FLUSH_EXPIRE = 0,
391	IDMAP_FLUSH_DELETE = 1
392};
393
394/*
395 * Represents an error from the directory lookup service.
396 *
397 * code is an ASCII string that is a key for the error.  It is not
398 * localized.
399 *
400 * fmt is a format string with %n markers for where to include
401 * params[n-1].  It should be, but NEEDSWORK is not localized to
402 * the caller's locale.
403 *
404 * params is a list of parameters for the error - e.g. the name that
405 * encountered a failure, the server that reported the failure, et cetera.
406 * The values are to be used both as marked in fmt and for machine
407 * interpretation of the error.
408 */
409struct directory_error_rpc {
410	idmap_utf8str	code;
411	idmap_utf8str	fmt;
412	idmap_utf8str	params<>;
413};
414
415/*
416 * One value of a multivalued attribute.
417 */
418typedef opaque			directory_value_rpc<>;
419
420/*
421 * The value of an attribute, if found.  Note that this is a list
422 * of directory_value_rpc objects, to support multivalued attributes.
423 */
424union directory_values_rpc switch (bool found) {
425	case TRUE:
426		directory_value_rpc values<>;
427	case FALSE:
428		void;
429};
430
431/*
432 * The status of the lookup for any particular identifier.
433 */
434enum directory_lookup_status_rpc {
435	DIRECTORY_NOT_FOUND = 0,
436	DIRECTORY_FOUND = 1,
437	DIRECTORY_ERROR = 2
438};
439
440/*
441 * This is the data returned for a particular identifier, either a
442 * list of attribute values or an error.
443 */
444union directory_entry_rpc switch (directory_lookup_status_rpc status) {
445	case DIRECTORY_NOT_FOUND:
446		void;
447	case DIRECTORY_FOUND:
448		directory_values_rpc attrs<>;
449	case DIRECTORY_ERROR:
450		directory_error_rpc err;
451};
452
453/*
454 * This is the result from a request, either a list of the entries for
455 * the identifiers specified, or an error.
456 */
457union directory_results_rpc switch (bool failed) {
458	case TRUE:
459		directory_error_rpc	err;
460	case FALSE:
461		directory_entry_rpc	entries<>;
462};
463#endif	/* IDMAP_XDR_MAPPING_ONLY */
464
465program IDMAP_PROG {
466	version IDMAP_V1 {
467#ifndef	IDMAP_XDR_MAPPING_ONLY
468		void
469		IDMAP_NULL(void) = 0;
470#endif	/* IDMAP_XDR_MAPPING_ONLY */
471
472		/* Batch of requests to get mapped identities */
473		idmap_ids_res
474		IDMAP_GET_MAPPED_IDS(idmap_mapping_batch batch) = 1;
475
476#ifndef	IDMAP_XDR_MAPPING_ONLY
477		/* List all identity mappings */
478		idmap_mappings_res
479		IDMAP_LIST_MAPPINGS(int64_t lastrowid,
480			uint64_t limit, int32_t flag) = 2;
481
482		/* List all name-based mapping rules */
483		idmap_namerules_res
484		IDMAP_LIST_NAMERULES(idmap_namerule rule,
485			uint64_t lastrowid, uint64_t limit) = 3;
486
487		/* Batch of update requests */
488		idmap_update_res
489		IDMAP_UPDATE(idmap_update_batch batch) = 4;
490
491		/* Get mapped identity by name */
492		idmap_mappings_res
493		IDMAP_GET_MAPPED_ID_BY_NAME(idmap_mapping request) = 5;
494
495		/* Get configuration property */
496		idmap_prop_res
497		IDMAP_GET_PROP(idmap_prop_type) = 6;
498
499		/*
500		 * Retrieve directory information about a list of users
501		 * or groups by name or SID.
502		 *
503		 * ids is a list of user names, group names, or SIDs.
504		 *
505		 * types is a list of types of the ids in the id list.
506		 * If the type list is shorter than the id list, the last
507		 * type listed applies to all of the ids from that point.
508		 * The defined types are:
509		 *     'n' - name (could be user or group)
510		 *     'u' - user
511		 *     'g' - group
512		 *     's' - SID
513		 *
514		 * attrs is a list of attribute names to retrieve.
515		 */
516		directory_results_rpc DIRECTORY_GET_COMMON(
517			idmap_utf8str_list ids,
518			idmap_utf8str types,
519			idmap_utf8str_list attrs) = 7;
520
521		idmap_retcode
522		IDMAP_FLUSH(idmap_flush_op) = 8;
523#endif	/* IDMAP_XDR_MAPPING_ONLY */
524	} = 1;
525} = 100172;
526