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 */
139 typedef	string	idmap_utf8str<>;
140 typedef	idmap_utf8str	idmap_utf8str_list<>;
141 
142 /* Return status */
143 typedef int idmap_retcode;
144 
145 /* Identity types */
146 enum 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 */
157 enum 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 */
170 enum 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 */
180 struct idmap_sid {
181 	string		prefix<>;
182 	uint32_t	rid;
183 };
184 
185 /* Identity (sid-posix) */
186 union 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 */
198 struct 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 };
207 struct idmap_namerules_res {
208 	idmap_retcode	retcode;
209 	uint64_t	lastrowid;
210 	idmap_namerule	rules<>;
211 };
212 
213 /* How ID is mapped */
214 struct idmap_how_ds_based {
215 	idmap_utf8str	dn;
216 	idmap_utf8str	attr;
217 	idmap_utf8str	value;
218 };
219 
220 union 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 
231 struct idmap_info {
232 	idmap_map_src	src;
233 	idmap_how	how;
234 	nvlist_t_ptr	trace;
235 };
236 
237 
238 /* Id result */
239 struct idmap_id_res {
240 	idmap_retcode	retcode;
241 	idmap_id	id;
242 	int		direction;
243 	idmap_info	info;
244 };
245 struct 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 */
256 const IDMAP_REQ_FLG_NO_NEW_ID_ALLOC	= 0x00000001;
257 
258 /* Validate the given identity before mapping */
259 const IDMAP_REQ_FLG_VALIDATE		= 0x00000002;
260 
261 /* Avoid name service lookups to prevent looping */
262 const IDMAP_REQ_FLG_NO_NAMESERVICE	= 0x00000004;
263 
264 /* Request how a mapping was formed */
265 const 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 */
274 const IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY	= 0x00000020;
275 
276 /* Request trace of mapping process */
277 const IDMAP_REQ_FLG_TRACE	= 0x00000040;
278 
279 
280 /*
281  * Mapping direction definitions
282  */
283 const IDMAP_DIRECTION_UNDEF =	-1;	/* not defined */
284 const IDMAP_DIRECTION_BI =	0;	/* bi-directional */
285 const IDMAP_DIRECTION_W2U =	1;	/* windows to unix only */
286 const IDMAP_DIRECTION_U2W =	2;	/* unix to windows only */
287 
288 
289 /* Identity mappings (sid-posix) */
290 struct 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 
302 typedef idmap_mapping	idmap_mapping_batch<>;
303 
304 #ifndef IDMAP_XDR_MAPPING_ONLY
305 struct idmap_mappings_res {
306 	idmap_retcode		retcode;
307 	uint64_t		lastrowid;
308 	idmap_mapping		mappings<>;
309 };
310 
311 
312 /* Update result */
313 struct 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 */
321 enum idmap_opnum {
322 	OP_NONE = 0,
323 	OP_ADD_NAMERULE = 1,
324 	OP_RM_NAMERULE = 2,
325 	OP_FLUSH_NAMERULES = 3
326 };
327 union 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 };
334 typedef idmap_update_op idmap_update_batch<>;
335 
336 const AD_DISC_MAXHOSTNAME = 256;
337 
338 struct 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 */
347 enum 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 
363 union 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 
383 struct idmap_prop_res {
384 	idmap_retcode	retcode;
385 	idmap_prop_val	value;
386 	bool		auto_discovered;
387 };
388 
389 enum 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  */
409 struct 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  */
418 typedef 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  */
424 union 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  */
434 enum 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  */
444 union 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  */
457 union 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 
465 program 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