Mercurial > illumos > illumos-gate
changeset 5064:0fbdaabf14a1
PSARC/2007/457 Winchester idmap(1M) update
6567797 ambiguity: "unixname" as an ID type for both Unix users and groups
6577598 idmap should return non-zero status on add/remove rule failures
6577601 idmap should pinpoint the exact entry from the batch on update rules failures
6579694 idmap should not display sid2pid fallback mapping if pid == -1
6601140 idmap remove winname:aaa should remove the group rule too
6599176 No strdup of idmap_utf8str_val
author | dm199847 |
---|---|
date | Mon, 17 Sep 2007 08:07:28 -0700 |
parents | c7cb857a0196 |
children | fcf530c3356e |
files | usr/src/cmd/idmap/idmap/idmap.c usr/src/cmd/idmap/idmap/idmap_engine.c usr/src/cmd/idmap/idmap/idmap_engine.h usr/src/cmd/idmap/idmapd/dbutils.c usr/src/cmd/idmap/idmapd/idmapd.c usr/src/cmd/idmap/idmapd/idmapd.h usr/src/cmd/idmap/idmapd/rpc_svc.c usr/src/cmd/idmap/idmapd/server.c usr/src/head/rpcsvc/idmap_prot.x usr/src/lib/libidmap/common/idmap_api.c usr/src/lib/libidmap/common/idmap_impl.h usr/src/lib/libidmap/common/idmap_priv.h usr/src/lib/libidmap/common/mapfile-vers |
diffstat | 13 files changed, 1123 insertions(+), 743 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/idmap/idmap/idmap.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmap/idmap.c Mon Sep 17 08:07:28 2007 -0700 @@ -31,6 +31,7 @@ #include <strings.h> #include <errno.h> #include <limits.h> +#include <sys/varargs.h> #include "idmap_engine.h" #include "idmap_priv.h" @@ -46,13 +47,6 @@ #define I_NO 0 #define I_UNKNOWN -1 -/* Directions */ - -#define DIR_W2U 1 -#define DIR_U2W 2 -#define DIR_BI 0 -#define DIR_UNKNOWN -1 - /* * used in do_show for the type of argument, which can be winname, * unixname, uid, gid, sid or not given at all: @@ -60,28 +54,35 @@ #define TYPE_SID 0x010 /* sid */ #define TYPE_WN 0x110 /* winname */ +#define TYPE_WU 0x111 /* winuser */ +#define TYPE_WG 0x112 /* wingroup */ #define TYPE_UID 0x001 /* uid */ #define TYPE_GID 0x002 /* gid */ #define TYPE_PID 0x000 /* pid */ #define TYPE_UN 0x100 /* unixname */ +#define TYPE_UU 0x101 /* unixuser */ +#define TYPE_UG 0x102 /* unixgroup */ #define IS_WIN 0x010 /* mask for the windows types */ #define IS_NAME 0x100 /* mask for string name types */ -#define IS_GROUP 0x002 /* mask for, well, TYPE_GID */ +#define IS_USER 0x001 /* mask for user types */ +#define IS_GROUP 0x002 /* mask for group types */ /* Identity type strings */ #define ID_WINNAME "winname" #define ID_UNIXNAME "unixname" +#define ID_UNIXUSER "unixuser" +#define ID_UNIXGROUP "unixgroup" +#define ID_WINUSER "winuser" +#define ID_WINGROUP "wingroup" #define ID_SID "sid" #define ID_UID "uid" #define ID_GID "gid" /* Flags */ -#define g_FLAG 'g' -#define u_FLAG 'u' #define f_FLAG 'f' #define t_FLAG 't' #define d_FLAG 'd' @@ -116,8 +117,8 @@ * * DEFAULT_FORMAT are in fact the idmap subcommands suitable for * piping to idmap standart input. For example - * add -u -d winname:bob@foo.com unixname:fred - * add -u -d winname:bob2bar.com unixname:fred + * add -d winuser:bob@foo.com unixuser:fred + * add -d winuser:bob2bar.com unixuser:fred * * SMBUSERS is the format of Samba username map (smbusers). For full * documentation, search for "username map" in smb.conf manpage. @@ -175,6 +176,15 @@ /* Are we in the batch mode? */ static int batch_mode = 0; +/* Self describing stricture for positions */ +struct pos_sds { + int size; + int last; + cmd_pos_t *pos[1]; +}; + +static struct pos_sds *positions; + /* Handles for idmap_api batch */ static idmap_handle_t *handle = NULL; static idmap_udt_handle_t *udt = NULL; @@ -184,15 +194,18 @@ /* Command handlers */ -static int do_show_mapping(flag_t *f, int argc, char **argv); -static int do_dump(flag_t *f, int argc, char **argv); -static int do_import(flag_t *f, int argc, char **argv); -static int do_list_name_mappings(flag_t *f, int argc, char **argv); -static int do_add_name_mapping(flag_t *f, int argc, char **argv); -static int do_remove_name_mapping(flag_t *f, int argc, char **argv); -static int do_exit(flag_t *f, int argc, char **argv); -static int do_export(flag_t *f, int argc, char **argv); -static int do_help(flag_t *f, int argc, char **argv); +static int do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos); +static int do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos); +static int do_import(flag_t *f, int argc, char **argv, cmd_pos_t *pos); +static int do_list_name_mappings(flag_t *f, int argc, char **argv, + cmd_pos_t *pos); +static int do_add_name_mapping(flag_t *f, int argc, char **argv, + cmd_pos_t *pos); +static int do_remove_name_mapping(flag_t *f, int argc, char **argv, + cmd_pos_t *pos); +static int do_exit(flag_t *f, int argc, char **argv, cmd_pos_t *pos); +static int do_export(flag_t *f, int argc, char **argv, cmd_pos_t *pos); +static int do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos); /* Command names and their hanlers to be passed to idmap_engine */ @@ -204,7 +217,7 @@ }, { "dump", - "n(names)g(group)u(user)", + "n(names)", do_dump }, { @@ -219,17 +232,17 @@ }, { "list", - "g(group)u(user)", + "", do_list_name_mappings }, { "add", - "g(group)u(user)d(directional)", + "d(directional)", do_add_name_mapping }, { "remove", - "a(all)u(user)g(group)t(to)f(from)d(directional)", + "a(all)t(to)f(from)d(directional)", do_remove_name_mapping }, { @@ -244,6 +257,106 @@ } }; +/* Print error message, possibly with a position */ +/* printflike */ +static void +print_error(cmd_pos_t *pos, const char *format, ...) { + size_t length; + + va_list ap; + + va_start(ap, format); + + if (pos != NULL) { + length = strlen(pos->line); + + /* Skip newlines etc at the end: */ + while (length > 0 && isspace(pos->line[length - 1])) + length--; + + (void) fprintf(stderr, + gettext("Error at line %d: %.*s\n"), + pos->linenum, + length, + pos->line); + } + (void) vfprintf(stderr, format, ap); + + va_end(ap); +} + +/* Inits positions sds. 0 means everything went OK, -1 for errors */ +static int +init_positions() { + int init_size = 32; /* Initial size of the positions array */ + + positions = (struct pos_sds *) malloc(sizeof (struct pos_sds) + + (init_size - 1) * sizeof (cmd_pos_t *)); + + if (positions == NULL) { + print_error(NULL, gettext("Not enough memory.\n")); + return (-1); + } + + positions->size = init_size; + positions->last = 0; + return (0); +} + +/* Free the positions array */ +static void +fini_positions() { + int i; + for (i = 0; i < positions->last; i++) { + if (positions->pos[i] == NULL) + continue; + free(positions->pos[i]->line); + free(positions->pos[i]); + } + free(positions); + + positions = NULL; +} + +/* + * Add another position to the positions array. 0 means everything + * went OK, -1 for errors + */ +static int +positions_add(cmd_pos_t *pos) { + if (positions->last >= positions->size) { + positions->size *= 2; + positions = (struct pos_sds *)realloc(positions, + sizeof (struct pos_sds) + + (positions->size - 1) * sizeof (cmd_pos_t *)); + if (positions == NULL) + goto nomemory; + } + + if (pos == NULL) + positions->pos[positions->last] = NULL; + else { + positions->pos[positions->last] = (cmd_pos_t *)calloc(1, + sizeof (cmd_pos_t)); + if (positions->pos[positions->last] == NULL) + goto nomemory; + + *positions->pos[positions->last] = *pos; + positions->pos[positions->last]->line = strdup(pos->line); + if (positions->pos[positions->last]->line == NULL) + goto nomemory; + } + + positions->last++; + return (0); + +nomemory: + print_error(NULL, gettext("Not enough memory.\n")); + return (-1); +} + + + /* * Compare two strings just like strcmp, but stop before the end of @@ -268,12 +381,12 @@ "idmap\n" "idmap -f command-file\n" "idmap show [-c] identity [targettype]\n" - "idmap dump [-u|-g] [-n]\n" - "idmap add -u|-g [-d] name1 name2\n" - "idmap remove -u|-g -a\n" - "idmap remove -u|-g name\n" - "idmap remove -u|-g [-d] name1 name2\n" - "idmap list [-u|-g]\n" + "idmap dump [-n]\n" + "idmap add [-d] name1 name2\n" + "idmap remove -a\n" + "idmap remove name\n" + "idmap remove [-d] name1 name2\n" + "idmap list\n" "idmap import [-F] [-f file] format\n" "idmap export [-f file] format\n" "idmap help\n"); @@ -282,7 +395,7 @@ /* The handler for the "help" command. */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_help(flag_t *f, int argc, char **argv) +do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { help(); return (0); @@ -295,7 +408,7 @@ stat = idmap_init(&handle); if (stat < 0) { - (void) fprintf(stderr, + print_error(NULL, gettext("Connection not established (%s)\n"), idmap_stat2string(NULL, stat)); return (-1); @@ -332,11 +445,15 @@ stat = idmap_udt_create(handle, &udt); if (stat < 0) { - (void) fprintf(stderr, + print_error(NULL, gettext("Error initiating transaction (%s)"), idmap_stat2string(handle, stat)); return (-1); } + + if (init_positions() < 0) + return (-1); + return (0); } @@ -353,43 +470,69 @@ /* If everythings is OK, send the udt batch to idmapd */ -static void -fini_udt_command(int ok) { - idmap_stat stat; +static int +fini_udt_command(int ok, cmd_pos_t *pos) { + int rc = 0; + int64_t failpos; + idmap_stat stat, stat1; + cmd_pos_t *reported_pos; if (batch_mode) - return; - if (udt == NULL) - return; + return (0); + if (udt == NULL) { + print_error(pos, + gettext("Internal error: uninitiated batch.\n")); + return (-1); + } if (ok && udt_used) { stat = idmap_udt_commit(udt); - if (stat < 0) { - (void) fprintf(stderr, - gettext("Error commiting transaction (%s)\n"), - idmap_stat2string(handle, stat)); + if (stat == IDMAP_SUCCESS) + goto out; + + rc = -1; + + stat1 = idmap_udt_get_error_index(udt, &failpos); + if (stat1 != IDMAP_SUCCESS) { + print_error(NULL, + gettext("Error diagnosing transaction (%s)\n"), + idmap_stat2string(handle, stat1)); + goto out; } + + + if (failpos < 0) + reported_pos = pos; + else + reported_pos = positions->pos[failpos]; + + print_error(reported_pos, + gettext("Error commiting transaction (%s)\n"), + idmap_stat2string(handle, stat)); } +out: idmap_udt_destroy(udt); udt = NULL; udt_used = 0; fini_command(); + fini_positions(); + return (rc); } /* Convert numeric expression of the direction to it's string form */ static char * direction2string(int direction) { switch (direction) { - case DIR_BI: + case IDMAP_DIRECTION_BI: return ("=="); - case DIR_W2U: + case IDMAP_DIRECTION_W2U: return ("=>"); - case DIR_U2W: + case IDMAP_DIRECTION_U2W: return ("<="); default: /* This can never happen: */ - (void) fprintf(stderr, + print_error(NULL, gettext("Internal error: invalid direction.\n")); return (""); } @@ -434,6 +577,22 @@ } /* + * Returns 1 if c is a shell-meta-character requiring quoting even + * inside double quotes, 0 otherwise. It means \, " and $ . + * + * This set of characters is a subset of those in is_shell_special(). + */ +static int +is_dq_special(char c) { + if (strchr("\\\"$", c) != NULL) + return (1); + return (0); +} + + + + +/* * Quote any shell meta-characters in the given string. If 'quote' is * true then use double-quotes to quote the whole string, else use * back-slash to quote each individual meta-character. @@ -455,7 +614,7 @@ for (i = 0; i < len_orig; i++) { if (is_shell_special(string[i])) { noss++; - if (string[i] == '"' || string[i] == '\\') + if (is_dq_special(string[i])) noqb++; } @@ -465,7 +624,7 @@ if (noss == 0) { out = strdup(string); if (out == NULL) { - (void) fprintf(stderr, gettext("Not enough memory.\n")); + print_error(NULL, gettext("Not enough memory.\n")); return (-1); } *res = out; @@ -480,7 +639,7 @@ out = (char *)malloc(len * sizeof (char)); if (out == NULL) { - (void) fprintf(stderr, gettext("Not enough memory.\n")); + print_error(NULL, gettext("Not enough memory.\n")); return (-1); } @@ -490,7 +649,7 @@ for (i = 0; i < len_orig; i++) { /* Quote the dangerous chars by a backslash */ - if (quote && (string[i] == '"' || string[i] == '\\') || + if (quote && is_dq_special(string[i]) || (!quote && is_shell_special(string[i]))) { out[j++] = '\\'; } @@ -537,12 +696,13 @@ return (to); } -/* Assemble winname, e.g. "winname:bob@foo.sun.com", from name_mapping_t */ +/* Assemble winname, e.g. "winuser:bob@foo.sun.com", from name_mapping_t */ static int nm2winqn(name_mapping_t *nm, char **winqn) { char *out; size_t length = 0; int is_domain = 1; + char *prefix; /* Sometimes there are no text names. Return a sid, then. */ if (nm->winname == NULL) { @@ -553,7 +713,20 @@ return (0); } - length = strlen(ID_WINNAME ":") + strlen(nm->winname); + switch (nm->is_user) { + case I_YES: + prefix = ID_WINUSER ":"; + break; + case I_NO: + prefix = ID_WINGROUP ":"; + break; + case I_UNKNOWN: + prefix = ID_WINNAME ":"; + break; + + } + + length = strlen(prefix) + strlen(nm->winname); /* Windomain is not mandatory: */ if (nm->windomain == NULL || @@ -565,12 +738,12 @@ out = (char *)malloc((length + 1) * sizeof (char)); if (out == NULL) { - (void) fprintf(stderr, + print_error(NULL, gettext("Not enough memory.\n")); return (-1); } - (void) strcpy(out, ID_WINNAME ":"); + (void) strcpy(out, prefix); if (!is_domain) (void) strcat(out, nm->winname); @@ -588,12 +761,13 @@ return (0); } -/* Assemble a text unixname, e.g. unixname:fred */ +/* Assemble a text unixname, e.g. unixuser:fred */ static int nm2unixname(name_mapping_t *nm, char **unixname) { size_t length = 0; char *out; char *it; + char *prefix; /* Sometimes there is no name, just pid: */ if (nm->unixname == NULL) { @@ -607,17 +781,31 @@ if (shell_app(&it, nm->unixname, 0)) return (-1); - length = strlen(ID_UNIXNAME ":") + strlen(it); + + switch (nm->is_user) { + case I_YES: + prefix = ID_UNIXUSER ":"; + break; + case I_NO: + prefix = ID_UNIXGROUP ":"; + break; + case I_UNKNOWN: + prefix = ID_UNIXNAME ":"; + break; + + } + + length = strlen(prefix) + strlen(it); out = (char *)malloc((length + 1) * sizeof (char)); if (out == NULL) { - (void) fprintf(stderr, + print_error(NULL, gettext("Not enough memory.\n")); free(it); return (-1); } - (void) strcpy(out, ID_UNIXNAME ":"); + (void) strcpy(out, prefix); (void) strcat(out, it); free(it); @@ -672,7 +860,6 @@ { char *dirstring; char *winname_qm, *windomain_qm, *unixname_qm; - char type; char *winname = NULL; char *winname1 = NULL; char *unixname = NULL; @@ -691,7 +878,7 @@ case MAPPING_ID: if (pnm_format == MAPPING_ID) { if (nm->sidprefix == NULL) { - (void) fprintf(stderr, + print_error(NULL, gettext("SID not given.\n")); return (-1); } @@ -715,11 +902,11 @@ break; case SMBUSERS: if (!nm->is_user) { - (void) fprintf(stderr, + print_error(NULL, gettext("Group rule: ")); f = stderr; - } else if (nm->direction == DIR_U2W) { - (void) fprintf(stderr, + } else if (nm->direction == IDMAP_DIRECTION_U2W) { + print_error(NULL, gettext("Opposite direction of the mapping: ")); f = stderr; } @@ -745,7 +932,7 @@ break; case USERMAP_CFG: if (!nm->is_user) { - (void) fprintf(stderr, + print_error(NULL, gettext("Group rule: ")); f = stderr; } @@ -773,12 +960,10 @@ break; case DEFAULT_FORMAT: - /* 'u', 'g' refer to -u, -g switch of idmap add */ - type = nm->is_user ? 'u' : 'g'; if (nm2winqn(nm, &winname1) < 0) return (-1); - if (shell_app(&winname, winname1, 0)) { + if (shell_app(&winname, winname1, 1)) { free(winname1); return (-1); } @@ -790,14 +975,14 @@ return (-1); } - if (nm->direction == DIR_U2W) { + if (nm->direction == IDMAP_DIRECTION_U2W) { (void) fprintf(f, - "add -%c -d\t%s\t%s\n", - type, unixname, winname); + "add -d\t%s\t%s\n", + unixname, winname); } else { (void) fprintf(f, - "add -%c %s\t%s\t%s\n", - type, nm->direction == DIR_BI ? "" : "-d", + "add %s\t%s\t%s\n", + nm->direction == IDMAP_DIRECTION_BI? "" : "-d", winname, unixname); } free(winname); @@ -805,7 +990,7 @@ break; default: /* This can never happen: */ - (void) fprintf(stderr, + print_error(NULL, gettext("Internal error: invalid print format.\n")); return (-1); } @@ -818,14 +1003,14 @@ name_mapping_init() { name_mapping_t *nm = (name_mapping_t *)malloc(sizeof (name_mapping_t)); if (nm == NULL) { - (void) fprintf(stderr, gettext("Not enough memory.\n")); + print_error(NULL, gettext("Not enough memory.\n")); return (NULL); } nm->winname = nm->windomain = nm->unixname = nm->sidprefix = NULL; nm->rid = UNDEFINED_RID; nm->is_nt4 = B_FALSE; nm->is_user = I_UNKNOWN; - nm->direction = DIR_UNKNOWN; + nm->direction = IDMAP_DIRECTION_UNDEF; nm->pid = UNDEFINED_UID; return (nm); } @@ -842,40 +1027,11 @@ free(nm); } -/* Is there exactly one of -g, -u flags? */ -static int -is_type_determined(flag_t *f) -{ - if (f[u_FLAG] == NULL && f[g_FLAG] == NULL || /* none */ - f[u_FLAG] != NULL && f[g_FLAG] != NULL) /* both */ { - (void) fprintf(stderr, - gettext("Type (-u|-g) not determined.\n")); - return (0); - } - return (1); -} - -/* Does user request a user-related operation? */ -static int -is_user_wanted(flag_t *f) { - if (f[u_FLAG] != NULL || f[g_FLAG] == NULL) - return (1); - return (0); -} - -/* Does user request a group-related operation? */ -static int -is_group_wanted(flag_t *f) { - if (f[g_FLAG] != NULL || f[u_FLAG] == NULL) - return (1); - return (0); -} - /* dump command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_dump(flag_t *f, int argc, char **argv) +do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { idmap_stat stat; idmap_iter_t *ihandle; @@ -889,17 +1045,9 @@ stdout); for (is_user = I_YES; is_user >= I_NO; is_user--) { - /* - * If there is exactly one of -u, -g flags, we print - * only that type. Otherwise both of them: - */ - if (!is_user_wanted(f) && is_user || - !is_group_wanted(f) && !is_user) - continue; - stat = idmap_iter_mappings(handle, is_user, &ihandle); if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Iteration handle not obtained (%s)\n"), idmap_stat2string(handle, stat)); rc = -1; @@ -929,7 +1077,7 @@ /* IDMAP_ERR_NOTFOUND indicates end of the list */ if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) { - (void) fprintf(stderr, + print_error(pos, gettext("Error during iteration (%s)\n"), idmap_stat2string(handle, stat)); rc = -1; @@ -952,7 +1100,7 @@ strndup(char *from, size_t length) { char *out = (char *)malloc((length + 1) * sizeof (char)); if (out == NULL) { - (void) fprintf(stderr, gettext("Not enough memory\n")); + print_error(NULL, gettext("Not enough memory\n")); return (NULL); } (void) strncpy(out, from, length); @@ -966,7 +1114,7 @@ * print an error message and return 0. */ static int -pid_convert(char *string, uid_t *number, int type) { +pid_convert(char *string, uid_t *number, int type, cmd_pos_t *pos) { int i; long long ll; char *type_string; @@ -981,7 +1129,7 @@ for (i = 0; i < len; i++) { if (!isdigit(string[i])) { - (void) fprintf(stderr, + print_error(pos, gettext("\"%s\" is not a valid %s: the non-digit" " character '%c' found.\n"), string, type_string, string[i]); @@ -994,7 +1142,7 @@ /* Isn't it too large? */ if (type == TYPE_UID && (uid_t)ll != ll || type == TYPE_GID && (gid_t)ll != ll) { - (void) fprintf(stderr, + print_error(pos, gettext("%llu: too large for a %s.\n"), ll, type_string); return (0); @@ -1010,7 +1158,7 @@ * message and return 0. */ static int -sid_convert(char *from, char **prefix, idmap_rid_t *rid) { +sid_convert(char *from, char **prefix, idmap_rid_t *rid, cmd_pos_t *pos) { int i, j; char *cp; char *ecp; @@ -1019,14 +1167,14 @@ unsigned long r; if (strcmp_no0(from, "S-1-") != 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": it doesn't start " "with \"%s\".\n"), ID_SID, from, "S-1-"); return (0); } if (strlen(from) <= strlen("S-1-")) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": the authority and RID parts are" " missing.\n"), ID_SID, from); @@ -1039,12 +1187,12 @@ j++, cp = strchr(cp + 1, '-')) { /* can't end on a '-' */ if (*(cp + 1) == '\0') { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": '-' at the end.\n"), ID_SID, from); return (0); } else if (*(cp + 1) == '-') { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": double '-'.\n"), ID_SID, from); return (0); @@ -1055,7 +1203,7 @@ /* check that we only have digits and '-' */ i = strspn(from + 1, "0123456789-") + 1; if (i < strlen(from)) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": invalid character '%c'.\n"), ID_SID, from, from[i]); return (0); @@ -1070,7 +1218,7 @@ /* errors parsing the authority or too many bits */ if (cp == ecp || (a == 0 && errno == EINVAL)) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": unable to parse the " "authority \"%.*s\".\n"), ID_SID, from, ecp - cp, cp); @@ -1079,7 +1227,7 @@ if ((a == ULLONG_MAX && errno == ERANGE) || (a & 0x0000ffffffffffffULL) != a) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": the authority " "\"%.*s\" is too large.\n"), ID_SID, from, ecp - cp, cp); @@ -1089,7 +1237,7 @@ cp = ecp; if (j < 3) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": must have at least one RID.\n"), ID_SID, from); return (0); @@ -1098,7 +1246,7 @@ for (i = 2; i < j; i++) { if (*cp++ != '-') { /* Should never happen */ - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": internal error:" " '-' missing.\n"), ID_SID, from); @@ -1111,7 +1259,7 @@ /* errors parsing the RID */ if (cp == ecp || (r == 0 && errno == EINVAL)) { /* should never happen */ - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": internal error: " "unable to parse the RID " "after \"%.*s\".\n"), ID_SID, @@ -1120,7 +1268,7 @@ } if (r == ULONG_MAX && errno == ERANGE) { - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": the RID \"%.*s\"" " is too large.\n"), ID_SID, from, ecp - cp, cp); @@ -1133,7 +1281,7 @@ /* check that all of the string SID has been consumed */ if (*cp != '\0') { /* Should never happen */ - (void) fprintf(stderr, + print_error(pos, gettext("Invalid %s \"%s\": internal error: " "something is still left.\n"), ID_SID, from); @@ -1145,7 +1293,7 @@ /* -1 for the '-' at the end: */ *prefix = strndup(from, prefix_end - from - 1); if (*prefix == NULL) { - (void) fprintf(stderr, + print_error(pos, gettext("Not enough memory.\n")); return (0); } @@ -1167,13 +1315,12 @@ * there cannot be a protected quotation mark inside. */ static char * -ucp_qm_interior(char **line, int line_num) { +ucp_qm_interior(char **line, cmd_pos_t *pos) { char *out; char *qm = strchr(*line + 1, '"'); if (qm == NULL) { - (void) fprintf(stderr, - gettext("Line %d: Unclosed quotations\n"), - line_num); + print_error(pos, + gettext("Unclosed quotations\n")); return (NULL); } @@ -1189,10 +1336,10 @@ * reporting. */ static char * -ucp_grab_token(char **line, int line_num, const char *terminators) { +ucp_grab_token(char **line, cmd_pos_t *pos, const char *terminators) { char *token; if (**line == '"') - token = ucp_qm_interior(line, line_num); + token = ucp_qm_interior(line, pos); else { int length = strcspn(*line, terminators); token = strndup(*line, length); @@ -1204,14 +1351,13 @@ /* - * Convert a line in usermap.cfg format to name_mapping. line_num is - * the line number of input used for error reporting. + * Convert a line in usermap.cfg format to name_mapping. * * Return values: -1 for error, 0 for empty line, 1 for a mapping * found. */ static int -ucp_line2nm(char *line, int line_num, name_mapping_t *nm) { +ucp_line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm) { char *it; char *token; char *token2; @@ -1226,14 +1372,13 @@ /* We do not support network qualifiers */ if (ucp_is_IP_qualifier(it)) { - (void) fprintf(stderr, - gettext("Line %d: unable to handle network qualifier.\n"), - line_num); + print_error(pos, + gettext("Unable to handle network qualifier.\n")); return (-1); } /* The windows name: */ - token = ucp_grab_token(&it, line_num, " \t#\\\n@=<"); + token = ucp_grab_token(&it, pos, " \t#\\\n@=<"); if (token == NULL) return (-1); @@ -1242,25 +1387,23 @@ /* Didn't we bump to the end of line? */ if (separator == '\0' || separator == '#') { free(token); - (void) fprintf(stderr, - gettext("Line %d: UNIX_name not found.\n"), - line_num); + print_error(pos, + gettext("UNIX_name not found.\n")); return (-1); } /* Do we have a domainname? */ if (separator == '\\' || separator == '@') { it ++; - token2 = ucp_grab_token(&it, line_num, " \t\n#"); + token2 = ucp_grab_token(&it, pos, " \t\n#"); if (token2 == NULL) { free(token); return (-1); } else if (*it == '\0' || *it == '#') { free(token); free(token2); - (void) fprintf(stderr, - gettext("Line %d: UNIX_name not found.\n"), - line_num); + print_error(pos, + gettext("UNIX_name not found.\n")); } if (separator == '\\') { @@ -1284,16 +1427,16 @@ /* Direction string is optional: */ if (strncmp(it, "==", 2) == 0) { - nm->direction = DIR_BI; + nm->direction = IDMAP_DIRECTION_BI; is_direction = 1; } else if (strncmp(it, "<=", 2) == 0) { - nm->direction = DIR_U2W; + nm->direction = IDMAP_DIRECTION_U2W; is_direction = 1; } else if (strncmp(it, "=>", 2) == 0) { - nm->direction = DIR_W2U; + nm->direction = IDMAP_DIRECTION_W2U; is_direction = 1; } else { - nm->direction = DIR_BI; + nm->direction = IDMAP_DIRECTION_BI; is_direction = 0; } @@ -1302,16 +1445,15 @@ it += strspn(it, " \t\n"); if (*it == '\0' || *it == '#') { - (void) fprintf(stderr, - gettext("Line %d: UNIX_name not found.\n"), - line_num); + print_error(pos, + gettext("UNIX_name not found.\n")); return (-1); } } /* Now unixname: */ it += strspn(it, " \t\n"); - token = ucp_grab_token(&it, line_num, " \t\n#"); + token = ucp_grab_token(&it, pos, " \t\n#"); if (token == NULL) /* nm->winname to be freed by name_mapping_fini */ @@ -1319,9 +1461,8 @@ /* Neither here we support IP qualifiers */ if (ucp_is_IP_qualifier(token)) { - (void) fprintf(stderr, - gettext("Line %d: unable to handle network qualifier.\n"), - line_num); + print_error(pos, + gettext("Unable to handle network qualifier.\n")); free(token); return (-1); } @@ -1332,9 +1473,8 @@ /* Does something remain on the line */ if (*it != '\0' && *it != '#') { - (void) fprintf(stderr, - gettext("Line %d: unrecognized parameters \"%s\".\n"), - line_num, it); + print_error(pos, + gettext("Unrecognized parameters \"%s\".\n"), it); return (-1); } @@ -1351,7 +1491,7 @@ * rc = 1: mapping found and there remains other on the line */ static int -sup_line2nm(char *line, int line_num, name_mapping_t *nm) { +sup_line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm) { static char *ll = NULL; static char *unixname = NULL; static size_t unixname_l = 0; @@ -1377,12 +1517,12 @@ if (*ll == '\0'|| *ll == '#') return (0); - token = ucp_grab_token(&ll, line_num, " \t\n"); + token = ucp_grab_token(&ll, pos, " \t\n"); if (token == NULL) return (-1); nm->is_nt4 = 0; - nm->direction = DIR_W2U; + nm->direction = IDMAP_DIRECTION_W2U; nm->windomain = NULL; nm->winname = token; @@ -1396,18 +1536,18 @@ /* Parse line to name_mapping_t. Basicaly just a format switch. */ static int -line2nm(char *line, int line_num, name_mapping_t *nm, format_t f) { +line2nm(char *line, cmd_pos_t *pos, name_mapping_t *nm, format_t f) { switch (f) { case USERMAP_CFG: if (line == NULL) return (0); else - return (ucp_line2nm(line, line_num, nm)); + return (ucp_line2nm(line, pos, nm)); case SMBUSERS: - return (sup_line2nm(line, line_num, nm)); + return (sup_line2nm(line, pos, nm)); default: /* This can never happen */ - (void) fprintf(stderr, + print_error(pos, gettext("Internal error: invalid line format.\n")); } @@ -1420,7 +1560,7 @@ ff2format(char *ff, int is_mandatory) { if (ff == NULL && is_mandatory) { - (void) fprintf(stderr, gettext("Format not given.\n")); + print_error(NULL, gettext("Format not given.\n")); return (UNDEFINED_FORMAT); } @@ -1433,7 +1573,7 @@ if (strcasecmp(ff, "smbusers") == 0) return (SMBUSERS); - (void) fprintf(stderr, + print_error(NULL, gettext("The only known formats are: \"usermap.cfg\" and " "\"smbusers\".\n")); return (UNDEFINED_FORMAT); @@ -1441,36 +1581,40 @@ /* Delete all namerules of the given type */ static int -flush_nm(boolean_t is_user) +flush_nm(boolean_t is_user, cmd_pos_t *pos) { idmap_stat stat; stat = idmap_udt_flush_namerules(udt, is_user); if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, is_user ? gettext("Unable to flush users (%s).\n") : gettext("Unable to flush groups (%s).\n"), idmap_stat2string(handle, stat)); return (-1); } + + if (positions_add(pos) < 0) + return (-1); + return (0); } /* import command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_import(flag_t *f, int argc, char **argv) +do_import(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { name_mapping_t *nm; + cmd_pos_t pos2; char line[MAX_INPUT_LINE_SZ]; format_t format; int rc = 0; idmap_stat stat; - int line_num; FILE *file = NULL; if (batch_mode) { - (void) fprintf(stderr, + print_error(pos, gettext("Import is not allowed in the batch mode.\n")); return (-1); } @@ -1484,15 +1628,13 @@ /* We don't flush groups in the usermap.cfg nor smbusers format */ if (f[F_FLAG] != NULL && - flush_nm(B_TRUE) < 0 && + flush_nm(B_TRUE, pos) < 0 && (format == USERMAP_CFG || format == SMBUSERS || - flush_nm(B_FALSE) < 0)) { + flush_nm(B_FALSE, pos) < 0)) { rc = -1; goto cleanup; } - line_num = 0; - /* Where we import from? */ if (f[f_FLAG] == NULL) file = stdin; @@ -1504,10 +1646,12 @@ } } + pos2.linenum = 0; + pos2.line = line; while (fgets(line, MAX_INPUT_LINE_SZ, file)) { char *line2 = line; - line_num++; + pos2.linenum++; /* * In SMBUSERS format there can be more mappings on @@ -1520,7 +1664,7 @@ goto cleanup; } - rc = line2nm(line2, line_num, nm, format); + rc = line2nm(line2, &pos2, nm, format); line2 = NULL; if (rc < 1) { @@ -1532,25 +1676,29 @@ nm->is_user ? B_TRUE : B_FALSE, nm->winname, nm->unixname, nm->is_nt4, nm->direction); if (stat < 0) { - (void) fprintf(stderr, + print_error(&pos2, gettext("Transaction error (%s)\n"), idmap_stat2string(handle, stat)); rc = -1; } + if (rc >= 0) + rc = positions_add(&pos2); + name_mapping_fini(nm); } while (rc >= 0); if (rc < 0) { - (void) fprintf(stderr, + print_error(NULL, gettext("Import canceled.\n")); break; } } cleanup: - fini_udt_command(rc < 0 ? 0 : 1); + if (fini_udt_command((rc < 0 ? 0 : 1), pos)) + rc = -1; if (file != NULL && file != stdin) (void) fclose(file); return (rc); @@ -1563,7 +1711,7 @@ * file fi. */ static int -list_name_mappings(int list_users, int list_groups, format_t format, FILE *fi) +list_name_mappings(format_t format, FILE *fi) { idmap_stat stat; idmap_iter_t *ihandle; @@ -1571,10 +1719,6 @@ int is_user; for (is_user = I_YES; is_user >= I_NO; is_user--) { - if (is_user && !list_users) - continue; - if (!is_user && !list_groups) - continue; /* Only users can be in USERMAP_CFG format, not a group */ if (!is_user && format == USERMAP_CFG) continue; @@ -1582,7 +1726,7 @@ stat = idmap_iter_namerules(handle, NULL, is_user, NULL, NULL, &ihandle); if (stat < 0) { - (void) fprintf(stderr, + print_error(NULL, gettext("Iteration handle not obtained (%s)\n"), idmap_stat2string(handle, stat)); idmap_iter_destroy(ihandle); @@ -1613,7 +1757,7 @@ (void) print_mapping_fini(); if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) { - (void) fprintf(stderr, + print_error(NULL, gettext("Error during iteration (%s)\n"), idmap_stat2string(handle, stat)); idmap_iter_destroy(ihandle); @@ -1628,7 +1772,7 @@ /* Export command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_export(flag_t *f, int argc, char **argv) { +do_export(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { int rc; format_t format; FILE *fi; @@ -1654,10 +1798,7 @@ } /* List the requested types: */ - rc = list_name_mappings(is_user_wanted(f), - is_group_wanted(f), - format, - fi); + rc = list_name_mappings(format, fi); fini_command(); @@ -1670,7 +1811,7 @@ /* List command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_list_name_mappings(flag_t *f, int argc, char **argv) +do_list_name_mappings(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { int rc; @@ -1679,10 +1820,7 @@ } /* List the requested types: */ - rc = list_name_mappings(is_user_wanted(f), - is_group_wanted(f), - DEFAULT_FORMAT, - stdout); + rc = list_name_mappings(DEFAULT_FORMAT, stdout); fini_command(); return (rc); @@ -1713,7 +1851,7 @@ * 1 ... determined */ static int -name2parts(char *name, name_mapping_t *nm) { +name2parts(char *name, name_mapping_t *nm, cmd_pos_t *pos) { char *it; int is_win = I_NO; int is_unix = I_NO; @@ -1723,17 +1861,70 @@ /* If it starts with type string, that is easy: */ if (it = strchr(name, ':')) { - if (strcmp_no0(name, ID_UNIXNAME ":") == 0) { + if (strcmp_no0(name, ID_UNIXUSER ":") == 0) { + if (nm->is_user == I_NO) { + print_error(pos, + gettext("%s - invalid combination of user" + " and group identity types.\n"), + ID_UNIXUSER); + return (-1); + } + if (nm->unixname != NULL) + return (0); + + nm->is_user = I_YES; + is_unix = I_YES; + + } else if (strcmp_no0(name, ID_UNIXGROUP ":") == 0) { + if (nm->is_user == I_YES) { + print_error(pos, + gettext("%s - invalid combination of user" + " and group identity types.\n"), + ID_UNIXGROUP); + return (-1); + } if (nm->unixname != NULL) return (0); + + nm->is_user = I_NO; is_unix = I_YES; + + } else if (strcmp_no0(name, ID_WINUSER ":") == 0) { + if (nm->is_user == I_NO) { + print_error(pos, + gettext("%s - invalid combination of user" + " and group identity types.\n"), + ID_WINUSER); + return (-1); + } + if (nm->winname != NULL) + return (0); + + nm->is_user = I_YES; + is_win = I_YES; + + } else if (strcmp_no0(name, ID_WINGROUP ":") == 0) { + if (nm->is_user == I_YES) { + print_error(pos, + gettext("%s - invalid combination of user" + " and group identity types.\n"), + ID_WINGROUP); + return (-1); + } + if (nm->winname != NULL) + return (0); + + nm->is_user = I_NO; + is_win = I_YES; + } else if (strcmp_no0(name, ID_WINNAME ":") == 0) { if (nm->winname != NULL) return (0); is_win = I_YES; } else { - (void) fprintf(stderr, - gettext("Error: invalid identity type\n")); + print_error(pos, + gettext("Error: invalid identity type \"%.*s\"\n"), + it - name, name); return (-1); } name = it + 1; @@ -1742,14 +1933,14 @@ /* If it contains '@' or '\\', then it is a winname with domain */ if (!is_unix && nm->winname == NULL) { if ((it = strchr(name, '@')) != NULL) { - int length = it-name+1; + int length = it - name + 1; nm->winname = (char *)malloc(length * sizeof (char)); (void) strncpy(nm->winname, name, length - 1); nm->winname[length - 1] = '\0'; nm->windomain = strdup(it + 1); return (1); } else if ((it = strrchr(name, '\\')) != NULL) { - int length = it-name+1; + int length = it - name + 1; nm->windomain = (char *)malloc(length * sizeof (char)); (void) strncpy(nm->windomain, name, length - 1); nm->windomain[length - 1] = '\0'; @@ -1784,7 +1975,7 @@ /* add command handler. */ static int -do_add_name_mapping(flag_t *f, int argc, char **argv) +do_add_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { name_mapping_t *nm; int rc = 0; @@ -1793,15 +1984,14 @@ idmap_stat stat; - /* Two arguments and exactly one of -u, -g must be specified */ + /* Exactly two arguments must be specified */ if (argc < 2) { - (void) fprintf(stderr, gettext("Not enough arguments.\n")); + print_error(pos, gettext("Not enough arguments.\n")); return (-1); } else if (argc > 2) { - (void) fprintf(stderr, gettext("Too many arguments.\n")); + print_error(pos, gettext("Too many arguments.\n")); return (-1); - } else if (!is_type_determined(f)) - return (-1); + } /* * Direction can be determined by the opposite name, so we @@ -1812,10 +2002,8 @@ if (nm == NULL) return (-1); - nm->is_user = f[u_FLAG] != NULL ? I_YES : I_NO; - for (i = 0; i < 3; i++) { - switch (name2parts(argv[i % 2], nm)) { + switch (name2parts(argv[i % 2], nm, pos)) { case -1: name_mapping_fini(nm); return (-1); @@ -1828,15 +2016,17 @@ } if (nm->winname == NULL || nm->unixname == NULL) { - (void) fprintf(stderr, gettext("Name types not determined.\n")); + print_error(pos, gettext("Name types not determined.\n")); name_mapping_fini(nm); return (-1); } if (f[d_FLAG] != NULL) - nm->direction = is_argv0_unix ? DIR_U2W : DIR_W2U; + nm->direction = is_argv0_unix + ? IDMAP_DIRECTION_U2W + : IDMAP_DIRECTION_W2U; else - nm->direction = DIR_BI; + nm->direction = IDMAP_DIRECTION_BI; /* Now let us write it: */ @@ -1855,55 +2045,59 @@ (void) print_mapping_fini(); if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Mapping not created (%s)\n"), idmap_stat2string(handle, stat)); rc = -1; } + if (rc == 0) + rc = positions_add(pos); + cleanup: name_mapping_fini(nm); - fini_udt_command(1); + if (fini_udt_command(1, pos)) + rc = -1; return (rc); } /* remove command handler */ static int -do_remove_name_mapping(flag_t *f, int argc, char **argv) +do_remove_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { name_mapping_t *nm; int rc = 0; int i; int is_argv0_unix = -1; idmap_stat stat; + int is_user; /* "-a" means we flush all of them */ if (f[a_FLAG] != NULL) { if (argc) { - (void) fprintf(stderr, + print_error(pos, gettext("Too many arguments.\n")); return (-1); } - if (!is_type_determined(f)) - return (-1); - if (init_udt_command()) return (-1); - rc = flush_nm(f[u_FLAG] != NULL ? B_TRUE : B_FALSE); - - fini_udt_command(rc ? 0 : 1); + rc = flush_nm(B_TRUE, pos); + + if (rc >= 0) + rc = flush_nm(B_FALSE, pos); + + if (fini_udt_command(rc ? 0 : 1, pos)) + rc = -1; return (rc); } /* Contrary to add_name_mapping, we can have only one argument */ if (argc < 1) { - (void) fprintf(stderr, gettext("Not enough arguments.\n")); + print_error(pos, gettext("Not enough arguments.\n")); return (-1); } else if (argc > 2) { - (void) fprintf(stderr, gettext("Too many arguments.\n")); - return (-1); - } else if (!is_type_determined(f)) { + print_error(pos, gettext("Too many arguments.\n")); return (-1); } else if ( /* both -f and -t: */ @@ -1912,7 +2106,7 @@ argc == 1 && f[d_FLAG] != NULL || /* -f or -t with two arguments: */ argc == 2 && (f[f_FLAG] != NULL || f[t_FLAG] != NULL)) { - (void) fprintf(stderr, + print_error(pos, gettext("Direction ambiguous.\n")); return (-1); } @@ -1926,10 +2120,8 @@ if (nm == NULL) return (-1); - nm->is_user = f[u_FLAG] != NULL ? I_YES : I_NO; - for (i = 0; i < 2 * argc - 1; i++) { - switch (name2parts(argv[i % 2], nm)) { + switch (name2parts(argv[i % 2], nm, pos)) { case -1: name_mapping_fini(nm); return (-1); @@ -1942,42 +2134,57 @@ if (nm->winname == NULL && nm->unixname == NULL) { - (void) fprintf(stderr, gettext("Name types not determined.\n")); + print_error(pos, gettext("Name types not determined.\n")); name_mapping_fini(nm); return (-1); } /* * If the direction is not specified by a -d/-f/-t flag, then it - * is DIR_UNKNOWN, because in that case we want to remove any - * mapping. If it was DIR_BI, idmap_api would delete a - * bidirectional one only. + * is IDMAP_DIRECTION_UNDEF, because in that case we want to + * remove any mapping. If it was IDMAP_DIRECTION_BI, idmap_api would + * delete a bidirectional one only. */ if (f[d_FLAG] != NULL || f[f_FLAG] != NULL) - nm->direction = is_argv0_unix ? DIR_U2W : DIR_W2U; + nm->direction = is_argv0_unix + ? IDMAP_DIRECTION_U2W + : IDMAP_DIRECTION_W2U; else if (f[t_FLAG] != NULL) - nm->direction = is_argv0_unix ? DIR_W2U : DIR_U2W; + nm->direction = is_argv0_unix + ? IDMAP_DIRECTION_W2U + : IDMAP_DIRECTION_U2W; else - nm->direction = DIR_UNKNOWN; + nm->direction = IDMAP_DIRECTION_UNDEF; if (init_udt_command()) { name_mapping_fini(nm); return (-1); } - stat = idmap_udt_rm_namerule(udt, nm->is_user ? B_TRUE : B_FALSE, - nm->windomain, nm->winname, nm->unixname, nm->direction); - - if (stat < 0) { - (void) fprintf(stderr, - gettext("Mapping not deleted (%s)\n"), - idmap_stat2string(handle, stat)); - rc = -1; + for (is_user = I_YES; is_user >= I_NO; is_user--) { + if ((is_user == I_YES && nm->is_user == I_NO) || + (is_user == I_NO && nm->is_user == I_YES)) + continue; + + stat = idmap_udt_rm_namerule(udt, is_user ? B_TRUE : B_FALSE, + nm->windomain, nm->winname, nm->unixname, nm->direction); + + if (stat < 0) { + print_error(pos, + gettext("Mapping not deleted (%s)\n"), + idmap_stat2string(handle, stat)); + rc = -1; + break; + } } + if (rc == 0) + rc = positions_add(pos); + cleanup: name_mapping_fini(nm); - fini_udt_command(1); + if (fini_udt_command(1, pos)) + rc = -1; return (rc); } @@ -1985,7 +2192,7 @@ /* exit command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ -do_exit(flag_t *f, int argc, char **argv) { +do_exit(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { return (0); } @@ -1993,7 +2200,7 @@ /* debug command handler: just print the parameters */ static int /* LINTED E_STATIC_UNUSED */ -debug_print_params(flag_t *f, int argc, char **argv) +debug_print_params(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { int i; #if 0 @@ -2034,6 +2241,8 @@ *to = sid_format(nm->sidprefix, nm->rid); return (0); case TYPE_WN: + case TYPE_WU: + case TYPE_WG: return (nm2winqn(nm, to)); case TYPE_UID: case TYPE_GID: @@ -2044,10 +2253,12 @@ else return (0); case TYPE_UN: + case TYPE_UU: + case TYPE_UG: return (nm2unixname(nm, to)); default: /* This can never happen: */ - (void) fprintf(stderr, + print_error(NULL, gettext("Internal error: invalid name type.\n")); return (-1); } @@ -2056,7 +2267,7 @@ /* show command handler */ static int -do_show_mapping(flag_t *f, int argc, char **argv) +do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { idmap_stat stat = 0; int flag; @@ -2069,11 +2280,11 @@ char *toname; if (argc == 0) { - (void) fprintf(stderr, + print_error(pos, gettext("No identity given\n")); return (-1); } else if (argc > 2) { - (void) fprintf(stderr, + print_error(pos, gettext("Too many arguments.\n")); return (-1); } @@ -2094,17 +2305,39 @@ type_from = TYPE_GID; else if ((root = get_root(argv[0], ID_SID ":")) != NULL) type_from = TYPE_SID; - else if (name2parts(argv[0], nm) > 0) { - if (nm->unixname != NULL) - type_from = TYPE_UN; - else - type_from = TYPE_WN; - } else { - (void) fprintf(stderr, - gettext("Invalid type.\n")); - stat = IDMAP_ERR_ARG; - goto cleanup; - } + else + switch (name2parts(argv[0], nm, pos)) { + case 1: /* name2parts determined the type */ + if (nm->unixname != NULL) + switch (nm->is_user) { + case I_YES: + type_from = TYPE_UU; + break; + case I_NO: + type_from = TYPE_UG; + break; + default: + type_from = TYPE_UN; + } + else + switch (nm->is_user) { + case I_YES: + type_from = TYPE_WU; + break; + case I_NO: + type_from = TYPE_WG; + break; + default: + type_from = TYPE_WN; + } + break; + case 0: /* name2parts didn't determine the type: */ + print_error(pos, gettext("Invalid type.\n")); + /* LINTED E_CASE_FALLTHRU */ + case -1: + stat = IDMAP_ERR_ARG; + goto cleanup; + } /* Second, determine type_to: */ if (argc < 2) { @@ -2117,32 +2350,51 @@ type_to = TYPE_GID; else if (strcasecmp(argv[1], ID_SID) == 0) type_to = TYPE_SID; - else if (strcmp(argv[1], ID_UNIXNAME) == 0) - type_to = TYPE_UN; + else if (strcmp(argv[1], ID_UNIXUSER) == 0) + type_to = TYPE_UU; + else if (strcmp(argv[1], ID_UNIXGROUP) == 0) + type_to = TYPE_UG; else if (strcmp(argv[1], ID_WINNAME) == 0) type_to = TYPE_WN; + else if (strcmp(argv[1], ID_WINUSER) == 0) + type_to = TYPE_WU; + else if (strcmp(argv[1], ID_WINGROUP) == 0) + type_to = TYPE_WG; else { - (void) fprintf(stderr, - gettext("Ivnalid target type.\n")); + print_error(pos, + gettext("Invalid target type.\n")); stat = IDMAP_ERR_ARG; goto cleanup; } /* Are both arguments the same OS side? */ if (!(type_from & IS_WIN ^ type_to & IS_WIN)) { - (void) fprintf(stderr, + print_error(pos, gettext("Direction ambiguous.\n")); stat = IDMAP_ERR_ARG; goto cleanup; } + /* Are both arguments the same userness/groupness? */ + if ((type_from & IS_USER) && (type_to & IS_GROUP)) { + print_error(pos, + gettext("Mapping of user to group impossible.\n")); + stat = IDMAP_ERR_ARG; + goto cleanup; + } else if ((type_from & IS_GROUP) && (type_to & IS_USER)) { + print_error(pos, + gettext("Mapping of group to user impossible.\n")); + stat = IDMAP_ERR_ARG; + goto cleanup; + } + if (type_from == TYPE_SID) { - if (!sid_convert(root, &nm->sidprefix, &nm->rid)) { + if (!sid_convert(root, &nm->sidprefix, &nm->rid, pos)) { stat = IDMAP_ERR_ARG; goto cleanup; } } else if (type_from == TYPE_UID || type_from == TYPE_GID) { - if (!pid_convert(root, &nm->pid, type_from)) { + if (!pid_convert(root, &nm->pid, type_from, pos)) { stat = IDMAP_ERR_ARG; goto cleanup; } @@ -2202,7 +2454,7 @@ /* Create an in-memory structure for all the batch: */ stat = idmap_get_create(handle, &ghandle); if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Unable to create handle for communicating" " with idmapd(1M) (%s)\n"), idmap_stat2string(handle, stat)); @@ -2253,13 +2505,13 @@ nm->is_user = I_NO; } else { /* This can never happen: */ - (void) fprintf(stderr, + print_error(pos, gettext("Internal error in show.\n")); exit(1); } if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Request for %.3s not sent (%s)\n"), argv[0], idmap_stat2string(handle, stat)); idmap_get_destroy(ghandle); @@ -2269,7 +2521,7 @@ /* Send the batch to idmapd and obtain results: */ stat = idmap_get_mappings(ghandle); if (stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("Mappings not obtained because of" " RPC problem (%s)\n"), idmap_stat2string(handle, stat)); @@ -2292,7 +2544,7 @@ * the case of error: */ if (map_stat < 0) { - (void) fprintf(stderr, + print_error(pos, gettext("%s\n"), idmap_stat2string(handle, map_stat)); if (flag == IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) @@ -2300,6 +2552,19 @@ } + /* + * idmapd returns fallback uid/gid in case of errors. However + * it uses special sentinel value i.e 4294967295 (or -1) to + * indicate that falbback pid is not available either. In such + * case idmap(1M) should not display the mapping because there + * is no fallback mapping. + */ + + if (type_to == TYPE_UID && nm->pid == UNDEFINED_UID || + type_to == TYPE_GID && nm->pid == (uid_t)UNDEFINED_GID) { + goto cleanup; + } + if (nm2type(nm, type_from, &fromname) < 0) goto cleanup; @@ -2357,7 +2622,8 @@ if (batch_mode) { batch_mode = 0; - fini_udt_command(rc == 0 ? 1 : 0); + if (fini_udt_command(rc == 0 ? 1 : 0, NULL)) + rc = -1; } (void) engine_fini();
--- a/usr/src/cmd/idmap/idmap/idmap_engine.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmap/idmap_engine.c Mon Sep 17 08:07:28 2007 -0700 @@ -112,7 +112,7 @@ /* determine which subcommand is argv[0] and execute its handler */ static int -run_command(int argc, char **argv) { +run_command(int argc, char **argv, cmd_pos_t *pos) { int i; if (argc == 0) { @@ -134,7 +134,10 @@ return (-1); } - rc = my_comv[i].p_do_func(flags, argc - optind, argv + optind); + rc = my_comv[i].p_do_func(flags, + argc - optind, + argv + optind, + pos); return (rc); } @@ -402,7 +405,7 @@ } } - rc = run_command(my_argc, my_argv); + rc = run_command(my_argc, my_argv, NULL); if (strcmp(my_argv[0], "exit") == 0 && rc == 0) { break; @@ -425,6 +428,7 @@ int is_stdin; int rc = -1; char line[MAX_CMD_LINE_SZ]; + cmd_pos_t pos; if (name == NULL || strcmp("-", name) == 0) { f = stdin; @@ -438,7 +442,11 @@ } } + pos.linenum = 0; + pos.line = line; + while (fgets(line, MAX_CMD_LINE_SZ, f)) { + pos.linenum ++; if (line2array(line) < 0) { (void) fprintf(stderr, @@ -460,7 +468,7 @@ break; } - rc = run_command(my_argc, my_argv); + rc = run_command(my_argc, my_argv, &pos); my_argv_clean(); } @@ -569,7 +577,7 @@ goto cleanup; } - rc = run_command(argc, argv); + rc = run_command(argc, argv, NULL); cleanup: return (rc);
--- a/usr/src/cmd/idmap/idmap/idmap_engine.h Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmap/idmap_engine.h Mon Sep 17 08:07:28 2007 -0700 @@ -48,13 +48,21 @@ #define IDMAP_ENG_ERROR -1 #define IDMAP_ENG_ERROR_SILENT -2 +typedef struct cmd_pos { + int linenum; /* line number */ + char *line; /* line content */ +} cmd_pos_t; + + typedef struct cmd_ops { const char *cmd; /* the subcommand */ const char *options; /* getopt string for the subcommand params */ - int (*p_do_func)(flag_t *f, int argc, char **argv); /* handle */ + int (*p_do_func)(flag_t *f, + int argc, + char **argv, + cmd_pos_t *pos); /* handle */ } cmd_ops_t; - extern int engine_init(int comc, cmd_ops_t *comv, int argc, char **argv, int *is_batch_mode); extern int engine_fini();
--- a/usr/src/cmd/idmap/idmapd/dbutils.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmapd/dbutils.c Mon Sep 17 08:07:28 2007 -0700 @@ -56,8 +56,6 @@ #define EMPTY_NAME(name) (*name == 0 || strcmp(name, "\"\"") == 0) -#define EMPTY_STRING(str) (str == NULL || *str == 0) - #define DO_NOT_ALLOC_NEW_ID_MAPPING(req)\ (req->flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) @@ -478,29 +476,21 @@ */ idmap_retcode gen_sql_expr_from_utf8str(const char *prefix, const char *col, - const char *op, idmap_utf8str *value, + const char *op, char *value, const char *suffix, char **out) { - char *str; - idmap_stat retcode; - if (out == NULL) return (IDMAP_ERR_ARG); if (value == NULL) return (IDMAP_SUCCESS); - retcode = idmap_utf82str(&str, 0, value); - if (retcode != IDMAP_SUCCESS) - return (retcode); - if (prefix == NULL) prefix = ""; if (suffix == NULL) suffix = ""; *out = sqlite_mprintf("%s %s %s %Q %s", - prefix, col, op, str, suffix); - idmap_free(str); + prefix, col, op, value, suffix); if (*out == NULL) return (IDMAP_ERR_MEMORY); return (IDMAP_SUCCESS); @@ -685,23 +675,12 @@ add_namerule(sqlite *db, idmap_namerule *rule) { char *sql = NULL; idmap_stat retcode; - char *windomain = NULL, *winname = NULL, *dom = NULL; - char *unixname = NULL; + char *dom = NULL; int w2u_order, u2w_order; char w2ubuf[11], u2wbuf[11]; - retcode = idmap_utf82str(&windomain, 0, &rule->windomain); - if (retcode != IDMAP_SUCCESS) - goto out; - retcode = idmap_utf82str(&winname, 0, &rule->winname); - if (retcode != IDMAP_SUCCESS) - goto out; - retcode = idmap_utf82str(&unixname, 0, &rule->unixname); - if (retcode != IDMAP_SUCCESS) - goto out; - - retcode = get_namerule_order(winname, windomain, unixname, - rule->direction, &w2u_order, &u2w_order); + retcode = get_namerule_order(rule->winname, rule->windomain, + rule->unixname, rule->direction, &w2u_order, &u2w_order); if (retcode != IDMAP_SUCCESS) goto out; @@ -716,9 +695,9 @@ * 2) Use "" instead of NULL for "no domain" */ - if (windomain != NULL) - dom = windomain; - else if (lookup_wksids_name2sid(winname, NULL, NULL, NULL) + if (rule->windomain != NULL) + dom = rule->windomain; + else if (lookup_wksids_name2sid(rule->winname, NULL, NULL, NULL) == IDMAP_SUCCESS) { /* well-known SIDs don't need domain */ dom = ""; @@ -737,8 +716,8 @@ "VALUES(%d, %Q, %Q, %d, %Q, %q, %q);", rule->is_user?1:0, dom, - winname, rule->is_nt4?1:0, - unixname, + rule->winname, rule->is_nt4?1:0, + rule->unixname, w2u_order?w2ubuf:NULL, u2w_order?u2wbuf:NULL); UNLOCK_CONFIG(); @@ -755,12 +734,6 @@ retcode = IDMAP_ERR_CFG; out: - if (windomain != NULL) - idmap_free(windomain); - if (winname != NULL) - idmap_free(winname); - if (unixname != NULL) - idmap_free(unixname); if (sql != NULL) sqlite_freemem(sql); return (retcode); @@ -799,10 +772,8 @@ char *s_unixname = NULL; char buf[80]; - if (rule->direction < 0 && - rule->windomain.idmap_utf8str_len < 1 && - rule->winname.idmap_utf8str_len < 1 && - rule->unixname.idmap_utf8str_len < 1) + if (rule->direction < 0 && EMPTY_STRING(rule->windomain) && + EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) return (IDMAP_SUCCESS); if (rule->direction < 0) { @@ -819,24 +790,21 @@ } retcode = IDMAP_ERR_INTERNAL; - if (rule->windomain.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule->windomain)) { if (gen_sql_expr_from_utf8str("AND", "windomain", "=", - &rule->windomain, - "", &s_windomain) != IDMAP_SUCCESS) + rule->windomain, "", &s_windomain) != IDMAP_SUCCESS) goto out; } - if (rule->winname.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule->winname)) { if (gen_sql_expr_from_utf8str("AND", "winname", "=", - &rule->winname, - "", &s_winname) != IDMAP_SUCCESS) + rule->winname, "", &s_winname) != IDMAP_SUCCESS) goto out; } - if (rule->unixname.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule->unixname)) { if (gen_sql_expr_from_utf8str("AND", "unixname", "=", - &rule->unixname, - "", &s_unixname) != IDMAP_SUCCESS) + rule->unixname, "", &s_unixname) != IDMAP_SUCCESS) goto out; } @@ -1094,7 +1062,6 @@ sqlite_vm *vm = NULL; int ncol, is_user; uid_t pid; - idmap_utf8str *str; time_t curtime, exp; idmap_retcode retcode; @@ -1199,9 +1166,8 @@ res->direction = IDMAP_DIRECTION_W2U; if (values[3] != NULL) { - str = &req->id2name; - retcode = idmap_str2utf8(&str, values[3], 0); - if (retcode != IDMAP_SUCCESS) { + req->id2name = strdup(values[3]); + if (req->id2name == NULL) { idmapdlog(LOG_ERR, "Out of memory"); retcode = IDMAP_ERR_MEMORY; } @@ -1320,7 +1286,6 @@ char *sidprefix; idmap_rid_t rid; char *name = NULL, *domain = NULL; - idmap_utf8str *str; sidprefix = req->id1.idmap_id_u.sid.prefix; rid = req->id1.idmap_id_u.sid.rid; @@ -1342,14 +1307,10 @@ retcode = verify_type(req->id2.idtype, type, res); /* update state in 'req' */ - if (name != NULL) { - str = &req->id1name; - (void) idmap_str2utf8(&str, name, 1); - } - if (domain != NULL) { - str = &req->id1domain; - (void) idmap_str2utf8(&str, domain, 1); - } + if (name != NULL) + req->id1name = name; + if (domain != NULL) + req->id1domain = domain; } else { if (name != NULL) free(name); @@ -1394,8 +1355,8 @@ state->ad_lookup, req->id1.idmap_id_u.sid.prefix, &req->id1.idmap_id_u.sid.rid, - &req->id1name.idmap_utf8str_val, - &req->id1domain.idmap_utf8str_val, + &req->id1name, + &req->id1domain, (int *)&res->id.idtype, &res->retcode); @@ -1470,8 +1431,8 @@ /* * Check if we already have the name (i.e name2pid lookups) */ - if (req->id1name.idmap_utf8str_val != NULL && - req->id1domain.idmap_utf8str_val != NULL) { + if (req->id1name != NULL && + req->id1domain != NULL) { retcode = IDMAP_SUCCESS; req->direction |= _IDMAP_F_S2N_CACHE; goto out; @@ -1677,12 +1638,11 @@ char *end; const char **values; sqlite_vm *vm = NULL; - idmap_utf8str *str; int ncol, r, i, is_user; const char *me = "name_based_mapping_sid2pid"; - winname = req->id1name.idmap_utf8str_val; - windomain = req->id1domain.idmap_utf8str_val; + winname = req->id1name; + windomain = req->id1domain; is_user = (res->id.idtype == IDMAP_UID)?1:0; i = 0; @@ -1776,8 +1736,7 @@ IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; else res->direction = IDMAP_DIRECTION_W2U; - str = &req->id2name; - retcode = idmap_str2utf8(&str, unixname, 0); + req->id2name = strdup(unixname); } if (vm != NULL) (void) sqlite_finalize(vm, NULL); @@ -2026,10 +1985,10 @@ "strftime('%%s','now') + 600, %q, 1); ", res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, - req->id2domain.idmap_utf8str_val, - req->id2name.idmap_utf8str_val, + req->id2domain, + req->id2name, req->id1.idmap_id_u.uid, - req->id1name.idmap_utf8str_val, + req->id1name, (req->id1.idtype == IDMAP_UID)?1:0, (res->direction == 0)?"1":NULL); @@ -2051,7 +2010,7 @@ if (req->direction & _IDMAP_F_S2N_CACHE) goto out; - if (req->id2name.idmap_utf8str_val == NULL) + if (req->id2name == NULL) goto out; sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " @@ -2059,8 +2018,8 @@ "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, - req->id2name.idmap_utf8str_val, - req->id2domain.idmap_utf8str_val, + req->id2name, + req->id2domain, (req->id1.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); if (sql == NULL) { @@ -2128,10 +2087,10 @@ "strftime('%%s','now') + 600, 1, %q); ", req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, - req->id1domain.idmap_utf8str_val, - req->id1name.idmap_utf8str_val, + req->id1domain, + req->id1name, res->id.idmap_id_u.uid, - req->id2name.idmap_utf8str_val, + req->id2name, (res->id.idtype == IDMAP_UID)?1:0, (res->direction == 0)?"1":NULL); @@ -2153,7 +2112,7 @@ if (req->direction & _IDMAP_F_S2N_CACHE) goto out; - if (req->id1name.idmap_utf8str_val == NULL) + if (req->id1name == NULL) goto out; sql = sqlite_mprintf("INSERT OR REPLACE into name_cache " @@ -2161,8 +2120,8 @@ "VALUES(%Q, %u, %Q, %Q, %d, strftime('%%s','now') + 3600); ", req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, - req->id1name.idmap_utf8str_val, - req->id1domain.idmap_utf8str_val, + req->id1name, + req->id1domain, (res->id.idtype == IDMAP_UID)?_IDMAP_T_USER:_IDMAP_T_GROUP); if (sql == NULL) { @@ -2188,7 +2147,6 @@ sqlite_vm *vm = NULL; int ncol; idmap_retcode retcode = IDMAP_SUCCESS; - idmap_utf8str *str; time_t curtime; /* Current time */ @@ -2246,9 +2204,8 @@ if (getname == 0 || values[2] == NULL) break; - str = &req->id2name; - retcode = idmap_str2utf8(&str, values[2], 0); - if (retcode != IDMAP_SUCCESS) { + req->id2name = strdup(values[2]); + if (req->id2name == NULL) { idmapdlog(LOG_ERR, "Out of memory"); retcode = IDMAP_ERR_MEMORY; goto out; @@ -2256,9 +2213,8 @@ if (values[3] == NULL) break; - str = &req->id2domain; - retcode = idmap_str2utf8(&str, values[3], 0); - if (retcode != IDMAP_SUCCESS) { + req->id2domain = strdup(values[3]); + if (req->id2domain == NULL) { idmapdlog(LOG_ERR, "Out of memory"); retcode = IDMAP_ERR_MEMORY; goto out; @@ -2453,7 +2409,6 @@ char *end; const char **values; sqlite_vm *vm = NULL; - idmap_utf8str *str; int ncol, r; const char *me = "name_based_mapping_pid2sid"; @@ -2555,15 +2510,15 @@ IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; else res->direction = IDMAP_DIRECTION_U2W; - str = &req->id2name; - retcode = idmap_str2utf8(&str, winname, 0); - if (retcode == IDMAP_SUCCESS) { - str = &req->id2domain; + + req->id2name = strdup(winname); + if (req->id2name != NULL) { if (windomain == mapping_domain) { - (void) idmap_str2utf8(&str, windomain, 1); + req->id2domain = (char *)windomain; mapping_domain = NULL; - } else - retcode = idmap_str2utf8(&str, windomain, 0); + } else { + req->id2domain = strdup(windomain); + } } } if (vm != NULL) @@ -2580,7 +2535,6 @@ char *unixname = NULL; struct passwd pwd; struct group grp; - idmap_utf8str *str; char buf[1024]; int errnum; idmap_retcode retcode = IDMAP_SUCCESS; @@ -2611,9 +2565,9 @@ } /* uid/gid to name */ - if (req->id1name.idmap_utf8str_val != NULL) { - unixname = req->id1name.idmap_utf8str_val; - } if (is_user) { + if (req->id1name != NULL) { + unixname = req->id1name; + } else if (is_user) { errno = 0; if (getpwuid_r(req->id1.idmap_id_u.uid, &pwd, buf, sizeof (buf)) == NULL) { @@ -2660,12 +2614,9 @@ (void) generate_localsid(req, res, is_user); out: - if (retcode == IDMAP_SUCCESS) { - if (req->id1name.idmap_utf8str_val == NULL && - unixname != NULL) { - str = &req->id1name; - retcode = idmap_str2utf8(&str, unixname, 0); - } + if (retcode == IDMAP_SUCCESS && req->id1name == NULL && + unixname != NULL) { + req->id1name = strdup(unixname); } if (req->direction != _IDMAP_F_DONE) state->pid2sid_done = FALSE; @@ -2730,50 +2681,30 @@ mapping->id1.idmap_id_u.sid.prefix = strdup(request->id1.idmap_id_u.sid.prefix); if (mapping->id1.idmap_id_u.sid.prefix == NULL) - return (-1); + goto errout; } } else { mapping->id1.idmap_id_u.uid = request->id1.idmap_id_u.uid; } - mapping->id1domain.idmap_utf8str_len = - request->id1domain.idmap_utf8str_len; - if (mapping->id1domain.idmap_utf8str_len) { - mapping->id1domain.idmap_utf8str_val = - strdup(request->id1domain.idmap_utf8str_val); - if (mapping->id1domain.idmap_utf8str_val == NULL) - return (-1); - } + mapping->id1domain = strdup(request->id1domain); + if (mapping->id1domain == NULL) + goto errout; - mapping->id1name.idmap_utf8str_len = - request->id1name.idmap_utf8str_len; - if (mapping->id1name.idmap_utf8str_len) { - mapping->id1name.idmap_utf8str_val = - strdup(request->id1name.idmap_utf8str_val); - if (mapping->id1name.idmap_utf8str_val == NULL) - return (-1); - } + mapping->id1name = strdup(request->id1name); + if (mapping->id1name == NULL) + goto errout; /* We don't need the rest of the request i.e request->id2 */ return (0); errout: - if (mapping->id1.idmap_id_u.sid.prefix != NULL) { + if (mapping->id1.idmap_id_u.sid.prefix != NULL) free(mapping->id1.idmap_id_u.sid.prefix); - mapping->id1.idmap_id_u.sid.prefix = NULL; - } - - if (mapping->id1domain.idmap_utf8str_val != NULL) { - free(mapping->id1domain.idmap_utf8str_val); - mapping->id1domain.idmap_utf8str_val = NULL; - mapping->id1domain.idmap_utf8str_len = 0; - } - - if (mapping->id1name.idmap_utf8str_val != NULL) { - free(mapping->id1name.idmap_utf8str_val); - mapping->id1name.idmap_utf8str_val = NULL; - mapping->id1name.idmap_utf8str_len = 0; - } + if (mapping->id1domain != NULL) + free(mapping->id1domain); + if (mapping->id1name != NULL) + free(mapping->id1name); (void) memset(mapping, 0, sizeof (*mapping)); return (-1); @@ -2785,7 +2716,6 @@ idmap_mapping *mapping) { idmap_id_res idres; lookup_state_t state; - idmap_utf8str *str; char *cp; int is_user; idmap_retcode retcode; @@ -2811,8 +2741,8 @@ goto out; } - winname = mapping->id1name.idmap_utf8str_val; - windomain = mapping->id1domain.idmap_utf8str_val; + winname = mapping->id1name; + windomain = mapping->id1domain; if (winname == NULL && windomain != NULL) { retcode = IDMAP_ERR_ARG; @@ -2820,30 +2750,35 @@ } if (winname != NULL && windomain == NULL) { - str = &mapping->id1domain; - + retcode = IDMAP_SUCCESS; if ((cp = strchr(winname, '@')) != NULL) { /* * if winname is qualified with a domain, use it. */ *cp = '\0'; - retcode = idmap_str2utf8(&str, cp + 1, 0); - } else if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { + mapping->id1domain = strdup(cp + 1); + if (mapping->id1domain == NULL) + retcode = IDMAP_ERR_MEMORY; + } else { + RDLOCK_CONFIG(); + if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { /* * otherwise use the mapping domain */ - RDLOCK_CONFIG(); - retcode = idmap_str2utf8(&str, - _idmapdstate.cfg->pgcfg.mapping_domain, 0); + mapping->id1domain = + strdup(_idmapdstate.cfg-> + pgcfg.mapping_domain); + if (mapping->id1domain == NULL) + retcode = IDMAP_ERR_MEMORY; + } UNLOCK_CONFIG(); - } else - retcode = IDMAP_SUCCESS; + } if (retcode != IDMAP_SUCCESS) { idmapdlog(LOG_ERR, "Out of memory"); goto out; } - windomain = mapping->id1domain.idmap_utf8str_val; + windomain = mapping->id1domain; } if (winname != NULL && mapping->id1.idmap_id_u.sid.prefix == NULL) { @@ -2866,8 +2801,8 @@ retcode = lookup_win_sid2name( mapping->id1.idmap_id_u.sid.prefix, mapping->id1.idmap_id_u.sid.rid, - &mapping->id1name.idmap_utf8str_val, - &mapping->id1domain.idmap_utf8str_val, + &mapping->id1name, + &mapping->id1domain, (int *)&idres.id.idtype); idres.retcode = retcode; @@ -2921,7 +2856,7 @@ goto out; } - unixname = mapping->id1name.idmap_utf8str_val; + unixname = mapping->id1name; if (unixname == NULL && mapping->id1.idmap_id_u.uid == SENTINEL_PID) { retcode = IDMAP_ERR_ARG;
--- a/usr/src/cmd/idmap/idmapd/idmapd.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmapd/idmapd.c Mon Sep 17 08:07:28 2007 -0700 @@ -263,6 +263,7 @@ static void init_idmapd() { int error; + int connmaxrec = RPC_MAX_SIZE; /* create directories as root and chown to daemon uid */ if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) @@ -309,6 +310,12 @@ goto errout; } + if (!svc_control(xprt, SVCSET_CONNMAXREC, &connmaxrec)) { + idmapdlog(LOG_ERR, + "idmapd: unable to limit RPC request size"); + goto errout; + } + dfd = xprt->xp_fd; if (dfd == -1) {
--- a/usr/src/cmd/idmap/idmapd/idmapd.h Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmapd/idmapd.h Mon Sep 17 08:07:28 2007 -0700 @@ -140,6 +140,10 @@ #define IDMAP_CACHEDIR "/var/run/idmap" #define IDMAP_DBNAME IDMAP_DBDIR "/idmap.db" #define IDMAP_CACHENAME IDMAP_CACHEDIR "/idmap.db" +#define IDMAP_CACHENAME IDMAP_CACHEDIR "/idmap.db" +#define RPC_MAX_SIZE 65536 + +#define EMPTY_STRING(str) (str == NULL || *str == 0) typedef idmap_retcode (*update_list_res_cb)(void *, const char **, uint64_t); typedef int (*list_svc_cb)(void *, int, char **, char **); @@ -165,7 +169,7 @@ extern idmap_retcode gen_sql_expr_from_utf8str(const char *, const char *, const char *, - idmap_utf8str *, const char *, + char *, const char *, char **); extern idmap_retcode validate_list_cb_data(list_cb_data_t *, int, char **, int, uchar_t **, size_t);
--- a/usr/src/cmd/idmap/idmapd/rpc_svc.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmapd/rpc_svc.c Mon Sep 17 08:07:28 2007 -0700 @@ -69,9 +69,9 @@ } int -_idmap_update_1(idmap_update_batch *argp, idmap_retcode *result, +_idmap_update_1(idmap_update_batch *argp, idmap_update_res *res, struct svc_req *rqstp) { - return (idmap_update_1_svc(*argp, result, rqstp)); + return (idmap_update_1_svc(*argp, res, rqstp)); } int @@ -95,7 +95,7 @@ idmap_ids_res idmap_get_mapped_ids_1_res; idmap_mappings_res idmap_list_mappings_1_res; idmap_namerules_res idmap_list_namerules_1_res; - idmap_retcode idmap_update_1_res; + idmap_update_res idmap_update_1_res; idmap_mappings_res idmap_get_mapped_id_by_name_1_res; } result; bool_t retval; @@ -136,7 +136,7 @@ case IDMAP_UPDATE: _xdr_argument = (xdrproc_t)xdr_idmap_update_batch; - _xdr_result = (xdrproc_t)xdr_idmap_retcode; + _xdr_result = (xdrproc_t)xdr_idmap_update_res; local = (bool_t (*) (char *, void *, struct svc_req *)) _idmap_update_1; break;
--- a/usr/src/cmd/idmap/idmapd/server.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/cmd/idmap/idmapd/server.c Mon Sep 17 08:07:28 2007 -0700 @@ -63,6 +63,14 @@ res->retcode = IDMAP_ERR_NOTFOUND; +#define STRDUP_OR_FAIL(to, from) \ + if ((from) == NULL) \ + to = NULL; \ + else { \ + if ((to = strdup(from)) == NULL) \ + return (1); \ + } + /* ARGSUSED */ bool_t idmap_null_1_svc(void *result, struct svc_req *rqstp) { @@ -268,7 +276,6 @@ list_cb_data_t *cb_data; char *str; idmap_mappings_res *result; - idmap_utf8str *ptr; idmap_retcode retcode; int w2u, u2w; char *end; @@ -306,17 +313,15 @@ result->mappings.mappings_val[cb_data->next].direction = IDMAP_DIRECTION_BI; - ptr = &result->mappings.mappings_val[cb_data->next].id1domain; - if (idmap_str2utf8(&ptr, argv[6], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1domain, + argv[6]); - ptr = &result->mappings.mappings_val[cb_data->next].id1name; - if (idmap_str2utf8(&ptr, argv[7], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id1name, + argv[7]); - ptr = &result->mappings.mappings_val[cb_data->next].id2name; - if (idmap_str2utf8(&ptr, argv[8], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id2name, + argv[8]); + result->lastrowid = strtoll(argv[0], &end, 10); cb_data->next++; @@ -393,7 +398,6 @@ list_cb_data_t *cb_data; idmap_namerules_res *result; idmap_retcode retcode; - idmap_utf8str *ptr; int w2u_order, u2w_order; char *end; @@ -408,20 +412,17 @@ result->rules.rules_val[cb_data->next].is_user = strtol(argv[1], &end, 10); - ptr = &result->rules.rules_val[cb_data->next].windomain; - if (idmap_str2utf8(&ptr, argv[2], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].windomain, + argv[2]); - ptr = &result->rules.rules_val[cb_data->next].winname; - if (idmap_str2utf8(&ptr, argv[3], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].winname, + argv[3]); result->rules.rules_val[cb_data->next].is_nt4 = strtol(argv[4], &end, 10); - ptr = &result->rules.rules_val[cb_data->next].unixname; - if (idmap_str2utf8(&ptr, argv[5], 0) != IDMAP_SUCCESS) - return (1); + STRDUP_OR_FAIL(result->rules.rules_val[cb_data->next].unixname, + argv[5]); w2u_order = argv[6]?strtol(argv[6], &end, 10):0; u2w_order = argv[7]?strtol(argv[7], &end, 10):0; @@ -488,25 +489,25 @@ } /* Create where statement for windomain */ - if (rule.windomain.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule.windomain)) { if (gen_sql_expr_from_utf8str("AND", "windomain", "=", - &rule.windomain, + rule.windomain, "", &s_windomain) != IDMAP_SUCCESS) goto out; } /* Create where statement for winname */ - if (rule.winname.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule.winname)) { if (gen_sql_expr_from_utf8str("AND", "winname", "=", - &rule.winname, + rule.winname, "", &s_winname) != IDMAP_SUCCESS) goto out; } /* Create where statement for unixname */ - if (rule.unixname.idmap_utf8str_len > 0) { + if (!EMPTY_STRING(rule.unixname)) { if (gen_sql_expr_from_utf8str("AND", "unixname", "=", - &rule.unixname, + rule.unixname, "", &s_unixname) != IDMAP_SUCCESS) goto out; } @@ -602,33 +603,45 @@ return (1); } +/* + * Meaning of the return values is the following: For retcode == + * IDMAP_SUCCESS, everything went OK and error_index is + * undefined. Otherwise, error_index >=0 shows the failed batch + * element. errro_index == -1 indicates failure at the beginning, + * error_index == -2 at the end. + */ + /* ARGSUSED */ bool_t -idmap_update_1_svc(idmap_update_batch batch, idmap_retcode *result, +idmap_update_1_svc(idmap_update_batch batch, idmap_update_res *res, struct svc_req *rqstp) { sqlite *db = NULL; idmap_update_op *up; int i; int trans = FALSE; + res->error_index = -1; + (void) memset(&res->error_rule, 0, sizeof (res->error_rule)); + (void) memset(&res->conflict_rule, 0, sizeof (res->conflict_rule)); + if (verify_rules_auth(rqstp) < 0) { - *result = IDMAP_ERR_PERMISSION_DENIED; + res->retcode = IDMAP_ERR_PERMISSION_DENIED; goto out; } if (batch.idmap_update_batch_len == 0 || batch.idmap_update_batch_val == NULL) { - *result = IDMAP_SUCCESS; + res->retcode = IDMAP_SUCCESS; goto out; } /* Get db handle */ - *result = get_db_handle(&db); - if (*result != IDMAP_SUCCESS) + res->retcode = get_db_handle(&db); + if (res->retcode != IDMAP_SUCCESS) goto out; - *result = sql_exec_no_cb(db, "BEGIN TRANSACTION;"); - if (*result != IDMAP_SUCCESS) + res->retcode = sql_exec_no_cb(db, "BEGIN TRANSACTION;"); + if (res->retcode != IDMAP_SUCCESS) goto out; trans = TRUE; @@ -636,37 +649,53 @@ up = &batch.idmap_update_batch_val[i]; switch (up->opnum) { case OP_NONE: - *result = IDMAP_SUCCESS; + res->retcode = IDMAP_SUCCESS; break; case OP_ADD_NAMERULE: - *result = add_namerule(db, + res->retcode = add_namerule(db, &up->idmap_update_op_u.rule); break; case OP_RM_NAMERULE: - *result = rm_namerule(db, + res->retcode = rm_namerule(db, &up->idmap_update_op_u.rule); break; case OP_FLUSH_NAMERULES: - *result = flush_namerules(db, + res->retcode = flush_namerules(db, up->idmap_update_op_u.is_user); break; default: - *result = IDMAP_ERR_NOTSUPPORTED; - goto out; + res->retcode = IDMAP_ERR_NOTSUPPORTED; + break; }; - if (*result != IDMAP_SUCCESS) + if (res->retcode != IDMAP_SUCCESS) { + res->error_index = i; + if (up->opnum == OP_ADD_NAMERULE || + up->opnum == OP_RM_NAMERULE) { + idmap_stat r2 = + idmap_namerule_cpy(&res->error_rule, + &up->idmap_update_op_u.rule); + if (r2 != IDMAP_SUCCESS) + res->retcode = r2; + } goto out; + } } out: if (trans) { - if (*result == IDMAP_SUCCESS) - *result = sql_exec_no_cb(db, "COMMIT TRANSACTION;"); + if (res->retcode == IDMAP_SUCCESS) { + res->retcode = + sql_exec_no_cb(db, "COMMIT TRANSACTION;"); + if (res->retcode != IDMAP_SUCCESS) + res->error_index = -2; + } else (void) sql_exec_no_cb(db, "ROLLBACK TRANSACTION;"); } - *result = idmap_stat4prot(*result); + + res->retcode = idmap_stat4prot(res->retcode); + return (TRUE); }
--- a/usr/src/head/rpcsvc/idmap_prot.x Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/head/rpcsvc/idmap_prot.x Mon Sep 17 08:07:28 2007 -0700 @@ -26,7 +26,7 @@ %#pragma ident "%Z%%M% %I% %E% SMI" /* opaque type to support non-ASCII strings */ -typedef opaque idmap_utf8str<>; +typedef string idmap_utf8str<>; /* Return status */ typedef int idmap_retcode; @@ -109,6 +109,13 @@ idmap_namerule rules<>; }; +struct idmap_update_res { + idmap_retcode retcode; + int64_t error_index; + idmap_namerule error_rule; + idmap_namerule conflict_rule; +}; + /* Update requests */ enum idmap_opnum { @@ -149,7 +156,7 @@ uint64_t lastrowid, uint64_t limit) = 3; /* Batch of update requests */ - idmap_retcode + idmap_update_res IDMAP_UPDATE(idmap_update_batch batch) = 4; /* Get mapped identity by name */
--- a/usr/src/lib/libidmap/common/idmap_api.c Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/lib/libidmap/common/idmap_api.c Mon Sep 17 08:07:28 2007 -0700 @@ -44,6 +44,7 @@ static struct timeval TIMEOUT = { 25, 0 }; static int idmap_stat2errno(idmap_stat); +static idmap_stat idmap_strdupnull(char **, const char *); #define __ITER_CREATE(itera, argu, handl, ityp)\ if (handl == NULL) {\ @@ -88,6 +89,7 @@ return (IDMAP_ERR_ARG);\ } +#define EMPTY_STRING(str) (str == NULL || *str == '\0') /* * Free memory allocated by libidmap API @@ -202,26 +204,217 @@ idmap_udt_commit(idmap_udt_handle_t *udthandle) { CLIENT *clnt; enum clnt_stat clntstat; - idmap_retcode retcode; + idmap_update_res res; + idmap_stat retcode; if (udthandle == NULL) { errno = EINVAL; return (IDMAP_ERR_ARG); } + + (void) memset(&res, 0, sizeof (res)); + _IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt); clntstat = clnt_call(clnt, IDMAP_UPDATE, (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch, - (xdrproc_t)xdr_idmap_retcode, (caddr_t)&retcode, + (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res, TIMEOUT); + if (clntstat != RPC_SUCCESS) { + retcode = _idmap_rpc2stat(clnt); + goto out; + } + + retcode = udthandle->commit_stat = res.retcode; + udthandle->error_index = res.error_index; + + if (retcode != IDMAP_SUCCESS) { + + if (udthandle->error_index < 0) + goto out; + + retcode = idmap_namerule_cpy(&udthandle->error_rule, + &res.error_rule); + if (retcode != IDMAP_SUCCESS) { + udthandle->error_index = -2; + goto out; + } + + retcode = idmap_namerule_cpy(&udthandle->conflict_rule, + &res.conflict_rule); + if (retcode != IDMAP_SUCCESS) { + udthandle->error_index = -2; + goto out; + } + } + + retcode = res.retcode; + + +out: /* reset handle so that it can be used again */ - _IDMAP_RESET_UDT_HANDLE(udthandle); + if (retcode == IDMAP_SUCCESS) { + _IDMAP_RESET_UDT_HANDLE(udthandle); + } + + (void) xdr_free(xdr_idmap_update_res, (caddr_t)&res); + errno = idmap_stat2errno(retcode); + return (retcode); +} + + +static void +idmap_namerule_parts_clear(char **windomain, char **winname, + char **unixname, boolean_t *is_user, boolean_t *is_nt4, + int *direction) { + if (windomain) + *windomain = NULL; + if (winname) + *winname = NULL; + if (unixname) + *unixname = NULL; + + if (is_nt4) + *is_nt4 = 0; + if (is_user) + *is_user = -1; + if (direction) + *direction = IDMAP_DIRECTION_UNDEF; +} + +static idmap_stat +idmap_namerule2parts(idmap_namerule *rule, + char **windomain, char **winname, + char **unixname, boolean_t *is_user, boolean_t *is_nt4, + int *direction) { + idmap_stat retcode; + + if (EMPTY_STRING(rule->winname) && EMPTY_STRING(rule->unixname)) + return (IDMAP_ERR_NORESULT); + + + retcode = idmap_strdupnull(windomain, rule->windomain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(winname, rule->winname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(unixname, rule->unixname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + + if (is_user) + *is_user = rule->is_user; + if (is_nt4) + *is_nt4 = rule->is_nt4; + if (direction) + *direction = rule->direction; + + + return (IDMAP_SUCCESS); - if (clntstat != RPC_SUCCESS) - return (_idmap_rpc2stat(clnt)); - if (retcode != IDMAP_SUCCESS) - errno = idmap_stat2errno(retcode); +errout: + if (windomain && *windomain) + free(*windomain); + if (winname && *winname) + free(*winname); + if (unixname && *unixname) + free(*unixname); + + idmap_namerule_parts_clear(windomain, winname, + unixname, is_user, is_nt4, direction); + return (retcode); + +} + +/* + * Retrieve the index of the failed batch element. error_index == -1 + * indicates failure at the beginning, -2 at the end. + * + * If idmap_udt_commit didn't return error, the returned value is undefined. + * + * Return value: + * IDMAP_SUCCESS + */ + +idmap_stat +idmap_udt_get_error_index(idmap_udt_handle_t *udthandle, + int64_t *error_index) { + if (error_index) + *error_index = udthandle->error_index; + + return (IDMAP_SUCCESS); +} + + +/* + * Retrieve the rule which caused the batch to fail. If + * idmap_udt_commit didn't return error or if error_index is < 0, the + * retrieved rule is undefined. + * + * Return value: + * IDMAP_ERR_NORESULT if there is no error rule. + * IDMAP_SUCCESS if the rule was obtained OK. + * other error code (IDMAP_ERR_NOMEMORY etc) + */ + +idmap_stat +idmap_udt_get_error_rule(idmap_udt_handle_t *udthandle, + char **windomain, char **winname, + char **unixname, boolean_t *is_user, boolean_t *is_nt4, + int *direction) { + idmap_namerule_parts_clear(windomain, winname, + unixname, is_user, is_nt4, direction); + + if (udthandle->commit_stat == IDMAP_SUCCESS || + udthandle->error_index < 0) + return (IDMAP_ERR_NORESULT); + + return (idmap_namerule2parts( + &udthandle->error_rule, + windomain, + winname, + unixname, + is_user, + is_nt4, + direction)); +} + +/* + * Retrieve the rule with which there was a conflict. TODO: retrieve + * the value. + * + * Return value: + * IDMAP_ERR_NORESULT if there is no error rule. + * IDMAP_SUCCESS if the rule was obtained OK. + * other error code (IDMAP_ERR_NOMEMORY etc) + */ + +idmap_stat +idmap_udt_get_conflict_rule(idmap_udt_handle_t *udthandle, + char **windomain, char **winname, + char **unixname, boolean_t *is_user, boolean_t *is_nt4, + int *direction) { + idmap_namerule_parts_clear(windomain, winname, + unixname, is_user, is_nt4, direction); + + if (udthandle->commit_stat != IDMAP_ERR_W2U_NAMERULE_CONFLICT && + udthandle->commit_stat != IDMAP_ERR_U2W_NAMERULE_CONFLICT) { + return (IDMAP_ERR_NORESULT); + } + + return (idmap_namerule2parts( + &udthandle->conflict_rule, + windomain, + winname, + unixname, + is_user, + is_nt4, + direction)); } @@ -233,6 +426,8 @@ if (udthandle == NULL) return; (void) xdr_free(xdr_idmap_update_batch, (caddr_t)&udthandle->batch); + (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->error_rule); + (void) xdr_free(xdr_idmap_namerule, (caddr_t)&udthandle->conflict_rule); free(udthandle); } @@ -243,7 +438,6 @@ boolean_t is_nt4, int direction) { idmap_retcode retcode; idmap_namerule *rule = NULL; - idmap_utf8str *str; retcode = _udt_extend_batch(udthandle); if (retcode != IDMAP_SUCCESS) @@ -255,24 +449,18 @@ rule->is_user = is_user; rule->direction = direction; rule->is_nt4 = is_nt4; - if (windomain) { - str = &rule->windomain; - retcode = idmap_str2utf8(&str, windomain, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (winname) { - str = &rule->winname; - retcode = idmap_str2utf8(&str, winname, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (unixname) { - str = &rule->unixname; - retcode = idmap_str2utf8(&str, unixname, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } + + retcode = idmap_strdupnull(&rule->windomain, windomain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->winname, winname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->unixname, unixname); + if (retcode != IDMAP_SUCCESS) + goto errout; udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = OP_ADD_NAMERULE; @@ -295,7 +483,6 @@ const char *unixname, int direction) { idmap_retcode retcode; idmap_namerule *rule = NULL; - idmap_utf8str *str; retcode = _udt_extend_batch(udthandle); if (retcode != IDMAP_SUCCESS) @@ -306,24 +493,19 @@ idmap_update_op_u.rule; rule->is_user = is_user; rule->direction = direction; - if (windomain) { - str = &rule->windomain; - retcode = idmap_str2utf8(&str, windomain, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (winname) { - str = &rule->winname; - retcode = idmap_str2utf8(&str, winname, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (unixname) { - str = &rule->unixname; - retcode = idmap_str2utf8(&str, unixname, 0); - if (retcode != IDMAP_SUCCESS) - goto errout; - } + + retcode = idmap_strdupnull(&rule->windomain, windomain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->winname, winname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->unixname, unixname); + if (retcode != IDMAP_SUCCESS) + goto errout; + udthandle->batch.idmap_update_batch_val[udthandle->next].opnum = OP_RM_NAMERULE; udthandle->next++; @@ -398,7 +580,6 @@ idmap_iter_t *tmpiter; idmap_list_namerules_1_argument *arg = NULL; idmap_namerule *rule; - idmap_utf8str *str; idmap_retcode retcode; __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES); @@ -406,30 +587,18 @@ rule = &arg->rule; rule->is_user = is_user; rule->direction = IDMAP_DIRECTION_UNDEF; - if (windomain) { - str = &rule->windomain; - retcode = idmap_str2utf8(&str, windomain, 0); - if (retcode != IDMAP_SUCCESS) { - errno = ENOMEM; - goto errout; - } - } - if (winname) { - str = &rule->winname; - retcode = idmap_str2utf8(&str, winname, 0); - if (retcode != IDMAP_SUCCESS) { - errno = ENOMEM; - goto errout; - } - } - if (unixname) { - str = &rule->unixname; - retcode = idmap_str2utf8(&str, unixname, 0); - if (retcode != IDMAP_SUCCESS) { - errno = ENOMEM; - goto errout; - } - } + + retcode = idmap_strdupnull(&rule->windomain, windomain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->winname, winname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(&rule->unixname, unixname); + if (retcode != IDMAP_SUCCESS) + goto errout; *iter = tmpiter; return (IDMAP_SUCCESS); @@ -515,24 +684,21 @@ return (IDMAP_ERR_ARG); } - if (windomain) { - retcode = idmap_utf82str(windomain, 0, - &namerules->rules.rules_val[iter->next].windomain); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (winname) { - retcode = idmap_utf82str(winname, 0, - &namerules->rules.rules_val[iter->next].winname); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (unixname) { - retcode = idmap_utf82str(unixname, 0, - &namerules->rules.rules_val[iter->next].unixname); - if (retcode != IDMAP_SUCCESS) - goto errout; - } + retcode = idmap_strdupnull(windomain, + namerules->rules.rules_val[iter->next].windomain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(winname, + namerules->rules.rules_val[iter->next].winname); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(unixname, + namerules->rules.rules_val[iter->next].unixname); + if (retcode != IDMAP_SUCCESS) + goto errout; + if (is_nt4) *is_nt4 = namerules->rules.rules_val[iter->next].is_nt4; if (direction) @@ -669,24 +835,23 @@ if (rid) *rid = mappings->mappings.mappings_val[iter->next].id1. idmap_id_u.sid.rid; - if (winname) { - retcode = idmap_utf82str(winname, 0, - &mappings->mappings.mappings_val[iter->next].id1name); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (windomain) { - retcode = idmap_utf82str(windomain, 0, - &mappings->mappings.mappings_val[iter->next].id1domain); - if (retcode != IDMAP_SUCCESS) - goto errout; - } - if (unixname) { - retcode = idmap_utf82str(unixname, 0, - &mappings->mappings.mappings_val[iter->next].id2name); - if (retcode != IDMAP_SUCCESS) - goto errout; - } + + retcode = idmap_strdupnull(windomain, + mappings->mappings.mappings_val[iter->next].id1domain); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(winname, + mappings->mappings.mappings_val[iter->next].id1name); + if (retcode != IDMAP_SUCCESS) + goto errout; + + retcode = idmap_strdupnull(unixname, + mappings->mappings.mappings_val[iter->next].id2name); + if (retcode != IDMAP_SUCCESS) + goto errout; + + if (pid) *pid = mappings->mappings.mappings_val[iter->next].id2. idmap_id_u.uid; @@ -1187,7 +1352,6 @@ idmap_mapping request, *mapping; idmap_mappings_res result; idmap_retcode retcode, rc; - idmap_utf8str *str; if (handle == NULL) { errno = EINVAL; @@ -1214,16 +1378,14 @@ request.id1.idmap_id_u.sid.prefix = (char *)sidprefix; request.id1.idmap_id_u.sid.rid = *rid; } else if (winname) { - str = &request.id1name; - retcode = idmap_str2utf8(&str, winname, 1); - if (retcode != IDMAP_SUCCESS) + retcode = idmap_strdupnull(&request.id1name, winname); + if (retcode != SUCCESS) goto out; - if (windomain) { - str = &request.id1domain; - retcode = idmap_str2utf8(&str, windomain, 1); - if (retcode != IDMAP_SUCCESS) - return (retcode); - } + + retcode = idmap_strdupnull(&request.id1domain, windomain); + if (retcode != SUCCESS) + goto out; + request.id1.idmap_id_u.sid.prefix = NULL; } else { errno = EINVAL; @@ -1266,11 +1428,10 @@ *direction = mapping->direction; if (pid) *pid = mapping->id2.idmap_id_u.uid; - if (unixname) { - rc = idmap_utf82str(unixname, 0, &mapping->id2name); - if (rc != IDMAP_SUCCESS) - retcode = rc; - } + + rc = idmap_strdupnull(unixname, mapping->id2name); + if (rc != IDMAP_SUCCESS) + retcode = rc; out: xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); @@ -1295,7 +1456,6 @@ idmap_mapping request, *mapping; idmap_mappings_res result; idmap_retcode retcode, rc; - idmap_utf8str *str; if (handle == NULL) { errno = EINVAL; @@ -1324,10 +1484,7 @@ if (pid && *pid != UINT32_MAX) { request.id1.idmap_id_u.uid = *pid; } else if (unixname) { - str = &request.id1name; - retcode = idmap_str2utf8(&str, unixname, 1); - if (retcode != IDMAP_SUCCESS) - goto out; + request.id1name = (char *)unixname; request.id1.idmap_id_u.uid = UINT32_MAX; } else { errno = EINVAL; @@ -1364,20 +1521,14 @@ } if (rid) *rid = mapping->id2.idmap_id_u.sid.rid; - if (winname) { - rc = idmap_utf82str(winname, 0, &mapping->id2name); - if (rc != IDMAP_SUCCESS) { - retcode = rc; - goto errout; - } - } - if (windomain) { - rc = idmap_utf82str(windomain, 0, &mapping->id2domain); - if (rc != IDMAP_SUCCESS) { - retcode = rc; - goto errout; - } - } + + rc = idmap_strdupnull(winname, mapping->id2name); + if (rc != IDMAP_SUCCESS) + retcode = rc; + + rc = idmap_strdupnull(windomain, mapping->id2domain); + if (rc != IDMAP_SUCCESS) + retcode = rc; goto out; @@ -1403,94 +1554,6 @@ } -/* - * utf8str to string - */ -idmap_stat -idmap_utf82str(char **out, size_t outsize, idmap_utf8str *in) { - int len; - - if (in == NULL || out == NULL) - return (IDMAP_ERR_ARG); - - if (outsize == 0) { - *out = NULL; - if ((len = in->idmap_utf8str_len) == 0) - return (IDMAP_SUCCESS); - if (in->idmap_utf8str_val == NULL) - return (IDMAP_ERR_ARG); - if (in->idmap_utf8str_val[len - 1] != '\0') - len++; - *out = calloc(1, len); - if (*out == NULL) - return (IDMAP_ERR_MEMORY); - } else { - if (*out == NULL) - return (IDMAP_ERR_ARG); - (void) memset(*out, 0, outsize); - if ((len = in->idmap_utf8str_len) == 0) - return (IDMAP_SUCCESS); - if (in->idmap_utf8str_val == NULL) - return (IDMAP_ERR_ARG); - if (in->idmap_utf8str_val[len - 1] != '\0') - len++; - if (outsize < len) - return (IDMAP_ERR_ARG); - } - (void) memcpy(*out, in->idmap_utf8str_val, in->idmap_utf8str_len); - return (IDMAP_SUCCESS); -} - - -/* - * string to utf8str - */ -idmap_stat -idmap_str2utf8(idmap_utf8str **out, const char *in, int flag) { - idmap_utf8str *tmp; - - if (out == NULL) - return (IDMAP_ERR_ARG); - else if (*out == NULL) { - tmp = malloc(sizeof (idmap_utf8str)); - if (tmp == NULL) - return (IDMAP_ERR_MEMORY); - } else { - tmp = *out; - } - - if (in == NULL) { - tmp->idmap_utf8str_len = 0; - tmp->idmap_utf8str_val = NULL; - if (*out == NULL) - *out = tmp; - return (IDMAP_SUCCESS); - } - - /* include the null terminator */ - tmp->idmap_utf8str_len = strlen(in) + 1; - - if (flag == 1) { - /* Don't malloc, simply assign */ - tmp->idmap_utf8str_val = (char *)in; - if (*out == NULL) - *out = tmp; - return (IDMAP_SUCCESS); - } - - tmp->idmap_utf8str_val = malloc(tmp->idmap_utf8str_len); - if (tmp->idmap_utf8str_val == NULL) { - tmp->idmap_utf8str_len = 0; - if (*out == NULL) - free(tmp); - return (IDMAP_ERR_MEMORY); - } - (void) memcpy(tmp->idmap_utf8str_val, in, tmp->idmap_utf8str_len); - if (*out == NULL) - *out = tmp; - return (IDMAP_SUCCESS); -} - #define gettext(s) s static stat_table_t stattable[] = { @@ -1642,6 +1705,42 @@ /* + * duplicate a string, possibly null + */ +static idmap_stat +idmap_strdupnull(char **to, const char *from) { + if (from == NULL || *from == '\0') { + *to = NULL; + return (IDMAP_SUCCESS); + } + + *to = strdup(from); + if (*to == NULL) + return (IDMAP_ERR_MEMORY); + return (IDMAP_SUCCESS); +} + +idmap_stat +idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) { + idmap_stat retval; + + (void) memcpy(to, from, sizeof (idmap_namerule)); + + retval = idmap_strdupnull(&to->windomain, from->windomain); + if (retval != IDMAP_SUCCESS) + return (retval); + + retval = idmap_strdupnull(&to->winname, from->winname); + if (retval != IDMAP_SUCCESS) + return (retval); + + retval = idmap_strdupnull(&to->unixname, from->unixname); + + return (retval); +} + + +/* * Get uid given Windows name */ idmap_stat
--- a/usr/src/lib/libidmap/common/idmap_impl.h Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/lib/libidmap/common/idmap_impl.h Mon Sep 17 08:07:28 2007 -0700 @@ -61,11 +61,18 @@ struct idmap_handle *ih; idmap_update_batch batch; uint64_t next; + int64_t error_index; + idmap_stat commit_stat; + idmap_namerule error_rule; + idmap_namerule conflict_rule; }; #define _IDMAP_RESET_UDT_HANDLE(uh) \ (void) xdr_free(xdr_idmap_update_batch, (caddr_t)&uh->batch);\ - uh->next = 0; + uh->next = 0;\ + uh->error_index = -1;\ + (void) xdr_free(xdr_idmap_namerule, (caddr_t)&uh->error_rule);\ + (void) xdr_free(xdr_idmap_namerule, (caddr_t)&uh->conflict_rule); typedef struct idmap_get_res { idmap_id_type idtype;
--- a/usr/src/lib/libidmap/common/idmap_priv.h Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/lib/libidmap/common/idmap_priv.h Mon Sep 17 08:07:28 2007 -0700 @@ -69,6 +69,17 @@ /* Commit */ extern idmap_stat idmap_udt_commit(idmap_udt_handle_t *); +/* Get index of the failed batch element */ +extern idmap_stat idmap_udt_get_error_index(idmap_udt_handle_t *, int64_t *); + +/* Get the rule which caused the batch to failed */ +extern idmap_stat idmap_udt_get_error_rule(idmap_udt_handle_t *, char **, + char **, char **, boolean_t *, boolean_t *, int *); + +/* Get the rule which caused a conflict */ +extern idmap_stat idmap_udt_get_conflict_rule(idmap_udt_handle_t *, char **, + char **, char **, boolean_t *, boolean_t *, int *); + /* Destroy the update handle */ extern void idmap_udt_destroy(idmap_udt_handle_t *); @@ -127,18 +138,15 @@ * Miscellaneous */ -/* utf8 to string */ -extern idmap_stat idmap_utf82str(char **, size_t, idmap_utf8str *); - -/* string to utf8 */ -extern idmap_stat idmap_str2utf8(idmap_utf8str **, const char *, int); - /* string to status */ extern idmap_stat idmap_string2stat(const char *); /* internal status to protocol status */ extern idmap_stat idmap_stat4prot(idmap_stat); +/* copy idmap_namerule including strings */ +extern idmap_stat idmap_namerule_cpy(idmap_namerule *, idmap_namerule *); + #ifdef __cplusplus } #endif
--- a/usr/src/lib/libidmap/common/mapfile-vers Mon Sep 17 08:01:53 2007 -0700 +++ b/usr/src/lib/libidmap/common/mapfile-vers Mon Sep 17 08:07:28 2007 -0700 @@ -27,7 +27,6 @@ SUNWprivate { global: - xdr_idmap_utf8str; xdr_idmap_retcode; xdr_idmap_namerule; xdr_idmap_namerules_res; @@ -39,14 +38,13 @@ xdr_idmap_list_namerules_1_argument; xdr_idmap_mapping; xdr_idmap_id_res; + xdr_idmap_update_res; idmap_init; idmap_fini; idmap_free; idmap_stat2string; idmap_string2stat; idmap_stat4prot; - idmap_str2utf8; - idmap_utf82str; idmap_iter_namerules; idmap_iter_next_namerule; idmap_iter_mappings; @@ -67,11 +65,15 @@ idmap_udt_destroy; idmap_udt_commit; idmap_udt_create; + idmap_udt_get_error_index; + idmap_udt_get_error_rule; + idmap_udt_get_conflict_rule; idmap_udt_flush_namerules; idmap_getwinnamebyuid; idmap_getwinnamebygid; idmap_getuidbywinname; idmap_getgidbywinname; + idmap_namerule_cpy; local: *; };