xref: /illumos-gate/usr/src/cmd/idmap/idmap/idmap.c (revision bbf21555)
1c5c4113dSnw /*
2c5c4113dSnw  * CDDL HEADER START
3c5c4113dSnw  *
4c5c4113dSnw  * The contents of this file are subject to the terms of the
5c5c4113dSnw  * Common Development and Distribution License (the "License").
6c5c4113dSnw  * You may not use this file except in compliance with the License.
7c5c4113dSnw  *
8c5c4113dSnw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw  * See the License for the specific language governing permissions
11c5c4113dSnw  * and limitations under the License.
12c5c4113dSnw  *
13c5c4113dSnw  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw  *
19c5c4113dSnw  * CDDL HEADER END
20c5c4113dSnw  */
2123a1cceaSRoger A. Faulkner 
22c5c4113dSnw /*
23c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24c5c4113dSnw  */
25c5c4113dSnw 
26c5c4113dSnw #include <stdio.h>
27c5c4113dSnw #include <stdlib.h>
28c5c4113dSnw #include <locale.h>
29c5c4113dSnw #include <strings.h>
30821da340Sdm #include <errno.h>
31821da340Sdm #include <limits.h>
327a8a68f5SJulian Pullen #include <syslog.h>
339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <stdarg.h>
349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <note.h>
35c5c4113dSnw #include "idmap_engine.h"
36c5c4113dSnw #include "idmap_priv.h"
37c5866007SKeyur Desai #include "namemaps.h"
38c5866007SKeyur Desai #include "libadutils.h"
39c5c4113dSnw 
40c5c4113dSnw /* Initialization values for pids/rids: */
41c5c4113dSnw 
42c5c4113dSnw #define	UNDEFINED_UID (uid_t)-1
43c5c4113dSnw #define	UNDEFINED_GID (gid_t)-1
44c5c4113dSnw #define	UNDEFINED_RID (idmap_rid_t)-1;
45c5c4113dSnw 
46479ac375Sdm #define	CHECK_NULL(s)	(s != NULL ? s : "null")
47c5c4113dSnw /*
48c5c4113dSnw  * used in do_show for the type of argument, which can be winname,
49c5c4113dSnw  * unixname, uid, gid, sid or not given at all:
50c5c4113dSnw  */
51c5c4113dSnw 
52c5c4113dSnw #define	TYPE_SID	0x010	/* sid */
53cd37da74Snw #define	TYPE_USID	0x011	/* usid */
54cd37da74Snw #define	TYPE_GSID	0x012	/* gsid */
55c5c4113dSnw #define	TYPE_WN		0x110	/* winname */
568e228215Sdm #define	TYPE_WU		0x111	/* winuser */
578e228215Sdm #define	TYPE_WG		0x112	/* wingroup */
58c5c4113dSnw #define	TYPE_UID	0x001	/* uid */
59c5c4113dSnw #define	TYPE_GID	0x002	/* gid */
60c5c4113dSnw #define	TYPE_PID	0x000	/* pid */
61c5c4113dSnw #define	TYPE_UN		0x100	/* unixname */
628e228215Sdm #define	TYPE_UU		0x101	/* unixuser */
638e228215Sdm #define	TYPE_UG		0x102	/* unixgroup */
64c5c4113dSnw 
65c5c4113dSnw #define	IS_WIN		0x010	/* mask for the windows types */
66c5c4113dSnw #define	IS_NAME		0x100	/* mask for string name types */
678e228215Sdm #define	IS_USER		0x001	/* mask for user types */
688e228215Sdm #define	IS_GROUP	0x002	/* mask for group types */
69c5c4113dSnw 
70479ac375Sdm #define	TYPE_INVALID    0x1000	/* Invalid input */
71479ac375Sdm #define	TYPE_AUTO	0xaaa	/* Autodetection required */
72c5c4113dSnw 
73c5c4113dSnw /* Identity type strings */
74c5c4113dSnw 
75c5c4113dSnw #define	ID_WINNAME	"winname"
768e228215Sdm #define	ID_UNIXUSER	"unixuser"
778e228215Sdm #define	ID_UNIXGROUP	"unixgroup"
788e228215Sdm #define	ID_WINUSER	"winuser"
798e228215Sdm #define	ID_WINGROUP	"wingroup"
80cd37da74Snw #define	ID_USID	"usid"
81cd37da74Snw #define	ID_GSID	"gsid"
82c5c4113dSnw #define	ID_SID	"sid"
83c5c4113dSnw #define	ID_UID	"uid"
84c5c4113dSnw #define	ID_GID	"gid"
85c5c4113dSnw 
86479ac375Sdm #define	ID_UNKNOWN	"unknown"
87479ac375Sdm 
88cd37da74Snw #define	INHIBITED(str)	(str == NULL || *str == 0 || strcmp(str, "\"\"") == 0)
89cd37da74Snw 
90cd37da74Snw typedef struct {
91cd37da74Snw 	char *identity;
92cd37da74Snw 	int code;
93cd37da74Snw } id_code_t;
94cd37da74Snw 
95cd37da74Snw id_code_t identity2code[] = {
96cd37da74Snw 	{ID_WINNAME,	TYPE_WN},
97cd37da74Snw 	{ID_UNIXUSER,	TYPE_UU},
98cd37da74Snw 	{ID_UNIXGROUP,	TYPE_UG},
99cd37da74Snw 	{ID_WINUSER,	TYPE_WU},
100cd37da74Snw 	{ID_WINGROUP,	TYPE_WG},
101cd37da74Snw 	{ID_USID,	TYPE_USID},
102cd37da74Snw 	{ID_GSID,	TYPE_GSID},
103cd37da74Snw 	{ID_SID,	TYPE_SID},
104cd37da74Snw 	{ID_UID,	TYPE_UID},
105cd37da74Snw 	{ID_GID,	TYPE_GID}
106cd37da74Snw };
107cd37da74Snw 
108cd37da74Snw 
109c5c4113dSnw /* Flags */
110c5c4113dSnw 
111c5c4113dSnw #define	f_FLAG	'f'
112c5c4113dSnw #define	t_FLAG	't'
113c5c4113dSnw #define	d_FLAG	'd'
114479ac375Sdm #define	D_FLAG	'D'
115c5c4113dSnw #define	F_FLAG	'F'
116c5c4113dSnw #define	a_FLAG	'a'
117c5c4113dSnw #define	n_FLAG	'n'
118c5c4113dSnw #define	c_FLAG	'c'
11948258c6bSjp #define	v_FLAG	'v'
120148c5f43SAlan Wright #define	V_FLAG	'V'
121479ac375Sdm #define	j_FLAG	'j'
122c5c4113dSnw 
123c5c4113dSnw 
124c5c4113dSnw /* used in the function do_import */
125c5c4113dSnw #define	MAX_INPUT_LINE_SZ 2047
126c5c4113dSnw 
127c5c4113dSnw 
128c5c4113dSnw typedef struct {
129c5c4113dSnw 	int is_user;
130cd37da74Snw 	int is_wuser;
131c5c4113dSnw 	int direction;
132c5c4113dSnw 	boolean_t is_nt4;
133c5c4113dSnw 	char *unixname;
134c5c4113dSnw 	char *winname;
135c5c4113dSnw 	char *windomain;
136c5c4113dSnw 	char *sidprefix;
137c5c4113dSnw 	idmap_rid_t rid;
138c5c4113dSnw 	uid_t pid;
139c5c4113dSnw } name_mapping_t;
140c5c4113dSnw 
141c5c4113dSnw /*
142c5c4113dSnw  * Formats of the output:
143c5c4113dSnw  *
144c5c4113dSnw  * Idmap reads/prints mappings in several formats: ordinary mappings,
145c5c4113dSnw  * name mappings in Samba username map format (smbusers), Netapp
146c5c4113dSnw  * usermap.cfg.
147c5c4113dSnw  *
148c5c4113dSnw  * DEFAULT_FORMAT are in fact the idmap subcommands suitable for
149c5c4113dSnw  * piping to idmap standart input. For example
1508e228215Sdm  * add -d winuser:bob@foo.com unixuser:fred
1518e228215Sdm  * add -d winuser:bob2bar.com unixuser:fred
152c5c4113dSnw  *
153c5c4113dSnw  * SMBUSERS is the format of Samba username map (smbusers). For full
154c5c4113dSnw  * documentation, search for "username map" in smb.conf manpage.
155c5c4113dSnw  * The format is for example
156c5c4113dSnw  *    fred = bob@foo.com bob2@bar.com
157c5c4113dSnw  *
158c5c4113dSnw  * USERMAP_CFG is the format of Netapp usermap.cfg file. Search
159c5c4113dSnw  * http://www.netapp.com/ for more documentation. IP qualifiers are not
160c5c4113dSnw  * supported.
161c5c4113dSnw  * The format is for example
162c5c4113dSnw  *    bob@foo.com => fred
163c5c4113dSnw  *    "Bob With Spaces"@bar.com => fred  #comment
164c5c4113dSnw  *
165c5c4113dSnw  * The previous formats were for name rules. MAPPING_NAME and
166c5c4113dSnw  * MAPPING_ID are for the actual mappings, as seen in show/dump
167c5c4113dSnw  * commands. MAPPING_NAME prefers the string names of the user over
168c5c4113dSnw  * their numerical identificators. MAPPING_ID prints just the
169c5c4113dSnw  * identificators.
170c5c4113dSnw  * Example of the MAPPING_NAME:
171c5c4113dSnw  *   winname:bob@foo.com -> unixname:fred
172c5c4113dSnw  *
173c5c4113dSnw  * Example of the MAPPING_ID:
174c5c4113dSnw  *   sid:S-1-2-3-4 -> uid:5678
175c5c4113dSnw  */
176c5c4113dSnw 
177c5c4113dSnw typedef enum {
178c5c4113dSnw 	UNDEFINED_FORMAT = -1,
179c5c4113dSnw 	DEFAULT_FORMAT = 0,
180c5c4113dSnw 	MAPPING_ID,
181c5c4113dSnw 	MAPPING_NAME,
182c5c4113dSnw 	USERMAP_CFG,
183c5c4113dSnw 	SMBUSERS
184c5c4113dSnw } format_t;
185c5c4113dSnw 
186c5c4113dSnw 
187cd37da74Snw typedef struct {
188cd37da74Snw 	format_t format;
189cd37da74Snw 	FILE *file;
190cd37da74Snw 	name_mapping_t *last;
191cd37da74Snw } print_handle_t;
192c5c4113dSnw 
193c5c4113dSnw /*
194c5c4113dSnw  * idmap_api batch related variables:
195c5c4113dSnw  *
196c5c4113dSnw  * idmap can operate in two modes. It the batch mode, the idmap_api
197da6c28aaSamw  * batch is committed at the end of a batch of several
198c5c4113dSnw  * commands. At the end of input file, typically. This mode is used
199c5c4113dSnw  * for processing input from a file.
200da6c28aaSamw  *  In the non-batch mode, each command is committed immediately. This
201c5c4113dSnw  * mode is used for tty input.
202c5c4113dSnw  */
203c5c4113dSnw 
204c5c4113dSnw /* Are we in the batch mode? */
205c5c4113dSnw static int batch_mode = 0;
206c5c4113dSnw 
2078e228215Sdm /* Self describing stricture for positions */
2088e228215Sdm struct pos_sds {
2098e228215Sdm 	int size;
2108e228215Sdm 	int last;
2118e228215Sdm 	cmd_pos_t *pos[1];
2128e228215Sdm };
2138e228215Sdm 
2148e228215Sdm static struct pos_sds *positions;
2158e228215Sdm 
216c5c4113dSnw /* Handles for idmap_api batch */
217c5c4113dSnw static idmap_udt_handle_t *udt = NULL;
218c5c4113dSnw 
21961b364a9Sjp typedef struct {
22061b364a9Sjp 	char *user;
22161b364a9Sjp 	char *passwd;
22261b364a9Sjp 	char *auth;
22361b364a9Sjp 	char *windomain;
22461b364a9Sjp 	int direction;
22561b364a9Sjp 	idmap_nm_handle_t *handle;
22661b364a9Sjp } namemaps_t;
22761b364a9Sjp 
22861b364a9Sjp static namemaps_t namemaps = {NULL, NULL, NULL, NULL, 0, NULL};
22961b364a9Sjp 
23061b364a9Sjp 
231c5c4113dSnw /* Do we need to commit the udt batch at the end? */
232c5c4113dSnw static int udt_used;
233c5c4113dSnw 
234c5c4113dSnw /* Command handlers */
235c5c4113dSnw 
2368e228215Sdm static int do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2378e228215Sdm static int do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2388e228215Sdm static int do_import(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2398e228215Sdm static int do_list_name_mappings(flag_t *f, int argc, char **argv,
2408e228215Sdm     cmd_pos_t *pos);
2418e228215Sdm static int do_add_name_mapping(flag_t *f, int argc, char **argv,
2428e228215Sdm     cmd_pos_t *pos);
2438e228215Sdm static int do_remove_name_mapping(flag_t *f, int argc, char **argv,
2448e228215Sdm     cmd_pos_t *pos);
2459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int do_flush(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2468e228215Sdm static int do_exit(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2478e228215Sdm static int do_export(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
2488e228215Sdm static int do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
249479ac375Sdm static int do_set_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
250479ac375Sdm static int do_unset_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
251479ac375Sdm static int do_get_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos);
252c5c4113dSnw 
2537a8a68f5SJulian Pullen 
2549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* Command names and their handlers to be passed to idmap_engine */
255c5c4113dSnw 
256c5c4113dSnw static cmd_ops_t commands[] = {
257c5c4113dSnw 	{
258c5c4113dSnw 		"show",
259148c5f43SAlan Wright 		"c(create)v(verbose)V(trace)",
260c5c4113dSnw 		do_show_mapping
261c5c4113dSnw 	},
262c5c4113dSnw 	{
263c5c4113dSnw 		"dump",
26448258c6bSjp 		"n(names)v(verbose)",
265c5c4113dSnw 		do_dump
266c5c4113dSnw 	},
267c5c4113dSnw 	{
268c5c4113dSnw 		"import",
269c5c4113dSnw 		"F(flush)f:(file)",
270c5c4113dSnw 		do_import
271c5c4113dSnw 	},
272c5c4113dSnw 	{
273c5c4113dSnw 		"export",
274c5c4113dSnw 		"f:(file)",
275c5c4113dSnw 		do_export
276c5c4113dSnw 	},
277c5c4113dSnw 	{
278c5c4113dSnw 		"list",
2798e228215Sdm 		"",
280c5c4113dSnw 		do_list_name_mappings
281c5c4113dSnw 	},
282c5c4113dSnw 	{
283c5c4113dSnw 		"add",
2848e228215Sdm 		"d(directional)",
285c5c4113dSnw 		do_add_name_mapping
286c5c4113dSnw 	},
287c5c4113dSnw 	{
288c5c4113dSnw 		"remove",
2898e228215Sdm 		"a(all)t(to)f(from)d(directional)",
290c5c4113dSnw 		do_remove_name_mapping
291c5c4113dSnw 	},
2929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	{
2939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		"flush",
2949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		"a(all)",
2959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		do_flush
2969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	},
297c5c4113dSnw 	{
298c5c4113dSnw 		"exit",
299c5c4113dSnw 		"",
300c5c4113dSnw 		do_exit
301c5c4113dSnw 	},
302c5c4113dSnw 	{
303c5c4113dSnw 		"help",
304c5c4113dSnw 		"",
305c5c4113dSnw 		do_help
306479ac375Sdm 	},
307479ac375Sdm 	{
308479ac375Sdm 		"set-namemap",
309479ac375Sdm 		"a:(authentication)D:(bindDN)j:(passwd-file)",
310479ac375Sdm 		do_set_namemap
311479ac375Sdm 	},
312479ac375Sdm 	{
313479ac375Sdm 		"get-namemap",
314479ac375Sdm 		"",
315479ac375Sdm 		do_get_namemap
316479ac375Sdm 	},
317479ac375Sdm 	{
318479ac375Sdm 		"unset-namemap",
319479ac375Sdm 		"a:(authentication)D:(bindDN)j:(passwd-file):",
320479ac375Sdm 		do_unset_namemap
321c5c4113dSnw 	}
322c5c4113dSnw };
323c5c4113dSnw 
3247a8a68f5SJulian Pullen 
3258e228215Sdm /* Print error message, possibly with a position */
3268e228215Sdm /* printflike */
3278e228215Sdm static void
print_error(cmd_pos_t * pos,const char * format,...)328cd37da74Snw print_error(cmd_pos_t *pos, const char *format, ...)
329cd37da74Snw {
3308e228215Sdm 	size_t length;
3318e228215Sdm 
3328e228215Sdm 	va_list ap;
3338e228215Sdm 
3348e228215Sdm 	va_start(ap, format);
3358e228215Sdm 
3368e228215Sdm 	if (pos != NULL) {
3378e228215Sdm 		length = strlen(pos->line);
3388e228215Sdm 
3398e228215Sdm 		/* Skip newlines etc at the end: */
3408e228215Sdm 		while (length > 0 && isspace(pos->line[length - 1]))
3418e228215Sdm 			length--;
3428e228215Sdm 
3438e228215Sdm 		(void) fprintf(stderr,
3448e228215Sdm 		    gettext("Error at line %d: %.*s\n"),
3458e228215Sdm 		    pos->linenum,
3468e228215Sdm 		    length,
3478e228215Sdm 		    pos->line);
3488e228215Sdm 	}
3498e228215Sdm 	(void) vfprintf(stderr, format, ap);
3508e228215Sdm 
3518e228215Sdm 	va_end(ap);
3528e228215Sdm }
3538e228215Sdm 
3548e228215Sdm /* Inits positions sds. 0 means everything went OK, -1 for errors */
3558e228215Sdm static int
init_positions()356cd37da74Snw init_positions()
357cd37da74Snw {
3588e228215Sdm 	int init_size = 32; /* Initial size of the positions array */
3598e228215Sdm 
3608e228215Sdm 	positions = (struct pos_sds *) malloc(sizeof (struct pos_sds) +
3618e228215Sdm 	    (init_size - 1) * sizeof (cmd_pos_t *));
3628e228215Sdm 
3638e228215Sdm 	if (positions == NULL) {
36461b364a9Sjp 		print_error(NULL, "%s.\n", strerror(ENOMEM));
3658e228215Sdm 		return (-1);
3668e228215Sdm 	}
3678e228215Sdm 
3688e228215Sdm 	positions->size = init_size;
3698e228215Sdm 	positions->last = 0;
3708e228215Sdm 	return (0);
3718e228215Sdm }
3728e228215Sdm 
3738e228215Sdm /* Free the positions array */
3748e228215Sdm static void
fini_positions()375cd37da74Snw fini_positions()
376cd37da74Snw {
3778e228215Sdm 	int i;
3788e228215Sdm 	for (i = 0; i < positions->last; i++) {
3798e228215Sdm 		if (positions->pos[i] == NULL)
3808e228215Sdm 			continue;
3818e228215Sdm 		free(positions->pos[i]->line);
3828e228215Sdm 		free(positions->pos[i]);
3838e228215Sdm 	}
3848e228215Sdm 	free(positions);
3858e228215Sdm 
3868e228215Sdm 	positions = NULL;
3878e228215Sdm }
3888e228215Sdm 
3898e228215Sdm /*
3908e228215Sdm  * Add another position to the positions array. 0 means everything
3918e228215Sdm  * went OK, -1 for errors
3928e228215Sdm  */
3938e228215Sdm static int
positions_add(cmd_pos_t * pos)394cd37da74Snw positions_add(cmd_pos_t *pos)
395cd37da74Snw {
3968e228215Sdm 	if (positions->last >= positions->size) {
3978e228215Sdm 		positions->size *= 2;
3988e228215Sdm 		positions = (struct pos_sds *)realloc(positions,
3998e228215Sdm 		    sizeof (struct pos_sds) +
4008e228215Sdm 		    (positions->size - 1) * sizeof (cmd_pos_t *));
4018e228215Sdm 		if (positions == NULL)
4028e228215Sdm 			goto nomemory;
4038e228215Sdm 	}
4048e228215Sdm 
4058e228215Sdm 	if (pos == NULL)
4068e228215Sdm 		positions->pos[positions->last] = NULL;
4078e228215Sdm 	else {
4088e228215Sdm 		positions->pos[positions->last] = (cmd_pos_t *)calloc(1,
4098e228215Sdm 		    sizeof (cmd_pos_t));
4108e228215Sdm 		if (positions->pos[positions->last] == NULL)
4118e228215Sdm 			goto nomemory;
4128e228215Sdm 
4138e228215Sdm 		*positions->pos[positions->last] = *pos;
4148e228215Sdm 		positions->pos[positions->last]->line = strdup(pos->line);
4158e228215Sdm 		if (positions->pos[positions->last]->line == NULL)
4168e228215Sdm 			goto nomemory;
4178e228215Sdm 	}
4188e228215Sdm 
4198e228215Sdm 	positions->last++;
4208e228215Sdm 	return (0);
4218e228215Sdm 
4228e228215Sdm nomemory:
42361b364a9Sjp 	print_error(NULL, "%s.\n", strerror(ENOMEM));
4248e228215Sdm 	return (-1);
4258e228215Sdm }
4268e228215Sdm 
4278e228215Sdm 
4288e228215Sdm 
429821da340Sdm 
430821da340Sdm /*
431821da340Sdm  * Compare two strings just like strcmp, but stop before the end of
432821da340Sdm  * the s2
433821da340Sdm  */
434821da340Sdm static int
strcmp_no0(const char * s1,const char * s2)435cd37da74Snw strcmp_no0(const char *s1, const char *s2)
436cd37da74Snw {
437821da340Sdm 	return (strncmp(s1, s2, strlen(s2)));
438821da340Sdm }
439821da340Sdm 
440c5c4113dSnw /* Print help message */
441c5c4113dSnw static void
help()442cd37da74Snw help()
443cd37da74Snw {
444c5c4113dSnw 	(void) fprintf(stderr,
445c5c4113dSnw 	    "idmap\n"
446c5c4113dSnw 	    "idmap -f command-file\n"
4478e228215Sdm 	    "idmap add [-d] name1 name2\n"
448479ac375Sdm 	    "idmap dump [-n] [-v]\n"
449479ac375Sdm 	    "idmap export [-f file] format\n"
4509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    "idmap flush [-a]\n"
451479ac375Sdm 	    "idmap get-namemap name\n"
452479ac375Sdm 	    "idmap help\n"
453479ac375Sdm 	    "idmap import [-F] [-f file] format\n"
454479ac375Sdm 	    "idmap list\n"
4558e228215Sdm 	    "idmap remove -a\n"
456cd37da74Snw 	    "idmap remove [-f|-t] name\n"
4578e228215Sdm 	    "idmap remove [-d] name1 name2\n"
458fd9ee8b5Sjoyce mcintosh 	    "idmap set-namemap [-a authenticationMethod] [-D bindDN]\n"
459fd9ee8b5Sjoyce mcintosh 	    "    [-j passwdfile] name1 name2\n"
460479ac375Sdm 	    "idmap show [-c] [-v] identity [targettype]\n"
461fd9ee8b5Sjoyce mcintosh 	    "idmap unset-namemap [-a authenticationMethod] [-D bindDN]\n"
462fd9ee8b5Sjoyce mcintosh 	    "    [-j passwdfile] name [targettype]\n");
463c5c4113dSnw }
464c5c4113dSnw 
465c5c4113dSnw /* The handler for the "help" command. */
466c5c4113dSnw static int
467c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_help(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)4688e228215Sdm do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
469c5c4113dSnw {
470c5c4113dSnw 	help();
471c5c4113dSnw 	return (0);
472c5c4113dSnw }
473c5c4113dSnw 
474c5c4113dSnw /* Initialization of the commands which perform write operations  */
475c5c4113dSnw static int
init_udt_batch()476cd37da74Snw init_udt_batch()
477cd37da74Snw {
478c5c4113dSnw 	idmap_stat stat;
479c5c4113dSnw 
4801fdeec65Sjoyce mcintosh 	stat = idmap_udt_create(&udt);
481479ac375Sdm 	if (stat != IDMAP_SUCCESS) {
4828e228215Sdm 		print_error(NULL,
483c5c4113dSnw 		    gettext("Error initiating transaction (%s)"),
4841fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
485c5c4113dSnw 		return (-1);
486c5c4113dSnw 	}
4878e228215Sdm 
4888e228215Sdm 	if (init_positions() < 0)
4898e228215Sdm 		return (-1);
4908e228215Sdm 
491c5c4113dSnw 	return (0);
492c5c4113dSnw }
493c5c4113dSnw 
494c5c4113dSnw 
495c5c4113dSnw /* Finalization of the write commands  */
496c5c4113dSnw static int
init_udt_command()497cd37da74Snw init_udt_command()
498cd37da74Snw {
499c5c4113dSnw 	udt_used = 1;
500c5c4113dSnw 	if (batch_mode)
501c5c4113dSnw 		return (0);
502c5c4113dSnw 
503c5c4113dSnw 	return (init_udt_batch());
504c5c4113dSnw }
505c5c4113dSnw 
506c5c4113dSnw 
507c5c4113dSnw /* If everythings is OK, send the udt batch to idmapd  */
5088e228215Sdm static int
fini_udt_command(int ok,cmd_pos_t * pos)509cd37da74Snw fini_udt_command(int ok, cmd_pos_t *pos)
510cd37da74Snw {
5118e228215Sdm 	int rc = 0;
5128e228215Sdm 	int64_t failpos;
5138e228215Sdm 	idmap_stat stat, stat1;
5148e228215Sdm 	cmd_pos_t *reported_pos;
515c5c4113dSnw 
516c5c4113dSnw 	if (batch_mode)
5178e228215Sdm 		return (0);
5188e228215Sdm 	if (udt == NULL) {
5198e228215Sdm 		print_error(pos,
5208e228215Sdm 		    gettext("Internal error: uninitiated batch.\n"));
5218e228215Sdm 		return (-1);
5228e228215Sdm 	}
523c5c4113dSnw 
524c5c4113dSnw 	if (ok && udt_used) {
525c5c4113dSnw 		stat = idmap_udt_commit(udt);
5268e228215Sdm 		if (stat == IDMAP_SUCCESS)
5278e228215Sdm 			goto out;
5288e228215Sdm 
5298e228215Sdm 		rc = -1;
5308e228215Sdm 
5318e228215Sdm 		stat1 = idmap_udt_get_error_index(udt, &failpos);
5328e228215Sdm 		if (stat1 != IDMAP_SUCCESS) {
5338e228215Sdm 			print_error(NULL,
5348e228215Sdm 			    gettext("Error diagnosing transaction (%s)\n"),
5351fdeec65Sjoyce mcintosh 			    idmap_stat2string(stat1));
5368e228215Sdm 			goto out;
537c5c4113dSnw 		}
5388e228215Sdm 
5398e228215Sdm 
5408e228215Sdm 		if (failpos < 0)
5418e228215Sdm 			reported_pos = pos;
5428e228215Sdm 		else
5438e228215Sdm 			reported_pos = positions->pos[failpos];
5448e228215Sdm 
5458e228215Sdm 		print_error(reported_pos,
5468e228215Sdm 		    gettext("Error commiting transaction (%s)\n"),
5471fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
548c5c4113dSnw 	}
549c5c4113dSnw 
5508e228215Sdm out:
551c5c4113dSnw 	idmap_udt_destroy(udt);
552c5c4113dSnw 	udt = NULL;
553c5c4113dSnw 	udt_used = 0;
5548e228215Sdm 	fini_positions();
5558e228215Sdm 	return (rc);
556c5c4113dSnw }
557c5c4113dSnw 
55861b364a9Sjp 
55961b364a9Sjp /*
56061b364a9Sjp  * Compare two possibly NULL strings
56161b364a9Sjp  */
56261b364a9Sjp static int
strcasecmp_null(char * a,char * b)56361b364a9Sjp strcasecmp_null(char *a, char *b)
56461b364a9Sjp {
56561b364a9Sjp 	if (a == NULL && b == NULL)
56661b364a9Sjp 		return (0);
56761b364a9Sjp 	if (a == NULL)
56861b364a9Sjp 		return (-1);
56961b364a9Sjp 	if (b == NULL)
57061b364a9Sjp 		return (1);
57161b364a9Sjp 	return (strcasecmp(a, b));
57261b364a9Sjp }
57361b364a9Sjp 
57461b364a9Sjp /*
57561b364a9Sjp  * Compare two possibly NULL strings
57661b364a9Sjp  */
57761b364a9Sjp static int
strcmp_null(char * a,char * b)57861b364a9Sjp strcmp_null(char *a, char *b)
57961b364a9Sjp {
58061b364a9Sjp 	if (a == NULL && b == NULL)
58161b364a9Sjp 		return (0);
58261b364a9Sjp 	if (a == NULL)
58361b364a9Sjp 		return (-1);
58461b364a9Sjp 	if (b == NULL)
58561b364a9Sjp 		return (1);
58661b364a9Sjp 	return (strcmp(a, b));
58761b364a9Sjp }
58861b364a9Sjp 
58961b364a9Sjp static void
free_null(char ** ptr)59061b364a9Sjp free_null(char **ptr)
59161b364a9Sjp {
59261b364a9Sjp 	if (*ptr != NULL) {
59361b364a9Sjp 		free(*ptr);
59461b364a9Sjp 		*ptr = NULL;
59561b364a9Sjp 	}
59661b364a9Sjp }
59761b364a9Sjp 
59861b364a9Sjp static
59961b364a9Sjp void
namemaps_free()60061b364a9Sjp namemaps_free()
60161b364a9Sjp {
60261b364a9Sjp 	free_null(&namemaps.user);
60361b364a9Sjp 
60461b364a9Sjp 	if (namemaps.passwd != NULL)
60561b364a9Sjp 		(void) memset(namemaps.passwd, 0, strlen(namemaps.passwd));
60661b364a9Sjp 
60761b364a9Sjp 	free_null(&namemaps.passwd);
60861b364a9Sjp 	free_null(&namemaps.auth);
60961b364a9Sjp 	free_null(&namemaps.windomain);
61061b364a9Sjp 
61161b364a9Sjp 	namemaps.direction = IDMAP_DIRECTION_UNDEF;
61261b364a9Sjp 	if (namemaps.handle != NULL) {
61361b364a9Sjp 		idmap_fini_namemaps(namemaps.handle);
61461b364a9Sjp 		namemaps.handle = NULL;
61561b364a9Sjp 	}
61661b364a9Sjp }
61761b364a9Sjp 
61861b364a9Sjp /* Initialization of the commands which perform write operations  */
61961b364a9Sjp static
62061b364a9Sjp int
init_nm_command(char * user,char * passwd,char * auth,char * windomain,int direction,cmd_pos_t * pos)62161b364a9Sjp init_nm_command(char *user, char *passwd, char *auth, char *windomain,
62261b364a9Sjp     int direction, cmd_pos_t *pos)
62361b364a9Sjp {
62461b364a9Sjp 	idmap_stat stat;
62561b364a9Sjp 
62661b364a9Sjp 	if (namemaps.handle != NULL && (
62761b364a9Sjp 	    strcmp_null(user, namemaps.user) != 0 ||
62861b364a9Sjp 	    strcmp_null(passwd, namemaps.passwd) != 0 ||
62961b364a9Sjp 	    strcasecmp_null(auth, namemaps.auth) != 0 ||
63061b364a9Sjp 	    strcasecmp_null(windomain, namemaps.windomain) != 0 ||
63161b364a9Sjp 	    direction != namemaps.direction)) {
63261b364a9Sjp 		namemaps_free();
63361b364a9Sjp 	}
63461b364a9Sjp 
63561b364a9Sjp 	if (namemaps.handle == NULL) {
6361fdeec65Sjoyce mcintosh 		stat = idmap_init_namemaps(&namemaps.handle, user,
63761b364a9Sjp 		    passwd, auth, windomain, direction);
63861b364a9Sjp 		if (stat != IDMAP_SUCCESS) {
63961b364a9Sjp 			print_error(pos,
64061b364a9Sjp 			    gettext("Error: could not perform directory-based "
64161b364a9Sjp 			    "name mapping operation (%s)"),
6421fdeec65Sjoyce mcintosh 			    idmap_stat2string(stat));
64361b364a9Sjp 			namemaps_free();
64461b364a9Sjp 			return (-1);
64561b364a9Sjp 		}
64661b364a9Sjp 
64761b364a9Sjp 		if (user != NULL && (namemaps.user = strdup(user)) == NULL ||
64861b364a9Sjp 		    passwd != NULL && (namemaps.passwd =
64961b364a9Sjp 		    strdup(passwd)) == NULL ||
65061b364a9Sjp 		    auth != NULL && (namemaps.auth = strdup(auth)) == NULL ||
65161b364a9Sjp 		    windomain != NULL && (namemaps.windomain =
65261b364a9Sjp 		    strdup(windomain)) == NULL) {
65361b364a9Sjp 			print_error(pos, "%s.\n", strerror(ENOMEM));
65461b364a9Sjp 			namemaps_free();
65561b364a9Sjp 			return (-1);
65661b364a9Sjp 		}
65761b364a9Sjp 		namemaps.direction = direction;
65861b364a9Sjp 
65961b364a9Sjp 	}
66061b364a9Sjp 
66161b364a9Sjp 	return (0);
66261b364a9Sjp }
66361b364a9Sjp 
66461b364a9Sjp 
66561b364a9Sjp /* Cleanup after the xxx-namemaps commands  */
66661b364a9Sjp static void
fini_nm_command()66761b364a9Sjp fini_nm_command()
66861b364a9Sjp {
66961b364a9Sjp 	if (batch_mode)
67061b364a9Sjp 		return;
67161b364a9Sjp 
67261b364a9Sjp 	namemaps_free();
67361b364a9Sjp }
67461b364a9Sjp 
67561b364a9Sjp 
676c5c4113dSnw /* Convert numeric expression of the direction to it's string form */
677c5c4113dSnw static char *
direction2string(int direction)678cd37da74Snw direction2string(int direction)
679cd37da74Snw {
680c5c4113dSnw 	switch (direction) {
6818e228215Sdm 	case IDMAP_DIRECTION_BI:
682c5c4113dSnw 		return ("==");
6838e228215Sdm 	case IDMAP_DIRECTION_W2U:
684c5c4113dSnw 		return ("=>");
6858e228215Sdm 	case IDMAP_DIRECTION_U2W:
686c5c4113dSnw 		return ("<=");
687c5c4113dSnw 	default:
688821da340Sdm 		/* This can never happen: */
6898e228215Sdm 		print_error(NULL,
690821da340Sdm 		    gettext("Internal error: invalid direction.\n"));
691c5c4113dSnw 		return ("");
692c5c4113dSnw 	}
693c5c4113dSnw 	/* never reached */
694c5c4113dSnw }
695c5c4113dSnw 
696821da340Sdm /*
697821da340Sdm  * Returns 1 if c is a shell-meta-character requiring quoting, 0
698821da340Sdm  * otherwise.
699821da340Sdm  *
700821da340Sdm  * We don't quote '*' and ':' because they cannot do any harm
701821da340Sdm  * a) they have no meaning to idmap_engine b) even ifsomebody copy &
702821da340Sdm  * paste idmap output to a shell commandline, there is the identity
703821da340Sdm  * type string in front of them. On the other hand, '*' and ':' are
704821da340Sdm  * everywhere.
705821da340Sdm  */
706821da340Sdm static int
is_shell_special(char c)707cd37da74Snw is_shell_special(char c)
708cd37da74Snw {
709821da340Sdm 	if (isspace(c))
710821da340Sdm 		return (1);
711821da340Sdm 
712821da340Sdm 	if (strchr("&^{}#;'\"\\`!$()[]><|~", c) != NULL)
713821da340Sdm 		return (1);
714821da340Sdm 
715821da340Sdm 	return (0);
716821da340Sdm }
717821da340Sdm 
7188e228215Sdm /*
7198e228215Sdm  * Returns 1 if c is a shell-meta-character requiring quoting even
7208e228215Sdm  * inside double quotes, 0 otherwise. It means \, " and $ .
7218e228215Sdm  *
7228e228215Sdm  * This set of characters is a subset of those in is_shell_special().
7238e228215Sdm  */
7248e228215Sdm static int
is_dq_special(char c)725cd37da74Snw is_dq_special(char c)
726cd37da74Snw {
7278e228215Sdm 	if (strchr("\\\"$", c) != NULL)
7288e228215Sdm 		return (1);
7298e228215Sdm 	return (0);
7308e228215Sdm }
7318e228215Sdm 
7328e228215Sdm 
7338e228215Sdm 
7348e228215Sdm 
735821da340Sdm /*
736821da340Sdm  * Quote any shell meta-characters in the given string.  If 'quote' is
737821da340Sdm  * true then use double-quotes to quote the whole string, else use
738821da340Sdm  * back-slash to quote each individual meta-character.
739821da340Sdm  *
740821da340Sdm  * The resulting string is placed in *res.  Callers must free *res if the
741821da340Sdm  * return value isn't 0 (even if the given string had no meta-chars).
742821da340Sdm  * If there are any errors this returns -1, else 0.
743821da340Sdm  */
744c5c4113dSnw static int
shell_app(char ** res,char * string,int quote)745cd37da74Snw shell_app(char **res, char *string, int quote)
746cd37da74Snw {
747821da340Sdm 	int i, j;
748821da340Sdm 	uint_t noss = 0; /* Number Of Shell Special chars in the input */
749821da340Sdm 	uint_t noqb = 0; /* Number Of Quotes and Backslahes in the input */
750821da340Sdm 	char *out;
751821da340Sdm 	size_t len_orig = strlen(string);
752821da340Sdm 	size_t len;
753c5c4113dSnw 
754cd37da74Snw 	if (INHIBITED(string)) {
755cd37da74Snw 		out = strdup("\"\"");
756cd37da74Snw 		if (out == NULL) {
75761b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
758cd37da74Snw 			return (-1);
759cd37da74Snw 		}
760cd37da74Snw 		*res = out;
761cd37da74Snw 		return (0);
762cd37da74Snw 	}
763cd37da74Snw 
764821da340Sdm 	/* First, let us count how many characters we need to quote: */
765821da340Sdm 	for (i = 0; i < len_orig; i++) {
766821da340Sdm 		if (is_shell_special(string[i])) {
767821da340Sdm 			noss++;
7688e228215Sdm 			if (is_dq_special(string[i]))
769821da340Sdm 				noqb++;
770821da340Sdm 		}
771821da340Sdm 
772821da340Sdm 	}
773821da340Sdm 
774821da340Sdm 	/* Do we need to quote at all? */
775821da340Sdm 	if (noss == 0) {
776821da340Sdm 		out = strdup(string);
777821da340Sdm 		if (out == NULL) {
77861b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
779821da340Sdm 			return (-1);
780821da340Sdm 		}
781821da340Sdm 		*res = out;
782821da340Sdm 		return (0);
783821da340Sdm 	}
784821da340Sdm 
785821da340Sdm 	/* What is the length of the result? */
786821da340Sdm 	if (quote)
787821da340Sdm 		len = strlen(string) + 2 + noqb + 1; /* 2 for quotation marks */
788821da340Sdm 	else
789821da340Sdm 		len = strlen(string) + noss + 1;
790821da340Sdm 
791cd37da74Snw 	out = (char *)malloc(len);
792821da340Sdm 	if (out == NULL) {
79361b364a9Sjp 		print_error(NULL, "%s.\n", strerror(ENOMEM));
794c5c4113dSnw 		return (-1);
795c5c4113dSnw 	}
796c5c4113dSnw 
797821da340Sdm 	j = 0;
798821da340Sdm 	if (quote)
799821da340Sdm 		out[j++] = '"';
800c5c4113dSnw 
801821da340Sdm 	for (i = 0; i < len_orig; i++) {
802821da340Sdm 		/* Quote the dangerous chars by a backslash */
8038e228215Sdm 		if (quote && is_dq_special(string[i]) ||
804cd37da74Snw 		    (!quote && is_shell_special(string[i]))) {
805821da340Sdm 			out[j++] = '\\';
806c5c4113dSnw 		}
807821da340Sdm 		out[j++] = string[i];
808c5c4113dSnw 	}
809c5c4113dSnw 
810821da340Sdm 	if (quote)
811821da340Sdm 		out[j++] = '"';
812821da340Sdm 
813821da340Sdm 	out[j] = '\0';
814821da340Sdm 	*res = out;
815c5c4113dSnw 	return (0);
816c5c4113dSnw }
817c5c4113dSnw 
818c5c4113dSnw /* Assemble string form sid */
819c5c4113dSnw static char *
sid_format(name_mapping_t * nm)820cd37da74Snw sid_format(name_mapping_t *nm)
821cd37da74Snw {
822c5c4113dSnw 	char *to;
823c5c4113dSnw 	size_t len;
824cd37da74Snw 	char *typestring;
825cd37da74Snw 
826cd37da74Snw 	switch (nm->is_wuser) {
827479ac375Sdm 	case IDMAP_YES:
828cd37da74Snw 		typestring = ID_USID;
829cd37da74Snw 		break;
830479ac375Sdm 	case IDMAP_NO:
831cd37da74Snw 		typestring = ID_GSID;
832cd37da74Snw 		break;
833cd37da74Snw 	default:
834cd37da74Snw 		typestring = ID_SID;
835cd37da74Snw 		break;
836cd37da74Snw 	}
837c5c4113dSnw 
838cd37da74Snw 	/* 'usid:' + sidprefix + '-' + rid + '\0' */
839cd37da74Snw 	len = strlen(nm->sidprefix) + 7 + 3 * sizeof (nm->rid);
840cd37da74Snw 	to = (char *)malloc(len);
841c5c4113dSnw 	if (to == NULL)
842c5c4113dSnw 		return (NULL);
843c5c4113dSnw 
844cd37da74Snw 	(void) snprintf(to, len, "%s:%s-%u", typestring, nm->sidprefix,
845cd37da74Snw 	    nm->rid);
846c5c4113dSnw 	return (to);
847c5c4113dSnw }
848c5c4113dSnw 
849c5c4113dSnw /* Assemble string form uid or gid */
850c5c4113dSnw static char *
pid_format(uid_t from,int is_user)851cd37da74Snw pid_format(uid_t from, int is_user)
852cd37da74Snw {
853c5c4113dSnw 	char *to;
854c5c4113dSnw 	size_t len;
855c5c4113dSnw 
856c5c4113dSnw 	/* ID_UID ":" + uid + '\0' */
857c5c4113dSnw 	len = 5 + 3 * sizeof (uid_t);
858cd37da74Snw 	to = (char *)malloc(len);
859c5c4113dSnw 	if (to == NULL)
860c5c4113dSnw 		return (NULL);
861c5c4113dSnw 
862479ac375Sdm 	(void) snprintf(to, len, "%s:%u", is_user ? ID_UID : ID_GID, from);
863c5c4113dSnw 	return (to);
864c5c4113dSnw }
865c5c4113dSnw 
8668e228215Sdm /* Assemble winname, e.g. "winuser:bob@foo.sun.com", from name_mapping_t */
867c5c4113dSnw static int
nm2winqn(name_mapping_t * nm,char ** winqn)868cd37da74Snw nm2winqn(name_mapping_t *nm, char **winqn)
869cd37da74Snw {
870c5c4113dSnw 	char *out;
871c5c4113dSnw 	size_t length = 0;
872c5c4113dSnw 	int is_domain = 1;
8738e228215Sdm 	char *prefix;
874c5c4113dSnw 
875c5c4113dSnw 	/* Sometimes there are no text names. Return a sid, then. */
876cd37da74Snw 	if (nm->winname == NULL && nm->sidprefix != NULL) {
877cd37da74Snw 		*winqn = sid_format(nm);
878c5c4113dSnw 		return (0);
879c5c4113dSnw 	}
880c5c4113dSnw 
881cd37da74Snw 	switch (nm->is_wuser) {
882479ac375Sdm 	case IDMAP_YES:
8838e228215Sdm 		prefix = ID_WINUSER ":";
8848e228215Sdm 		break;
885479ac375Sdm 	case IDMAP_NO:
8868e228215Sdm 		prefix = ID_WINGROUP ":";
8878e228215Sdm 		break;
888479ac375Sdm 	case IDMAP_UNKNOWN:
8898e228215Sdm 		prefix = ID_WINNAME ":";
8908e228215Sdm 		break;
8918e228215Sdm 
8928e228215Sdm 	}
8938e228215Sdm 
894cd37da74Snw 	length = strlen(prefix);
895cd37da74Snw 
896cd37da74Snw 	if (nm->winname != NULL)
897cd37da74Snw 		length += strlen(nm->winname);
898c5c4113dSnw 
899c5c4113dSnw 	/* Windomain is not mandatory: */
900cd37da74Snw 	if (nm->windomain == NULL || INHIBITED(nm->winname))
901c5c4113dSnw 		is_domain = 0;
902c5c4113dSnw 	else
903c5c4113dSnw 		length += strlen(nm->windomain) + 1;
904c5c4113dSnw 
905cd37da74Snw 	out = (char *)malloc(length + 1);
906c5c4113dSnw 	if (out == NULL) {
9078e228215Sdm 		print_error(NULL,
90861b364a9Sjp 		    "%s.\n", strerror(ENOMEM));
909c5c4113dSnw 		return (-1);
910c5c4113dSnw 	}
911c5c4113dSnw 
9128e228215Sdm 	(void) strcpy(out, prefix);
913c5c4113dSnw 
914cd37da74Snw 	/* LINTED E_NOP_IF_STMT */
915cd37da74Snw 	if (nm->winname == NULL)
916cd37da74Snw 		;
917cd37da74Snw 	else if (!is_domain)
918c5c4113dSnw 		(void) strcat(out, nm->winname);
919c5c4113dSnw 	else if (nm->is_nt4) {
920c5c4113dSnw 		(void) strcat(out, nm->windomain);
921c5c4113dSnw 		(void) strcat(out, "\\");
922c5c4113dSnw 		(void) strcat(out, nm->winname);
923c5c4113dSnw 	} else {
924c5c4113dSnw 		(void) strcat(out, nm->winname);
925c5c4113dSnw 		(void) strcat(out, "@");
926c5c4113dSnw 		(void) strcat(out, nm->windomain);
927c5c4113dSnw 	}
928c5c4113dSnw 
929c5c4113dSnw 	*winqn = out;
930c5c4113dSnw 	return (0);
931c5c4113dSnw }
932c5c4113dSnw 
933cd37da74Snw /*
934cd37da74Snw  * Assemble a text unixname, e.g. unixuser:fred. Use only for
935cd37da74Snw  * mapping, not namerules - there an empty name means inhibited
936cd37da74Snw  * mappings, while here pid is printed if there is no name.
937cd37da74Snw  */
938cd37da74Snw static
939cd37da74Snw int
nm2unixname(name_mapping_t * nm,char ** unixname)940cd37da74Snw nm2unixname(name_mapping_t *nm, char **unixname)
941cd37da74Snw {
942c5c4113dSnw 	size_t length = 0;
943cd37da74Snw 	char *out, *it, *prefix;
944c5c4113dSnw 
945c5c4113dSnw 	/* Sometimes there is no name, just pid: */
946c5c4113dSnw 	if (nm->unixname == NULL) {
947c5c4113dSnw 		if (nm->pid == UNDEFINED_UID)
948c5c4113dSnw 			return (-1);
949c5c4113dSnw 
950c5c4113dSnw 		*unixname = pid_format(nm->pid, nm->is_user);
951c5c4113dSnw 		return (0);
952c5c4113dSnw 	}
953c5c4113dSnw 
954821da340Sdm 	if (shell_app(&it, nm->unixname, 0))
955c5c4113dSnw 		return (-1);
956c5c4113dSnw 
9578e228215Sdm 
9588e228215Sdm 	switch (nm->is_user) {
959479ac375Sdm 	case IDMAP_YES:
9608e228215Sdm 		prefix = ID_UNIXUSER ":";
9618e228215Sdm 		break;
962479ac375Sdm 	case IDMAP_NO:
9638e228215Sdm 		prefix = ID_UNIXGROUP ":";
9648e228215Sdm 		break;
965479ac375Sdm 	case IDMAP_UNKNOWN:
966479ac375Sdm 		prefix = ID_UNIXUSER ":";
9678e228215Sdm 		break;
9688e228215Sdm 
9698e228215Sdm 	}
9708e228215Sdm 
9718e228215Sdm 	length = strlen(prefix) + strlen(it);
972c5c4113dSnw 
973cd37da74Snw 	out = (char *)malloc(length + 1);
974c5c4113dSnw 	if (out == NULL) {
9758e228215Sdm 		print_error(NULL,
97661b364a9Sjp 		    "%s.\n", strerror(ENOMEM));
977c5c4113dSnw 		free(it);
978c5c4113dSnw 		return (-1);
979c5c4113dSnw 	}
980c5c4113dSnw 
9818e228215Sdm 	(void) strcpy(out, prefix);
982c5c4113dSnw 	(void) strcat(out, it);
983c5c4113dSnw 	free(it);
984c5c4113dSnw 
985c5c4113dSnw 	*unixname = out;
986c5c4113dSnw 	return (0);
987c5c4113dSnw }
988c5c4113dSnw 
989cd37da74Snw /* Allocate a new name_mapping_t and initialize the values. */
990cd37da74Snw static name_mapping_t *
name_mapping_init()991cd37da74Snw name_mapping_init()
992cd37da74Snw {
993cd37da74Snw 	name_mapping_t *nm = (name_mapping_t *)malloc(sizeof (name_mapping_t));
994cd37da74Snw 	if (nm == NULL) {
99561b364a9Sjp 		print_error(NULL, "%s.\n", strerror(ENOMEM));
996cd37da74Snw 		return (NULL);
997cd37da74Snw 	}
998cd37da74Snw 	nm->winname = nm->windomain = nm->unixname = nm->sidprefix = NULL;
999cd37da74Snw 	nm->rid = UNDEFINED_RID;
1000cd37da74Snw 	nm->is_nt4 = B_FALSE;
1001479ac375Sdm 	nm->is_user = IDMAP_UNKNOWN;
1002479ac375Sdm 	nm->is_wuser = IDMAP_UNKNOWN;
1003cd37da74Snw 	nm->direction = IDMAP_DIRECTION_UNDEF;
1004cd37da74Snw 	nm->pid = UNDEFINED_UID;
1005cd37da74Snw 	return (nm);
1006cd37da74Snw }
1007cd37da74Snw 
1008cd37da74Snw /* Free name_mapping_t */
1009cd37da74Snw static void
name_mapping_fini(name_mapping_t * nm)1010cd37da74Snw name_mapping_fini(name_mapping_t *nm)
1011cd37da74Snw {
1012cd37da74Snw 
1013cd37da74Snw 	free(nm->winname);
1014cd37da74Snw 	free(nm->windomain);
1015cd37da74Snw 	free(nm->unixname);
1016cd37da74Snw 	free(nm->sidprefix);
1017cd37da74Snw 
1018cd37da74Snw 	free(nm);
1019cd37da74Snw }
1020cd37da74Snw 
1021c5c4113dSnw static int
name_mapping_cpy(name_mapping_t * to,name_mapping_t * from)1022cd37da74Snw name_mapping_cpy(name_mapping_t *to, name_mapping_t *from)
1023cd37da74Snw {
1024cd37da74Snw 	free(to->winname);
1025cd37da74Snw 	free(to->windomain);
1026cd37da74Snw 	free(to->unixname);
1027cd37da74Snw 	free(to->sidprefix);
1028c5c4113dSnw 
1029cd37da74Snw 	(void) memcpy(to, from, sizeof (name_mapping_t));
1030cd37da74Snw 	to->winname = to->windomain = to->unixname = to->sidprefix = NULL;
1031cd37da74Snw 
1032cd37da74Snw 	if (from->winname != NULL) {
1033cd37da74Snw 		to->winname = strdup(from->winname);
1034cd37da74Snw 		if (to->winname == NULL) {
103561b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
1036cd37da74Snw 			return (-1);
1037cd37da74Snw 		}
1038cd37da74Snw 	}
1039cd37da74Snw 
1040cd37da74Snw 	if (from->windomain != NULL) {
1041cd37da74Snw 		to->windomain = strdup(from->windomain);
1042cd37da74Snw 		if (to->windomain == NULL)  {
104361b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
1044cd37da74Snw 			return (-1);
1045cd37da74Snw 		}
1046cd37da74Snw 	}
1047cd37da74Snw 
1048cd37da74Snw 	if (from->unixname != NULL) {
1049cd37da74Snw 		to->unixname = strdup(from->unixname);
1050cd37da74Snw 		if (to->unixname == NULL)  {
105161b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
1052cd37da74Snw 			return (-1);
1053cd37da74Snw 		}
1054cd37da74Snw 	}
1055cd37da74Snw 
1056cd37da74Snw 	if (from->sidprefix != NULL) {
1057cd37da74Snw 		to->sidprefix = strdup(from->sidprefix);
1058cd37da74Snw 		if (to->sidprefix == NULL)  {
105961b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
1060cd37da74Snw 			return (-1);
1061cd37da74Snw 		}
1062cd37da74Snw 	}
1063cd37da74Snw 
1064cd37da74Snw 	return (0);
1065cd37da74Snw }
1066cd37da74Snw 
1067cd37da74Snw static int
name_mapping_format(name_mapping_t * nm,char ** out)1068cd37da74Snw name_mapping_format(name_mapping_t *nm, char **out)
1069cd37da74Snw {
1070cd37da74Snw 	char *winname = NULL;
1071cd37da74Snw 	char *winname1 = NULL;
1072cd37da74Snw 	char *unixname = NULL;
1073cd37da74Snw 	int maxlen;
1074cd37da74Snw 
1075cd37da74Snw 	*out = NULL;
1076cd37da74Snw 
1077cd37da74Snw 	if (nm2winqn(nm, &winname1) < 0)
1078cd37da74Snw 		return (-1);
1079cd37da74Snw 
1080cd37da74Snw 	if (shell_app(&winname, winname1, 1)) {
1081cd37da74Snw 		free(winname1);
1082cd37da74Snw 		return (-1);
1083cd37da74Snw 	}
1084cd37da74Snw 
1085cd37da74Snw 	free(winname1);
1086cd37da74Snw 
1087cd37da74Snw 	if (nm2unixname(nm, &unixname)) {
1088cd37da74Snw 		free(winname);
1089cd37da74Snw 		return (-1);
1090c5c4113dSnw 	}
1091c5c4113dSnw 
1092cd37da74Snw 	/* 10 is strlen("add -d\t\t\n") + 1 */
1093cd37da74Snw 	maxlen = 10 + strlen(unixname) + strlen(winname);
1094cd37da74Snw 
1095cd37da74Snw 	*out = (char *)malloc(maxlen);
1096cd37da74Snw 
1097cd37da74Snw 	if (nm->direction == IDMAP_DIRECTION_U2W) {
1098cd37da74Snw 		(void) snprintf(*out, maxlen, "add -d\t%s\t%s\n",
1099cd37da74Snw 		    unixname, winname);
1100cd37da74Snw 	} else {
1101cd37da74Snw 		(void) snprintf(*out, maxlen, "add %s\t%s\t%s\n",
1102cd37da74Snw 		    nm->direction == IDMAP_DIRECTION_BI? "" : "-d",
1103cd37da74Snw 		    winname, unixname);
1104cd37da74Snw 	}
1105cd37da74Snw 	free(winname);
1106cd37da74Snw 	free(unixname);
1107c5c4113dSnw 	return (0);
1108c5c4113dSnw }
1109c5c4113dSnw 
1110cd37da74Snw /* Initialize print_mapping variables. Must be called before print_mapping */
1111cd37da74Snw static print_handle_t *
print_mapping_init(format_t f,FILE * fi)1112cd37da74Snw print_mapping_init(format_t f, FILE *fi)
1113cd37da74Snw {
1114cd37da74Snw 	print_handle_t *out;
1115cd37da74Snw 
1116cd37da74Snw 	out = (print_handle_t *)malloc(sizeof (print_handle_t));
1117cd37da74Snw 	if (out == NULL) {
111861b364a9Sjp 		print_error(NULL, "%s.\n", strerror(ENOMEM));
1119cd37da74Snw 		return (NULL);
1120cd37da74Snw 	}
1121cd37da74Snw 
1122cd37da74Snw 	out->format = f;
1123cd37da74Snw 	out->file = fi;
1124cd37da74Snw 	out->last = name_mapping_init();
1125cd37da74Snw 
1126cd37da74Snw 	if (out->last == NULL)
1127cd37da74Snw 		return (NULL);
1128cd37da74Snw 
1129cd37da74Snw 	return (out);
1130cd37da74Snw }
1131cd37da74Snw 
1132c5c4113dSnw /* Finalize print_mapping. */
1133c5c4113dSnw static int
print_mapping_fini(print_handle_t * pnm)1134cd37da74Snw print_mapping_fini(print_handle_t *pnm)
1135cd37da74Snw {
1136cd37da74Snw 	char *out = NULL;
1137cd37da74Snw 	int rc = 0;
1138cd37da74Snw 
1139cd37da74Snw 	switch (pnm->format) {
1140c5c4113dSnw 	case SMBUSERS:
1141cd37da74Snw 		if (pnm->last->unixname != NULL) {
1142cd37da74Snw 			(void) fprintf(pnm->file, "\n");
1143cd37da74Snw 		}
1144cd37da74Snw 		break;
1145cd37da74Snw 	case DEFAULT_FORMAT:
1146cd37da74Snw 		if (pnm->last->unixname == NULL)
1147cd37da74Snw 			break;
1148cd37da74Snw 		rc = name_mapping_format(pnm->last, &out);
1149cd37da74Snw 		if (rc >= 0) {
1150cd37da74Snw 			(void) fprintf(pnm->file, "%s", out);
1151cd37da74Snw 			free(out);
1152c5c4113dSnw 		}
1153c5c4113dSnw 		break;
1154c5c4113dSnw 	default:
1155c5c4113dSnw 		;
1156c5c4113dSnw 	}
1157c5c4113dSnw 
1158cd37da74Snw 	name_mapping_fini(pnm->last);
1159cd37da74Snw 	free(pnm);
1160c5c4113dSnw 
1161cd37da74Snw 	return (rc);
1162cd37da74Snw }
1163cd37da74Snw 
1164cd37da74Snw static char *
usermap_cfg_string(char * in)1165cd37da74Snw usermap_cfg_string(char *in)
1166cd37da74Snw {
1167cd37da74Snw 	int len;
1168cd37da74Snw 	char *out;
1169cd37da74Snw 
1170cd37da74Snw 	if (INHIBITED(in))
1171cd37da74Snw 		return (strdup("\"\""));
1172cd37da74Snw 
1173cd37da74Snw 	len = strlen(in);
1174cd37da74Snw 	if (len == strcspn(in, " \t#"))
1175cd37da74Snw 		return (strdup(in));
1176cd37da74Snw 
1177cd37da74Snw 	out = malloc(len + 3);
1178cd37da74Snw 	if (out == NULL)
1179cd37da74Snw 		return (NULL);
1180cd37da74Snw 
118199df425eSdm 	(void) snprintf(out, len + 3, "\"%s\"", in);
1182cd37da74Snw 	return (out);
1183cd37da74Snw }
1184cd37da74Snw 
1185c5c4113dSnw /*
1186c5c4113dSnw  * This prints both name rules and ordinary mappings, based on the pnm_format
1187c5c4113dSnw  * set in print_mapping_init().
1188c5c4113dSnw  */
1189c5c4113dSnw 
1190c5c4113dSnw static int
print_mapping(print_handle_t * pnm,name_mapping_t * nm)1191cd37da74Snw print_mapping(print_handle_t *pnm, name_mapping_t *nm)
1192c5c4113dSnw {
1193c5c4113dSnw 	char *dirstring;
1194c5c4113dSnw 	char *winname = NULL;
1195cd37da74Snw 	char *windomain = NULL;
1196c5c4113dSnw 	char *unixname = NULL;
1197cd37da74Snw 	FILE *f = pnm->file;
1198c5c4113dSnw 
1199cd37da74Snw 	switch (pnm->format) {
1200c5c4113dSnw 	case MAPPING_NAME:
1201c5c4113dSnw 		if (nm2winqn(nm, &winname) < 0)
1202c5c4113dSnw 			return (-1);
1203c5c4113dSnw 		if (nm2unixname(nm, &unixname) < 0) {
1204c5c4113dSnw 			free(winname);
1205c5c4113dSnw 			return (-1);
1206c5c4113dSnw 		}
120796d32a53SToomas Soome 		/* FALLTHROUGH */
1208c5c4113dSnw 	case MAPPING_ID:
1209cd37da74Snw 		if (pnm->format == MAPPING_ID) {
1210c5c4113dSnw 			if (nm->sidprefix == NULL) {
12118e228215Sdm 				print_error(NULL,
1212c5c4113dSnw 				    gettext("SID not given.\n"));
1213c5c4113dSnw 				return (-1);
1214c5c4113dSnw 			}
1215cd37da74Snw 			winname = sid_format(nm);
1216c5c4113dSnw 			if (winname == NULL)
1217c5c4113dSnw 				return (-1);
1218c5c4113dSnw 			unixname = pid_format(nm->pid, nm->is_user);
1219c5c4113dSnw 			if (unixname == NULL) {
1220c5c4113dSnw 				free(winname);
1221c5c4113dSnw 				return (-1);
1222c5c4113dSnw 			}
1223c5c4113dSnw 		}
1224c5c4113dSnw 
1225c5c4113dSnw 		dirstring = direction2string(nm->direction);
1226c5c4113dSnw 
1227c5c4113dSnw 		(void) fprintf(f, "%s\t%s\t%s\n", winname, dirstring,
1228c5c4113dSnw 		    unixname);
1229c5c4113dSnw 
1230c5c4113dSnw 		break;
1231c5c4113dSnw 	case SMBUSERS:
1232479ac375Sdm 		if (nm->is_user != IDMAP_YES || nm->is_wuser != IDMAP_YES) {
12338e228215Sdm 			print_error(NULL,
1234c5c4113dSnw 			    gettext("Group rule: "));
1235c5c4113dSnw 			f = stderr;
12368e228215Sdm 		} else 	if (nm->direction == IDMAP_DIRECTION_U2W) {
12378e228215Sdm 			print_error(NULL,
1238c5c4113dSnw 			    gettext("Opposite direction of the mapping: "));
1239c5c4113dSnw 			f = stderr;
1240cd37da74Snw 		} else if (INHIBITED(nm->winname) || INHIBITED(nm->unixname)) {
1241cd37da74Snw 			print_error(NULL, gettext("Inhibited rule: "));
1242cd37da74Snw 			f = stderr;
1243c5c4113dSnw 		}
1244cd37da74Snw 
1245821da340Sdm 		if (shell_app(&winname, nm->winname, 1))
1246c5c4113dSnw 			return (-1);
1247c5c4113dSnw 
1248cd37da74Snw 		unixname = INHIBITED(nm->unixname) ? "\"\"" : nm->unixname;
1249cd37da74Snw 
1250cd37da74Snw 		if (pnm->file != f) {
1251cd37da74Snw 			(void) fprintf(f, "%s=%s\n", unixname, winname);
1252cd37da74Snw 		} else if (pnm->last->unixname != NULL &&
1253cd37da74Snw 		    strcmp(pnm->last->unixname, unixname) == 0) {
1254c5c4113dSnw 			(void) fprintf(f, " %s", winname);
1255c5c4113dSnw 		} else {
1256cd37da74Snw 			if (pnm->last->unixname != NULL) {
1257c5c4113dSnw 				(void) fprintf(f, "\n");
1258cd37da74Snw 				free(pnm->last->unixname);
1259cd37da74Snw 			}
1260cd37da74Snw 			pnm->last->unixname = strdup(unixname);
1261cd37da74Snw 			if (pnm->last->unixname == NULL) {
1262cd37da74Snw 				print_error(NULL,
126361b364a9Sjp 				    "%s.\n", strerror(ENOMEM));
1264c5c4113dSnw 			}
1265c5c4113dSnw 
1266cd37da74Snw 			(void) fprintf(f, "%s=%s", unixname, winname);
1267cd37da74Snw 		}
1268c5c4113dSnw 
1269cd37da74Snw 		unixname = NULL;
1270c5c4113dSnw 		break;
1271c5c4113dSnw 	case USERMAP_CFG:
1272479ac375Sdm 		if (nm->is_user != IDMAP_YES || nm->is_wuser != IDMAP_YES) {
12738e228215Sdm 			print_error(NULL,
1274c5c4113dSnw 			    gettext("Group rule: "));
1275c5c4113dSnw 			f = stderr;
1276c5c4113dSnw 		}
1277c5c4113dSnw 
1278c5c4113dSnw 		dirstring = direction2string(nm->direction);
1279c5c4113dSnw 
1280cd37da74Snw 		if ((winname = usermap_cfg_string(nm->winname)) == NULL ||
1281cd37da74Snw 		    (unixname = usermap_cfg_string(nm->unixname)) == NULL ||
1282cd37da74Snw 		    (windomain = usermap_cfg_string(nm->windomain)) == NULL) {
128361b364a9Sjp 			print_error(NULL, "%s.\n", strerror(ENOMEM));
1284cd37da74Snw 			free(winname);
1285cd37da74Snw 			free(unixname);
1286cd37da74Snw 			free(windomain);
1287cd37da74Snw 			return (-1);
1288cd37da74Snw 		}
1289cd37da74Snw 
1290c5c4113dSnw 
1291cd37da74Snw 		if (nm->windomain == NULL) {
1292cd37da74Snw 			(void) fprintf(f, "%s\t%s\t%s\n",
1293cd37da74Snw 			    winname, dirstring, unixname);
1294cd37da74Snw 		} else
1295c5c4113dSnw 			(void) fprintf(f, nm->is_nt4 ?
1296cd37da74Snw 			    "%s\\%s\t%s\t%s\n" :
1297cd37da74Snw 			    "%2$s@%1$s\t%3$s\t%4$s\n",
1298cd37da74Snw 			    windomain, winname, dirstring, unixname);
1299cd37da74Snw 
1300c5c4113dSnw 		break;
1301c5c4113dSnw 
1302cd37da74Snw 	/* This is a format for namerules */
1303c5c4113dSnw 	case DEFAULT_FORMAT:
1304cd37da74Snw 		/*
1305cd37da74Snw 		 * If nm is the same as the last one except is_wuser, we combine
1306cd37da74Snw 		 * winuser & wingroup to winname
1307cd37da74Snw 		 */
1308cd37da74Snw 		if (nm->direction == pnm->last->direction &&
1309cd37da74Snw 		    nm->is_user == pnm->last->is_user &&
1310c5c4113dSnw 
1311cd37da74Snw 		    strcmp_null(pnm->last->unixname, nm->unixname) == 0 &&
1312cd37da74Snw 		    strcmp_null(pnm->last->winname, nm->winname) == 0 &&
1313cd37da74Snw 		    strcmp_null(pnm->last->windomain, nm->windomain) == 0) {
1314479ac375Sdm 			pnm->last->is_wuser = IDMAP_UNKNOWN;
1315c5c4113dSnw 		} else {
1316cd37da74Snw 			if (pnm->last->unixname != NULL ||
1317cd37da74Snw 			    pnm->last->winname != NULL) {
1318cd37da74Snw 				char *out = NULL;
1319cd37da74Snw 				if (name_mapping_format(pnm->last, &out) < 0)
1320cd37da74Snw 					return (-1);
1321cd37da74Snw 				(void) fprintf(f, "%s", out);
1322cd37da74Snw 				free(out);
1323cd37da74Snw 			}
1324cd37da74Snw 			if (name_mapping_cpy(pnm->last, nm) < 0)
1325cd37da74Snw 				return (-1);
1326c5c4113dSnw 		}
1327c5c4113dSnw 		break;
1328c5c4113dSnw 	default:
1329821da340Sdm 		/* This can never happen: */
13308e228215Sdm 		print_error(NULL,
1331821da340Sdm 		    gettext("Internal error: invalid print format.\n"));
1332c5c4113dSnw 		return (-1);
1333c5c4113dSnw 	}
1334c5c4113dSnw 
1335cd37da74Snw 	free(winname);
1336cd37da74Snw 	free(unixname);
1337cd37da74Snw 	free(windomain);
1338c5c4113dSnw 	return (0);
1339c5c4113dSnw }
1340c5c4113dSnw 
1341c5c4113dSnw 
134248258c6bSjp static
134348258c6bSjp void
print_how(idmap_how * how)134448258c6bSjp print_how(idmap_how *how)
134548258c6bSjp {
134648258c6bSjp 	idmap_namerule	*rule;
134748258c6bSjp 	name_mapping_t	nm;
134848258c6bSjp 	char		*rule_text;
134948258c6bSjp 
135048258c6bSjp 	switch (how->map_type) {
135148258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
135248258c6bSjp 		(void) printf(gettext("Method:\tAD Directory\n"));
135348258c6bSjp 		(void) printf(gettext("DN:\t%s\n"),
1354479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.ad.dn));
135548258c6bSjp 		(void) printf(gettext("Attribute:\t%s=%s\n"),
1356479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.ad.attr),
1357479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.ad.value));
135848258c6bSjp 		break;
135948258c6bSjp 
136048258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
136148258c6bSjp 		(void) printf(gettext("Method:\tNative LDAP Directory\n"));
136248258c6bSjp 		(void) printf(gettext("DN:\t%s\n"),
1363479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.nldap.dn));
136448258c6bSjp 		(void) printf(gettext("Attribute:\t%s=%s\n"),
1365479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.nldap.attr),
1366479ac375Sdm 		    CHECK_NULL(how->idmap_how_u.nldap.value));
136748258c6bSjp 		break;
136848258c6bSjp 
136948258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
137048258c6bSjp 		(void) printf(gettext("Method:\tName Rule\n"));
137148258c6bSjp 		rule = &how->idmap_how_u.rule;
137248258c6bSjp 		/*
137348258c6bSjp 		 * The name rules as specified by the user can have a
137448258c6bSjp 		 * "winname", "winuser" or "wingroup". "Winname" rules are
137548258c6bSjp 		 * decomposed to a "winuser" and "wingroup" rules by idmap.
137648258c6bSjp 		 * Currently is_wuser  is a boolean. Due to these reasons
137748258c6bSjp 		 * the returned is_wuser does not represent the original rule.
137848258c6bSjp 		 * It is therefore better set is_wuser to unknown.
137948258c6bSjp 		 */
138048258c6bSjp 		nm.is_user = rule->is_user;
1381479ac375Sdm 		nm.is_wuser = IDMAP_UNKNOWN;
138248258c6bSjp 		nm.direction = rule->direction;
138348258c6bSjp 		nm.winname = rule->winname;
138448258c6bSjp 		nm.windomain = rule->windomain;
138548258c6bSjp 		nm.unixname = rule->unixname;
138648258c6bSjp 		nm.is_nt4 = rule->is_nt4;
138748258c6bSjp 		if (name_mapping_format(&nm, &rule_text) == 0) {
138848258c6bSjp 			(void) printf(gettext("Rule:\t%s"), rule_text);
138948258c6bSjp 			free(rule_text);
139048258c6bSjp 		}
139148258c6bSjp 		break;
139248258c6bSjp 
139348258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
139448258c6bSjp 		(void) printf(gettext("Method:\tEphemeral\n"));
139548258c6bSjp 		break;
139648258c6bSjp 
139748258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
139848258c6bSjp 		(void) printf(gettext("Method:\tLocal SID\n"));
139948258c6bSjp 		break;
140048258c6bSjp 
140148258c6bSjp 	case IDMAP_MAP_TYPE_KNOWN_SID:
140248258c6bSjp 		(void) printf(gettext("Method:\tWell-Known mapping\n"));
140348258c6bSjp 		break;
1404e3f2c991SKeyur Desai 
1405e3f2c991SKeyur Desai 	case IDMAP_MAP_TYPE_IDMU:
1406e3f2c991SKeyur Desai 		(void) printf(gettext("Method:\tIDMU\n"));
1407e3f2c991SKeyur Desai 		(void) printf(gettext("DN:\t%s\n"),
1408e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.dn));
1409e3f2c991SKeyur Desai 		(void) printf(gettext("Attribute:\t%s=%s\n"),
1410e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.attr),
1411e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.value));
1412e3f2c991SKeyur Desai 		break;
141348258c6bSjp 	}
141448258c6bSjp }
141548258c6bSjp 
141648258c6bSjp 
141748258c6bSjp static
141848258c6bSjp void
print_info(idmap_info * info)141948258c6bSjp print_info(idmap_info *info)
142048258c6bSjp {
142148258c6bSjp 	if (info->how.map_type != IDMAP_MAP_TYPE_UNKNOWN) {
142248258c6bSjp 		switch (info->src) {
142348258c6bSjp 		case IDMAP_MAP_SRC_NEW:
142448258c6bSjp 			(void) printf(gettext("Source:\tNew\n"));
142548258c6bSjp 			break;
142648258c6bSjp 
142748258c6bSjp 		case IDMAP_MAP_SRC_CACHE:
142848258c6bSjp 			(void) printf(gettext("Source:\tCache\n"));
142948258c6bSjp 			break;
143048258c6bSjp 
143148258c6bSjp 		case IDMAP_MAP_SRC_HARD_CODED:
143248258c6bSjp 			(void) printf(gettext("Source:\tHard Coded\n"));
143348258c6bSjp 			break;
143448258c6bSjp 
143548258c6bSjp 		case IDMAP_MAP_SRC_ALGORITHMIC:
143648258c6bSjp 			(void) printf(gettext("Source:\tAlgorithmic\n"));
143748258c6bSjp 			break;
143848258c6bSjp 		}
143948258c6bSjp 		print_how(&info->how);
144048258c6bSjp 	}
1441148c5f43SAlan Wright 
1442148c5f43SAlan Wright 	if (info->trace != NULL) {
1443148c5f43SAlan Wright 		(void) printf(gettext("Trace:\n"));
1444148c5f43SAlan Wright 		idmap_trace_print(stdout, "\t", info->trace);
1445148c5f43SAlan Wright 	}
144648258c6bSjp }
144748258c6bSjp 
144848258c6bSjp 
144948258c6bSjp static
145048258c6bSjp void
print_error_info(idmap_info * info)145148258c6bSjp print_error_info(idmap_info *info)
145248258c6bSjp {
145348258c6bSjp 	idmap_how	*how = &info->how;
145448258c6bSjp 	idmap_namerule	*rule;
145548258c6bSjp 	name_mapping_t	nm;
145648258c6bSjp 	char		*rule_text;
145748258c6bSjp 
1458fc724630SAlan Wright 	(void) memset(&nm, 0, sizeof (nm));
1459fc724630SAlan Wright 
146048258c6bSjp 	switch (how->map_type) {
146148258c6bSjp 	case IDMAP_MAP_TYPE_DS_AD:
146248258c6bSjp 		(void) fprintf(stderr,
146348258c6bSjp 		    gettext("Failed Method:\tAD Directory\n"));
146448258c6bSjp 		(void) fprintf(stderr, gettext("DN:\t%s\n"),
146548258c6bSjp 		    how->idmap_how_u.ad.dn);
146648258c6bSjp 		(void) fprintf(stderr, gettext("Attribute:\t%s=%s\n"),
146748258c6bSjp 		    how->idmap_how_u.ad.attr,
146848258c6bSjp 		    how->idmap_how_u.ad.value);
146948258c6bSjp 		break;
147048258c6bSjp 
147148258c6bSjp 	case IDMAP_MAP_TYPE_DS_NLDAP:
147248258c6bSjp 		(void) fprintf(stderr,
147348258c6bSjp 		    gettext("Failed Method:\tNative LDAP Directory\n"));
147448258c6bSjp 		(void) fprintf(stderr, gettext("DN:\t%s\n"),
147548258c6bSjp 		    how->idmap_how_u.nldap.dn);
147648258c6bSjp 		(void) fprintf(stderr, gettext("Attribute:\t%s=%s\n"),
147748258c6bSjp 		    how->idmap_how_u.nldap.attr,
147848258c6bSjp 		    how->idmap_how_u.nldap.value);
147948258c6bSjp 		break;
148048258c6bSjp 
148148258c6bSjp 	case IDMAP_MAP_TYPE_RULE_BASED:
148248258c6bSjp 		(void) fprintf(stderr, gettext("Failed Method:\tName Rule\n"));
148348258c6bSjp 		rule = &how->idmap_how_u.rule;
148448258c6bSjp 		/*
148548258c6bSjp 		 * The name rules as specified by the user can have a
148648258c6bSjp 		 * "winname", "winuser" or "wingroup". "Winname" rules are
148748258c6bSjp 		 * decomposed to a "winuser" and "wingroup" rules by idmap.
148848258c6bSjp 		 * Currently is_wuser  is a boolean. Due to these reasons
148948258c6bSjp 		 * the returned is_wuser does not represent the original rule.
149048258c6bSjp 		 * It is therefore better to set is_wuser to unknown.
149148258c6bSjp 		 */
149248258c6bSjp 		nm.is_user = rule->is_user;
1493479ac375Sdm 		nm.is_wuser = IDMAP_UNKNOWN;
149448258c6bSjp 		nm.direction = rule->direction;
149548258c6bSjp 		nm.winname = rule->winname;
149648258c6bSjp 		nm.windomain = rule->windomain;
149748258c6bSjp 		nm.unixname = rule->unixname;
149848258c6bSjp 		nm.is_nt4 = rule->is_nt4;
149948258c6bSjp 		if (name_mapping_format(&nm, &rule_text) == 0) {
150048258c6bSjp 			(void) fprintf(stderr, gettext("Rule:\t%s"), rule_text);
150148258c6bSjp 			free(rule_text);
150248258c6bSjp 		}
150348258c6bSjp 		break;
150448258c6bSjp 
150548258c6bSjp 	case IDMAP_MAP_TYPE_EPHEMERAL:
150648258c6bSjp 		(void) fprintf(stderr, gettext("Failed Method:\tEphemeral\n"));
150748258c6bSjp 		break;
150848258c6bSjp 
150948258c6bSjp 	case IDMAP_MAP_TYPE_LOCAL_SID:
151048258c6bSjp 		(void) fprintf(stderr, gettext("Failed Method:\tLocal SID\n"));
151148258c6bSjp 		break;
151248258c6bSjp 
151348258c6bSjp 	case IDMAP_MAP_TYPE_KNOWN_SID:
151448258c6bSjp 		(void) fprintf(stderr,
151548258c6bSjp 		    gettext("Failed Method:\tWell-Known mapping\n"));
151648258c6bSjp 		break;
1517e3f2c991SKeyur Desai 
1518e3f2c991SKeyur Desai 	case IDMAP_MAP_TYPE_IDMU:
1519e3f2c991SKeyur Desai 		(void) fprintf(stderr,
1520e3f2c991SKeyur Desai 		    gettext("Failed Method:\tIDMU\n"));
1521e3f2c991SKeyur Desai 		(void) fprintf(stderr, gettext("DN:\t%s\n"),
1522e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.dn));
1523e3f2c991SKeyur Desai 		(void) fprintf(stderr, gettext("Attribute:\t%s=%s\n"),
1524e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.attr),
1525e3f2c991SKeyur Desai 		    CHECK_NULL(how->idmap_how_u.idmu.value));
1526e3f2c991SKeyur Desai 		break;
152748258c6bSjp 	}
1528148c5f43SAlan Wright 
1529148c5f43SAlan Wright 	if (info->trace != NULL) {
1530148c5f43SAlan Wright 		(void) printf(gettext("Trace:\n"));
1531148c5f43SAlan Wright 		idmap_trace_print(stderr, "\t", info->trace);
1532148c5f43SAlan Wright 	}
153348258c6bSjp }
153448258c6bSjp 
153548258c6bSjp 
153648258c6bSjp 
1537c5c4113dSnw /* dump command handler */
1538c5c4113dSnw static int
1539c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_dump(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)15408e228215Sdm do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
1541c5c4113dSnw {
154248258c6bSjp 	idmap_stat	stat;
154348258c6bSjp 	idmap_iter_t	*ihandle;
154448258c6bSjp 	int		rc = 0;
154548258c6bSjp 	boolean_t	is_user;
154648258c6bSjp 	boolean_t	is_wuser;
154748258c6bSjp 	print_handle_t	*ph;
154848258c6bSjp 	int		flag = 0;
154948258c6bSjp 	idmap_info	info;
1550c5c4113dSnw 
1551cd37da74Snw 	ph = print_mapping_init(f[n_FLAG] != NULL ? MAPPING_NAME : MAPPING_ID,
1552c5c4113dSnw 	    stdout);
1553cd37da74Snw 	if (ph == NULL)
1554cd37da74Snw 		return (-1);
1555c5c4113dSnw 
155648258c6bSjp 	if (f[v_FLAG] != NULL)
155748258c6bSjp 		flag = IDMAP_REQ_FLG_MAPPING_INFO;
155848258c6bSjp 
15591fdeec65Sjoyce mcintosh 	stat = idmap_iter_mappings(&ihandle, flag);
1560cd37da74Snw 	if (stat < 0) {
1561cd37da74Snw 		print_error(pos,
1562cd37da74Snw 		    gettext("Iteration handle not obtained (%s)\n"),
15631fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
1564cd37da74Snw 		rc = -1;
1565cd37da74Snw 		goto cleanup;
1566cd37da74Snw 	}
1567cd37da74Snw 
1568cd37da74Snw 	do {
1569cd37da74Snw 		name_mapping_t *nm = name_mapping_init();
1570cd37da74Snw 		if (nm == NULL) {
1571c5c4113dSnw 			rc = -1;
1572c5c4113dSnw 			goto cleanup;
1573c5c4113dSnw 		}
1574c5c4113dSnw 
1575cd37da74Snw 		stat = idmap_iter_next_mapping(ihandle,
1576cd37da74Snw 		    &nm->sidprefix, &nm->rid, &nm->pid,
1577cd37da74Snw 		    &nm->winname, &nm->windomain,
1578cd37da74Snw 		    &nm->unixname, &is_user, &is_wuser,
157948258c6bSjp 		    &nm->direction, &info);
1580c5c4113dSnw 
1581479ac375Sdm 		nm->is_user = is_user ? IDMAP_YES : IDMAP_NO;
1582479ac375Sdm 		nm->is_wuser = is_wuser ? IDMAP_YES : IDMAP_NO;
1583c5c4113dSnw 
158448258c6bSjp 		if (stat >= 0) {
1585cd37da74Snw 			(void) print_mapping(ph, nm);
1586148c5f43SAlan Wright 			print_how(&info.how);
158748258c6bSjp 			idmap_info_free(&info);
158848258c6bSjp 		}
1589cd37da74Snw 		name_mapping_fini(nm);
1590c5c4113dSnw 
1591cd37da74Snw 	} while (stat > 0);
1592c5c4113dSnw 
1593cd37da74Snw 	/* IDMAP_ERR_NOTFOUND indicates end of the list */
1594cd37da74Snw 	if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) {
1595cd37da74Snw 		print_error(pos,
1596cd37da74Snw 		    gettext("Error during iteration (%s)\n"),
15971fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
1598cd37da74Snw 		rc = -1;
1599cd37da74Snw 		goto cleanup;
1600cd37da74Snw 	}
1601c5c4113dSnw 
1602cd37da74Snw 	idmap_iter_destroy(ihandle);
1603c5c4113dSnw 
1604c5c4113dSnw cleanup:
1605cd37da74Snw 	(void) print_mapping_fini(ph);
1606c5c4113dSnw 	return (rc);
1607c5c4113dSnw }
1608c5c4113dSnw 
1609821da340Sdm /*
1610821da340Sdm  * Convert pid from string to it's numerical representation. If it is
1611821da340Sdm  * a valid string, i.e. number of a proper length, return 1. Otherwise
1612821da340Sdm  * print an error message and return 0.
1613821da340Sdm  */
1614821da340Sdm static int
pid_convert(char * string,uid_t * number,int type,cmd_pos_t * pos)1615cd37da74Snw pid_convert(char *string, uid_t *number, int type, cmd_pos_t *pos)
1616cd37da74Snw {
1617821da340Sdm 	int i;
1618821da340Sdm 	long long ll;
1619821da340Sdm 	char *type_string;
1620821da340Sdm 	size_t len = strlen(string);
1621821da340Sdm 
1622821da340Sdm 	if (type == TYPE_GID)
1623821da340Sdm 		type_string = ID_GID;
1624821da340Sdm 	else if (type == TYPE_UID)
1625821da340Sdm 		type_string = ID_UID;
1626821da340Sdm 	else
1627821da340Sdm 		return (0);
1628821da340Sdm 
1629821da340Sdm 	for (i = 0; i < len; i++) {
1630821da340Sdm 		if (!isdigit(string[i])) {
16318e228215Sdm 			print_error(pos,
1632821da340Sdm 			    gettext("\"%s\" is not a valid %s: the non-digit"
1633cd37da74Snw 			    " character '%c' found.\n"), string,
1634821da340Sdm 			    type_string, string[i]);
1635821da340Sdm 			return (0);
1636821da340Sdm 		}
1637821da340Sdm 	}
1638821da340Sdm 
1639821da340Sdm 	ll = atoll(string);
1640821da340Sdm 
1641821da340Sdm 	/* Isn't it too large? */
1642821da340Sdm 	if (type == TYPE_UID && (uid_t)ll != ll ||
1643821da340Sdm 	    type == TYPE_GID && (gid_t)ll != ll) {
16448e228215Sdm 		print_error(pos,
1645821da340Sdm 		    gettext("%llu: too large for a %s.\n"), ll,
1646821da340Sdm 		    type_string);
1647821da340Sdm 		return (0);
1648821da340Sdm 	}
1649821da340Sdm 
1650821da340Sdm 	*number = (uid_t)ll;
1651821da340Sdm 	return (1);
1652821da340Sdm }
1653821da340Sdm 
1654821da340Sdm /*
1655821da340Sdm  * Convert SID from string to prefix and rid. If it has a valid
1656821da340Sdm  * format, i.e. S(\-\d+)+, return 1. Otherwise print an error
1657821da340Sdm  * message and return 0.
1658821da340Sdm  */
1659821da340Sdm static int
sid_convert(char * from,char ** prefix,idmap_rid_t * rid,cmd_pos_t * pos)1660cd37da74Snw sid_convert(char *from, char **prefix, idmap_rid_t *rid, cmd_pos_t *pos)
1661cd37da74Snw {
1662821da340Sdm 	int i, j;
1663821da340Sdm 	char *cp;
1664821da340Sdm 	char *ecp;
1665821da340Sdm 	char *prefix_end;
1666821da340Sdm 	u_longlong_t	a;
1667821da340Sdm 	unsigned long	r;
1668821da340Sdm 
1669821da340Sdm 	if (strcmp_no0(from, "S-1-") != 0) {
16708e228215Sdm 		print_error(pos,
1671821da340Sdm 		    gettext("Invalid %s \"%s\": it doesn't start "
1672cd37da74Snw 		    "with \"%s\".\n"), ID_SID, from, "S-1-");
1673821da340Sdm 		return (0);
1674821da340Sdm 	}
1675821da340Sdm 
1676821da340Sdm 	if (strlen(from) <= strlen("S-1-")) {
16778e228215Sdm 		print_error(pos,
1678821da340Sdm 		    gettext("Invalid %s \"%s\": the authority and RID parts are"
1679cd37da74Snw 		    " missing.\n"),
1680821da340Sdm 		    ID_SID, from);
1681821da340Sdm 		return (0);
1682821da340Sdm 	}
1683821da340Sdm 
1684821da340Sdm 	/* count '-'s */
1685821da340Sdm 	for (j = 0, cp = strchr(from, '-');
1686cd37da74Snw 	    cp != NULL;
1687cd37da74Snw 	    j++, cp = strchr(cp + 1, '-')) {
1688821da340Sdm 		/* can't end on a '-' */
1689821da340Sdm 		if (*(cp + 1) == '\0') {
16908e228215Sdm 			print_error(pos,
1691821da340Sdm 			    gettext("Invalid %s \"%s\": '-' at the end.\n"),
1692821da340Sdm 			    ID_SID, from);
1693821da340Sdm 			return (0);
1694821da340Sdm 		} else 	if (*(cp + 1) == '-') {
16958e228215Sdm 			print_error(pos,
1696821da340Sdm 			    gettext("Invalid %s \"%s\": double '-'.\n"),
1697821da340Sdm 			    ID_SID, from);
1698821da340Sdm 			return (0);
1699821da340Sdm 		}
1700821da340Sdm 	}
1701821da340Sdm 
1702821da340Sdm 
1703821da340Sdm 	/* check that we only have digits and '-' */
1704821da340Sdm 	i = strspn(from + 1, "0123456789-") + 1;
1705821da340Sdm 	if (i < strlen(from)) {
17068e228215Sdm 		print_error(pos,
1707821da340Sdm 		    gettext("Invalid %s \"%s\": invalid character '%c'.\n"),
1708821da340Sdm 		    ID_SID, from, from[i]);
1709821da340Sdm 		return (0);
1710821da340Sdm 	}
1711821da340Sdm 
1712821da340Sdm 
1713821da340Sdm 	cp = from + strlen("S-1-");
1714821da340Sdm 
1715821da340Sdm 	/* 64-bit safe parsing of unsigned 48-bit authority value */
1716821da340Sdm 	errno = 0;
1717821da340Sdm 	a = strtoull(cp, &ecp, 10);
1718821da340Sdm 
1719821da340Sdm 	/* errors parsing the authority or too many bits */
1720821da340Sdm 	if (cp == ecp || (a == 0 && errno == EINVAL)) {
1721cd37da74Snw 		print_error(pos,
1722cd37da74Snw 		    gettext("Invalid %s \"%s\": unable to parse the "
1723cd37da74Snw 		    "authority \"%.*s\".\n"), ID_SID, from, ecp - cp,
1724cd37da74Snw 		    cp);
1725cd37da74Snw 		return (0);
1726821da340Sdm 	}
1727821da340Sdm 
1728821da340Sdm 	if ((a == ULLONG_MAX && errno == ERANGE) ||
1729821da340Sdm 	    (a & 0x0000ffffffffffffULL) != a) {
17308e228215Sdm 		print_error(pos,
1731821da340Sdm 		    gettext("Invalid %s \"%s\": the authority "
1732cd37da74Snw 		    "\"%.*s\" is too large.\n"), ID_SID, from,
1733821da340Sdm 		    ecp - cp, cp);
1734821da340Sdm 		return (0);
1735821da340Sdm 	}
1736821da340Sdm 
1737821da340Sdm 	cp = ecp;
1738821da340Sdm 
1739821da340Sdm 	if (j < 3) {
17408e228215Sdm 		print_error(pos,
1741821da340Sdm 		    gettext("Invalid %s \"%s\": must have at least one RID.\n"),
1742821da340Sdm 		    ID_SID, from);
1743821da340Sdm 		return (0);
1744821da340Sdm 	}
1745821da340Sdm 
1746821da340Sdm 	for (i = 2; i < j; i++) {
1747821da340Sdm 		if (*cp++ != '-') {
1748821da340Sdm 			/* Should never happen */
17498e228215Sdm 			print_error(pos,
1750821da340Sdm 			    gettext("Invalid %s \"%s\": internal error:"
1751cd37da74Snw 			    " '-' missing.\n"),
1752821da340Sdm 			    ID_SID, from);
1753821da340Sdm 			return (0);
1754821da340Sdm 		}
1755821da340Sdm 		/* 32-bit safe parsing of unsigned 32-bit RID */
1756821da340Sdm 		errno = 0;
1757821da340Sdm 		r = strtoul(cp, &ecp, 10);
1758821da340Sdm 
1759821da340Sdm 		/* errors parsing the RID */
1760821da340Sdm 		if (cp == ecp || (r == 0 && errno == EINVAL)) {
1761821da340Sdm 			/* should never happen */
1762cd37da74Snw 			print_error(pos,
1763cd37da74Snw 			    gettext("Invalid %s \"%s\": internal error: "
1764cd37da74Snw 			    "unable to parse the RID "
1765cd37da74Snw 			    "after \"%.*s\".\n"), ID_SID,
1766cd37da74Snw 			    from, cp - from, from);
1767cd37da74Snw 			return (0);
1768821da340Sdm 		}
1769821da340Sdm 
1770821da340Sdm 		if (r == ULONG_MAX && errno == ERANGE) {
17718e228215Sdm 			print_error(pos,
1772821da340Sdm 			    gettext("Invalid %s \"%s\": the RID \"%.*s\""
1773cd37da74Snw 			    " is too large.\n"), ID_SID,
1774821da340Sdm 			    from, ecp - cp, cp);
1775821da340Sdm 			return (0);
1776821da340Sdm 		}
1777821da340Sdm 		prefix_end = cp;
1778821da340Sdm 		cp = ecp;
1779821da340Sdm 	}
1780821da340Sdm 
1781821da340Sdm 	/* check that all of the string SID has been consumed */
1782821da340Sdm 	if (*cp != '\0') {
1783821da340Sdm 		/* Should never happen */
17848e228215Sdm 		print_error(pos,
1785821da340Sdm 		    gettext("Invalid %s \"%s\": internal error: "
1786cd37da74Snw 		    "something is still left.\n"),
1787821da340Sdm 		    ID_SID, from);
1788821da340Sdm 		return (0);
1789821da340Sdm 	}
1790821da340Sdm 
1791821da340Sdm 	*rid = (idmap_rid_t)r;
1792821da340Sdm 
1793821da340Sdm 	/* -1 for the '-' at the end: */
1794821da340Sdm 	*prefix = strndup(from, prefix_end - from - 1);
1795821da340Sdm 	if (*prefix == NULL) {
17968e228215Sdm 		print_error(pos,
179761b364a9Sjp 		    "%s.\n", strerror(ENOMEM));
1798821da340Sdm 		return (0);
1799821da340Sdm 	}
1800821da340Sdm 
1801821da340Sdm 	return (1);
1802821da340Sdm }
1803821da340Sdm 
1804821da340Sdm /* Does the line start with USERMAP_CFG IP qualifier? */
1805c5c4113dSnw static int
ucp_is_IP_qualifier(char * line)1806cd37da74Snw ucp_is_IP_qualifier(char *line)
1807cd37da74Snw {
1808c5c4113dSnw 	char *it;
1809c5c4113dSnw 	it = line + strcspn(line, " \t\n#:");
1810c5c4113dSnw 	return (*(it + 1) == ':' ? 1 : 0);
1811c5c4113dSnw }
1812c5c4113dSnw 
1813c5c4113dSnw 
1814c5c4113dSnw /*
1815c5c4113dSnw  * returns interior of quotation marks in USERMAP_CFG. In this format,
1816c5c4113dSnw  * there cannot be a protected quotation mark inside.
1817c5c4113dSnw  */
1818c5c4113dSnw static char *
ucp_qm_interior(char ** line,cmd_pos_t * pos)1819cd37da74Snw ucp_qm_interior(char **line, cmd_pos_t *pos)
1820cd37da74Snw {
1821c5c4113dSnw 	char *out;
1822c5c4113dSnw 	char *qm = strchr(*line + 1, '"');
1823c5c4113dSnw 	if (qm == NULL) {
18248e228215Sdm 		print_error(pos,
18258e228215Sdm 		    gettext("Unclosed quotations\n"));
1826c5c4113dSnw 		return (NULL);
1827c5c4113dSnw 	}
1828c5c4113dSnw 
1829c5c4113dSnw 	out = strndup(*line + 1, qm - *line - 1);
1830c5c4113dSnw 	*line = qm + 1;
1831c5c4113dSnw 	return (out);
1832c5c4113dSnw }
1833c5c4113dSnw 
1834c5c4113dSnw /*
1835c5c4113dSnw  * Grab next token from the line in USERMAP_CFG format. terminators,
1836c5c4113dSnw  * the 3rd parameter, contains all the characters which can terminate
1837c5c4113dSnw  * the token. line_num is the line number of input used for error
1838c5c4113dSnw  * reporting.
1839c5c4113dSnw  */
1840c5c4113dSnw static char *
ucp_grab_token(char ** line,cmd_pos_t * pos,const char * terminators)1841cd37da74Snw ucp_grab_token(char **line, cmd_pos_t *pos, const char *terminators)
1842cd37da74Snw {
1843c5c4113dSnw 	char *token;
1844c5c4113dSnw 	if (**line == '"')
18458e228215Sdm 		token = ucp_qm_interior(line, pos);
1846c5c4113dSnw 	else {
1847c5c4113dSnw 		int length = strcspn(*line, terminators);
1848c5c4113dSnw 		token = strndup(*line, length);
1849c5c4113dSnw 		*line += length;
1850c5c4113dSnw 	}
1851c5c4113dSnw 
1852c5c4113dSnw 	return (token);
1853c5c4113dSnw }
1854c5c4113dSnw 
1855c5c4113dSnw 
1856c5c4113dSnw /*
18578e228215Sdm  * Convert a line in usermap.cfg format to name_mapping.
1858c5c4113dSnw  *
1859c5c4113dSnw  * Return values: -1 for error, 0 for empty line, 1 for a mapping
1860c5c4113dSnw  * found.
1861c5c4113dSnw  */
1862c5c4113dSnw static int
ucp_line2nm(char * line,cmd_pos_t * pos,name_mapping_t * nm)1863cd37da74Snw ucp_line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm)
1864cd37da74Snw {
1865c5c4113dSnw 	char *it;
1866c5c4113dSnw 	char *token;
1867c5c4113dSnw 	char *token2;
1868c5c4113dSnw 	char separator;
1869c5c4113dSnw 	int is_direction = 0;
1870c5c4113dSnw 
1871c5c4113dSnw 	it = line + strspn(line, " \t\n");
1872c5c4113dSnw 
1873c5c4113dSnw 	/* empty or comment lines are OK: */
1874c5c4113dSnw 	if (*it == '\0' || *it == '#')
1875c5c4113dSnw 		return (0);
1876c5c4113dSnw 
1877c5c4113dSnw 	/* We do not support network qualifiers */
1878c5c4113dSnw 	if (ucp_is_IP_qualifier(it)) {
18798e228215Sdm 		print_error(pos,
18808e228215Sdm 		    gettext("Unable to handle network qualifier.\n"));
1881c5c4113dSnw 		return (-1);
1882c5c4113dSnw 	}
1883c5c4113dSnw 
1884c5c4113dSnw 	/* The windows name: */
18858e228215Sdm 	token = ucp_grab_token(&it, pos, " \t#\\\n@=<");
1886c5c4113dSnw 	if (token == NULL)
1887c5c4113dSnw 		return (-1);
1888c5c4113dSnw 
1889c5c4113dSnw 	separator = *it;
1890c5c4113dSnw 
1891c5c4113dSnw 	/* Didn't we bump to the end of line? */
1892c5c4113dSnw 	if (separator == '\0' || separator == '#') {
1893c5c4113dSnw 		free(token);
18948e228215Sdm 		print_error(pos,
18958e228215Sdm 		    gettext("UNIX_name not found.\n"));
1896c5c4113dSnw 		return (-1);
1897c5c4113dSnw 	}
1898c5c4113dSnw 
1899c5c4113dSnw 	/* Do we have a domainname? */
1900c5c4113dSnw 	if (separator == '\\' || separator == '@') {
1901c5c4113dSnw 		it ++;
19028e228215Sdm 		token2 = ucp_grab_token(&it, pos, " \t\n#");
1903c5c4113dSnw 		if (token2 == NULL) {
1904c5c4113dSnw 			free(token);
1905c5c4113dSnw 			return (-1);
1906c5c4113dSnw 		} else if (*it == '\0' || *it == '#') {
1907c5c4113dSnw 			free(token);
1908c5c4113dSnw 			free(token2);
19098e228215Sdm 			print_error(pos,
19108e228215Sdm 			    gettext("UNIX_name not found.\n"));
1911c5c4113dSnw 		}
1912c5c4113dSnw 
1913c5c4113dSnw 		if (separator == '\\') {
1914c5c4113dSnw 			nm->windomain = token;
1915c5c4113dSnw 			nm->winname = token2;
1916c5c4113dSnw 			nm->is_nt4 = 1;
1917c5c4113dSnw 		} else {
1918c5c4113dSnw 			nm->windomain = token2;
1919c5c4113dSnw 			nm->winname = token;
1920c5c4113dSnw 			nm->is_nt4 = 0;
1921c5c4113dSnw 
1922c5c4113dSnw 		}
1923c5c4113dSnw 	} else {
1924c5c4113dSnw 		nm->windomain = NULL;
1925c5c4113dSnw 		nm->winname = token;
1926c5c4113dSnw 		nm->is_nt4 = 0;
1927c5c4113dSnw 	}
1928c5c4113dSnw 
1929c5c4113dSnw 
1930c5c4113dSnw 	it = it + strspn(it, " \t\n");
1931c5c4113dSnw 
1932c5c4113dSnw 	/* Direction string is optional: */
1933c5c4113dSnw 	if (strncmp(it, "==", 2) == 0) {
19348e228215Sdm 		nm->direction = IDMAP_DIRECTION_BI;
1935c5c4113dSnw 		is_direction = 1;
1936c5c4113dSnw 	} else if (strncmp(it, "<=", 2) == 0) {
19378e228215Sdm 		nm->direction = IDMAP_DIRECTION_U2W;
1938c5c4113dSnw 		is_direction = 1;
1939c5c4113dSnw 	} else if (strncmp(it, "=>", 2) == 0) {
19408e228215Sdm 		nm->direction = IDMAP_DIRECTION_W2U;
1941c5c4113dSnw 		is_direction = 1;
1942c5c4113dSnw 	} else {
19438e228215Sdm 		nm->direction = IDMAP_DIRECTION_BI;
1944c5c4113dSnw 		is_direction = 0;
1945c5c4113dSnw 	}
1946c5c4113dSnw 
1947c5c4113dSnw 	if (is_direction) {
1948c5c4113dSnw 		it += 2;
1949c5c4113dSnw 		it += strspn(it, " \t\n");
1950c5c4113dSnw 
1951c5c4113dSnw 		if (*it == '\0' || *it == '#') {
19528e228215Sdm 			print_error(pos,
19538e228215Sdm 			    gettext("UNIX_name not found.\n"));
1954c5c4113dSnw 			return (-1);
1955c5c4113dSnw 		}
1956c5c4113dSnw 	}
1957c5c4113dSnw 
1958c5c4113dSnw 	/* Now unixname: */
1959c5c4113dSnw 	it += strspn(it, " \t\n");
19608e228215Sdm 	token = ucp_grab_token(&it, pos, " \t\n#");
1961c5c4113dSnw 
1962c5c4113dSnw 	if (token == NULL)
1963c5c4113dSnw 		/* nm->winname to be freed by name_mapping_fini */
1964c5c4113dSnw 		return (-1);
1965c5c4113dSnw 
1966c5c4113dSnw 	/* Neither here we support IP qualifiers */
1967c5c4113dSnw 	if (ucp_is_IP_qualifier(token)) {
19688e228215Sdm 		print_error(pos,
19698e228215Sdm 		    gettext("Unable to handle network qualifier.\n"));
1970c5c4113dSnw 		free(token);
1971c5c4113dSnw 		return (-1);
1972c5c4113dSnw 	}
1973c5c4113dSnw 
1974c5c4113dSnw 	nm->unixname = token;
1975c5c4113dSnw 
1976c5c4113dSnw 	it += strspn(it, " \t\n");
1977c5c4113dSnw 
1978c5c4113dSnw 	/* Does something remain on the line */
1979c5c4113dSnw 	if (*it  != '\0' && *it != '#') {
19808e228215Sdm 		print_error(pos,
19818e228215Sdm 		    gettext("Unrecognized parameters \"%s\".\n"), it);
1982c5c4113dSnw 		return (-1);
1983c5c4113dSnw 	}
1984c5c4113dSnw 
1985c5c4113dSnw 	return (1);
1986c5c4113dSnw }
1987c5c4113dSnw 
1988c5c4113dSnw /*
1989c5c4113dSnw  * Parse SMBUSERS line to name_mapping_t. if line is NULL, then
1990c5c4113dSnw  * pasrsing of the previous line is continued. line_num is input line
1991c5c4113dSnw  * number used for error reporting.
1992c5c4113dSnw  * Return values:
1993c5c4113dSnw  *    rc -1: error
1994c5c4113dSnw  *    rc = 0: mapping found and the line is finished,
1995c5c4113dSnw  *    rc = 1: mapping found and there remains other on the line
1996c5c4113dSnw  */
1997c5c4113dSnw static int
sup_line2nm(char * line,cmd_pos_t * pos,name_mapping_t * nm)1998cd37da74Snw sup_line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm)
1999cd37da74Snw {
2000c5c4113dSnw 	static char *ll = NULL;
2001c5c4113dSnw 	static char *unixname = NULL;
2002c5c4113dSnw 	static size_t unixname_l = 0;
2003c5c4113dSnw 	char *token;
2004c5c4113dSnw 
2005c5c4113dSnw 	if (line != NULL) {
2006c5c4113dSnw 		ll = line;
2007c5c4113dSnw 
2008c5c4113dSnw 		unixname = ll += strspn(ll, " \t");
2009c5c4113dSnw 		if (*ll == '\0' || *ll == '#')
2010c5c4113dSnw 			return (0);
2011c5c4113dSnw 
2012c5c4113dSnw 		unixname_l = strcspn(ll, " \t:=#\n");
2013c5c4113dSnw 		ll += unixname_l;
2014c5c4113dSnw 
2015c5c4113dSnw 		if (*ll == '\0'|| *ll == '#')
2016c5c4113dSnw 			return (0);
2017c5c4113dSnw 
2018c5c4113dSnw 		ll +=  strspn(ll, " \t:=#\n");
2019c5c4113dSnw 
2020c5c4113dSnw 	}
2021c5c4113dSnw 
2022c5c4113dSnw 	if (*ll == '\0'|| *ll == '#')
2023c5c4113dSnw 		return (0);
2024c5c4113dSnw 
20258e228215Sdm 	token = ucp_grab_token(&ll, pos, " \t\n");
2026c5c4113dSnw 	if (token == NULL)
2027c5c4113dSnw 		return (-1);
2028c5c4113dSnw 
2029c5c4113dSnw 	nm->is_nt4 = 0;
20308e228215Sdm 	nm->direction = IDMAP_DIRECTION_W2U;
2031c5c4113dSnw 
2032c5c4113dSnw 	nm->windomain = NULL;
2033c5c4113dSnw 	nm->winname = token;
2034c5c4113dSnw 	nm->unixname = strndup(unixname, unixname_l);
2035c5c4113dSnw 	if (nm->unixname == NULL)
2036c5c4113dSnw 		return (-1);
2037c5c4113dSnw 
2038c5c4113dSnw 	ll += strspn(ll, " \t\n");
2039c5c4113dSnw 	return (1);
2040c5c4113dSnw }
2041c5c4113dSnw 
2042c5c4113dSnw /* Parse line to name_mapping_t. Basicaly just a format switch. */
2043c5c4113dSnw static int
line2nm(char * line,cmd_pos_t * pos,name_mapping_t * nm,format_t f)2044cd37da74Snw line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm, format_t f)
2045cd37da74Snw {
2046c5c4113dSnw 	switch (f) {
2047c5c4113dSnw 	case USERMAP_CFG:
2048c5c4113dSnw 		if (line == NULL)
2049c5c4113dSnw 			return (0);
2050c5c4113dSnw 		else
20518e228215Sdm 			return (ucp_line2nm(line, pos, nm));
2052c5c4113dSnw 	case SMBUSERS:
20538e228215Sdm 		return (sup_line2nm(line, pos, nm));
2054c5c4113dSnw 	default:
2055821da340Sdm 		/* This can never happen */
20568e228215Sdm 		print_error(pos,
2057821da340Sdm 		    gettext("Internal error: invalid line format.\n"));
2058c5c4113dSnw 	}
2059c5c4113dSnw 
2060c5c4113dSnw 	return (-1);
2061c5c4113dSnw }
2062c5c4113dSnw 
2063c5c4113dSnw 
2064c5c4113dSnw /* Examine -f flag and return the appropriate format_t */
2065c5c4113dSnw static format_t
ff2format(char * ff,int is_mandatory)2066cd37da74Snw ff2format(char *ff, int is_mandatory)
2067cd37da74Snw {
2068c5c4113dSnw 
2069c5c4113dSnw 	if (ff == NULL && is_mandatory) {
20708e228215Sdm 		print_error(NULL, gettext("Format not given.\n"));
2071c5c4113dSnw 		return (UNDEFINED_FORMAT);
2072c5c4113dSnw 	}
2073c5c4113dSnw 
2074c5c4113dSnw 	if (ff == NULL)
2075c5c4113dSnw 		return (DEFAULT_FORMAT);
2076c5c4113dSnw 
2077c5c4113dSnw 	if (strcasecmp(ff, "usermap.cfg") == 0)
2078c5c4113dSnw 		return (USERMAP_CFG);
2079c5c4113dSnw 
2080c5c4113dSnw 	if (strcasecmp(ff, "smbusers") == 0)
2081c5c4113dSnw 		return (SMBUSERS);
2082c5c4113dSnw 
20838e228215Sdm 	print_error(NULL,
2084cd37da74Snw 	    gettext("The only known formats are: \"usermap.cfg\" and "
2085cd37da74Snw 	    "\"smbusers\".\n"));
2086c5c4113dSnw 	return (UNDEFINED_FORMAT);
2087c5c4113dSnw }
2088c5c4113dSnw 
2089c5c4113dSnw /* Delete all namerules of the given type */
2090c5c4113dSnw static int
flush_nm(boolean_t is_user,cmd_pos_t * pos)20918e228215Sdm flush_nm(boolean_t is_user, cmd_pos_t *pos)
2092c5c4113dSnw {
2093c5c4113dSnw 	idmap_stat stat;
2094c5c4113dSnw 
2095cd37da74Snw 	stat = idmap_udt_flush_namerules(udt);
2096c5c4113dSnw 	if (stat < 0) {
20978e228215Sdm 		print_error(pos,
2098c5c4113dSnw 		    is_user ? gettext("Unable to flush users (%s).\n")
2099c5c4113dSnw 		    : gettext("Unable to flush groups (%s).\n"),
21001fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
2101c5c4113dSnw 		return (-1);
2102c5c4113dSnw 	}
21038e228215Sdm 
21048e228215Sdm 	if (positions_add(pos) < 0)
21058e228215Sdm 		return (-1);
21068e228215Sdm 
2107c5c4113dSnw 	return (0);
2108c5c4113dSnw }
2109c5c4113dSnw 
2110c5c4113dSnw /* import command handler */
2111c5c4113dSnw static int
2112c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_import(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)21138e228215Sdm do_import(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2114c5c4113dSnw {
2115c5c4113dSnw 	name_mapping_t *nm;
21168e228215Sdm 	cmd_pos_t pos2;
2117c5c4113dSnw 	char line[MAX_INPUT_LINE_SZ];
2118c5c4113dSnw 	format_t format;
2119c5c4113dSnw 	int rc = 0;
2120c5c4113dSnw 	idmap_stat stat;
2121c5c4113dSnw 	FILE *file = NULL;
2122c5c4113dSnw 
2123c5c4113dSnw 	if (batch_mode) {
21248e228215Sdm 		print_error(pos,
2125c5c4113dSnw 		    gettext("Import is not allowed in the batch mode.\n"));
2126c5c4113dSnw 		return (-1);
2127c5c4113dSnw 	}
2128c5c4113dSnw 
2129c5c4113dSnw 	format = ff2format(argv[0], 1);
2130c5c4113dSnw 	if (format == UNDEFINED_FORMAT)
2131c5c4113dSnw 		return (-1);
2132c5c4113dSnw 
2133c5c4113dSnw 	if (init_udt_command())
2134c5c4113dSnw 		return (-1);
2135c5c4113dSnw 
2136c5c4113dSnw 	/* We don't flush groups in the usermap.cfg nor smbusers format */
2137c5c4113dSnw 	if (f[F_FLAG] != NULL &&
21388e228215Sdm 	    flush_nm(B_TRUE, pos) < 0 &&
2139c5c4113dSnw 	    (format == USERMAP_CFG || format == SMBUSERS ||
21408e228215Sdm 	    flush_nm(B_FALSE, pos) < 0)) {
2141c5c4113dSnw 		rc = -1;
2142c5c4113dSnw 		goto cleanup;
2143c5c4113dSnw 	}
2144c5c4113dSnw 
2145c5c4113dSnw 	/* Where we import from? */
2146c5c4113dSnw 	if (f[f_FLAG] == NULL)
2147c5c4113dSnw 		file = stdin;
2148c5c4113dSnw 	else {
2149c5c4113dSnw 		file = fopen(f[f_FLAG], "r");
2150c5c4113dSnw 		if (file == NULL) {
2151c5c4113dSnw 			perror(f[f_FLAG]);
2152c5c4113dSnw 			goto cleanup;
2153c5c4113dSnw 		}
2154c5c4113dSnw 	}
2155c5c4113dSnw 
21568e228215Sdm 	pos2.linenum = 0;
21578e228215Sdm 	pos2.line = line;
2158c5c4113dSnw 
2159c5c4113dSnw 	while (fgets(line, MAX_INPUT_LINE_SZ, file)) {
2160c5c4113dSnw 		char *line2 = line;
21618e228215Sdm 		pos2.linenum++;
2162c5c4113dSnw 
2163c5c4113dSnw 		/*
2164c5c4113dSnw 		 * In SMBUSERS format there can be more mappings on
2165c5c4113dSnw 		 * each line. So we need the internal cycle for each line.
2166c5c4113dSnw 		 */
2167c5c4113dSnw 		do {
2168c5c4113dSnw 			nm = name_mapping_init();
2169c5c4113dSnw 			if (nm == NULL) {
2170c5c4113dSnw 				rc = -1;
2171c5c4113dSnw 				goto cleanup;
2172c5c4113dSnw 			}
2173c5c4113dSnw 
21748e228215Sdm 			rc = line2nm(line2, &pos2, nm, format);
2175c5c4113dSnw 			line2 = NULL;
2176c5c4113dSnw 
2177c5c4113dSnw 			if (rc < 1) {
2178c5c4113dSnw 				name_mapping_fini(nm);
2179c5c4113dSnw 				break;
2180c5c4113dSnw 			}
2181c5c4113dSnw 
2182c5c4113dSnw 			stat = idmap_udt_add_namerule(udt, nm->windomain,
2183cd37da74Snw 			    nm->is_user ? B_TRUE : B_FALSE,
2184cd37da74Snw 			    nm->is_wuser ? B_TRUE : B_FALSE,
2185cd37da74Snw 			    nm->winname,
2186c5c4113dSnw 			    nm->unixname, nm->is_nt4, nm->direction);
2187c5c4113dSnw 			if (stat < 0) {
21888e228215Sdm 				print_error(&pos2,
2189c5c4113dSnw 				    gettext("Transaction error (%s)\n"),
21901fdeec65Sjoyce mcintosh 				    idmap_stat2string(stat));
2191c5c4113dSnw 				rc = -1;
2192c5c4113dSnw 			}
2193c5c4113dSnw 
21948e228215Sdm 			if (rc >= 0)
21958e228215Sdm 				rc = positions_add(&pos2);
21968e228215Sdm 
2197c5c4113dSnw 			name_mapping_fini(nm);
2198c5c4113dSnw 
2199c5c4113dSnw 		} while (rc >= 0);
2200c5c4113dSnw 
2201c5c4113dSnw 		if (rc < 0) {
22028e228215Sdm 			print_error(NULL,
2203c5c4113dSnw 			    gettext("Import canceled.\n"));
2204c5c4113dSnw 			break;
2205c5c4113dSnw 		}
2206c5c4113dSnw 	}
2207c5c4113dSnw 
2208c5c4113dSnw cleanup:
22098e228215Sdm 	if (fini_udt_command((rc < 0 ? 0 : 1), pos))
22108e228215Sdm 		rc = -1;
2211c5c4113dSnw 	if (file != NULL && file != stdin)
2212c5c4113dSnw 		(void) fclose(file);
2213c5c4113dSnw 	return (rc);
2214c5c4113dSnw }
2215c5c4113dSnw 
2216c5c4113dSnw 
2217c5c4113dSnw /*
2218c5c4113dSnw  * List name mappings in the format specified. list_users /
2219c5c4113dSnw  * list_groups determine which type to list. The output goes to the
2220c5c4113dSnw  * file fi.
2221c5c4113dSnw  */
2222c5c4113dSnw static int
list_name_mappings(format_t format,FILE * fi)22238e228215Sdm list_name_mappings(format_t format, FILE *fi)
2224c5c4113dSnw {
2225c5c4113dSnw 	idmap_stat stat;
2226c5c4113dSnw 	idmap_iter_t *ihandle;
2227c5c4113dSnw 	name_mapping_t *nm;
2228cd37da74Snw 	boolean_t is_user;
2229cd37da74Snw 	boolean_t is_wuser;
2230cd37da74Snw 	print_handle_t *ph;
2231c5c4113dSnw 
22321fdeec65Sjoyce mcintosh 	stat = idmap_iter_namerules(NULL, 0, 0, NULL, NULL, &ihandle);
2233cd37da74Snw 	if (stat < 0) {
2234cd37da74Snw 		print_error(NULL,
2235cd37da74Snw 		    gettext("Iteration handle not obtained (%s)\n"),
22361fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
2237cd37da74Snw 		idmap_iter_destroy(ihandle);
2238cd37da74Snw 		return (-1);
2239cd37da74Snw 	}
2240c5c4113dSnw 
2241cd37da74Snw 	ph = print_mapping_init(format, fi);
2242cd37da74Snw 	if (ph == NULL)
2243cd37da74Snw 		return (-1);
2244cd37da74Snw 
2245cd37da74Snw 	do {
2246cd37da74Snw 		nm = name_mapping_init();
2247cd37da74Snw 		if (nm == NULL) {
2248c5c4113dSnw 			idmap_iter_destroy(ihandle);
2249c5c4113dSnw 			return (-1);
2250c5c4113dSnw 		}
2251c5c4113dSnw 
2252cd37da74Snw 		stat = idmap_iter_next_namerule(ihandle, &nm->windomain,
2253cd37da74Snw 		    &nm->winname, &nm->unixname, &is_user, &is_wuser,
2254cd37da74Snw 		    &nm->is_nt4, &nm->direction);
2255cd37da74Snw 		if (stat >= 0) {
2256479ac375Sdm 			nm->is_user = is_user ? IDMAP_YES : IDMAP_NO;
2257479ac375Sdm 			nm->is_wuser = is_wuser ? IDMAP_YES : IDMAP_NO;
2258cd37da74Snw 			(void) print_mapping(ph, nm);
2259cd37da74Snw 		}
2260c5c4113dSnw 
2261cd37da74Snw 		name_mapping_fini(nm);
2262c5c4113dSnw 
2263cd37da74Snw 	} while (stat > 0);
2264c5c4113dSnw 
2265cd37da74Snw 	(void) print_mapping_fini(ph);
2266c5c4113dSnw 
2267cd37da74Snw 	if (stat < 0 && stat !=  IDMAP_ERR_NOTFOUND) {
2268cd37da74Snw 		print_error(NULL,
2269cd37da74Snw 		    gettext("Error during iteration (%s)\n"),
22701fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
2271c5c4113dSnw 		idmap_iter_destroy(ihandle);
2272cd37da74Snw 		return (-1);
2273c5c4113dSnw 	}
2274cd37da74Snw 
2275cd37da74Snw 	idmap_iter_destroy(ihandle);
2276c5c4113dSnw 	return (0);
2277c5c4113dSnw }
2278c5c4113dSnw 
2279821da340Sdm /* Export command handler  */
2280c5c4113dSnw static int
2281c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_export(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)2282cd37da74Snw do_export(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2283cd37da74Snw {
2284c5c4113dSnw 	int rc;
2285c5c4113dSnw 	format_t format;
2286c5c4113dSnw 	FILE *fi;
2287c5c4113dSnw 
2288c5c4113dSnw 	format = ff2format(argv[0], 1);
2289c5c4113dSnw 	if (format == UNDEFINED_FORMAT)
2290c5c4113dSnw 		return (-1);
2291c5c4113dSnw 
2292c5c4113dSnw 	/* Where do we output to? */
2293c5c4113dSnw 	if (f[f_FLAG] == NULL)
2294c5c4113dSnw 		fi = stdout;
2295c5c4113dSnw 	else {
2296c5c4113dSnw 		fi = fopen(f[f_FLAG], "w");
2297c5c4113dSnw 		if (fi == NULL) {
2298c5c4113dSnw 			perror(f[f_FLAG]);
2299c5c4113dSnw 			return (-1);
2300c5c4113dSnw 		}
2301c5c4113dSnw 	}
2302c5c4113dSnw 
2303c5c4113dSnw 	/* List the requested types: */
23048e228215Sdm 	rc = list_name_mappings(format, fi);
2305c5c4113dSnw 
2306c5c4113dSnw cleanup:
2307c5c4113dSnw 	if (fi != NULL && fi != stdout)
2308c5c4113dSnw 		(void) fclose(fi);
2309c5c4113dSnw 	return (rc);
2310c5c4113dSnw }
2311c5c4113dSnw 
2312c5c4113dSnw /* List command handler */
2313c5c4113dSnw static int
2314c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_list_name_mappings(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)23158e228215Sdm do_list_name_mappings(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2316c5c4113dSnw {
2317c5c4113dSnw 	int rc;
2318c5c4113dSnw 
2319c5c4113dSnw 	/* List the requested types: */
23208e228215Sdm 	rc = list_name_mappings(DEFAULT_FORMAT, stdout);
2321c5c4113dSnw 
2322c5c4113dSnw 	return (rc);
2323c5c4113dSnw }
2324c5c4113dSnw 
2325c5c4113dSnw /* This is just a debug function for dumping flags */
2326c5c4113dSnw static void
print_flags(flag_t * f)2327c5c4113dSnw print_flags(flag_t *f)
2328c5c4113dSnw {
2329c5c4113dSnw 	int c;
2330c5c4113dSnw 	for (c = 0; c < FLAG_ALPHABET_SIZE; c++) {
2331c5c4113dSnw 		if (f[c] == FLAG_SET)
2332c5c4113dSnw 			(void) printf("FLAG: -%c, VALUE: %p\n", c,
2333c5c4113dSnw 			    (void *) f[c]);
2334c5c4113dSnw 		else if (f[c])
2335c5c4113dSnw 			(void) printf("FLAG: -%c, VALUE: %s\n", c, f[c]);
2336c5c4113dSnw 	}
2337c5c4113dSnw }
2338c5c4113dSnw 
2339479ac375Sdm /* Convert string like sid or winname to the identity type code */
2340479ac375Sdm 
2341479ac375Sdm static int
string2type(char * str,cmd_pos_t * pos)234296d32a53SToomas Soome string2type(char *str, cmd_pos_t *pos)
234396d32a53SToomas Soome {
2344479ac375Sdm 	int i;
2345479ac375Sdm 	int code = TYPE_INVALID;
2346479ac375Sdm 
2347479ac375Sdm 	for (i = 0; i < sizeof (identity2code) / sizeof (id_code_t); i++) {
2348479ac375Sdm 		if (strcasecmp(identity2code[i].identity, str) == 0) {
2349479ac375Sdm 			code = identity2code[i].code;
2350479ac375Sdm 			break;
2351479ac375Sdm 		}
2352479ac375Sdm 	}
2353479ac375Sdm 
2354479ac375Sdm 	if (code == TYPE_INVALID) {
2355479ac375Sdm 		print_error(pos,
2356479ac375Sdm 		    gettext("Error: invalid identity type \"%s\"\n"), str);
2357479ac375Sdm 	}
2358479ac375Sdm 
2359479ac375Sdm 	return (code);
2360479ac375Sdm }
2361479ac375Sdm 
2362479ac375Sdm 
2363479ac375Sdm 
2364cd37da74Snw 
2365c5c4113dSnw /*
2366cd37da74Snw  * Split argument to its identity code and a name part
2367cd37da74Snw  * return values:
2368479ac375Sdm  *    TYPE_INVALID for unknown identity
2369479ac375Sdm  *    TYPE_AUTO for no identity (to be autodetected)
2370479ac375Sdm  *    <TYPE_XXX> for known identity
2371c5c4113dSnw  */
2372cd37da74Snw 
2373c5c4113dSnw static int
get_identity(char * arg,char ** name,cmd_pos_t * pos)2374cd37da74Snw get_identity(char *arg, char **name, cmd_pos_t *pos)
2375cd37da74Snw {
2376c5c4113dSnw 	char *it;
2377479ac375Sdm 	int code = TYPE_INVALID;
2378c5c4113dSnw 
2379cd37da74Snw 	if ((it = strchr(arg, ':')) == NULL) {
2380cd37da74Snw 		*name = arg;
2381479ac375Sdm 		return (TYPE_AUTO);
2382cd37da74Snw 	}
2383c5c4113dSnw 
23848e228215Sdm 
2385cd37da74Snw 	*it = '\0';
2386479ac375Sdm 	code = string2type(arg, pos);
2387479ac375Sdm 	*it = ':'; /* restore the original string: */
23888e228215Sdm 
2389cd37da74Snw 	*name = it + 1;
2390cd37da74Snw 	return (code);
2391cd37da74Snw }
23928e228215Sdm 
2393cd37da74Snw /*
2394cd37da74Snw  * This function splits name to the relevant pieces: is_user, winname,
2395cd37da74Snw  * windomain unixname. E.g. for winname, it strdups nm->winname and possibly
2396cd37da74Snw  * nm->windomain and return TYPE_WN.
2397cd37da74Snw  *
2398cd37da74Snw  * If there is already one of the text fields allocated, it is OK.
2399cd37da74Snw  * Return values:
2400cd37da74Snw  *     -1 ... syntax error
2401cd37da74Snw  *     0 ... it wasnt possible to determine
2402cd37da74Snw  *     <TYPE_XXX> otherwise
2403cd37da74Snw  */
24048e228215Sdm 
2405cd37da74Snw static int
name2parts(char * name,name_mapping_t * nm,cmd_pos_t * pos)2406cd37da74Snw name2parts(char *name, name_mapping_t *nm, cmd_pos_t *pos)
2407cd37da74Snw {
2408cd37da74Snw 	char *it;
2409cd37da74Snw 	int code;
24108e228215Sdm 
2411cd37da74Snw 	code = get_identity(name, &it, pos);
2412cd37da74Snw 
2413cd37da74Snw 	switch (code) {
2414479ac375Sdm 	case TYPE_INVALID:
2415cd37da74Snw 		/* syntax error: */
2416cd37da74Snw 		return (-1);
2417479ac375Sdm 	case TYPE_AUTO:
2418cd37da74Snw 		/* autodetection: */
2419479ac375Sdm 		if (nm->winname != NULL && nm->is_wuser != IDMAP_UNKNOWN)
2420479ac375Sdm 			code = nm->is_wuser == IDMAP_YES ? TYPE_UU : TYPE_UG;
2421cd37da74Snw 		else if (nm->unixname != NULL ||
2422cd37da74Snw 		    strchr(name, '@') != NULL ||
2423cd37da74Snw 		    strchr(name, '\\') != NULL)
2424479ac375Sdm 			/* btw, nm->is_user can never be IDMAP_UNKNOWN here */
2425cd37da74Snw 			code = TYPE_WN;
2426cd37da74Snw 		else
2427cd37da74Snw 			return (0);
2428cd37da74Snw 		/* If the code was guessed succesfully, we are OK. */
2429cd37da74Snw 		break;
2430cd37da74Snw 	default:
2431cd37da74Snw 		name = it;
2432cd37da74Snw 	}
2433cd37da74Snw 
2434cd37da74Snw 	if (code & IS_WIN) {
2435cd37da74Snw 		if (code & IS_USER)
2436479ac375Sdm 			nm->is_wuser = IDMAP_YES;
2437cd37da74Snw 		else if (code & IS_GROUP)
2438479ac375Sdm 			nm->is_wuser = IDMAP_NO;
2439cd37da74Snw 	} else {
2440cd37da74Snw 		if (code & IS_USER)
2441479ac375Sdm 			nm->is_user = IDMAP_YES;
244248258c6bSjp 		else if (code & IS_GROUP)
2443479ac375Sdm 			nm->is_user = IDMAP_NO;
2444c5c4113dSnw 	}
2445c5c4113dSnw 
2446cd37da74Snw 	if (code & IS_WIN && code & IS_NAME) {
2447cd37da74Snw 		if (nm->winname != NULL || nm->windomain != NULL)
2448cd37da74Snw 			return (code);
2449cd37da74Snw 
2450c5c4113dSnw 		if ((it = strchr(name, '@')) != NULL) {
24518e228215Sdm 			int length = it - name + 1;
2452cd37da74Snw 			nm->winname = (char *)malloc(length);
2453c5c4113dSnw 			(void) strncpy(nm->winname, name, length - 1);
2454c5c4113dSnw 			nm->winname[length - 1] = '\0';
2455c5c4113dSnw 			nm->windomain = strdup(it + 1);
2456c5c4113dSnw 		} else if ((it = strrchr(name, '\\')) != NULL) {
24578e228215Sdm 			int length = it - name + 1;
2458cd37da74Snw 			nm->windomain = (char *)malloc(length);
2459c5c4113dSnw 			(void) strncpy(nm->windomain, name, length - 1);
2460c5c4113dSnw 			nm->windomain[length - 1] = '\0';
2461c5c4113dSnw 			nm->winname = strdup(it + 1);
2462c5c4113dSnw 			nm->is_nt4 = B_TRUE;
2463cd37da74Snw 		} else
2464cd37da74Snw 			nm->winname = strdup(name);
2465cd37da74Snw 
2466cd37da74Snw 		return (code);
2467c5c4113dSnw 	}
2468c5c4113dSnw 
2469cd37da74Snw 
2470cd37da74Snw 	if (!(code & IS_WIN) && code & IS_NAME) {
2471cd37da74Snw 		if (nm->unixname != NULL)
2472cd37da74Snw 			return (code);
2473cd37da74Snw 
2474c5c4113dSnw 		if (strlen(name) == 0)
2475c5c4113dSnw 			nm->unixname = strdup("\"\"");
2476c5c4113dSnw 		else
2477c5c4113dSnw 			nm->unixname = strdup(name);
2478cd37da74Snw 		return (code);
2479cd37da74Snw 	}
2480cd37da74Snw 
2481cd37da74Snw 
2482cd37da74Snw 	if (code & IS_WIN && !(code & IS_NAME)) {
2483cd37da74Snw 		if (!sid_convert(name, &nm->sidprefix, &nm->rid, pos))
2484cd37da74Snw 			return (-1);
2485c5c4113dSnw 		else
2486cd37da74Snw 			return (code);
2487cd37da74Snw 	}
2488cd37da74Snw 
2489cd37da74Snw /*
2490cd37da74Snw  * it is (!(code & TYPE_WIN) &&  !(code & TYPE_NAME)) here - the other
2491cd37da74Snw  * possiblities are exhausted.
2492cd37da74Snw  */
2493cd37da74Snw 
2494cd37da74Snw 	if (!pid_convert(name, &nm->pid, code, pos))
2495cd37da74Snw 			return (-1);
2496cd37da74Snw 		else
2497cd37da74Snw 			return (code);
2498cd37da74Snw 
2499cd37da74Snw }
2500cd37da74Snw 
2501cd37da74Snw /*
2502cd37da74Snw  * Cycle through add/remove arguments until they are identified or found
2503cd37da74Snw  * invalid.
2504cd37da74Snw  */
2505cd37da74Snw static
2506479ac375Sdm name_mapping_t *
args2nm(int * is_first_win,int argc,char ** argv,cmd_pos_t * pos)2507479ac375Sdm args2nm(int *is_first_win, int argc, char **argv,
2508cd37da74Snw     cmd_pos_t *pos)
2509cd37da74Snw {
2510cd37da74Snw 	int code;
2511cd37da74Snw 	int i;
2512479ac375Sdm 	name_mapping_t *nm;
2513479ac375Sdm 
2514479ac375Sdm 	nm = name_mapping_init();
2515479ac375Sdm 	if (nm == NULL)
2516479ac375Sdm 		return (NULL);
2517cd37da74Snw 
2518cd37da74Snw 	for (i = 0; i < 2 * argc - 1; i++) {
2519cd37da74Snw 		code = name2parts(argv[i % 2], nm, pos);
2520cd37da74Snw 		switch (code) {
2521cd37da74Snw 			case -1:
2522479ac375Sdm 				goto fail;
2523cd37da74Snw 		case 0:
2524cd37da74Snw 			if (i > 0) {
2525cd37da74Snw 				print_error(pos,
2526cd37da74Snw 				    gettext("Missing identity type"
2527cd37da74Snw 				    " cannot be determined for %s.\n"),
2528cd37da74Snw 				    argv[i % 2]);
2529479ac375Sdm 				goto fail;
2530cd37da74Snw 			}
2531cd37da74Snw 			break;
2532cd37da74Snw 		default:
2533cd37da74Snw 			if (!(code & IS_NAME)) {
2534cd37da74Snw 				print_error(pos,
2535cd37da74Snw 				    gettext("%s is not a valid name\n"),
2536cd37da74Snw 				    argv[i % 2]);
2537479ac375Sdm 				goto fail;
2538cd37da74Snw 			}
2539cd37da74Snw 		}
2540cd37da74Snw 	}
2541cd37da74Snw 
2542cd37da74Snw 	if (argc == 2 && nm->winname == NULL) {
2543cd37da74Snw 		print_error(pos, gettext("No windows identity found.\n"));
2544479ac375Sdm 		goto fail;
2545cd37da74Snw 	}
2546cd37da74Snw 	if (argc == 2 && nm->unixname == NULL) {
2547cd37da74Snw 		print_error(pos, gettext("No unix identity found.\n"));
2548479ac375Sdm 		goto fail;
2549479ac375Sdm 	}
2550479ac375Sdm 	if (argc == 1 && nm->winname == NULL && nm->unixname == NULL) {
2551479ac375Sdm 		print_error(pos, gettext("No identity type determined.\n"));
2552479ac375Sdm 		goto fail;
2553c5c4113dSnw 	}
2554c5c4113dSnw 
2555479ac375Sdm 	if (is_first_win != NULL)
2556479ac375Sdm 		*is_first_win = code & IS_WIN;
2557479ac375Sdm 	return (nm);
2558479ac375Sdm fail:
2559479ac375Sdm 	name_mapping_fini(nm);
2560479ac375Sdm 	return (NULL);
2561c5c4113dSnw }
2562c5c4113dSnw 
2563cd37da74Snw 
2564cd37da74Snw 
2565c5c4113dSnw /* add command handler. */
2566c5c4113dSnw static int
do_add_name_mapping(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)25678e228215Sdm do_add_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2568c5c4113dSnw {
2569c5c4113dSnw 	name_mapping_t *nm;
2570c5c4113dSnw 	int rc = 0;
2571cd37da74Snw 	int is_first_win;
2572c5c4113dSnw 	idmap_stat stat;
2573cd37da74Snw 	int is_wuser;
2574cd37da74Snw 	print_handle_t *ph;
2575cd37da74Snw 
2576c5c4113dSnw 
2577c5c4113dSnw 
25788e228215Sdm 	/* Exactly two arguments must be specified */
2579c5c4113dSnw 	if (argc < 2) {
25808e228215Sdm 		print_error(pos, gettext("Not enough arguments.\n"));
2581c5c4113dSnw 		return (-1);
2582c5c4113dSnw 	} else if (argc > 2)  {
25838e228215Sdm 		print_error(pos, gettext("Too many arguments.\n"));
2584c5c4113dSnw 		return (-1);
25858e228215Sdm 	}
2586c5c4113dSnw 
2587479ac375Sdm 	nm = args2nm(&is_first_win, argc, argv, pos);
2588c5c4113dSnw 	if (nm == NULL)
2589c5c4113dSnw 		return (-1);
2590c5c4113dSnw 
2591c5c4113dSnw 	if (f[d_FLAG] != NULL)
2592cd37da74Snw 		nm->direction = is_first_win
2593cd37da74Snw 		    ? IDMAP_DIRECTION_W2U
2594cd37da74Snw 		    : IDMAP_DIRECTION_U2W;
2595c5c4113dSnw 	else
25968e228215Sdm 		nm->direction = IDMAP_DIRECTION_BI;
2597c5c4113dSnw 
2598c5c4113dSnw 	/* Now let us write it: */
2599c5c4113dSnw 
2600c5c4113dSnw 	if (init_udt_command()) {
2601c5c4113dSnw 		name_mapping_fini(nm);
2602c5c4113dSnw 		return (-1);
2603c5c4113dSnw 	}
2604c5c4113dSnw 
2605479ac375Sdm 	for (is_wuser = IDMAP_YES; is_wuser >= IDMAP_NO; is_wuser--) {
2606479ac375Sdm 		/* nm->is_wuser can be IDMAP_YES, IDMAP_NO or IDMAP_UNKNOWN */
2607479ac375Sdm 		if ((is_wuser == IDMAP_YES && nm->is_wuser == IDMAP_NO) ||
2608479ac375Sdm 		    (is_wuser == IDMAP_NO && nm->is_wuser == IDMAP_YES))
2609cd37da74Snw 			continue;
2610cd37da74Snw 
2611cd37da74Snw 		stat = idmap_udt_add_namerule(udt, nm->windomain,
2612cd37da74Snw 		    nm->is_user ? B_TRUE : B_FALSE,
2613cd37da74Snw 		    is_wuser ? B_TRUE : B_FALSE,
2614cd37da74Snw 		    nm->winname, nm->unixname, nm->is_nt4, nm->direction);
2615cd37da74Snw 	}
2616c5c4113dSnw 
2617c5c4113dSnw 	/* We echo the mapping */
2618cd37da74Snw 	ph = print_mapping_init(DEFAULT_FORMAT, stdout);
2619cd37da74Snw 	if (ph == NULL) {
2620cd37da74Snw 		rc = -1;
2621cd37da74Snw 		goto cleanup;
2622cd37da74Snw 	}
2623cd37da74Snw 	(void) print_mapping(ph, nm);
2624cd37da74Snw 	(void) print_mapping_fini(ph);
2625c5c4113dSnw 
2626479ac375Sdm 	if (stat != IDMAP_SUCCESS) {
26278e228215Sdm 		print_error(pos,
2628c5c4113dSnw 		    gettext("Mapping not created (%s)\n"),
26291fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
2630c5c4113dSnw 		rc = -1;
2631c5c4113dSnw 	}
2632c5c4113dSnw 
26338e228215Sdm 	if (rc == 0)
26348e228215Sdm 		rc = positions_add(pos);
26358e228215Sdm 
2636c5c4113dSnw cleanup:
2637c5c4113dSnw 	name_mapping_fini(nm);
26388e228215Sdm 	if (fini_udt_command(1, pos))
26398e228215Sdm 		rc = -1;
2640c5c4113dSnw 	return (rc);
2641c5c4113dSnw }
2642c5c4113dSnw 
2643c5c4113dSnw /* remove command handler */
2644c5c4113dSnw static int
do_remove_name_mapping(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)26458e228215Sdm do_remove_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2646c5c4113dSnw {
2647c5c4113dSnw 	name_mapping_t *nm;
2648c5c4113dSnw 	int rc = 0;
2649c5c4113dSnw 	idmap_stat stat;
2650cd37da74Snw 	int is_first_win;
2651cd37da74Snw 	int is_wuser;
2652c5c4113dSnw 
2653c5c4113dSnw 	/* "-a" means we flush all of them */
2654c5c4113dSnw 	if (f[a_FLAG] != NULL) {
2655c5c4113dSnw 		if (argc) {
26568e228215Sdm 			print_error(pos,
2657c5c4113dSnw 			    gettext("Too many arguments.\n"));
2658c5c4113dSnw 			return (-1);
2659c5c4113dSnw 		}
2660c5c4113dSnw 
2661c5c4113dSnw 		if (init_udt_command())
2662c5c4113dSnw 			return (-1);
26638e228215Sdm 		rc = flush_nm(B_TRUE, pos);
2664c5c4113dSnw 
26658e228215Sdm 		if (rc >= 0)
26668e228215Sdm 			rc = flush_nm(B_FALSE, pos);
26678e228215Sdm 
26688e228215Sdm 		if (fini_udt_command(rc ? 0 : 1, pos))
26698e228215Sdm 			rc = -1;
2670c5c4113dSnw 		return (rc);
2671c5c4113dSnw 	}
2672c5c4113dSnw 
2673c5c4113dSnw 	/* Contrary to add_name_mapping, we can have only one argument */
2674c5c4113dSnw 	if (argc < 1) {
26758e228215Sdm 		print_error(pos, gettext("Not enough arguments.\n"));
2676c5c4113dSnw 		return (-1);
2677c5c4113dSnw 	} else if (argc > 2) {
26788e228215Sdm 		print_error(pos, gettext("Too many arguments.\n"));
2679c5c4113dSnw 		return (-1);
2680c5c4113dSnw 	} else if (
2681c5c4113dSnw 		/* both -f and -t: */
2682c5c4113dSnw 	    f[f_FLAG] != NULL && f[t_FLAG] != NULL ||
2683c5c4113dSnw 		/* -d with a single argument: */
2684c5c4113dSnw 	    argc == 1 && f[d_FLAG] != NULL ||
2685c5c4113dSnw 		/* -f or -t with two arguments: */
2686c5c4113dSnw 	    argc == 2 && (f[f_FLAG] != NULL || f[t_FLAG] != NULL)) {
26878e228215Sdm 		print_error(pos,
2688c5c4113dSnw 		    gettext("Direction ambiguous.\n"));
2689c5c4113dSnw 		return (-1);
2690c5c4113dSnw 	}
2691c5c4113dSnw 
2692c5c4113dSnw 
2693c5c4113dSnw 	/*
2694c5c4113dSnw 	 * Similar to do_add_name_mapping - see the comments
2695c5c4113dSnw 	 * there. Except we may have only one argument here.
2696c5c4113dSnw 	 */
2697479ac375Sdm 	nm = args2nm(&is_first_win, argc, argv, pos);
2698c5c4113dSnw 	if (nm == NULL)
2699c5c4113dSnw 		return (-1);
2700c5c4113dSnw 
2701c5c4113dSnw 	/*
2702c5c4113dSnw 	 * If the direction is not specified by a -d/-f/-t flag, then it
27038e228215Sdm 	 * is IDMAP_DIRECTION_UNDEF, because in that case we want to
27048e228215Sdm 	 * remove any mapping. If it was IDMAP_DIRECTION_BI, idmap_api would
27058e228215Sdm 	 * delete a bidirectional one only.
2706c5c4113dSnw 	 */
2707c5c4113dSnw 	if (f[d_FLAG] != NULL || f[f_FLAG] != NULL)
2708cd37da74Snw 		nm->direction = is_first_win
27098e228215Sdm 		    ? IDMAP_DIRECTION_W2U
27108e228215Sdm 		    : IDMAP_DIRECTION_U2W;
2711cd37da74Snw 	else if (f[t_FLAG] != NULL)
2712cd37da74Snw 		nm->direction = is_first_win
2713cd37da74Snw 		    ? IDMAP_DIRECTION_U2W
2714cd37da74Snw 		    : IDMAP_DIRECTION_W2U;
2715c5c4113dSnw 	else
27168e228215Sdm 		nm->direction = IDMAP_DIRECTION_UNDEF;
2717c5c4113dSnw 
2718c5c4113dSnw 	if (init_udt_command()) {
2719c5c4113dSnw 		name_mapping_fini(nm);
2720c5c4113dSnw 		return (-1);
2721c5c4113dSnw 	}
2722c5c4113dSnw 
2723479ac375Sdm 	for (is_wuser = IDMAP_YES; is_wuser >= IDMAP_NO; is_wuser--) {
2724479ac375Sdm 		if ((is_wuser == IDMAP_YES && nm->is_wuser == IDMAP_NO) ||
2725479ac375Sdm 		    (is_wuser == IDMAP_NO && nm->is_wuser == IDMAP_YES))
27268e228215Sdm 			continue;
27278e228215Sdm 
2728cd37da74Snw 		stat = idmap_udt_rm_namerule(udt,
2729cd37da74Snw 		    nm->is_user ? B_TRUE : B_FALSE,
2730cd37da74Snw 		    is_wuser ? B_TRUE : B_FALSE,
27318e228215Sdm 		    nm->windomain, nm->winname, nm->unixname, nm->direction);
2732c5c4113dSnw 
2733479ac375Sdm 		if (stat != IDMAP_SUCCESS) {
27348e228215Sdm 			print_error(pos,
27358e228215Sdm 			    gettext("Mapping not deleted (%s)\n"),
27361fdeec65Sjoyce mcintosh 			    idmap_stat2string(stat));
27378e228215Sdm 			rc = -1;
27388e228215Sdm 			break;
27398e228215Sdm 		}
2740c5c4113dSnw 	}
2741c5c4113dSnw 
27428e228215Sdm 	if (rc == 0)
27438e228215Sdm 		rc = positions_add(pos);
27448e228215Sdm 
2745c5c4113dSnw cleanup:
2746c5c4113dSnw 	name_mapping_fini(nm);
27478e228215Sdm 	if (fini_udt_command(1, pos))
27488e228215Sdm 		rc = -1;
2749c5c4113dSnw 	return (rc);
2750c5c4113dSnw }
2751c5c4113dSnw 
27529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* flush command handler */
27539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int
do_flush(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)27549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States do_flush(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
27559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
27569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	NOTE(ARGUNUSED(argv))
27579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	idmap_flush_op op;
27589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	idmap_stat stat;
27599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int rc = 0;
27609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
27619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (argc > 0) {
27629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		print_error(pos,
27639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    gettext("Too many arguments.\n"));
27649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (-1);
27659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
27669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (f[a_FLAG] != NULL)
27679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		op = IDMAP_FLUSH_DELETE;
27689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	else
27699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		op = IDMAP_FLUSH_EXPIRE;
27709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
27711fdeec65Sjoyce mcintosh 	stat = idmap_flush(op);
27729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (stat != IDMAP_SUCCESS) {
27739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		print_error(pos,
27749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    gettext("%s\n"),
27751fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
27769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		rc = -1;
27779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
27789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
27799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (rc);
27809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
27819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2782c5c4113dSnw 
2783c5c4113dSnw /* exit command handler */
2784c5c4113dSnw static int
2785c5c4113dSnw /* LINTED E_FUNC_ARG_UNUSED */
do_exit(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)2786cd37da74Snw do_exit(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2787cd37da74Snw {
2788c5c4113dSnw 	return (0);
2789c5c4113dSnw }
2790c5c4113dSnw 
2791c5c4113dSnw 
2792c5c4113dSnw /* debug command handler: just print the parameters */
2793c5c4113dSnw static int
2794c5c4113dSnw /* LINTED E_STATIC_UNUSED */
debug_print_params(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)27958e228215Sdm debug_print_params(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2796c5c4113dSnw {
2797c5c4113dSnw 	int i;
2798c5c4113dSnw #if 0
2799c5c4113dSnw 	char *leaktest = (char *)malloc(100);
2800c5c4113dSnw #endif
2801c5c4113dSnw 
2802c5c4113dSnw 	print_flags(f);
2803c5c4113dSnw 
2804c5c4113dSnw 	for (i = 0; i < argc; i++) {
2805c5c4113dSnw 		(void) printf("Argument %d: %s\n", i, argv[i]);
2806c5c4113dSnw 	}
2807c5c4113dSnw 
2808c5c4113dSnw 	(void) fflush(stdout);
2809c5c4113dSnw 	return (0);
2810c5c4113dSnw }
2811c5c4113dSnw 
2812c5c4113dSnw /*
2813c5c4113dSnw  * From name_mapping_t, asseble a string containing identity of the
2814c5c4113dSnw  * given type.
2815c5c4113dSnw  */
2816c5c4113dSnw static int
nm2type(name_mapping_t * nm,int type,char ** to)2817cd37da74Snw nm2type(name_mapping_t *nm, int type, char **to)
2818cd37da74Snw {
2819c5c4113dSnw 	switch (type) {
2820c5c4113dSnw 	case TYPE_SID:
2821cd37da74Snw 	case TYPE_USID:
2822cd37da74Snw 	case TYPE_GSID:
2823c5c4113dSnw 		if (nm->sidprefix == NULL)
2824c5c4113dSnw 			return (-1);
2825cd37da74Snw 		*to = sid_format(nm);
2826c5c4113dSnw 		return (0);
2827c5c4113dSnw 	case TYPE_WN:
28288e228215Sdm 	case TYPE_WU:
28298e228215Sdm 	case TYPE_WG:
2830c5c4113dSnw 		return (nm2winqn(nm, to));
2831c5c4113dSnw 	case TYPE_UID:
2832c5c4113dSnw 	case TYPE_GID:
2833c5c4113dSnw 	case TYPE_PID:
2834c5c4113dSnw 		*to = pid_format(nm->pid, nm->is_user);
2835c5c4113dSnw 		if (*to == NULL)
2836c5c4113dSnw 			return (-1);
2837c5c4113dSnw 		else
2838c5c4113dSnw 			return (0);
2839c5c4113dSnw 	case TYPE_UN:
28408e228215Sdm 	case TYPE_UU:
28418e228215Sdm 	case TYPE_UG:
2842c5c4113dSnw 		return (nm2unixname(nm, to));
2843c5c4113dSnw 	default:
2844821da340Sdm 		/* This can never happen: */
28458e228215Sdm 		print_error(NULL,
2846821da340Sdm 		    gettext("Internal error: invalid name type.\n"));
2847c5c4113dSnw 		return (-1);
2848c5c4113dSnw 	}
2849c5c4113dSnw 	/* never reached */
2850c5c4113dSnw }
2851c5c4113dSnw 
2852c5c4113dSnw /* show command handler */
2853c5c4113dSnw static int
do_show_mapping(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)28548e228215Sdm do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
2855c5c4113dSnw {
2856c5c4113dSnw 	idmap_stat stat = 0;
2857c5c4113dSnw 	int flag;
2858c5c4113dSnw 	idmap_stat map_stat = 0;
2859c5c4113dSnw 	int type_from;
2860c5c4113dSnw 	int type_to;
2861c5c4113dSnw 	name_mapping_t *nm = NULL;
2862c5c4113dSnw 	char *fromname;
2863c5c4113dSnw 	char *toname;
286448258c6bSjp 	idmap_info info;
286548258c6bSjp 
286648258c6bSjp 	(void) memset(&info, 0, sizeof (info));
2867c5c4113dSnw 
2868c5c4113dSnw 	if (argc == 0) {
28698e228215Sdm 		print_error(pos,
2870c5c4113dSnw 		    gettext("No identity given\n"));
2871c5c4113dSnw 		return (-1);
2872c5c4113dSnw 	} else if (argc > 2) {
28738e228215Sdm 		print_error(pos,
2874c5c4113dSnw 		    gettext("Too many arguments.\n"));
2875c5c4113dSnw 		return (-1);
2876c5c4113dSnw 	}
2877c5c4113dSnw 
2878148c5f43SAlan Wright 	flag = 0;
2879148c5f43SAlan Wright 	if (f[c_FLAG] == NULL)
2880148c5f43SAlan Wright 		flag |= IDMAP_REQ_FLG_NO_NEW_ID_ALLOC;
2881148c5f43SAlan Wright 	if (f[v_FLAG] != NULL)
2882148c5f43SAlan Wright 		flag |= IDMAP_REQ_FLG_MAPPING_INFO;
2883148c5f43SAlan Wright 	if (f[V_FLAG] != NULL)
2884148c5f43SAlan Wright 		flag |= IDMAP_REQ_FLG_TRACE;
2885c5c4113dSnw 
2886c5c4113dSnw 	nm = name_mapping_init();
2887c5c4113dSnw 	if (nm == NULL)
2888c5c4113dSnw 		goto cleanup;
2889c5c4113dSnw 
2890cd37da74Snw 	type_from = name2parts(argv[0], nm, pos);
2891cd37da74Snw 	if (type_from <= 0) {
2892cd37da74Snw 		stat = IDMAP_ERR_ARG;
2893cd37da74Snw 		goto cleanup;
2894cd37da74Snw 	}
2895cd37da74Snw 
2896c5c4113dSnw 
2897c5c4113dSnw 	/* Second, determine type_to: */
2898c5c4113dSnw 	if (argc < 2) {
2899c5c4113dSnw 		type_to = type_from & IS_WIN ? TYPE_PID : TYPE_SID;
2900c5c4113dSnw 		if (type_from & IS_NAME)
2901c5c4113dSnw 			type_to |= IS_NAME;
2902cd37da74Snw 	} else {
2903479ac375Sdm 		type_to = string2type(argv[1], pos);
2904479ac375Sdm 		if (type_to == TYPE_INVALID) {
2905cd37da74Snw 			stat = IDMAP_ERR_ARG;
2906cd37da74Snw 			goto cleanup;
2907cd37da74Snw 		}
2908cd37da74Snw 	}
2909cd37da74Snw 
2910cd37da74Snw 	if (type_to & IS_WIN) {
2911cd37da74Snw 		if (type_to & IS_USER)
2912479ac375Sdm 			nm->is_wuser = IDMAP_YES;
2913cd37da74Snw 		else if (type_to & IS_GROUP)
2914479ac375Sdm 			nm->is_wuser = IDMAP_NO;
2915cd37da74Snw 		else
2916479ac375Sdm 			nm->is_wuser = IDMAP_UNKNOWN;
2917cd37da74Snw 	} else {
2918cd37da74Snw 		if (type_to & IS_USER)
2919479ac375Sdm 			nm->is_user = IDMAP_YES;
2920cd37da74Snw 		else if (type_to & IS_GROUP)
2921479ac375Sdm 			nm->is_user = IDMAP_NO;
2922c5c4113dSnw 	}
2923c5c4113dSnw 
2924c5c4113dSnw 	/* Are both arguments the same OS side? */
2925c5c4113dSnw 	if (!(type_from & IS_WIN ^ type_to & IS_WIN)) {
29268e228215Sdm 		print_error(pos,
2927c5c4113dSnw 		    gettext("Direction ambiguous.\n"));
2928c5c4113dSnw 		stat = IDMAP_ERR_ARG;
2929c5c4113dSnw 		goto cleanup;
2930c5c4113dSnw 	}
2931c5c4113dSnw 
2932c5c4113dSnw /*
2933c5c4113dSnw  * We have two interfaces for retrieving the mappings:
2934c5c4113dSnw  * idmap_get_sidbyuid & comp (the batch interface) and
2935c5c4113dSnw  * idmap_get_w2u_mapping & comp. We  want to use both of them, because
2936c5c4113dSnw  * the former mimicks kernel interface better and the later offers the
2937c5c4113dSnw  * string names. In the batch case, our batch has always size 1.
2938cd37da74Snw  *
2939cd37da74Snw  * Btw, type_from cannot be IDMAP_PID, because there is no type string
2940cd37da74Snw  * for it.
2941c5c4113dSnw  */
2942479ac375Sdm 
2943cd37da74Snw 	if (type_from & IS_NAME || type_to & IS_NAME ||
2944cd37da74Snw 	    type_from  == TYPE_GSID || type_from  == TYPE_USID ||
2945cd37da74Snw 	    type_to  == TYPE_GSID || type_to  == TYPE_USID) {
2946c5c4113dSnw 		if (type_from & IS_WIN) {
29471fdeec65Sjoyce mcintosh 			map_stat = idmap_get_w2u_mapping(
2948c5c4113dSnw 			    nm->sidprefix,
2949c5c4113dSnw 			    &nm->rid,
2950c5c4113dSnw 			    nm->winname,
2951c5c4113dSnw 			    nm->windomain,
2952c5c4113dSnw 			    flag,
2953cd37da74Snw 			    &nm->is_user, &nm->is_wuser,
2954c5c4113dSnw 			    &nm->pid,
2955c5c4113dSnw 			    &nm->unixname,
295648258c6bSjp 			    &nm->direction,
295748258c6bSjp 			    &info);
2958c5c4113dSnw 		} else {
29591fdeec65Sjoyce mcintosh 			map_stat = idmap_get_u2w_mapping(
2960c5c4113dSnw 			    &nm->pid,
2961c5c4113dSnw 			    nm->unixname,
2962c5c4113dSnw 			    flag,
2963cd37da74Snw 			    nm->is_user, &nm->is_wuser,
2964c5c4113dSnw 			    &nm->sidprefix,
2965c5c4113dSnw 			    &nm->rid,
2966c5c4113dSnw 			    &nm->winname,
2967c5c4113dSnw 			    &nm->windomain,
296848258c6bSjp 			    &nm->direction,
296948258c6bSjp 			    &info);
2970c5c4113dSnw 		}
2971c5c4113dSnw 
2972c5c4113dSnw 	} else {
2973c5c4113dSnw 		/* batch handle */
2974c5c4113dSnw 		idmap_get_handle_t *ghandle = NULL;
2975c5c4113dSnw 		/* To be passed to idmap_get_uidbysid  */
2976c5c4113dSnw 		gid_t gid = UNDEFINED_GID;
2977c5c4113dSnw 		/* To be passed to idmap_get_gidbysid  */
2978c5c4113dSnw 		uid_t uid = UNDEFINED_UID;
2979c5c4113dSnw 
2980c5c4113dSnw 
2981c5c4113dSnw 		/* Create an in-memory structure for all the batch: */
29821fdeec65Sjoyce mcintosh 		stat = idmap_get_create(&ghandle);
2983479ac375Sdm 		if (stat != IDMAP_SUCCESS) {
29848e228215Sdm 			print_error(pos,
2985c5c4113dSnw 			    gettext("Unable to create handle for communicating"
2986*bbf21555SRichard Lowe 			    " with idmapd(8) (%s)\n"),
29871fdeec65Sjoyce mcintosh 			    idmap_stat2string(stat));
2988c5c4113dSnw 			idmap_get_destroy(ghandle);
2989c5c4113dSnw 			goto cleanup;
2990c5c4113dSnw 		}
2991c5c4113dSnw 
2992c5c4113dSnw 		/* Schedule the request: */
2993cd37da74Snw 		if (type_to == TYPE_UID) {
299448258c6bSjp 			stat = idmap_getext_uidbysid(ghandle,
2995c5c4113dSnw 			    nm->sidprefix,
2996c5c4113dSnw 			    nm->rid,
2997c5c4113dSnw 			    flag,
2998c5c4113dSnw 			    &uid,
299948258c6bSjp 			    &info,
3000c5c4113dSnw 			    &map_stat);
3001cd37da74Snw 		} else if (type_to == TYPE_GID) {
300248258c6bSjp 			stat =  idmap_getext_gidbysid(ghandle,
3003c5c4113dSnw 			    nm->sidprefix,
3004c5c4113dSnw 			    nm->rid,
3005c5c4113dSnw 			    flag,
3006c5c4113dSnw 			    &gid,
300748258c6bSjp 			    &info,
3008c5c4113dSnw 			    &map_stat);
3009cd37da74Snw 		} else if (type_to == TYPE_PID) {
301048258c6bSjp 			stat = idmap_getext_pidbysid(ghandle,
3011c5c4113dSnw 			    nm->sidprefix,
3012c5c4113dSnw 			    nm->rid,
3013c5c4113dSnw 			    flag,
3014c5c4113dSnw 			    &nm->pid,
3015c5c4113dSnw 			    &nm->is_user,
301648258c6bSjp 			    &info,
3017c5c4113dSnw 			    &map_stat);
3018cd37da74Snw 		} else if (type_from == TYPE_UID) {
301948258c6bSjp 			stat = idmap_getext_sidbyuid(ghandle,
3020c5c4113dSnw 			    nm->pid,
3021c5c4113dSnw 			    flag,
3022c5c4113dSnw 			    &nm->sidprefix,
3023c5c4113dSnw 			    &nm->rid,
302448258c6bSjp 			    &info,
3025c5c4113dSnw 			    &map_stat);
3026cd37da74Snw 		} else if (type_from == TYPE_GID) {
302748258c6bSjp 			stat = idmap_getext_sidbygid(ghandle,
3028c5c4113dSnw 			    (gid_t)nm->pid,
3029c5c4113dSnw 			    flag,
3030c5c4113dSnw 			    &nm->sidprefix,
3031c5c4113dSnw 			    &nm->rid,
303248258c6bSjp 			    &info,
3033c5c4113dSnw 			    &map_stat);
3034c5c4113dSnw 		} else {
3035821da340Sdm 			/* This can never happen: */
30368e228215Sdm 			print_error(pos,
3037821da340Sdm 			    gettext("Internal error in show.\n"));
3038c5c4113dSnw 			exit(1);
3039c5c4113dSnw 		}
3040c5c4113dSnw 
3041c5c4113dSnw 		if (stat < 0) {
30428e228215Sdm 			print_error(pos,
3043c5c4113dSnw 			    gettext("Request for %.3s not sent (%s)\n"),
30441fdeec65Sjoyce mcintosh 			    argv[0], idmap_stat2string(stat));
3045c5c4113dSnw 			idmap_get_destroy(ghandle);
3046c5c4113dSnw 			goto cleanup;
3047c5c4113dSnw 		}
3048c5c4113dSnw 
3049c5c4113dSnw 		/* Send the batch to idmapd and obtain results: */
3050c5c4113dSnw 		stat = idmap_get_mappings(ghandle);
3051c5c4113dSnw 		if (stat < 0) {
30528e228215Sdm 			print_error(pos,
3053c5c4113dSnw 			    gettext("Mappings not obtained because of"
3054c5c4113dSnw 			    " RPC problem (%s)\n"),
30551fdeec65Sjoyce mcintosh 			    idmap_stat2string(stat));
3056c5c4113dSnw 			idmap_get_destroy(ghandle);
3057c5c4113dSnw 			goto cleanup;
3058c5c4113dSnw 		}
3059c5c4113dSnw 
3060c5c4113dSnw 		/* Destroy the batch handle: */
3061c5c4113dSnw 		idmap_get_destroy(ghandle);
3062c5c4113dSnw 
3063c5c4113dSnw 		if (type_to == TYPE_UID)
3064c5c4113dSnw 			nm->pid = uid;
3065c5c4113dSnw 		else if (type_to == TYPE_GID)
3066c5c4113dSnw 			nm->pid = (uid_t)gid;
3067c5c4113dSnw 
3068c5c4113dSnw 	}
3069c5c4113dSnw 
3070c5c4113dSnw 	/*
3071c5c4113dSnw 	 * If there was -c flag, we do output whatever we can even in
3072c5c4113dSnw 	 * the case of error:
3073c5c4113dSnw 	 */
307448258c6bSjp 	if (map_stat < 0 && flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC)
307548258c6bSjp 		goto errormsg;
3076c5c4113dSnw 
30778e228215Sdm 	/*
30788e228215Sdm 	 * idmapd returns fallback uid/gid in case of errors. However
30798e228215Sdm 	 * it uses special sentinel value i.e 4294967295 (or -1) to
30808e228215Sdm 	 * indicate that falbback pid is not available either. In such
3081*bbf21555SRichard Lowe 	 * case idmap(8) should not display the mapping because there
30828e228215Sdm 	 * is no fallback mapping.
30838e228215Sdm 	 */
30848e228215Sdm 
308548258c6bSjp 	if ((type_to == TYPE_UID || type_to == TYPE_GID ||
308648258c6bSjp 	    type_to == TYPE_PID) && nm->pid == UNDEFINED_UID)
308748258c6bSjp 		goto errormsg;
30888e228215Sdm 
3089c5c4113dSnw 	if (nm2type(nm, type_from, &fromname) < 0)
309048258c6bSjp 		goto errormsg;
3091c5c4113dSnw 
3092c5c4113dSnw 	if (nm2type(nm, type_to, &toname) < 0) {
309348258c6bSjp 		if (!(flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC))
3094c5c4113dSnw 			(void) printf("%s -> %s:%u\n",
3095c5c4113dSnw 			    fromname,
3096cd37da74Snw 			    type_to & IS_GROUP ? ID_GID : ID_UID,
3097c5c4113dSnw 			    UID_NOBODY);
3098c5c4113dSnw 		free(fromname);
309948258c6bSjp 	} else {
310048258c6bSjp 		(void) printf("%s -> %s\n", fromname, toname);
310148258c6bSjp 		free(fromname);
310248258c6bSjp 		free(toname);
3103c5c4113dSnw 	}
3104c5c4113dSnw 
310548258c6bSjp errormsg:
310648258c6bSjp 	if (map_stat < 0) {
310748258c6bSjp 		print_error(pos, gettext("Error:\t%s\n"),
31081fdeec65Sjoyce mcintosh 		    idmap_stat2string(map_stat));
310948258c6bSjp 		print_error_info(&info);
3110148c5f43SAlan Wright 	} else {
311148258c6bSjp 		print_info(&info);
3112148c5f43SAlan Wright 	}
311348258c6bSjp 	idmap_info_free(&info);
3114c5c4113dSnw 
3115c5c4113dSnw cleanup:
3116c5c4113dSnw 	if (nm != NULL)
3117c5c4113dSnw 		name_mapping_fini(nm);
3118c5c4113dSnw 	return (stat < 0 || map_stat < 0 ? -1 : 0);
3119c5c4113dSnw }
3120c5c4113dSnw 
3121479ac375Sdm 
3122479ac375Sdm static int
flags2cred(flag_t * f,char ** user,char ** passwd,cmd_pos_t * pos)3123479ac375Sdm flags2cred(flag_t *f, char **user, char **passwd,  cmd_pos_t *pos)
3124479ac375Sdm {
3125479ac375Sdm 
3126479ac375Sdm 	*user = NULL;
3127479ac375Sdm 	*passwd = NULL;
3128479ac375Sdm 
3129479ac375Sdm 	if (f[D_FLAG] == NULL)
3130479ac375Sdm 		return (0); /* GSSAPI authentification => OK */
3131479ac375Sdm 
3132479ac375Sdm 	*user = strdup(f[D_FLAG]);
3133479ac375Sdm 	if (*user == NULL) {
313461b364a9Sjp 		print_error(pos, "%s.\n", strerror(ENOMEM));
3135479ac375Sdm 		return (-1);
3136479ac375Sdm 	}
3137479ac375Sdm 
3138479ac375Sdm 	/* Password: */
3139479ac375Sdm 
3140479ac375Sdm 	if (f[j_FLAG] != NULL) {
3141479ac375Sdm 		char line[MAX_INPUT_LINE_SZ];
3142479ac375Sdm 		int i;
3143479ac375Sdm 		FILE *file = fopen(f[j_FLAG], "r");
3144479ac375Sdm 
3145479ac375Sdm 		if (file == NULL) {
3146479ac375Sdm 			print_error(pos,
3147479ac375Sdm 			    gettext("Failed to open password file \"%s\": (%s)"
3148479ac375Sdm 			    ".\n"), f[j_FLAG], strerror(errno));
3149479ac375Sdm 			goto fail;
3150479ac375Sdm 		}
3151479ac375Sdm 
3152479ac375Sdm 		/* The password is the fist line, we ignore the rest: */
3153479ac375Sdm 		if (fgets(line, MAX_INPUT_LINE_SZ, file) == NULL) {
3154479ac375Sdm 			print_error(pos,
3155479ac375Sdm 			    gettext("The password file \"%s\" is empty.\n"),
3156479ac375Sdm 			    f[j_FLAG]);
3157479ac375Sdm 			(void) fclose(file);
3158479ac375Sdm 			goto fail;
3159479ac375Sdm 		}
3160479ac375Sdm 
3161479ac375Sdm 		if (fclose(file) != 0) {
3162479ac375Sdm 			print_error(pos,
3163479ac375Sdm 			    gettext("Unable to close the password file \"%s\""
3164479ac375Sdm 			    ".\n"), f[j_FLAG], strerror(errno));
3165479ac375Sdm 			goto fail;
3166479ac375Sdm 		}
3167479ac375Sdm 
3168479ac375Sdm 		/* Trim the eol: */
3169479ac375Sdm 		for (i = strlen(line) - 1;
3170479ac375Sdm 		    i >= 0 && (line[i] == '\r' || line[i] == '\n');
3171479ac375Sdm 		    i--)
3172479ac375Sdm 			line[i] = '\0';
3173479ac375Sdm 
3174479ac375Sdm 		*passwd = strdup(line);
3175479ac375Sdm 		if (*passwd == NULL) {
317661b364a9Sjp 			print_error(pos, "%s.\n", strerror(ENOMEM));
3177479ac375Sdm 			goto fail;
3178479ac375Sdm 		}
3179479ac375Sdm 	} else if (!batch_mode) {
3180479ac375Sdm 		/* If in the interactive mode, read the terminal input: */
3181479ac375Sdm 		char *it = getpassphrase("Enter password:");
3182479ac375Sdm 		if (it == NULL) {
3183479ac375Sdm 			print_error(NULL,
3184479ac375Sdm 			    gettext("Failed to get password (%s).\n"),
3185479ac375Sdm 			    strerror(errno));
3186479ac375Sdm 			goto fail;
3187479ac375Sdm 		}
3188479ac375Sdm 
3189479ac375Sdm 		*passwd = strdup(it);
3190479ac375Sdm 		(void) memset(it, 0, strlen(it));
3191479ac375Sdm 
3192479ac375Sdm 		if (*passwd == NULL) {
319361b364a9Sjp 			print_error(pos, "%s.\n", strerror(ENOMEM));
3194479ac375Sdm 			goto fail;
3195479ac375Sdm 		}
3196479ac375Sdm 	} else {
3197479ac375Sdm 		print_error(pos, gettext("No password given.\n"));
3198479ac375Sdm 		goto fail;
3199479ac375Sdm 	}
3200479ac375Sdm 
3201479ac375Sdm 	return (0);
3202479ac375Sdm fail:
3203479ac375Sdm 	if (*passwd != NULL) {
3204479ac375Sdm 		(void) memset(*passwd, 0, strlen(*passwd));
3205479ac375Sdm 		free(*passwd);
3206479ac375Sdm 		*passwd = NULL;
3207479ac375Sdm 	}
3208479ac375Sdm 
3209479ac375Sdm 	free(*user);
3210479ac375Sdm 	return (-1);
3211479ac375Sdm }
3212479ac375Sdm 
3213479ac375Sdm 
3214479ac375Sdm static int
do_set_namemap(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)3215479ac375Sdm do_set_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
3216479ac375Sdm {
3217479ac375Sdm 	idmap_stat stat;
3218479ac375Sdm 	name_mapping_t *nm;
3219479ac375Sdm 	int is_first_win;
3220479ac375Sdm 	char *user;
3221479ac375Sdm 	char *passwd;
3222479ac375Sdm 
3223479ac375Sdm 	if (argc < 2) {
3224479ac375Sdm 		print_error(pos,
3225479ac375Sdm 		    gettext("Not enough arguments: two names needed for a "
3226479ac375Sdm 		    "namemap.\n"));
3227479ac375Sdm 		return (-1);
3228479ac375Sdm 	} else if (argc > 2) {
3229479ac375Sdm 		print_error(pos,
3230479ac375Sdm 		    gettext("Too many arguments: two names needed for a "
3231479ac375Sdm 		    "namemap.\n"));
3232479ac375Sdm 		return (-1);
3233479ac375Sdm 	}
3234479ac375Sdm 
3235479ac375Sdm 	nm = args2nm(&is_first_win, argc, argv, pos);
3236479ac375Sdm 	if (nm == NULL)
3237479ac375Sdm 		return (-1);
3238479ac375Sdm 
3239479ac375Sdm 	if (flags2cred(f, &user, &passwd, pos) < 0)
3240479ac375Sdm 		return (-1);
3241479ac375Sdm 
3242479ac375Sdm 	nm->direction = is_first_win ? IDMAP_DIRECTION_W2U
3243479ac375Sdm 	    : IDMAP_DIRECTION_U2W;
3244479ac375Sdm 
324561b364a9Sjp 	if (init_nm_command(user, passwd, f[a_FLAG], nm->windomain,
324661b364a9Sjp 	    nm->direction, pos) < 0)
324761b364a9Sjp 		return (-1);
324861b364a9Sjp 
3249479ac375Sdm 
325061b364a9Sjp 	stat = idmap_set_namemap(namemaps.handle, nm->winname, nm->unixname,
3251479ac375Sdm 	    nm->is_user, nm->is_wuser, nm->direction);
3252479ac375Sdm 
3253479ac375Sdm 	if (stat != IDMAP_SUCCESS) {
3254479ac375Sdm 		print_error(pos,
3255479ac375Sdm 		    gettext("Failed to set namemap (%s).\n"),
32561fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
3257479ac375Sdm 	}
3258479ac375Sdm 
3259479ac375Sdm 	if (passwd != NULL) {
3260479ac375Sdm 		(void) memset(passwd, 0, strlen(passwd));
3261479ac375Sdm 		free(passwd);
3262479ac375Sdm 	}
3263479ac375Sdm 
3264479ac375Sdm 	free(user);
3265479ac375Sdm 
326661b364a9Sjp 	fini_nm_command();
3267479ac375Sdm 	name_mapping_fini(nm);
3268479ac375Sdm 	return (stat != IDMAP_SUCCESS ? -1 : 0);
3269479ac375Sdm }
3270479ac375Sdm 
3271479ac375Sdm static int
do_unset_namemap(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)3272479ac375Sdm do_unset_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
3273479ac375Sdm {
3274479ac375Sdm 	idmap_stat stat;
3275479ac375Sdm 	name_mapping_t *nm;
3276479ac375Sdm 	int is_first_win;
3277479ac375Sdm 	char *user;
3278479ac375Sdm 	char *passwd;
3279479ac375Sdm 
3280479ac375Sdm 	if (argc < 1) {
3281479ac375Sdm 		print_error(pos,
3282479ac375Sdm 		    gettext("Not enough arguments: a name needed to unset a "
3283479ac375Sdm 		    "namemap.\n"));
3284479ac375Sdm 		return (-1);
3285479ac375Sdm 	} else if (argc > 2) {
3286479ac375Sdm 		print_error(pos,
3287479ac375Sdm 		    gettext("Too many arguments: Only target name and type is "
3288479ac375Sdm 		    "needed to unset namemap.\n"));
3289479ac375Sdm 		return (-1);
3290479ac375Sdm 	}
3291479ac375Sdm 
3292479ac375Sdm 	nm = args2nm(&is_first_win, 1, argv, pos);
3293479ac375Sdm 	if (nm == NULL)
3294479ac375Sdm 		return (-1);
3295479ac375Sdm 
3296479ac375Sdm 	if (flags2cred(f, &user, &passwd, pos) < 0)
3297479ac375Sdm 		return (-1);
3298479ac375Sdm 
3299479ac375Sdm 	nm->direction = is_first_win ? IDMAP_DIRECTION_W2U
3300479ac375Sdm 	    : IDMAP_DIRECTION_U2W;
3301479ac375Sdm 
3302479ac375Sdm 	if (argc > 1 && !is_first_win) {
3303479ac375Sdm 			print_error(pos,
3304479ac375Sdm 			    gettext("Target type \"%s\" is redundant.\n"),
3305479ac375Sdm 			    argv[1]);
3306479ac375Sdm 			stat = IDMAP_ERR_ARG;
3307479ac375Sdm 			goto cleanup;
3308479ac375Sdm 	} else	if (argc > 1) {
3309479ac375Sdm 		switch (string2type(argv[1], pos)) {
3310479ac375Sdm 		case TYPE_INVALID:
3311479ac375Sdm 			name_mapping_fini(nm);
3312479ac375Sdm 			return (-1);
3313479ac375Sdm 		case TYPE_UU:
3314479ac375Sdm 			nm->is_user = IDMAP_YES;
3315479ac375Sdm 			break;
3316479ac375Sdm 		case TYPE_UG:
3317479ac375Sdm 			nm->is_user = IDMAP_NO;
3318479ac375Sdm 			break;
3319479ac375Sdm 		default:
3320479ac375Sdm 			print_error(pos,
3321479ac375Sdm 			    gettext("Invalid target type \"%s\": here the "
3322479ac375Sdm 			    "possible target type is unixuser or "
3323479ac375Sdm 			    "unixgroup.\n"), argv[1]);
3324479ac375Sdm 			stat = IDMAP_ERR_ARG;
3325479ac375Sdm 			goto cleanup;
3326479ac375Sdm 		}
3327479ac375Sdm 	}
3328479ac375Sdm 
332961b364a9Sjp 	if (init_nm_command(user, passwd, f[a_FLAG], nm->windomain,
333061b364a9Sjp 	    nm->direction, pos) < 0)
333161b364a9Sjp 		return (-1);
3332479ac375Sdm 
333361b364a9Sjp 	stat = idmap_unset_namemap(namemaps.handle, nm->winname, nm->unixname,
3334479ac375Sdm 	    nm->is_user, nm->is_wuser, nm->direction);
3335479ac375Sdm 
3336479ac375Sdm 	if (stat != IDMAP_SUCCESS) {
3337479ac375Sdm 		print_error(pos,
3338479ac375Sdm 		    gettext("Failed to unset namemap (%s).\n"),
33391fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
3340479ac375Sdm 	}
3341479ac375Sdm 
3342479ac375Sdm cleanup:
3343479ac375Sdm 	if (passwd != NULL) {
3344479ac375Sdm 		(void) memset(passwd, 0, strlen(passwd));
3345479ac375Sdm 		free(passwd);
3346479ac375Sdm 	}
3347479ac375Sdm 
3348479ac375Sdm 	free(user);
3349479ac375Sdm 
335061b364a9Sjp 	fini_nm_command();
3351479ac375Sdm 	name_mapping_fini(nm);
3352479ac375Sdm 	return (stat == IDMAP_SUCCESS ? 0 : -1);
3353479ac375Sdm }
3354479ac375Sdm 
3355479ac375Sdm static int
3356479ac375Sdm /* LINTED E_FUNC_ARG_UNUSED */
do_get_namemap(flag_t * f,int argc,char ** argv,cmd_pos_t * pos)3357479ac375Sdm do_get_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos)
3358479ac375Sdm {
3359479ac375Sdm 	idmap_stat stat;
3360479ac375Sdm 	name_mapping_t *nm;
3361479ac375Sdm 	int is_first_win;
3362479ac375Sdm 	int is_source_ad;
3363479ac375Sdm 	char *winname = NULL;
3364479ac375Sdm 	char *unixname = NULL;
3365479ac375Sdm 	char *unixuser = NULL;
3366479ac375Sdm 	char *unixgroup = NULL;
3367479ac375Sdm 
3368479ac375Sdm 	if (argc < 1) {
3369479ac375Sdm 		print_error(pos,
3370479ac375Sdm 		    gettext("Not enough arguments: a name needed to get a "
3371479ac375Sdm 		    "namemap.\n"));
3372479ac375Sdm 		return (-1);
3373479ac375Sdm 	} else if (argc > 1) {
3374479ac375Sdm 		print_error(pos,
3375479ac375Sdm 		    gettext("Too many arguments: just one name needed to get "
3376479ac375Sdm 		    "a namemap.\n"));
3377479ac375Sdm 		return (-1);
3378479ac375Sdm 	}
3379479ac375Sdm 
3380479ac375Sdm 	nm = args2nm(&is_first_win, argc, argv, pos);
3381479ac375Sdm 	if (nm == NULL)
3382479ac375Sdm 		return (-1);
3383479ac375Sdm 
3384479ac375Sdm 	nm->direction = is_first_win ? IDMAP_DIRECTION_W2U
3385479ac375Sdm 	    : IDMAP_DIRECTION_U2W;
3386479ac375Sdm 
3387479ac375Sdm 	/* nm->is_user is IDMAP_UNKNOWN for IDMAP_DIRECTION_W2U */
3388479ac375Sdm 	if (nm->is_user == IDMAP_YES) {
3389479ac375Sdm 		unixuser = strdup(nm->unixname);
3390479ac375Sdm 		if (unixuser == NULL) {
339161b364a9Sjp 			print_error(pos, "%s.\n", strerror(ENOMEM));
3392479ac375Sdm 			goto cleanup;
3393479ac375Sdm 		}
3394479ac375Sdm 	} else if (nm->is_user == IDMAP_NO) {
3395479ac375Sdm 		unixgroup = strdup(nm->unixname);
3396479ac375Sdm 		if (unixgroup == NULL) {
339761b364a9Sjp 			print_error(pos, "%s.\n", strerror(ENOMEM));
3398479ac375Sdm 			goto cleanup;
3399479ac375Sdm 		}
3400479ac375Sdm 	}
3401479ac375Sdm 
340261b364a9Sjp 	if (init_nm_command(NULL, NULL, NULL, nm->windomain,
340361b364a9Sjp 	    nm->direction, pos) < 0)
340461b364a9Sjp 		return (-1);
3405479ac375Sdm 
340661b364a9Sjp 	stat = idmap_get_namemap(namemaps.handle, &is_source_ad, &nm->winname,
340761b364a9Sjp 	    &nm->windomain, &nm->is_wuser, &unixuser, &unixgroup);
3408479ac375Sdm 
3409479ac375Sdm 	if (stat != IDMAP_SUCCESS) {
3410479ac375Sdm 		print_error(pos,
3411479ac375Sdm 		    gettext("Failed to get namemap info (%s).\n"),
34121fdeec65Sjoyce mcintosh 		    idmap_stat2string(stat));
3413479ac375Sdm 		goto cleanup;
3414479ac375Sdm 	}
3415479ac375Sdm 
3416479ac375Sdm 	if (nm2winqn(nm, &winname) < 0)
3417479ac375Sdm 			goto cleanup;
3418479ac375Sdm 
3419479ac375Sdm 	switch (is_source_ad) {
3420479ac375Sdm 	case IDMAP_YES:
3421479ac375Sdm 		if (unixuser == NULL && unixgroup == NULL)
3422479ac375Sdm 			(void) printf(gettext("\t\tNo namemap found in AD.\n"));
3423479ac375Sdm 		else {
3424479ac375Sdm 			(void) printf(gettext("AD namemaps for %s\n"), winname);
3425479ac375Sdm 			if (unixuser != NULL)
3426479ac375Sdm 				(void) printf(gettext("\t\t->\t%s:%s\n"),
3427479ac375Sdm 				    ID_UNIXUSER, unixuser);
3428479ac375Sdm 
3429479ac375Sdm 			if (unixgroup != NULL)
3430479ac375Sdm 				(void) printf(gettext("\t\t->\t%s:%s\n"),
3431479ac375Sdm 				    ID_UNIXGROUP, unixgroup);
3432479ac375Sdm 		}
3433479ac375Sdm 		break;
3434479ac375Sdm 	case IDMAP_NO:
3435479ac375Sdm 		if (nm2unixname(nm, &unixname) < 0)
3436479ac375Sdm 			goto cleanup;
3437479ac375Sdm 
3438479ac375Sdm 		if (nm->winname == NULL)
3439479ac375Sdm 			(void) printf(gettext("\t\tNo namemap found in "
3440479ac375Sdm 			    "native LDAP.\n"));
3441479ac375Sdm 		else {
3442479ac375Sdm 			(void) printf(gettext("Native LDAP namemap for %s\n"),
3443479ac375Sdm 			    unixname);
3444479ac375Sdm 			(void) printf(gettext("\t\t->\t%s\n"), winname);
3445479ac375Sdm 		}
3446479ac375Sdm 		break;
3447479ac375Sdm 	default:
3448479ac375Sdm 		/*
3449479ac375Sdm 		 * This can never happen; the error must be recognized in
3450479ac375Sdm 		 * args2nm
3451479ac375Sdm 		 */
3452479ac375Sdm 		print_error(pos,
3453479ac375Sdm 		    gettext("Internal error: unknown source of namemaps.\n"));
3454479ac375Sdm 	}
3455479ac375Sdm 
3456479ac375Sdm cleanup:
345761b364a9Sjp 	fini_nm_command();
3458479ac375Sdm 	name_mapping_fini(nm);
3459479ac375Sdm 	if (winname != NULL)
3460479ac375Sdm 		free(winname);
3461479ac375Sdm 	if (unixuser != NULL)
3462479ac375Sdm 		free(unixuser);
3463479ac375Sdm 	if (unixgroup != NULL)
3464479ac375Sdm 		free(unixgroup);
3465479ac375Sdm 	return (stat == IDMAP_SUCCESS ? 0 : -1);
3466479ac375Sdm }
3467479ac375Sdm 
3468479ac375Sdm 
34697a8a68f5SJulian Pullen /* printflike */
3470c5866007SKeyur Desai static
34717a8a68f5SJulian Pullen void
idmap_cli_logger(int pri,const char * format,...)3472c5866007SKeyur Desai idmap_cli_logger(int pri, const char *format, ...)
34737a8a68f5SJulian Pullen {
34747a8a68f5SJulian Pullen 	va_list args;
34757a8a68f5SJulian Pullen 
3476c5866007SKeyur Desai 	if (pri == LOG_DEBUG)
3477c5866007SKeyur Desai 		return;
3478c5866007SKeyur Desai 
34797a8a68f5SJulian Pullen 	va_start(args, format);
34807a8a68f5SJulian Pullen 
34817a8a68f5SJulian Pullen 	(void) vfprintf(stderr, format, args);
34827a8a68f5SJulian Pullen 	(void) fprintf(stderr, "\n");
34837a8a68f5SJulian Pullen 
34847a8a68f5SJulian Pullen 	va_end(args);
34857a8a68f5SJulian Pullen }
34867a8a68f5SJulian Pullen 
3487479ac375Sdm 
3488c5c4113dSnw /* main function. Returns 1 for error, 0 otherwise */
3489c5c4113dSnw int
main(int argc,char * argv[])3490cd37da74Snw main(int argc, char *argv[])
3491cd37da74Snw {
3492c5c4113dSnw 	int rc;
3493c5c4113dSnw 
3494c5c4113dSnw 	/* set locale and domain for internationalization */
3495c5c4113dSnw 	(void) setlocale(LC_ALL, "");
3496c5c4113dSnw 	(void) textdomain(TEXT_DOMAIN);
3497c5c4113dSnw 
34987a8a68f5SJulian Pullen 	/* Redirect logging */
3499c5866007SKeyur Desai 	idmap_set_logger(idmap_cli_logger);
3500c5866007SKeyur Desai 	adutils_set_logger(idmap_cli_logger);
35017a8a68f5SJulian Pullen 
3502c5c4113dSnw 	/* idmap_engine determines the batch_mode: */
3503c5c4113dSnw 	rc = engine_init(sizeof (commands) / sizeof (cmd_ops_t),
3504cd37da74Snw 	    commands,
3505cd37da74Snw 	    argc - 1,
3506cd37da74Snw 	    argv + 1,
3507cd37da74Snw 	    &batch_mode);
3508c5c4113dSnw 
3509c5c4113dSnw 	if (rc < 0) {
3510c5c4113dSnw 		(void) engine_fini();
3511c5c4113dSnw 		if (rc == IDMAP_ENG_ERROR_SILENT)
3512c5c4113dSnw 			help();
3513c5c4113dSnw 		return (1);
3514c5c4113dSnw 	}
3515c5c4113dSnw 
3516c5c4113dSnw 	udt_used = 0;
3517c5c4113dSnw 	if (batch_mode) {
3518c5c4113dSnw 		if (init_udt_batch() < 0)
3519c5c4113dSnw 			return (1);
3520c5c4113dSnw 	}
3521c5c4113dSnw 
3522c5c4113dSnw 	rc = run_engine(argc - 1, argv + 1);
3523c5c4113dSnw 
3524c5c4113dSnw 	if (batch_mode) {
3525c5c4113dSnw 		batch_mode = 0;
35268e228215Sdm 		if (fini_udt_command(rc == 0 ? 1 : 0, NULL))
35278e228215Sdm 			rc = -1;
352861b364a9Sjp 		fini_nm_command();
3529c5c4113dSnw 	}
3530c5c4113dSnw 
3531c5c4113dSnw 	(void) engine_fini();
3532c5c4113dSnw 	return (rc == 0 ? 0 : 1);
3533c5c4113dSnw }
3534