diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/idmap/idmap/idmap.c | 266 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/adutils.c | 78 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/adutils.h | 14 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/dbutils.c | 615 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/idmapd.h | 3 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/rpc_svc.c | 4 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/schema.h | 48 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/server.c | 99 | ||||
-rw-r--r-- | usr/src/head/rpcsvc/idmap_prot.x | 92 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/idmap_api.c | 339 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/idmap_impl.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/idmap_priv.h | 46 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/mapfile-vers | 10 | ||||
-rw-r--r-- | usr/src/uts/common/sys/idmap.h | 3 |
14 files changed, 1436 insertions, 184 deletions
diff --git a/usr/src/cmd/idmap/idmap/idmap.c b/usr/src/cmd/idmap/idmap/idmap.c index 765e07da3f..5ce0db6999 100644 --- a/usr/src/cmd/idmap/idmap/idmap.c +++ b/usr/src/cmd/idmap/idmap/idmap.c @@ -116,6 +116,7 @@ id_code_t identity2code[] = { #define a_FLAG 'a' #define n_FLAG 'n' #define c_FLAG 'c' +#define v_FLAG 'v' /* used in the function do_import */ @@ -237,12 +238,12 @@ static int do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos); static cmd_ops_t commands[] = { { "show", - "c(create)", + "c(create)v(verbose)", do_show_mapping }, { "dump", - "n(names)", + "n(names)v(verbose)", do_dump }, { @@ -404,8 +405,8 @@ help() (void) fprintf(stderr, "idmap\n" "idmap -f command-file\n" - "idmap show [-c] identity [targettype]\n" - "idmap dump [-n]\n" + "idmap show [-c] [-v] identity [targettype]\n" + "idmap dump [-n] [-v]\n" "idmap add [-d] name1 name2\n" "idmap remove -a\n" "idmap remove [-f|-t] name\n" @@ -1231,16 +1232,186 @@ print_mapping(print_handle_t *pnm, name_mapping_t *nm) } +static +void +print_how(idmap_how *how) +{ + idmap_namerule *rule; + name_mapping_t nm; + char *rule_text; + + switch (how->map_type) { + case IDMAP_MAP_TYPE_DS_AD: + (void) printf(gettext("Method:\tAD Directory\n")); + (void) printf(gettext("DN:\t%s\n"), + how->idmap_how_u.ad.dn); + (void) printf(gettext("Attribute:\t%s=%s\n"), + how->idmap_how_u.ad.attr, + how->idmap_how_u.ad.value); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + (void) printf(gettext("Method:\tNative LDAP Directory\n")); + (void) printf(gettext("DN:\t%s\n"), + how->idmap_how_u.nldap.dn); + (void) printf(gettext("Attribute:\t%s=%s\n"), + how->idmap_how_u.nldap.attr, + how->idmap_how_u.nldap.value); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + (void) printf(gettext("Method:\tName Rule\n")); + rule = &how->idmap_how_u.rule; + /* + * The name rules as specified by the user can have a + * "winname", "winuser" or "wingroup". "Winname" rules are + * decomposed to a "winuser" and "wingroup" rules by idmap. + * Currently is_wuser is a boolean. Due to these reasons + * the returned is_wuser does not represent the original rule. + * It is therefore better set is_wuser to unknown. + */ + nm.is_user = rule->is_user; + nm.is_wuser = I_UNKNOWN; + nm.direction = rule->direction; + nm.winname = rule->winname; + nm.windomain = rule->windomain; + nm.unixname = rule->unixname; + nm.is_nt4 = rule->is_nt4; + if (name_mapping_format(&nm, &rule_text) == 0) { + (void) printf(gettext("Rule:\t%s"), rule_text); + free(rule_text); + } + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + (void) printf(gettext("Method:\tEphemeral\n")); + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + (void) printf(gettext("Method:\tLocal SID\n")); + break; + + case IDMAP_MAP_TYPE_KNOWN_SID: + (void) printf(gettext("Method:\tWell-Known mapping\n")); + break; + } +} + + + + + +static +void +print_info(idmap_info *info) +{ + if (info->how.map_type != IDMAP_MAP_TYPE_UNKNOWN) { + switch (info->src) { + case IDMAP_MAP_SRC_NEW: + (void) printf(gettext("Source:\tNew\n")); + break; + + case IDMAP_MAP_SRC_CACHE: + (void) printf(gettext("Source:\tCache\n")); + break; + + case IDMAP_MAP_SRC_HARD_CODED: + (void) printf(gettext("Source:\tHard Coded\n")); + break; + + case IDMAP_MAP_SRC_ALGORITHMIC: + (void) printf(gettext("Source:\tAlgorithmic\n")); + break; + } + print_how(&info->how); + } +} + + +static +void +print_error_info(idmap_info *info) +{ + idmap_how *how = &info->how; + idmap_namerule *rule; + name_mapping_t nm; + char *rule_text; + + switch (how->map_type) { + case IDMAP_MAP_TYPE_DS_AD: + (void) fprintf(stderr, + gettext("Failed Method:\tAD Directory\n")); + (void) fprintf(stderr, gettext("DN:\t%s\n"), + how->idmap_how_u.ad.dn); + (void) fprintf(stderr, gettext("Attribute:\t%s=%s\n"), + how->idmap_how_u.ad.attr, + how->idmap_how_u.ad.value); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + (void) fprintf(stderr, + gettext("Failed Method:\tNative LDAP Directory\n")); + (void) fprintf(stderr, gettext("DN:\t%s\n"), + how->idmap_how_u.nldap.dn); + (void) fprintf(stderr, gettext("Attribute:\t%s=%s\n"), + how->idmap_how_u.nldap.attr, + how->idmap_how_u.nldap.value); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + (void) fprintf(stderr, gettext("Failed Method:\tName Rule\n")); + rule = &how->idmap_how_u.rule; + /* + * The name rules as specified by the user can have a + * "winname", "winuser" or "wingroup". "Winname" rules are + * decomposed to a "winuser" and "wingroup" rules by idmap. + * Currently is_wuser is a boolean. Due to these reasons + * the returned is_wuser does not represent the original rule. + * It is therefore better to set is_wuser to unknown. + */ + nm.is_user = rule->is_user; + nm.is_wuser = I_UNKNOWN; + nm.direction = rule->direction; + nm.winname = rule->winname; + nm.windomain = rule->windomain; + nm.unixname = rule->unixname; + nm.is_nt4 = rule->is_nt4; + if (name_mapping_format(&nm, &rule_text) == 0) { + (void) fprintf(stderr, gettext("Rule:\t%s"), rule_text); + free(rule_text); + } + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + (void) fprintf(stderr, gettext("Failed Method:\tEphemeral\n")); + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + (void) fprintf(stderr, gettext("Failed Method:\tLocal SID\n")); + break; + + case IDMAP_MAP_TYPE_KNOWN_SID: + (void) fprintf(stderr, + gettext("Failed Method:\tWell-Known mapping\n")); + break; + } +} + + + /* dump command handler */ static int /* LINTED E_FUNC_ARG_UNUSED */ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { - idmap_stat stat; - idmap_iter_t *ihandle; - int rc = 0; - boolean_t is_user, is_wuser; - print_handle_t *ph; + idmap_stat stat; + idmap_iter_t *ihandle; + int rc = 0; + boolean_t is_user; + boolean_t is_wuser; + print_handle_t *ph; + int flag = 0; + idmap_info info; if (init_command()) return (-1); @@ -1250,7 +1421,10 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (ph == NULL) return (-1); - stat = idmap_iter_mappings(handle, &ihandle); + if (f[v_FLAG] != NULL) + flag = IDMAP_REQ_FLG_MAPPING_INFO; + + stat = idmap_iter_mappings(handle, &ihandle, flag); if (stat < 0) { print_error(pos, gettext("Iteration handle not obtained (%s)\n"), @@ -1270,14 +1444,16 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) &nm->sidprefix, &nm->rid, &nm->pid, &nm->winname, &nm->windomain, &nm->unixname, &is_user, &is_wuser, - &nm->direction); + &nm->direction, &info); nm->is_user = is_user ? I_YES : I_NO; nm->is_wuser = is_wuser ? I_YES : I_NO; - if (stat >= 0) + if (stat >= 0) { (void) print_mapping(ph, nm); - + (void) print_how(&info.how); + idmap_info_free(&info); + } name_mapping_fini(nm); } while (stat > 0); @@ -2154,7 +2330,7 @@ name2parts(char *name, name_mapping_t *nm, cmd_pos_t *pos) } else { if (code & IS_USER) nm->is_user = I_YES; - else + else if (code & IS_GROUP) nm->is_user = I_NO; } @@ -2545,6 +2721,9 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) name_mapping_t *nm = NULL; char *fromname; char *toname; + idmap_info info; + + (void) memset(&info, 0, sizeof (info)); if (argc == 0) { print_error(pos, @@ -2557,6 +2736,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) } flag = f[c_FLAG] != NULL ? 0 : IDMAP_REQ_FLG_NO_NEW_ID_ALLOC; + flag |= f[v_FLAG] == NULL ? 0 : IDMAP_REQ_FLG_MAPPING_INFO; if (init_command()) return (-1); @@ -2643,7 +2823,8 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) &nm->is_user, &nm->is_wuser, &nm->pid, &nm->unixname, - &nm->direction); + &nm->direction, + &info); } else { map_stat = idmap_get_u2w_mapping(handle, &nm->pid, @@ -2654,7 +2835,8 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) &nm->rid, &nm->winname, &nm->windomain, - &nm->direction); + &nm->direction, + &info); } } else { @@ -2679,40 +2861,45 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) /* Schedule the request: */ if (type_to == TYPE_UID) { - stat = idmap_get_uidbysid(ghandle, + stat = idmap_getext_uidbysid(ghandle, nm->sidprefix, nm->rid, flag, &uid, + &info, &map_stat); } else if (type_to == TYPE_GID) { - stat = idmap_get_gidbysid(ghandle, + stat = idmap_getext_gidbysid(ghandle, nm->sidprefix, nm->rid, flag, &gid, + &info, &map_stat); } else if (type_to == TYPE_PID) { - stat = idmap_get_pidbysid(ghandle, + stat = idmap_getext_pidbysid(ghandle, nm->sidprefix, nm->rid, flag, &nm->pid, &nm->is_user, + &info, &map_stat); } else if (type_from == TYPE_UID) { - stat = idmap_get_sidbyuid(ghandle, + stat = idmap_getext_sidbyuid(ghandle, nm->pid, flag, &nm->sidprefix, &nm->rid, + &info, &map_stat); } else if (type_from == TYPE_GID) { - stat = idmap_get_sidbygid(ghandle, + stat = idmap_getext_sidbygid(ghandle, (gid_t)nm->pid, flag, &nm->sidprefix, &nm->rid, + &info, &map_stat); } else { /* This can never happen: */ @@ -2754,14 +2941,8 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) * If there was -c flag, we do output whatever we can even in * the case of error: */ - if (map_stat < 0) { - print_error(pos, - gettext("%s\n"), - idmap_stat2string(handle, map_stat)); - if (flag == IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) - goto cleanup; - } - + if (map_stat < 0 && flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC) + goto errormsg; /* * idmapd returns fallback uid/gid in case of errors. However @@ -2771,27 +2952,34 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) * 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 ((type_to == TYPE_UID || type_to == TYPE_GID || + type_to == TYPE_PID) && nm->pid == UNDEFINED_UID) + goto errormsg; if (nm2type(nm, type_from, &fromname) < 0) - goto cleanup; + goto errormsg; if (nm2type(nm, type_to, &toname) < 0) { - if (flag == 0) + if (!(flag & IDMAP_REQ_FLG_NO_NEW_ID_ALLOC)) (void) printf("%s -> %s:%u\n", fromname, type_to & IS_GROUP ? ID_GID : ID_UID, UID_NOBODY); free(fromname); - goto cleanup; + } else { + (void) printf("%s -> %s\n", fromname, toname); + free(fromname); + free(toname); } - (void) printf("%s -> %s\n", fromname, toname); - free(fromname); - free(toname); +errormsg: + if (map_stat < 0) { + print_error(pos, gettext("Error:\t%s\n"), + idmap_stat2string(handle, map_stat)); + print_error_info(&info); + } else + print_info(&info); + idmap_info_free(&info); cleanup: if (nm != NULL) diff --git a/usr/src/cmd/idmap/idmapd/adutils.c b/usr/src/cmd/idmap/idmapd/adutils.c index b5c5731810..a66f64c750 100644 --- a/usr/src/cmd/idmap/idmapd/adutils.c +++ b/usr/src/cmd/idmap/idmapd/adutils.c @@ -131,6 +131,9 @@ typedef struct idmap_q { rid_t *rid; /* RID */ int *sid_type; /* user or group SID? */ char **unixname; /* unixname for name mapping */ + char **dn; /* DN of entry */ + char **attr; /* Attr for name mapping */ + char **value; /* value for name mapping */ idmap_retcode *rc; /* lookup state */ @@ -1076,8 +1079,8 @@ idmap_msgid2query(ad_host_t *adh, int msgid, */ static void -idmap_setqresults(idmap_q_t *q, char *san, char *dn, char *sid, - rid_t rid, int sid_type, char *unixname) +idmap_setqresults(idmap_q_t *q, char *san, char *dn, const char *attr, + char *sid, rid_t rid, int sid_type, char *unixname) { char *domain; int err1, err2; @@ -1102,6 +1105,16 @@ idmap_setqresults(idmap_q_t *q, char *san, char *dn, char *sid, goto out; } + /* Copy the DN and attr and value */ + if (q->dn != NULL) + *q->dn = strdup(dn); + + if (q->attr != NULL && attr != NULL) + *q->attr = strdup(attr); + + if (q->value != NULL && unixname != NULL) + *q->value = strdup(unixname); + /* Set results */ if (q->sid) { *q->sid = sid; @@ -1353,6 +1366,7 @@ idmap_extract_object(idmap_query_state_t *state, int qid, LDAPMessage *res) bvalues = ldap_get_values_len(adh->ld, res, attr); unixuser = idmap_bv_name2str(bvalues); has_unixuser = (unixuser != NULL); + } else if (!has_unixgroup && unixgroup_attr != NULL && strcasecmp(attr, unixgroup_attr) == 0) { bvalues = ldap_get_values_len(adh->ld, res, attr); @@ -1389,7 +1403,9 @@ idmap_extract_object(idmap_query_state_t *state, int qid, LDAPMessage *res) * find some attributes that we were looking for. In either * case set the result with what we got. */ - idmap_setqresults(q, san, dn, sid, rid, sid_type, + idmap_setqresults(q, san, dn, + (unixuser != NULL) ? unixuser_attr : unixgroup_attr, + sid, rid, sid_type, (unixuser != NULL) ? unixuser : unixgroup); } @@ -1587,10 +1603,12 @@ idmap_lookup_batch_end(idmap_query_state_t **state) */ static idmap_retcode -idmap_batch_add1(idmap_query_state_t *state, - const char *filter, char *ecanonname, char *edomain, int eunixtype, - char **canonname, char **dname, char **sid, rid_t *rid, - int *sid_type, char **unixname, idmap_retcode *rc) +idmap_batch_add1(idmap_query_state_t *state, const char *filter, + char *ecanonname, char *edomain, int eunixtype, + char **dn, char **attr, char **value, + char **canonname, char **dname, + char **sid, rid_t *rid, int *sid_type, char **unixname, + idmap_retcode *rc) { idmap_retcode retcode = IDMAP_SUCCESS; int lrc, qid, i; @@ -1625,6 +1643,9 @@ idmap_batch_add1(idmap_query_state_t *state, q->sid_type = sid_type; q->rc = rc; q->unixname = unixname; + q->dn = dn; + q->attr = attr; + q->value = value; /* Add unixuser/unixgroup attribute names to the attrs list */ if (unixname != NULL) { @@ -1659,6 +1680,12 @@ idmap_batch_add1(idmap_query_state_t *state, *dname = NULL; if (rid != NULL) *rid = 0; + if (dn != NULL) + *dn = NULL; + if (attr != NULL) + *attr = NULL; + if (value != NULL) + *value = NULL; /* Send this lookup, don't wait for a result here */ (void) pthread_mutex_lock(&state->qadh->lock); @@ -1701,8 +1728,9 @@ idmap_batch_add1(idmap_query_state_t *state, idmap_retcode idmap_name2sid_batch_add1(idmap_query_state_t *state, const char *name, const char *dname, int eunixtype, - char **canonname, char **sid, rid_t *rid, int *sid_type, - char **unixname, idmap_retcode *rc) + char **dn, char **attr, char **value, + char **canonname, char **sid, rid_t *rid, + int *sid_type, char **unixname, idmap_retcode *rc) { idmap_retcode retcode; int len, samAcctNameLen; @@ -1771,7 +1799,8 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state, (void) snprintf(filter, len, SANFILTER, samAcctNameLen, name); retcode = idmap_batch_add1(state, filter, ecanonname, edomain, - eunixtype, canonname, NULL, sid, rid, sid_type, unixname, rc); + eunixtype, dn, attr, value, canonname, NULL, sid, rid, sid_type, + unixname, rc); free(filter); @@ -1781,8 +1810,9 @@ idmap_name2sid_batch_add1(idmap_query_state_t *state, idmap_retcode idmap_sid2name_batch_add1(idmap_query_state_t *state, const char *sid, const rid_t *rid, int eunixtype, - char **name, char **dname, int *sid_type, char **unixname, - idmap_retcode *rc) + char **dn, char **attr, char **value, + char **name, char **dname, int *sid_type, + char **unixname, idmap_retcode *rc) { idmap_retcode retcode; int flen, ret; @@ -1808,7 +1838,7 @@ idmap_sid2name_batch_add1(idmap_query_state_t *state, (void) snprintf(filter, flen, OBJSIDFILTER, cbinsid); retcode = idmap_batch_add1(state, filter, NULL, NULL, eunixtype, - name, dname, NULL, NULL, sid_type, unixname, rc); + dn, attr, value, name, dname, NULL, NULL, sid_type, unixname, rc); free(filter); @@ -1818,8 +1848,9 @@ idmap_sid2name_batch_add1(idmap_query_state_t *state, idmap_retcode idmap_unixname2sid_batch_add1(idmap_query_state_t *state, const char *unixname, int is_user, int is_wuser, - char **sid, rid_t *rid, char **name, char **dname, int *sid_type, - idmap_retcode *rc) + char **dn, char **attr, char **value, + char **sid, rid_t *rid, char **name, + char **dname, int *sid_type, idmap_retcode *rc) { idmap_retcode retcode; int len, ulen; @@ -1842,7 +1873,22 @@ idmap_unixname2sid_batch_add1(idmap_query_state_t *state, is_wuser ? "user" : "group", attrname, ulen, unixname); retcode = idmap_batch_add1(state, filter, NULL, NULL, - _IDMAP_T_UNDEF, name, dname, sid, rid, sid_type, NULL, rc); + _IDMAP_T_UNDEF, dn, NULL, NULL, name, dname, sid, rid, sid_type, + NULL, rc); + + if (retcode == IDMAP_SUCCESS && attr != NULL) { + if ((*attr = strdup(attrname)) == NULL) + retcode = IDMAP_ERR_MEMORY; + } + + if (retcode == IDMAP_SUCCESS && value != NULL) { + if (ulen > 0) { + if ((*value = strdup(unixname)) == NULL) + retcode = IDMAP_ERR_MEMORY; + } + else + *value = NULL; + } free(filter); diff --git a/usr/src/cmd/idmap/idmapd/adutils.h b/usr/src/cmd/idmap/idmapd/adutils.h index 8c27c88983..c81c0a8dab 100644 --- a/usr/src/cmd/idmap/idmapd/adutils.h +++ b/usr/src/cmd/idmap/idmapd/adutils.h @@ -156,8 +156,9 @@ void idmap_lookup_release_batch(idmap_query_state_t **state); */ idmap_retcode idmap_name2sid_batch_add1(idmap_query_state_t *state, const char *name, const char *dname, int eunixtype, - char **canonname, char **sid, rid_t *rid, int *sid_type, - char **unixname, idmap_retcode *rc); + char **dn, char **attr, char **value, char **canonname, + char **sid, rid_t *rid, int *sid_type, char **unixname, + idmap_retcode *rc); /* * Add a SID->name lookup * @@ -174,16 +175,17 @@ idmap_retcode idmap_name2sid_batch_add1(idmap_query_state_t *state, */ idmap_retcode idmap_sid2name_batch_add1(idmap_query_state_t *state, const char *sid, const rid_t *rid, int eunixtype, - char **name, char **dname, int *sid_type, - char **unixname, idmap_retcode *rc); + char **dn, char **attr, char **value, char **name, + char **dname, int *sid_type, char **unixname, + idmap_retcode *rc); /* * Add a unixname->SID lookup */ idmap_retcode idmap_unixname2sid_batch_add1(idmap_query_state_t *state, const char *unixname, int is_user, int is_wuser, - char **sid, rid_t *rid, char **name, char **dname, - int *sid_type, idmap_retcode *rc); + char **dn, char **attr, char **value, char **sid, rid_t *rid, + char **name, char **dname, int *sid_type, idmap_retcode *rc); /* * Set unixname attribute names for the batch for AD-based name mapping diff --git a/usr/src/cmd/idmap/idmapd/dbutils.c b/usr/src/cmd/idmap/idmapd/dbutils.c index 76ac2466b2..d3d6d9c6c4 100644 --- a/usr/src/cmd/idmap/idmapd/dbutils.c +++ b/usr/src/cmd/idmap/idmapd/dbutils.c @@ -457,12 +457,13 @@ get_cache_handle(sqlite **cache) int init_dbs() { - char *sql[2]; + char *sql[4]; int created, upgraded; /* name-based mappings; probably OK to blow away in a pinch(?) */ sql[0] = DB_INSTALL_SQL; sql[1] = DB_UPGRADE_FROM_v1_SQL; + sql[2] = NULL; if (init_db_instance(IDMAP_DBNAME, DB_VERSION, DB_VERSION_SQL, sql, FAIL_IF_CORRUPT, &created, &upgraded) < 0) @@ -471,6 +472,9 @@ init_dbs() /* mappings, name/SID lookup cache + ephemeral IDs; OK to blow away */ sql[0] = CACHE_INSTALL_SQL; sql[1] = CACHE_UPGRADE_FROM_v1_SQL; + sql[2] = CACHE_UPGRADE_FROM_v2_SQL; + sql[3] = NULL; + if (init_db_instance(IDMAP_CACHENAME, CACHE_VERSION, CACHE_VERSION_SQL, sql, REMOVE_IF_CORRUPT, &created, &upgraded) < 0) return (-1); @@ -677,7 +681,7 @@ out: */ idmap_retcode process_list_svc_sql(sqlite *db, const char *dbname, char *sql, uint64_t limit, - list_svc_cb cb, void *result) + int flag, list_svc_cb cb, void *result) { list_cb_data_t cb_data; char *errmsg = NULL; @@ -687,6 +691,7 @@ process_list_svc_sql(sqlite *db, const char *dbname, char *sql, uint64_t limit, (void) memset(&cb_data, 0, sizeof (cb_data)); cb_data.result = result; cb_data.limit = limit; + cb_data.flag = flag; r = sqlite_exec(db, sql, cb, &cb_data, &errmsg); @@ -1112,6 +1117,56 @@ get_ds_namemap_type(lookup_state_t *state) } /* + * Set the rule with sepecified values. + * All the strings are copied. + */ +static void +idmap_namerule_set(idmap_namerule *rule, const char *windomain, + const char *winname, const char *unixname, boolean_t is_user, + boolean_t is_wuser, boolean_t is_nt4, int direction) +{ + /* + * Only update if they differ because we have to free + * and duplicate the strings + */ + if (rule->windomain == NULL || windomain == NULL || + strcmp(rule->windomain, windomain) != 0) { + if (rule->windomain != NULL) { + free(rule->windomain); + rule->windomain = NULL; + } + if (windomain != NULL) + rule->windomain = strdup(windomain); + } + + if (rule->winname == NULL || winname == NULL || + strcmp(rule->winname, winname) != 0) { + if (rule->winname != NULL) { + free(rule->winname); + rule->winname = NULL; + } + if (winname != NULL) + rule->winname = strdup(winname); + } + + if (rule->unixname == NULL || unixname == NULL || + strcmp(rule->unixname, unixname) != 0) { + if (rule->unixname != NULL) { + free(rule->unixname); + rule->unixname = NULL; + } + if (unixname != NULL) + rule->unixname = strdup(unixname); + } + + rule->is_user = is_user; + rule->is_wuser = is_wuser; + rule->is_nt4 = is_nt4; + rule->direction = direction; +} + + +/* * Table for well-known SIDs. * * Background: @@ -1271,18 +1326,33 @@ lookup_wksids_sid2pid(idmap_mapping *req, idmap_id_res *res, int *wksid) continue; res->id.idmap_id_u.uid = wksids[i].pid; res->direction = wksids[i].direction; + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = + IDMAP_MAP_TYPE_KNOWN_SID; + res->info.src = IDMAP_MAP_SRC_HARD_CODED; + } return (IDMAP_SUCCESS); case IDMAP_GID: if (wksids[i].is_user == 1) continue; res->id.idmap_id_u.gid = wksids[i].pid; res->direction = wksids[i].direction; + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = + IDMAP_MAP_TYPE_KNOWN_SID; + res->info.src = IDMAP_MAP_SRC_HARD_CODED; + } return (IDMAP_SUCCESS); case IDMAP_POSIXID: res->id.idmap_id_u.uid = wksids[i].pid; res->id.idtype = (!wksids[i].is_user) ? IDMAP_GID : IDMAP_UID; res->direction = wksids[i].direction; + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = + IDMAP_MAP_TYPE_KNOWN_SID; + res->info.src = IDMAP_MAP_SRC_HARD_CODED; + } return (IDMAP_SUCCESS); default: return (IDMAP_ERR_NOTSUPPORTED); @@ -1315,6 +1385,11 @@ lookup_wksids_pid2sid(idmap_mapping *req, idmap_id_res *res, int is_user) return (IDMAP_ERR_MEMORY); } res->direction = wksids[i].direction; + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = + IDMAP_MAP_TYPE_KNOWN_SID; + res->info.src = IDMAP_MAP_SRC_HARD_CODED; + } return (IDMAP_SUCCESS); } } @@ -1394,9 +1469,12 @@ lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) } /* SQL to lookup the cache */ + if (req->id1.idmap_id_u.sid.prefix != NULL) { sql = sqlite_mprintf("SELECT pid, is_user, expiration, " - "unixname, u2w, is_wuser " + "unixname, u2w, is_wuser, " + "map_type, map_dn, map_attr, map_value, " + "map_windomain, map_winname, map_unixname, map_is_nt4 " "FROM idmap_cache WHERE is_user = %s AND " "sidprefix = %Q AND rid = %u AND w2u = 1 AND " "(pid >= 2147483648 OR " @@ -1408,26 +1486,29 @@ lookup_cache_sid2pid(sqlite *cache, idmap_mapping *req, idmap_id_res *res) if ((lower_name = tolower_u8(req->id1name)) == NULL) lower_name = req->id1name; sql = sqlite_mprintf("SELECT pid, is_user, expiration, " - "unixname, u2w, is_wuser " + "unixname, u2w, is_wuser, " + "map_type, map_dn, map_attr, map_value, " + "map_windomain, map_winname, map_unixname, map_is_nt4 " "FROM idmap_cache WHERE is_user = %s AND " "winname = %Q AND windomain = %Q AND w2u = 1 AND " "(pid >= 2147483648 OR " "(expiration = 0 OR expiration ISNULL OR " "expiration > %d));", - is_user_string, lower_name, req->id1domain, curtime); + is_user_string, lower_name, req->id1domain, + curtime); if (lower_name != req->id1name) free(lower_name); } else { retcode = IDMAP_ERR_ARG; goto out; } - if (sql == NULL) { idmapdlog(LOG_ERR, "Out of memory"); retcode = IDMAP_ERR_MEMORY; goto out; } - retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 6, &values); + retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, + 14, &values); sqlite_freemem(sql); if (retcode == IDMAP_ERR_NOTFOUND) { @@ -1495,6 +1576,58 @@ out: req->id1.idtype = strncmp(values[5], "0", 2) ? IDMAP_USID : IDMAP_GSID; + + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.src = IDMAP_MAP_SRC_CACHE; + res->info.how.map_type = strtoul(values[6], &end, 10); + switch (res->info.how.map_type) { + case IDMAP_MAP_TYPE_DS_AD: + res->info.how.idmap_how_u.ad.dn = + strdup(values[7]); + res->info.how.idmap_how_u.ad.attr = + strdup(values[8]); + res->info.how.idmap_how_u.ad.value = + strdup(values[9]); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + res->info.how.idmap_how_u.nldap.dn = + strdup(values[7]); + res->info.how.idmap_how_u.nldap.attr = + strdup(values[8]); + res->info.how.idmap_how_u.nldap.value = + strdup(values[9]); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + res->info.how.idmap_how_u.rule.windomain = + strdup(values[10]); + res->info.how.idmap_how_u.rule.winname = + strdup(values[11]); + res->info.how.idmap_how_u.rule.unixname = + strdup(values[12]); + res->info.how.idmap_how_u.rule.is_nt4 = + strtoul(values[13], &end, 1); + res->info.how.idmap_how_u.rule.is_user = + is_user; + res->info.how.idmap_how_u.rule.is_wuser = + strtoul(values[5], &end, 1); + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + + case IDMAP_MAP_TYPE_KNOWN_SID: + break; + + default: + /* Unknow mapping type */ + assert(FALSE); + } + } } if (vm != NULL) (void) sqlite_finalize(vm, NULL); @@ -1649,6 +1782,7 @@ ad_lookup_batch(lookup_state_t *state, idmap_mapping_batch *batch, idmap_mapping *req; idmap_id_res *res; idmap_query_state_t *qs = NULL; + idmap_how *how; /* * Since req->id2.idtype is unused, we will use it here @@ -1683,6 +1817,8 @@ retry: for (i = 0, add = 0; i < batch->idmap_mapping_batch_len; i++) { req = &batch->idmap_mapping_batch_val[i]; res = &result->ids.ids_val[i]; + how = &res->info.how; + retcode = IDMAP_SUCCESS; req->id2.idtype = IDMAP_NONE; @@ -1694,6 +1830,11 @@ retry: res->retcode = IDMAP_ERR_RETRIABLE_NET_ERR; else if (res->retcode != IDMAP_ERR_RETRIABLE_NET_ERR) continue; + /* + * Make sure that info is not set as we may be performing + * a retry. + */ + idmap_info_free(&res->info); if (IS_REQUEST_SID(*req, 1)) { /* win to unix */ @@ -1718,9 +1859,14 @@ retry: } } add = 1; + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = idmap_sid2name_batch_add1( qs, req->id1.idmap_id_u.sid.prefix, &req->id1.idmap_id_u.sid.rid, eunixtype, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, (req->id1name == NULL) ? &req->id1name : NULL, (req->id1domain == NULL) ? &req->id1domain : NULL, (int *)&req->id2.idtype, unixname, &res->retcode); @@ -1741,10 +1887,16 @@ retry: * SID to get winname. */ add = 1; + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = idmap_sid2name_batch_add1( qs, res->id.idmap_id_u.sid.prefix, &res->id.idmap_id_u.sid.rid, - _IDMAP_T_UNDEF, &req->id2name, + _IDMAP_T_UNDEF, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, + &req->id2name, &req->id2domain, (int *)&req->id2.idtype, NULL, &res->retcode); } else if (req->id2name != NULL) { @@ -1753,9 +1905,15 @@ retry: * winname to get SID. */ add = 1; + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = idmap_name2sid_batch_add1( qs, req->id2name, req->id2domain, - _IDMAP_T_UNDEF, NULL, + _IDMAP_T_UNDEF, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, + NULL, &res->id.idmap_id_u.sid.prefix, &res->id.idmap_id_u.sid.rid, (int *)&req->id2.idtype, NULL, @@ -1773,8 +1931,13 @@ retry: else is_wuser = is_user; add = 1; + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = idmap_unixname2sid_batch_add1( qs, req->id1name, is_user, is_wuser, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, &res->id.idmap_id_u.sid.prefix, &res->id.idmap_id_u.sid.rid, &req->id2name, &req->id2domain, @@ -1817,6 +1980,7 @@ out: type = req->id2.idtype; req->id2.idtype = IDMAP_NONE; res = &result->ids.ids_val[i]; + how = &res->info.how; if (!(req->direction & _IDMAP_F_LOOKUP_AD)) /* Entry that wasn't marked for AD lookup - skip */ @@ -1831,6 +1995,12 @@ out: continue; + if (res->retcode == IDMAP_ERR_NOTFOUND) { + /* Nothing found - remove the preset info */ + res->info.src = IDMAP_MAP_SRC_UNKNOWN; + how->map_type = IDMAP_MAP_TYPE_UNKNOWN; + } + if (IS_REQUEST_SID(*req, 1)) { if (res->retcode != IDMAP_SUCCESS) continue; @@ -1998,7 +2168,7 @@ sid2pid_first_pass(lookup_state_t *state, sqlite *cache, idmap_mapping *req, goto out; if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { - retcode = IDMAP_ERR_NOMAPPING; + retcode = IDMAP_ERR_NONEGENERATED; goto out; } @@ -2057,7 +2227,8 @@ out: */ static idmap_retcode -generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) +generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user, + int fallback) { free(res->id.idmap_id_u.sid.prefix); res->id.idmap_id_u.sid.prefix = NULL; @@ -2096,6 +2267,11 @@ generate_localsid(idmap_mapping *req, idmap_id_res *res, int is_user) if (res->id.idtype == IDMAP_SID) res->id.idtype = is_user ? IDMAP_USID : IDMAP_GSID; + if (!fallback && req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID; + res->info.src = IDMAP_MAP_SRC_ALGORITHMIC; + } + /* * Don't update name_cache because local sids don't have * valid windows names. @@ -2158,6 +2334,10 @@ lookup_localsid2pid(idmap_mapping *req, idmap_id_res *res) default: return (IDMAP_ERR_NOTSUPPORTED); } + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.how.map_type = IDMAP_MAP_TYPE_LOCAL_SID; + res->info.src = IDMAP_MAP_SRC_ALGORITHMIC; + } return (IDMAP_SUCCESS); } @@ -2307,6 +2487,8 @@ name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) const char **values; sqlite_vm *vm = NULL; int ncol, r, i, is_user, is_wuser; + idmap_namerule *rule = &res->info.how.idmap_how_u.rule; + int direction; const char *me = "name_based_mapping_sid2pid"; assert(req->id1name != NULL); /* We have winname */ @@ -2357,7 +2539,8 @@ name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) if ((lower_winname = tolower_u8(winname)) == NULL) lower_winname = winname; /* hope for the best */ sql = sqlite_mprintf( - "SELECT unixname, u2w_order FROM namerules WHERE " + "SELECT unixname, u2w_order, winname_display, windomain, is_nt4 " + "FROM namerules WHERE " "w2u_order > 0 AND is_user = %d AND is_wuser = %d AND " "(winname = %Q OR winname = '*') AND " "(windomain = %Q OR windomain = '*' %s) " @@ -2378,12 +2561,12 @@ name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) goto out; } - for (; ; ) { + for (;;) { r = sqlite_step(vm, &ncol, &values, NULL); assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); if (r == SQLITE_ROW) { - if (ncol < 2) { + if (ncol < 5) { retcode = IDMAP_ERR_INTERNAL; goto out; } @@ -2392,22 +2575,45 @@ name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) goto out; } + if (values[1] != NULL) + direction = + (strtol(values[1], &end, 10) == 0)? + IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; + else + direction = IDMAP_DIRECTION_W2U; + if (EMPTY_NAME(values[0])) { + idmap_namerule_set(rule, values[3], values[2], + values[0], is_wuser, is_user, + strtol(values[4], &end, 10), + direction); retcode = IDMAP_ERR_NOMAPPING; goto out; } - unixname = (values[0][0] == '*') ? winname : values[0]; - lower_unixname = (values[0][0] == '*') ? - lower_winname : NULL; + + if (values[0][0] == '*') { + unixname = winname; + lower_unixname = lower_winname; + } else { + unixname = values[0]; + lower_unixname = NULL; + } + retcode = ns_lookup_byname(unixname, lower_unixname, &res->id); if (retcode == IDMAP_ERR_NOTFOUND) { - if (unixname == winname) + if (values[0][0] == '*') /* Case 4 */ continue; - else + else { /* Case 3 */ + idmap_namerule_set(rule, values[3], + values[2], values[0], is_wuser, + is_user, + strtol(values[4], &end, 10), + direction); retcode = IDMAP_ERR_NOMAPPING; + } } goto out; } else if (r == SQLITE_DONE) { @@ -2425,7 +2631,9 @@ name_based_mapping_sid2pid(sqlite *db, idmap_mapping *req, idmap_id_res *res) } out: - sqlite_freemem(sql); + if (sql != NULL) + sqlite_freemem(sql); + res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED; if (retcode == IDMAP_SUCCESS) { if (values[1] != NULL) res->direction = @@ -2433,7 +2641,12 @@ out: IDMAP_DIRECTION_W2U:IDMAP_DIRECTION_BI; else res->direction = IDMAP_DIRECTION_W2U; + req->id2name = strdup(unixname); + idmap_namerule_set(rule, values[3], values[2], + values[0], is_wuser, is_user, strtol(values[4], &end, 10), + res->direction); + res->info.src = IDMAP_MAP_SRC_NEW; } if (lower_winname != NULL && lower_winname != winname) free(lower_winname); @@ -2574,13 +2787,18 @@ dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, res->direction = IDMAP_DIRECTION_BI; - if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) + if (IS_EPHEMERAL(res->id.idmap_id_u.uid)) { + res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; + res->info.src = IDMAP_MAP_SRC_CACHE; return (IDMAP_SUCCESS); + } if (state->sid_history != NULL && get_from_sid_history(state, req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, &next_pid)) { res->id.idmap_id_u.uid = next_pid; + res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; + res->info.src = IDMAP_MAP_SRC_NEW; return (IDMAP_SUCCESS); } @@ -2594,6 +2812,8 @@ dynamic_ephemeral_mapping(lookup_state_t *state, sqlite *cache, res->id.idmap_id_u.gid = next_pid; } + res->info.how.map_type = IDMAP_MAP_TYPE_EPHEMERAL; + res->info.src = IDMAP_MAP_SRC_NEW; if (state->sid_history != NULL) add_to_sid_history(state, req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid); @@ -2693,6 +2913,10 @@ sid2pid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, } } + /* Free any mapping info from Directory based mapping */ + if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN) + idmap_info_free(&res->info); + /* * If we don't have unixname then evaluate local name-based * mapping rules. @@ -2721,6 +2945,13 @@ update_cache_pid2sid(lookup_state_t *state, sqlite *cache, { char *sql = NULL; idmap_retcode retcode; + char *map_dn = NULL; + char *map_attr = NULL; + char *map_value = NULL; + char *map_windomain = NULL; + char *map_winname = NULL; + char *map_unixname = NULL; + int map_is_nt4 = FALSE; /* Check if we need to cache anything */ if (ARE_WE_DONE(req->direction)) @@ -2731,6 +2962,40 @@ update_cache_pid2sid(lookup_state_t *state, sqlite *cache, return (IDMAP_SUCCESS); assert(res->direction != IDMAP_DIRECTION_UNDEF); + assert(req->id1.idmap_id_u.uid != SENTINEL_PID); + assert(res->id.idtype != IDMAP_SID); + + assert(res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN); + switch (res->info.how.map_type) { + case IDMAP_MAP_TYPE_DS_AD: + map_dn = res->info.how.idmap_how_u.ad.dn; + map_attr = res->info.how.idmap_how_u.ad.attr; + map_value = res->info.how.idmap_how_u.ad.value; + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + map_dn = res->info.how.idmap_how_u.nldap.dn; + map_attr = res->info.how.idmap_how_u.nldap.attr; + map_value = res->info.how.idmap_how_u.nldap.value; + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + map_windomain = res->info.how.idmap_how_u.rule.windomain; + map_winname = res->info.how.idmap_how_u.rule.winname; + map_unixname = res->info.how.idmap_how_u.rule.unixname; + map_is_nt4 = res->info.how.idmap_how_u.rule.is_nt4; + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + + default: + /* Dont cache other mapping types */ + assert(FALSE); + } /* * Using NULL for u2w instead of 0 so that our trigger allows @@ -2738,14 +3003,19 @@ update_cache_pid2sid(lookup_state_t *state, sqlite *cache, */ sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " "(sidprefix, rid, windomain, canon_winname, pid, unixname, " - "is_user, is_wuser, expiration, w2u, u2w) " + "is_user, is_wuser, expiration, w2u, u2w, " + "map_type, map_dn, map_attr, map_value, map_windomain, " + "map_winname, map_unixname, map_is_nt4) " "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " - "strftime('%%s','now') + 600, %q, 1); ", + "strftime('%%s','now') + 600, %q, 1, " + "%d, %Q, %Q, %Q, %Q, %Q, %Q, %d); ", res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, req->id2domain, req->id2name, req->id1.idmap_id_u.uid, req->id1name, (req->id1.idtype == IDMAP_UID) ? 1 : 0, (res->id.idtype == IDMAP_USID) ? 1 : 0, - (res->direction == 0) ? "1" : NULL); + (res->direction == 0) ? "1" : NULL, + res->info.how.map_type, map_dn, map_attr, map_value, + map_windomain, map_winname, map_unixname, map_is_nt4); if (sql == NULL) { retcode = IDMAP_ERR_INTERNAL; @@ -2784,6 +3054,8 @@ update_cache_pid2sid(lookup_state_t *state, sqlite *cache, retcode = sql_exec_no_cb(cache, IDMAP_CACHENAME, sql); out: + if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO)) + idmap_info_free(&res->info); if (sql != NULL) sqlite_freemem(sql); return (retcode); @@ -2796,6 +3068,13 @@ update_cache_sid2pid(lookup_state_t *state, sqlite *cache, char *sql = NULL; idmap_retcode retcode; int is_eph_user; + char *map_dn = NULL; + char *map_attr = NULL; + char *map_value = NULL; + char *map_windomain = NULL; + char *map_winname = NULL; + char *map_unixname = NULL; + int map_is_nt4 = FALSE; /* Check if we need to cache anything */ if (ARE_WE_DONE(req->direction)) @@ -2835,18 +3114,52 @@ update_cache_sid2pid(lookup_state_t *state, sqlite *cache, } assert(res->direction != IDMAP_DIRECTION_UNDEF); + assert(res->id.idmap_id_u.uid != SENTINEL_PID); + + switch (res->info.how.map_type) { + case IDMAP_MAP_TYPE_DS_AD: + map_dn = res->info.how.idmap_how_u.ad.dn; + map_attr = res->info.how.idmap_how_u.ad.attr; + map_value = res->info.how.idmap_how_u.ad.value; + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + map_dn = res->info.how.idmap_how_u.nldap.dn; + map_attr = res->info.how.idmap_how_u.ad.attr; + map_value = res->info.how.idmap_how_u.nldap.value; + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + map_windomain = res->info.how.idmap_how_u.rule.windomain; + map_winname = res->info.how.idmap_how_u.rule.winname; + map_unixname = res->info.how.idmap_how_u.rule.unixname; + map_is_nt4 = res->info.how.idmap_how_u.rule.is_nt4; + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + default: + /* Dont cache other mapping types */ + assert(FALSE); + } sql = sqlite_mprintf("INSERT OR REPLACE into idmap_cache " "(sidprefix, rid, windomain, canon_winname, pid, unixname, " - "is_user, is_wuser, expiration, w2u, u2w) " + "is_user, is_wuser, expiration, w2u, u2w, " + "map_type, map_dn, map_attr, map_value, map_windomain, " + "map_winname, map_unixname, map_is_nt4) " "VALUES(%Q, %u, %Q, %Q, %u, %Q, %d, %d, " - "strftime('%%s','now') + 600, 1, %q); ", + "strftime('%%s','now') + 600, 1, %q, " + "%d, %Q, %Q, %Q, %Q, %Q, %Q, %d);", req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, (req->id1domain != NULL) ? req->id1domain : "", req->id1name, res->id.idmap_id_u.uid, req->id2name, (res->id.idtype == IDMAP_UID) ? 1 : 0, (req->id1.idtype == IDMAP_USID) ? 1 : 0, - (res->direction == 0) ? "1" : NULL); + (res->direction == 0) ? "1" : NULL, + res->info.how.map_type, map_dn, map_attr, map_value, + map_windomain, map_winname, map_unixname, map_is_nt4); if (sql == NULL) { retcode = IDMAP_ERR_INTERNAL; @@ -2885,6 +3198,9 @@ update_cache_sid2pid(lookup_state_t *state, sqlite *cache, retcode = sql_exec_no_cb(cache, IDMAP_CACHENAME, sql); out: + if (!(req->flag & IDMAP_REQ_FLG_MAPPING_INFO)) + idmap_info_free(&res->info); + if (sql != NULL) sqlite_freemem(sql); return (retcode); @@ -2915,8 +3231,10 @@ lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, /* SQL to lookup the cache by pid or by unixname */ if (req->id1.idmap_id_u.uid != SENTINEL_PID) { - sql = sqlite_mprintf("SELECT sidprefix, rid, canon_winname, " - "windomain, w2u, is_wuser " + sql = sqlite_mprintf("SELECT sidprefix, rid, " + "canon_winname, windomain, w2u, is_wuser, " + "map_type, map_dn, map_attr, map_value, map_windomain, " + "map_winname, map_unixname, map_is_nt4 " "FROM idmap_cache WHERE " "pid = %u AND u2w = 1 AND is_user = %d AND " "(pid >= 2147483648 OR " @@ -2924,14 +3242,19 @@ lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, "expiration > %d));", req->id1.idmap_id_u.uid, is_user, curtime); } else if (req->id1name != NULL) { - sql = sqlite_mprintf("SELECT sidprefix, rid, canon_winname, " - "windomain, w2u, is_wuser " + sql = sqlite_mprintf("SELECT sidprefix, rid, " + "canon_winname, windomain, w2u, is_wuser, " + "map_type, map_dn, map_attr, map_value, map_windomain, " + "map_winname, map_unixname, map_is_nt4 " "FROM idmap_cache WHERE " "unixname = %Q AND u2w = 1 AND is_user = %d AND " "(pid >= 2147483648 OR " "(expiration = 0 OR expiration ISNULL OR " "expiration > %d));", req->id1name, is_user, curtime); + } else { + retcode = IDMAP_ERR_ARG; + goto out; } if (sql == NULL) { @@ -2939,7 +3262,8 @@ lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, retcode = IDMAP_ERR_MEMORY; goto out; } - retcode = sql_compile_n_step_once(cache, sql, &vm, &ncol, 5, &values); + retcode = sql_compile_n_step_once( + cache, sql, &vm, &ncol, 14, &values); sqlite_freemem(sql); if (retcode == IDMAP_ERR_NOTFOUND) @@ -3008,6 +3332,57 @@ lookup_cache_pid2sid(sqlite *cache, idmap_mapping *req, idmap_id_res *res, retcode = IDMAP_ERR_NOTSUPPORTED; break; } + if (req->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + res->info.src = IDMAP_MAP_SRC_CACHE; + res->info.how.map_type = strtoul(values[6], &end, 10); + switch (res->info.how.map_type) { + case IDMAP_MAP_TYPE_DS_AD: + res->info.how.idmap_how_u.ad.dn = + strdup(values[7]); + res->info.how.idmap_how_u.ad.attr = + strdup(values[8]); + res->info.how.idmap_how_u.ad.value = + strdup(values[9]); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + res->info.how.idmap_how_u.nldap.dn = + strdup(values[7]); + res->info.how.idmap_how_u.nldap.attr = + strdup(values[8]); + res->info.how.idmap_how_u.nldap.value = + strdup(values[9]); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + res->info.how.idmap_how_u.rule.windomain = + strdup(values[10]); + res->info.how.idmap_how_u.rule.winname = + strdup(values[11]); + res->info.how.idmap_how_u.rule.unixname = + strdup(values[12]); + res->info.how.idmap_how_u.rule.is_nt4 = + strtoul(values[13], &end, 10); + res->info.how.idmap_how_u.rule.is_user = + is_user; + res->info.how.idmap_how_u.rule.is_wuser = + strtol(values[5], &end, 10); + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + + case IDMAP_MAP_TYPE_KNOWN_SID: + break; + + default: + /* Unknow mapping type */ + assert(FALSE); + } + } } out: @@ -3100,8 +3475,9 @@ static idmap_retcode ad_lookup_by_winname(lookup_state_t *state, const char *name, const char *domain, int eunixtype, - char **canonname, char **sidprefix, - idmap_rid_t *rid, int *wintype, char **unixname) + char **dn, char **attr, char **value, char **canonname, + char **sidprefix, idmap_rid_t *rid, int *wintype, + char **unixname) { int retries = 0; idmap_query_state_t *qs = NULL; @@ -3124,7 +3500,7 @@ retry: state->ad_unixgroup_attr); retcode = idmap_name2sid_batch_add1(qs, name, domain, eunixtype, - canonname, sidprefix, rid, wintype, unixname, &rc); + dn, attr, value, canonname, sidprefix, rid, wintype, unixname, &rc); if (retcode != IDMAP_SUCCESS) idmap_lookup_release_batch(&qs); @@ -3178,7 +3554,7 @@ lookup_name2sid(sqlite *cache, const char *name, const char *domain, /* Lookup AD */ retcode = ad_lookup_by_winname(NULL, name, domain, _IDMAP_T_UNDEF, - canonname, sidprefix, rid, &type, NULL); + NULL, NULL, NULL, canonname, sidprefix, rid, &type, NULL); if (retcode != IDMAP_SUCCESS) return (retcode); /* Don't need to set req->direction |= _IDMAP_F_LOOKUP_AD; */ @@ -3226,9 +3602,12 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, char *end; const char **values; sqlite_vm *vm = NULL; - int ncol, r, nrow; + int ncol, r; int is_wuser; const char *me = "name_based_mapping_pid2sid"; + int non_wild_match = FALSE; + idmap_namerule *rule = &res->info.how.idmap_how_u.rule; + int direction; assert(unixname != NULL); /* We have unixname */ assert(req->id2name == NULL); /* We don't have winname */ @@ -3248,7 +3627,9 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, UNLOCK_CONFIG(); sql = sqlite_mprintf( - "SELECT winname_display, windomain, w2u_order FROM namerules WHERE " + "SELECT winname_display, windomain, w2u_order, " + "is_wuser, unixname, is_nt4 " + "FROM namerules WHERE " "u2w_order > 0 AND is_user = %d AND " "(unixname = %Q OR unixname = '*') " "ORDER BY u2w_order ASC;", is_user, unixname); @@ -3266,12 +3647,11 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, goto out; } - for (nrow = 0; ; ) { + for (;;) { r = sqlite_step(vm, &ncol, &values, NULL); assert(r != SQLITE_LOCKED && r != SQLITE_BUSY); if (r == SQLITE_ROW) { - nrow++; - if (ncol < 3) { + if (ncol < 6) { retcode = IDMAP_ERR_INTERNAL; goto out; } @@ -3280,25 +3660,51 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, retcode = IDMAP_ERR_INTERNAL; goto out; } + + if (values[2] != NULL) + direction = + (strtol(values[2], &end, 10) == 0)? + IDMAP_DIRECTION_U2W:IDMAP_DIRECTION_BI; + else + direction = IDMAP_DIRECTION_U2W; + if (EMPTY_NAME(values[0])) { + idmap_namerule_set(rule, values[1], values[0], + values[4], is_user, + strtol(values[3], &end, 10), + strtol(values[5], &end, 10), + direction); retcode = IDMAP_ERR_NOMAPPING; goto out; } if (values[0][0] == '*') { - if (nrow > 1) { + winname = unixname; + if (non_wild_match) { /* - * There were non-wildcard rules where - * windows identity doesn't exist + * There were non-wildcard rules + * where the Windows identity doesn't + * exist. Return no mapping. */ retcode = IDMAP_ERR_NOMAPPING; goto out; } - winname = unixname; } else { + /* Save first non-wild match rule */ + if (!non_wild_match) { + idmap_namerule_set(rule, values[1], + values[0], values[4], + is_user, + strtol(values[3], &end, 10), + strtol(values[5], &end, 10), + direction); + non_wild_match = TRUE; + } winname = values[0]; } - + is_wuser = res->id.idtype == IDMAP_USID ? 1 + : res->id.idtype == IDMAP_GSID ? 0 + : -1; if (values[1] != NULL) windomain = values[1]; else if (default_domain != NULL) @@ -3308,11 +3714,6 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, retcode = IDMAP_ERR_DOMAIN_NOTFOUND; goto out; } - /* Lookup winname@domain to sid */ - - is_wuser = res->id.idtype == IDMAP_USID ? 1 - : res->id.idtype == IDMAP_GSID ? 0 - : -1; retcode = lookup_name2sid(cache, winname, windomain, &is_wuser, &canonname, @@ -3322,10 +3723,18 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, if (retcode == IDMAP_ERR_NOTFOUND) { continue; } - goto out; + } else if (r == SQLITE_DONE) { - retcode = IDMAP_ERR_NOTFOUND; + /* + * If there were non-wildcard rules where + * Windows identity doesn't exist + * return no mapping. + */ + if (non_wild_match) + retcode = IDMAP_ERR_NOMAPPING; + else + retcode = IDMAP_ERR_NOTFOUND; goto out; } else { (void) sqlite_finalize(vm, &errmsg); @@ -3341,6 +3750,7 @@ name_based_mapping_pid2sid(sqlite *db, sqlite *cache, const char *unixname, out: if (sql != NULL) sqlite_freemem(sql); + res->info.how.map_type = IDMAP_MAP_TYPE_RULE_BASED; if (retcode == IDMAP_SUCCESS) { res->id.idtype = is_wuser ? IDMAP_USID : IDMAP_GSID; @@ -3360,6 +3770,11 @@ out: req->id2domain = strdup(windomain); } } + idmap_namerule_set(rule, values[1], values[0], values[4], + is_user, strtol(values[3], &end, 10), + strtol(values[5], &end, 10), + rule->direction); + res->info.src = IDMAP_MAP_SRC_NEW; } if (vm != NULL) (void) sqlite_finalize(vm, NULL); @@ -3443,6 +3858,15 @@ pid2sid_first_pass(lookup_state_t *state, sqlite *cache, req->id2.idmap_id_u.sid.prefix = NULL; } + /* Find pid */ + if (req->id1.idmap_id_u.uid == SENTINEL_PID) { + if (ns_lookup_byname(req->id1name, NULL, &req->id1) + != IDMAP_SUCCESS) { + retcode = IDMAP_ERR_NOMAPPING; + goto out; + } + } + /* Lookup well-known SIDs table */ retcode = lookup_wksids_pid2sid(req, res, is_user); if (retcode != IDMAP_ERR_NOTFOUND) @@ -3459,7 +3883,12 @@ pid2sid_first_pass(lookup_state_t *state, sqlite *cache, goto out; } - if (DO_NOT_ALLOC_NEW_ID_MAPPING(req) || AVOID_NAMESERVICE(req)) { + if (DO_NOT_ALLOC_NEW_ID_MAPPING(req)) { + retcode = IDMAP_ERR_NONEGENERATED; + goto out; + } + + if (AVOID_NAMESERVICE(req)) { gen_localsid_on_err = TRUE; retcode = IDMAP_ERR_NOMAPPING; goto out; @@ -3503,7 +3932,7 @@ out: res->retcode = idmap_stat4prot(retcode); if (ARE_WE_DONE(req->direction) && res->retcode != IDMAP_SUCCESS) if (gen_localsid_on_err == TRUE) - (void) generate_localsid(req, res, is_user); + (void) generate_localsid(req, res, is_user, TRUE); return (retcode); } @@ -3553,11 +3982,15 @@ pid2sid_second_pass(lookup_state_t *state, sqlite *cache, sqlite *db, } } + /* Free any mapping info from Directory based mapping */ + if (res->info.how.map_type != IDMAP_MAP_TYPE_UNKNOWN) + idmap_info_free(&res->info); + /* Use unixname to evaluate local name-based mapping rules */ retcode = name_based_mapping_pid2sid(db, cache, req->id1name, is_user, req, res); if (retcode == IDMAP_ERR_NOTFOUND) { - retcode = generate_localsid(req, res, is_user); + retcode = generate_localsid(req, res, is_user, FALSE); gen_localsid_on_err = FALSE; } @@ -3566,7 +3999,7 @@ out: if (res->retcode != IDMAP_SUCCESS) { req->direction = _IDMAP_F_DONE; if (gen_localsid_on_err == TRUE) - (void) generate_localsid(req, res, is_user); + (void) generate_localsid(req, res, is_user, TRUE); } if (!ARE_WE_DONE(req->direction)) state->pid2sid_done = FALSE; @@ -3577,7 +4010,8 @@ static idmap_retcode ad_lookup_by_sid(lookup_state_t *state, const char *sidprefix, idmap_rid_t rid, int eunixtype, - char **name, char **domain, int *type, char **unixname) + char **dn, char **attr, char **value, char **name, + char **domain, int *type, char **unixname) { int retries = 0; idmap_query_state_t *qs = NULL; @@ -3599,7 +4033,7 @@ retry: state->ad_unixgroup_attr); retcode = idmap_sid2name_batch_add1(qs, sidprefix, &rid, eunixtype, - name, domain, type, unixname, &rc); + dn, attr, value, name, domain, type, unixname, &rc); if (retcode != IDMAP_SUCCESS) idmap_lookup_release_batch(&qs); @@ -3769,8 +4203,9 @@ get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, */ if (mapping->id1name != NULL && NLDAP_MODE(idres.id.idtype, (&state))) { retcode = nldap_lookup(mapping, &idres, 1, 1); - if (IDMAP_FATAL_ERROR(retcode)) + if (IDMAP_FATAL_ERROR(retcode)) { goto out; + } idres.retcode = IDMAP_SUCCESS; } @@ -3791,6 +4226,11 @@ out: */ mapping->direction = idres.direction; mapping->id2 = idres.id; + if (mapping->flag & IDMAP_REQ_FLG_MAPPING_INFO || + retcode != IDMAP_SUCCESS) + (void) idmap_info_mov(&mapping->info, &idres.info); + else + idmap_info_free(&idres.info); (void) memset(&idres, 0, sizeof (idres)); if (retcode != IDMAP_SUCCESS) mapping->id2.idmap_id_u.uid = UID_NOBODY; @@ -3922,6 +4362,11 @@ out: */ mapping->direction = idres.direction; mapping->id2 = idres.id; + if (mapping->flag & IDMAP_REQ_FLG_MAPPING_INFO || + retcode != IDMAP_SUCCESS) + (void) idmap_info_mov(&mapping->info, &idres.info); + else + idmap_info_free(&idres.info); (void) memset(&idres, 0, sizeof (idres)); xdr_free(xdr_idmap_id_res, (caddr_t)&idres); cleanup_lookup_state(&state); @@ -3932,8 +4377,8 @@ static idmap_retcode ad_lookup_by_unixname(lookup_state_t *state, const char *unixname, int is_user, int is_wuser, - char **sidprefix, idmap_rid_t *rid, char **winname, - char **domain, int *type) + char **dn, char **attr, char **value, char **sidprefix, + idmap_rid_t *rid, char **winname, char **domain, int *type) { /* Lookup AD by unixname */ int retries = 0; @@ -3957,7 +4402,8 @@ retry: state->ad_unixgroup_attr); retcode = idmap_unixname2sid_batch_add1(qs, unixname, is_user, - is_wuser, sidprefix, rid, winname, domain, type, &rc); + is_wuser, dn, attr, value, sidprefix, rid, winname, domain, + type, &rc); if (retcode != IDMAP_SUCCESS) idmap_lookup_release_batch(&qs); @@ -3990,6 +4436,7 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, idmap_retcode retcode; int type, eunixtype, is_user, is_wuser; char *canonname = NULL; + idmap_how *how = &res->info.how; if (w2u) { /* @@ -4009,9 +4456,14 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, if (req->id1.idmap_id_u.sid.prefix != NULL) { /* AD lookup by sid */ + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = ad_lookup_by_sid( state, req->id1.idmap_id_u.sid.prefix, req->id1.idmap_id_u.sid.rid, eunixtype, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, (req->id1name == NULL) ? &req->id1name : NULL, (req->id1domain == NULL) ? &req->id1domain : NULL, &type, (getunixattr && req->id2name == NULL) @@ -4019,9 +4471,15 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, } else { assert(req->id1name != NULL); /* AD lookup by winname */ + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = ad_lookup_by_winname( state, req->id1name, req->id1domain, eunixtype, - &canonname, &req->id1.idmap_id_u.sid.prefix, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, + &canonname, + &req->id1.idmap_id_u.sid.prefix, &req->id1.idmap_id_u.sid.rid, &type, (getunixattr && req->id2name == NULL) ? &req->id2name : NULL); @@ -4046,6 +4504,10 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, default: return (IDMAP_ERR_SID); } + } else if (retcode == IDMAP_ERR_NOTFOUND) { + /* Nothing found - remove the preset info */ + res->info.src = IDMAP_MAP_SRC_UNKNOWN; + how->map_type = IDMAP_MAP_TYPE_UNKNOWN; } return (retcode); } @@ -4069,30 +4531,45 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, is_wuser = 0; else is_wuser = is_user; + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = ad_lookup_by_unixname( state, req->id1name, is_user, is_wuser, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, (res->id.idmap_id_u.sid.prefix == NULL) ? &res->id.idmap_id_u.sid.prefix : NULL, (res->id.idmap_id_u.sid.prefix == NULL) ? &res->id.idmap_id_u.sid.rid : NULL, (req->id2name == NULL) ? &req->id2name : NULL, - (req->id2domain == NULL) ? &req->id2domain : NULL, NULL); + (req->id2domain == NULL) ? &req->id2domain : NULL, &type); } else if (res->id.idmap_id_u.sid.prefix != NULL) { /* AD lookup by sid */ + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = ad_lookup_by_sid( state, res->id.idmap_id_u.sid.prefix, res->id.idmap_id_u.sid.rid, eunixtype, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, (req->id2name == NULL) ? &req->id2name : NULL, (req->id2domain == NULL) ? &req->id2domain : NULL, - NULL, (getunixattr && req->id1name == NULL) + &type, (getunixattr && req->id1name == NULL) ? &req->id1name : NULL); } else { /* AD lookup by winname */ assert(req->id2name != NULL); + res->info.src = IDMAP_MAP_SRC_NEW; + how->map_type = IDMAP_MAP_TYPE_DS_AD; retcode = ad_lookup_by_winname( state, req->id2name, req->id2domain, eunixtype, + &how->idmap_how_u.ad.dn, + &how->idmap_how_u.ad.attr, + &how->idmap_how_u.ad.value, &canonname, &res->id.idmap_id_u.sid.prefix, - &res->id.idmap_id_u.sid.rid, NULL, + &res->id.idmap_id_u.sid.rid, &type, (getunixattr && req->id1name == NULL) ? &req->id1name : NULL); @@ -4115,6 +4592,10 @@ ad_lookup(lookup_state_t *state, idmap_mapping *req, idmap_id_res *res, default: return (IDMAP_ERR_SID); } + } else if (retcode == IDMAP_ERR_NOTFOUND) { + /* Nothing found - remove the preset info */ + res->info.src = IDMAP_MAP_SRC_UNKNOWN; + how->map_type = IDMAP_MAP_TYPE_UNKNOWN; } return (retcode); } diff --git a/usr/src/cmd/idmap/idmapd/idmapd.h b/usr/src/cmd/idmap/idmapd/idmapd.h index 5acb7a6a69..7404a6b408 100644 --- a/usr/src/cmd/idmap/idmapd/idmapd.h +++ b/usr/src/cmd/idmap/idmapd/idmapd.h @@ -140,6 +140,7 @@ typedef struct list_cb_data { uint64_t next; uint64_t len; uint64_t limit; + int flag; } list_cb_data_t; typedef struct msg_table { @@ -244,7 +245,7 @@ extern idmap_retcode gen_sql_expr_from_rule(idmap_namerule *, char **); extern idmap_retcode validate_list_cb_data(list_cb_data_t *, int, char **, int, uchar_t **, size_t); extern idmap_retcode process_list_svc_sql(sqlite *, const char *, char *, - uint64_t, list_svc_cb, void *); + uint64_t, int, list_svc_cb, void *); extern idmap_retcode sid2pid_first_pass(lookup_state_t *, sqlite *, idmap_mapping *, idmap_id_res *); extern idmap_retcode sid2pid_second_pass(lookup_state_t *, sqlite *, diff --git a/usr/src/cmd/idmap/idmapd/rpc_svc.c b/usr/src/cmd/idmap/idmapd/rpc_svc.c index 5a2862f338..4ce49667d4 100644 --- a/usr/src/cmd/idmap/idmapd/rpc_svc.c +++ b/usr/src/cmd/idmap/idmapd/rpc_svc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,7 +60,7 @@ _idmap_list_mappings_1(idmap_list_mappings_1_argument *argp, idmap_mappings_res *result, struct svc_req *rqstp) { return (idmap_list_mappings_1_svc(argp->lastrowid, - argp->limit, result, rqstp)); + argp->limit, argp->flag, result, rqstp)); } int diff --git a/usr/src/cmd/idmap/idmapd/schema.h b/usr/src/cmd/idmap/idmapd/schema.h index eec0a4b8d5..50602bd9be 100644 --- a/usr/src/cmd/idmap/idmapd/schema.h +++ b/usr/src/cmd/idmap/idmapd/schema.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -105,6 +105,23 @@ extern "C" { " expiration INTEGER" \ ")" +#define TABLE_IDMAP_CACHE_v2 \ + "CREATE TABLE idmap_cache " \ + "(" \ + " sidprefix TEXT," \ + " rid INTEGER," \ + " windomain TEXT," \ + " canon_winname TEXT," \ + " winname TEXT," \ + " pid INTEGER," \ + " unixname TEXT," \ + " is_user INTEGER," \ + " is_wuser INTEGER," \ + " w2u INTEGER," \ + " u2w INTEGER," \ + " expiration INTEGER" \ + ")" + #define TABLE_IDMAP_CACHE \ "CREATE TABLE idmap_cache " \ "(" \ @@ -119,6 +136,14 @@ extern "C" { " is_wuser INTEGER," \ " w2u INTEGER," \ " u2w INTEGER," \ + " map_type INTEGER," \ + " map_dn TEXT, "\ + " map_attr TEXT, "\ + " map_value TEXT, "\ + " map_windomain TEXT, "\ + " map_winname TEXT, "\ + " map_unixname TEXT, "\ + " map_is_nt4 INTEGER, "\ " expiration INTEGER" \ ")" @@ -217,6 +242,18 @@ extern "C" { "sql = '" INDEX_NAME_CACHE_SID "') " \ "WHEN 5 THEN 1 ELSE " \ "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ + "sql = '" TABLE_IDMAP_CACHE_v2"' OR " \ + "sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \ + "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \ + "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \ + "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \ + "sql = '" TABLE_NAME_CACHE "' OR " \ + "sql = '" INDEX_NAME_CACHE_SID "' OR " \ + "sql = '" INDEX_NAME_CACHE_NAME "' OR " \ + "sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \ + "sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \ + "WHEN 10 THEN 2 ELSE " \ + "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ "sql = '" TABLE_IDMAP_CACHE"' OR " \ "sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \ "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \ @@ -227,14 +264,19 @@ extern "C" { "sql = '" INDEX_NAME_CACHE_NAME "' OR " \ "sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \ "sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \ - "WHEN 10 THEN 2 ELSE -1 END) END) END AS version;" + "WHEN 10 THEN 3 ELSE -1 END) END) END) END AS version;" #define CACHE_UPGRADE_FROM_v1_SQL \ "DROP TABLE idmap_cache;" \ "DROP TABLE name_cache;" \ CACHE_INSTALL_SQL -#define CACHE_VERSION 2 +#define CACHE_UPGRADE_FROM_v2_SQL \ + "DROP TABLE idmap_cache;" \ + "DROP TABLE name_cache;" \ + CACHE_INSTALL_SQL + +#define CACHE_VERSION 3 #define TABLE_NAMERULES_v1 \ diff --git a/usr/src/cmd/idmap/idmapd/server.c b/usr/src/cmd/idmap/idmapd/server.c index 3d9fecd4f3..de0776aafa 100644 --- a/usr/src/cmd/idmap/idmapd/server.c +++ b/usr/src/cmd/idmap/idmapd/server.c @@ -57,8 +57,8 @@ return (1);\ } -#define PROCESS_LIST_SVC_SQL(rcode, db, dbname, sql, limit, cb, res, len)\ - rcode = process_list_svc_sql(db, dbname, sql, limit, cb, res);\ +#define PROCESS_LIST_SVC_SQL(rcode, db, dbname, sql, limit, flag, cb, res, len)\ + rcode = process_list_svc_sql(db, dbname, sql, limit, flag, cb, res);\ if (rcode == IDMAP_ERR_BUSY)\ res->retcode = IDMAP_ERR_BUSY;\ else if (rcode == IDMAP_SUCCESS && len == 0)\ @@ -404,6 +404,9 @@ list_mappings_cb(void *parg, int argc, char **argv, char **colnames) int w2u, u2w; char *end; static int validated_column_names = 0; + idmap_how *how; + + cb_data = (list_cb_data_t *)parg; if (!validated_column_names) { assert(strcmp(colnames[0], "rowid") == 0); @@ -417,14 +420,20 @@ list_mappings_cb(void *parg, int argc, char **argv, char **colnames) assert(strcmp(colnames[8], "unixname") == 0); assert(strcmp(colnames[9], "is_user") == 0); assert(strcmp(colnames[10], "is_wuser") == 0); + assert(strcmp(colnames[11], "map_type") == 0); + assert(strcmp(colnames[12], "map_dn") == 0); + assert(strcmp(colnames[13], "map_attr") == 0); + assert(strcmp(colnames[14], "map_value") == 0); + assert(strcmp(colnames[15], "map_windomain") == 0); + assert(strcmp(colnames[16], "map_winname") == 0); + assert(strcmp(colnames[17], "map_unixname") == 0); + assert(strcmp(colnames[18], "map_is_nt4") == 0); validated_column_names = 1; } - - cb_data = (list_cb_data_t *)parg; result = (idmap_mappings_res *)cb_data->result; - _VALIDATE_LIST_CB_DATA(11, &result->mappings.mappings_val, + _VALIDATE_LIST_CB_DATA(19, &result->mappings.mappings_val, sizeof (idmap_mapping)); result->mappings.mappings_len++; @@ -465,6 +474,55 @@ list_mappings_cb(void *parg, int argc, char **argv, char **colnames) STRDUP_OR_FAIL(result->mappings.mappings_val[cb_data->next].id2name, argv[8]); + if (cb_data->flag & IDMAP_REQ_FLG_MAPPING_INFO) { + how = &result->mappings.mappings_val[cb_data->next].info.how; + how->map_type = strtoul(argv[11], &end, 10); + switch (how->map_type) { + case IDMAP_MAP_TYPE_DS_AD: + how->idmap_how_u.ad.dn = + strdup(argv[12]); + how->idmap_how_u.ad.attr = + strdup(argv[13]); + how->idmap_how_u.ad.value = + strdup(argv[14]); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + how->idmap_how_u.nldap.dn = + strdup(argv[12]); + how->idmap_how_u.nldap.attr = + strdup(argv[13]); + how->idmap_how_u.nldap.value = + strdup(argv[14]); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + how->idmap_how_u.rule.windomain = + strdup(argv[15]); + how->idmap_how_u.rule.winname = + strdup(argv[16]); + how->idmap_how_u.rule.unixname = + strdup(argv[17]); + how->idmap_how_u.rule.is_nt4 = + strtoul(argv[18], &end, 10); + how->idmap_how_u.rule.is_user = + strtol(argv[9], &end, 10); + how->idmap_how_u.rule.is_wuser = + strtol(argv[10], &end, 10); + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + + default: + /* Unknow mapping type */ + assert(FALSE); + } + + } result->lastrowid = strtoll(argv[0], &end, 10); cb_data->next++; @@ -475,7 +533,7 @@ list_mappings_cb(void *parg, int argc, char **argv, char **colnames) /* ARGSUSED */ bool_t -idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, +idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, int32_t flag, idmap_mappings_res *result, struct svc_req *rqstp) { sqlite *cache = NULL; @@ -483,10 +541,20 @@ idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, uint64_t maxlimit; idmap_retcode retcode; char *sql = NULL; + time_t curtime; (void) memset(result, 0, sizeof (*result)); lbuf[0] = rbuf[0] = 0; + /* Current time */ + errno = 0; + if ((curtime = time(NULL)) == (time_t)-1) { + idmapdlog(LOG_ERR, "Failed to get current time (%s)", + strerror(errno)); + retcode = IDMAP_ERR_INTERNAL; + goto out; + } + RDLOCK_CONFIG(); maxlimit = _idmapdstate.cfg->pgcfg.list_size_limit; UNLOCK_CONFIG(); @@ -511,11 +579,16 @@ idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, * Combine all the above into a giant SELECT statement that * will return the requested mappings */ - sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, u2w, " - "windomain, canon_winname, unixname, is_user, is_wuser " - " FROM idmap_cache WHERE " - " %s %s;", - rbuf, lbuf); + + sql = sqlite_mprintf("SELECT rowid, sidprefix, rid, pid, w2u, " + "u2w, windomain, canon_winname, unixname, is_user, is_wuser, " + "map_type, map_dn, map_attr, map_value, map_windomain, " + "map_winname, map_unixname, map_is_nt4 " + "FROM idmap_cache WHERE %s AND " + "(pid >= 2147483648 OR (expiration = 0 OR " + "expiration ISNULL OR expiration > %d)) " + "%s;", + rbuf, curtime, lbuf); if (sql == NULL) { idmapdlog(LOG_ERR, "Out of memory"); goto out; @@ -523,7 +596,7 @@ idmap_list_mappings_1_svc(int64_t lastrowid, uint64_t limit, /* Execute the SQL statement and update the return buffer */ PROCESS_LIST_SVC_SQL(retcode, cache, IDMAP_CACHENAME, sql, limit, - list_mappings_cb, result, result->mappings.mappings_len); + flag, list_mappings_cb, result, result->mappings.mappings_len); out: if (sql) @@ -683,7 +756,7 @@ idmap_list_namerules_1_svc(idmap_namerule rule, uint64_t lastrowid, /* Execute the SQL statement and update the return buffer */ PROCESS_LIST_SVC_SQL(retcode, db, IDMAP_DBNAME, sql, limit, - list_namerules_cb, result, result->rules.rules_len); + 0, list_namerules_cb, result, result->rules.rules_len); out: if (expr) diff --git a/usr/src/head/rpcsvc/idmap_prot.x b/usr/src/head/rpcsvc/idmap_prot.x index c0bc59f8f8..fd5dad089d 100644 --- a/usr/src/head/rpcsvc/idmap_prot.x +++ b/usr/src/head/rpcsvc/idmap_prot.x @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,6 +42,28 @@ enum idmap_id_type { IDMAP_POSIXID }; +/* The type of ID mapping */ +enum idmap_map_type { + IDMAP_MAP_TYPE_UNKNOWN = 0, + IDMAP_MAP_TYPE_DS_AD, + IDMAP_MAP_TYPE_DS_NLDAP, + IDMAP_MAP_TYPE_RULE_BASED, + IDMAP_MAP_TYPE_EPHEMERAL, + IDMAP_MAP_TYPE_LOCAL_SID, + IDMAP_MAP_TYPE_KNOWN_SID +}; + + +/* Source of ID mapping */ +enum idmap_map_src { + IDMAP_MAP_SRC_UNKNOWN = 0, + IDMAP_MAP_SRC_NEW, + IDMAP_MAP_SRC_CACHE, + IDMAP_MAP_SRC_HARD_CODED, + IDMAP_MAP_SRC_ALGORITHMIC +}; + + /* SID */ struct idmap_sid { string prefix<>; @@ -58,10 +80,52 @@ union idmap_id switch(idmap_id_type idtype) { case IDMAP_NONE: void; case IDMAP_POSIXID: void; }; + + +/* Name-based mapping rules */ +struct idmap_namerule { + bool is_user; + bool is_wuser; + int direction; + idmap_utf8str windomain; + idmap_utf8str winname; + idmap_utf8str unixname; + bool is_nt4; +}; +struct idmap_namerules_res { + idmap_retcode retcode; + uint64_t lastrowid; + idmap_namerule rules<>; +}; + +/* How ID is mapped */ +struct idmap_how_ds_based { + idmap_utf8str dn; + idmap_utf8str attr; + idmap_utf8str value; +}; + +union idmap_how switch(idmap_map_type map_type) { + case IDMAP_MAP_TYPE_UNKNOWN: void; + case IDMAP_MAP_TYPE_DS_AD: idmap_how_ds_based ad; + case IDMAP_MAP_TYPE_DS_NLDAP: idmap_how_ds_based nldap; + case IDMAP_MAP_TYPE_RULE_BASED: idmap_namerule rule; + case IDMAP_MAP_TYPE_EPHEMERAL: void; + case IDMAP_MAP_TYPE_LOCAL_SID: void; +}; + +struct idmap_info { + idmap_map_src src; + idmap_how how; +}; + + +/* Id result */ struct idmap_id_res { idmap_retcode retcode; idmap_id id; int direction; + idmap_info info; }; struct idmap_ids_res { idmap_retcode retcode; @@ -78,6 +142,8 @@ const IDMAP_REQ_FLG_NO_NEW_ID_ALLOC = 0x00000001; const IDMAP_REQ_FLG_VALIDATE = 0x00000002; /* Avoid name service lookups to prevent looping */ const IDMAP_REQ_FLG_NO_NAMESERVICE = 0x00000004; +/* Request how a mapping was formed */ +const IDMAP_REQ_FLG_MAPPING_INFO = 0x00000008; /* Identity mappings (sid-posix) */ struct idmap_mapping { @@ -89,31 +155,19 @@ struct idmap_mapping { idmap_id id2; idmap_utf8str id2domain; idmap_utf8str id2name; + idmap_info info; }; + +typedef idmap_mapping idmap_mapping_batch<>; + struct idmap_mappings_res { idmap_retcode retcode; uint64_t lastrowid; idmap_mapping mappings<>; }; -typedef idmap_mapping idmap_mapping_batch<>; - -/* Name-based mapping rules */ -struct idmap_namerule { - bool is_user; - bool is_wuser; - int direction; - idmap_utf8str windomain; - idmap_utf8str winname; - idmap_utf8str unixname; - bool is_nt4; -}; -struct idmap_namerules_res { - idmap_retcode retcode; - uint64_t lastrowid; - idmap_namerule rules<>; -}; +/* Update result */ struct idmap_update_res { idmap_retcode retcode; int64_t error_index; @@ -151,7 +205,7 @@ program IDMAP_PROG { /* List all identity mappings */ idmap_mappings_res IDMAP_LIST_MAPPINGS(int64_t lastrowid, - uint64_t limit) = 2; + uint64_t limit, int32_t flag) = 2; /* List all name-based mapping rules */ idmap_namerules_res diff --git a/usr/src/lib/libidmap/common/idmap_api.c b/usr/src/lib/libidmap/common/idmap_api.c index 5dfeb56116..2dc063f804 100644 --- a/usr/src/lib/libidmap/common/idmap_api.c +++ b/usr/src/lib/libidmap/common/idmap_api.c @@ -783,13 +783,14 @@ errout: * iter - iterator */ idmap_stat -idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter) +idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag) { idmap_iter_t *tmpiter; idmap_list_mappings_1_argument *arg = NULL; __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS); + arg->flag = flag; *iter = tmpiter; return (IDMAP_SUCCESS); } @@ -814,7 +815,7 @@ idmap_stat idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix, idmap_rid_t *rid, uid_t *pid, char **winname, char **windomain, char **unixname, boolean_t *is_user, - boolean_t *is_wuser, int *direction) + boolean_t *is_wuser, int *direction, idmap_info *info) { idmap_mappings_res *mappings; idmap_list_mappings_1_argument *arg; @@ -922,6 +923,12 @@ idmap_iter_next_mapping(idmap_iter_t *iter, char **sidprefix, *is_wuser = (mappings->mappings.mappings_val[iter->next].id1 .idtype == IDMAP_USID)?1:0; + if (info) { + retcode = idmap_info_cpy(info, + &mappings->mappings.mappings_val[iter->next].info); + if (retcode != IDMAP_SUCCESS) + goto errout; + } iter->next++; if (iter->next == mappings->mappings.mappings_len) @@ -1026,7 +1033,30 @@ idmap_stat idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, int flag, uid_t *uid, idmap_stat *stat) { + return (idmap_getext_uidbysid(gh, sidprefix, rid, flag, uid, + NULL, stat)); +} + +/* + * Given SID, get UID + * + * Input: + * sidprefix - SID prefix + * rid - RID + * flag - flag + * + * Output: + * stat - status of the get request + * uid - POSIX UID if stat = 0 + * how - mapping type if stat = 0 + * + * Note: The output parameters will be set by idmap_get_mappings() + */ +idmap_stat +idmap_getext_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, + int flag, uid_t *uid, idmap_info *info, idmap_stat *stat) +{ idmap_retcode retcode; idmap_mapping *mapping = NULL; @@ -1055,6 +1085,7 @@ idmap_get_uidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, gh->retlist[gh->next].idtype = IDMAP_UID; gh->retlist[gh->next].uid = uid; gh->retlist[gh->next].stat = stat; + gh->retlist[gh->next].info = info; gh->next++; return (IDMAP_SUCCESS); @@ -1086,6 +1117,30 @@ idmap_stat idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, int flag, gid_t *gid, idmap_stat *stat) { + return (idmap_getext_gidbysid(gh, sidprefix, rid, flag, gid, + NULL, stat)); +} + + +/* + * Given SID, get GID + * + * Input: + * sidprefix - SID prefix + * rid - rid + * flag - flag + * + * Output: + * stat - status of the get request + * gid - POSIX GID if stat = 0 + * how - mapping type if stat = 0 + * + * Note: The output parameters will be set by idmap_get_mappings() + */ +idmap_stat +idmap_getext_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, + int flag, gid_t *gid, idmap_info *info, idmap_stat *stat) +{ idmap_retcode retcode; idmap_mapping *mapping = NULL; @@ -1115,6 +1170,7 @@ idmap_get_gidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, gh->retlist[gh->next].idtype = IDMAP_GID; gh->retlist[gh->next].gid = gid; gh->retlist[gh->next].stat = stat; + gh->retlist[gh->next].info = info; gh->next++; return (IDMAP_SUCCESS); @@ -1127,6 +1183,7 @@ errout: } + /* * Given SID, get POSIX ID i.e. UID/GID * @@ -1147,6 +1204,33 @@ idmap_stat idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, int flag, uid_t *pid, int *is_user, idmap_stat *stat) { + return (idmap_getext_pidbysid(gh, sidprefix, rid, flag, pid, is_user, + NULL, stat)); +} + + + +/* + * Given SID, get POSIX ID i.e. UID/GID + * + * Input: + * sidprefix - SID prefix + * rid - rid + * flag - flag + * + * Output: + * stat - status of the get request + * is_user - user or group + * pid - POSIX UID if stat = 0 and is_user = 1 + * POSIX GID if stat = 0 and is_user = 0 + * how - mapping type if stat = 0 + * + * Note: The output parameters will be set by idmap_get_mappings() + */ +idmap_stat +idmap_getext_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, + int flag, uid_t *pid, int *is_user, idmap_info *info, idmap_stat *stat) +{ idmap_retcode retcode; idmap_mapping *mapping = NULL; @@ -1177,6 +1261,7 @@ idmap_get_pidbysid(idmap_get_handle_t *gh, char *sidprefix, idmap_rid_t rid, gh->retlist[gh->next].gid = pid; gh->retlist[gh->next].is_user = is_user; gh->retlist[gh->next].stat = stat; + gh->retlist[gh->next].info = info; gh->next++; return (IDMAP_SUCCESS); @@ -1207,6 +1292,30 @@ idmap_stat idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) { + return (idmap_getext_sidbyuid(gh, uid, flag, sidprefix, rid, + NULL, stat)); +} + + +/* + * Given UID, get SID + * + * Input: + * uid - POSIX UID + * flag - flag + * + * Output: + * stat - status of the get request + * sid - SID prefix (if stat == 0) + * rid - rid + * how - mapping type if stat = 0 + * + * Note: The output parameters will be set by idmap_get_mappings() + */ +idmap_stat +idmap_getext_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, + char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) +{ idmap_retcode retcode; idmap_mapping *mapping = NULL; @@ -1233,6 +1342,7 @@ idmap_get_sidbyuid(idmap_get_handle_t *gh, uid_t uid, int flag, gh->retlist[gh->next].sidprefix = sidprefix; gh->retlist[gh->next].rid = rid; gh->retlist[gh->next].stat = stat; + gh->retlist[gh->next].info = info; gh->next++; return (IDMAP_SUCCESS); @@ -1263,6 +1373,30 @@ idmap_stat idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, char **sidprefix, idmap_rid_t *rid, idmap_stat *stat) { + return (idmap_getext_sidbygid(gh, gid, flag, sidprefix, rid, + NULL, stat)); +} + + +/* + * Given GID, get SID + * + * Input: + * gid - POSIX GID + * flag - flag + * + * Output: + * stat - status of the get request + * sidprefix - SID prefix (if stat == 0) + * rid - rid + * how - mapping type if stat = 0 + * + * Note: The output parameters will be set by idmap_get_mappings() + */ +idmap_stat +idmap_getext_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, + char **sidprefix, idmap_rid_t *rid, idmap_info *info, idmap_stat *stat) +{ idmap_retcode retcode; idmap_mapping *mapping = NULL; @@ -1289,6 +1423,7 @@ idmap_get_sidbygid(idmap_get_handle_t *gh, gid_t gid, int flag, gh->retlist[gh->next].sidprefix = sidprefix; gh->retlist[gh->next].rid = rid; gh->retlist[gh->next].stat = stat; + gh->retlist[gh->next].info = info; gh->next++; return (IDMAP_SUCCESS); @@ -1387,6 +1522,9 @@ idmap_get_mappings(idmap_get_handle_t *gh) *gh->retlist[i].stat = IDMAP_ERR_NORESULT; break; } + if (gh->retlist[i].info != NULL) + (void) idmap_info_cpy(gh->retlist[i].info, + &res.ids.ids_val[i].info); } retcode = IDMAP_SUCCESS; @@ -1421,7 +1559,7 @@ idmap_get_w2u_mapping(idmap_handle_t *handle, const char *sidprefix, idmap_rid_t *rid, const char *winname, const char *windomain, int flag, int *is_user, int *is_wuser, - uid_t *pid, char **unixname, int *direction) + uid_t *pid, char **unixname, int *direction, idmap_info *info) { CLIENT *clnt; enum clnt_stat clntstat; @@ -1521,6 +1659,10 @@ idmap_get_w2u_mapping(idmap_handle_t *handle, if (rc != IDMAP_SUCCESS) retcode = rc; + rc = idmap_info_cpy(info, &mapping->info); + if (rc != IDMAP_SUCCESS) + retcode = rc; + out: xdr_free(xdr_idmap_mappings_res, (caddr_t)&result); if (retcode != IDMAP_SUCCESS) @@ -1538,7 +1680,7 @@ idmap_get_u2w_mapping(idmap_handle_t *handle, int flag, int is_user, int *is_wuser, char **sidprefix, idmap_rid_t *rid, char **winname, char **windomain, - int *direction) + int *direction, idmap_info *info) { CLIENT *clnt; enum clnt_stat clntstat; @@ -1608,8 +1750,14 @@ idmap_get_u2w_mapping(idmap_handle_t *handle, if (direction != NULL) *direction = mapping->direction; - if (is_wuser != NULL) - *is_wuser = mapping->id2.idtype == IDMAP_USID ? 1 : 0; + if (is_wuser != NULL) { + if (mapping->id2.idtype == IDMAP_USID) + *is_wuser = 1; + else if (mapping->id2.idtype == IDMAP_GSID) + *is_wuser = 0; + else + *is_wuser = -1; + } if (sidprefix && mapping->id2.idmap_id_u.sid.prefix && *mapping->id2.idmap_id_u.sid.prefix != '\0') { @@ -1630,6 +1778,10 @@ idmap_get_u2w_mapping(idmap_handle_t *handle, if (rc != IDMAP_SUCCESS) retcode = rc; + rc = idmap_info_cpy(info, &mapping->info); + if (rc != IDMAP_SUCCESS) + retcode = rc; + goto out; errout: @@ -1704,6 +1856,9 @@ static stat_table_t stattable[] = { {IDMAP_ERR_BAD_UTF8, gettext("Invalid or illegal UTF-8 sequence found in " "a given Windows entity name or domain name"), EINVAL}, + {IDMAP_ERR_NONEGENERATED, + gettext("Mapping not found and none created (see -c option)"), + EINVAL}, {-1, NULL, 0} }; #undef gettext @@ -1833,27 +1988,191 @@ idmap_strdupnull(char **to, const char *from) return (IDMAP_SUCCESS); } + idmap_stat idmap_namerule_cpy(idmap_namerule *to, idmap_namerule *from) { idmap_stat retval; + if (to == NULL) + return (IDMAP_SUCCESS); + (void) memcpy(to, from, sizeof (idmap_namerule)); + to->windomain = NULL; + to->winname = NULL; + to->unixname = NULL; retval = idmap_strdupnull(&to->windomain, from->windomain); if (retval != IDMAP_SUCCESS) return (retval); retval = idmap_strdupnull(&to->winname, from->winname); - if (retval != IDMAP_SUCCESS) + if (retval != IDMAP_SUCCESS) { + free(to->windomain); + to->windomain = NULL; return (retval); + } retval = idmap_strdupnull(&to->unixname, from->unixname); + if (retval != IDMAP_SUCCESS) { + free(to->windomain); + to->windomain = NULL; + free(to->winname); + to->winname = NULL; + return (retval); + } + + return (retval); +} + + +static +idmap_stat +idmap_how_ds_based_cpy(idmap_how_ds_based *to, idmap_how_ds_based *from) +{ + idmap_stat retval; + + if (to == NULL) + return (IDMAP_SUCCESS); + + retval = idmap_strdupnull(&to->dn, from->dn); + if (retval != IDMAP_SUCCESS) + return (retval); + + retval = idmap_strdupnull(&to->attr, from->attr); + if (retval != IDMAP_SUCCESS) { + free(to->dn); + to->dn = NULL; + return (retval); + } + + retval = idmap_strdupnull(&to->value, from->value); + if (retval != IDMAP_SUCCESS) { + free(to->dn); + to->dn = NULL; + free(to->attr); + to->attr = NULL; + return (retval); + } + + return (retval); +} + + +idmap_stat +idmap_info_cpy(idmap_info *to, idmap_info *from) +{ + idmap_stat retval = IDMAP_SUCCESS; + + if (to == NULL) + return (IDMAP_SUCCESS); + + (void) memset(to, 0, sizeof (idmap_info)); + + to->src = from->src; + to->how.map_type = from->how.map_type; + switch (to->how.map_type) { + case IDMAP_MAP_TYPE_DS_AD: + retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.ad, + &from->how.idmap_how_u.ad); + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + retval = idmap_how_ds_based_cpy(&to->how.idmap_how_u.nldap, + &from->how.idmap_how_u.nldap); + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + retval = idmap_namerule_cpy(&to->how.idmap_how_u.rule, + &from->how.idmap_how_u.rule); + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + + case IDMAP_MAP_TYPE_KNOWN_SID: + break; + } + return (retval); +} + + +/* + * This routine is similar to idmap_info_cpy, but the strings + * are moved from the "from" info to the "to" info. + * This routine is equivelent of: + * + * idmap_info_cpy(to,from); + * idmap_info_free(from); + */ +idmap_stat +idmap_info_mov(idmap_info *to, idmap_info *from) +{ + idmap_stat retval = IDMAP_SUCCESS; + + if (to == NULL) { + idmap_info_free(from); + return (IDMAP_SUCCESS); + } + (void) memcpy(to, from, sizeof (idmap_info)); + + (void) memset(from, 0, sizeof (idmap_info)); return (retval); } +void +idmap_info_free(idmap_info *info) +{ + idmap_how *how; + + if (info == NULL) + return; + + how = &info->how; + switch (how->map_type) { + case IDMAP_MAP_TYPE_DS_AD: + free(how->idmap_how_u.ad.dn); + how->idmap_how_u.ad.dn = NULL; + free(how->idmap_how_u.ad.attr); + how->idmap_how_u.ad.attr = NULL; + free(how->idmap_how_u.ad.value); + how->idmap_how_u.ad.value = NULL; + break; + + case IDMAP_MAP_TYPE_DS_NLDAP: + free(how->idmap_how_u.nldap.dn); + how->idmap_how_u.nldap.dn = NULL; + free(how->idmap_how_u.nldap.attr); + how->idmap_how_u.nldap.attr = NULL; + free(how->idmap_how_u.nldap.value); + how->idmap_how_u.nldap.value = NULL; + break; + + case IDMAP_MAP_TYPE_RULE_BASED: + free(how->idmap_how_u.rule.windomain); + how->idmap_how_u.rule.windomain = NULL; + free(how->idmap_how_u.rule.winname); + how->idmap_how_u.rule.winname = NULL; + free(how->idmap_how_u.rule.unixname); + how->idmap_how_u.rule.unixname = NULL; + break; + + case IDMAP_MAP_TYPE_EPHEMERAL: + break; + + case IDMAP_MAP_TYPE_LOCAL_SID: + break; + } + how->map_type = IDMAP_MAP_TYPE_UNKNOWN; + info->src = IDMAP_MAP_SRC_UNKNOWN; +} + + /* * Get uid given Windows name */ @@ -1872,7 +2191,7 @@ idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) return (rc); rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, - &is_user, &is_wuser, uid, NULL, NULL); + &is_user, &is_wuser, uid, NULL, NULL, NULL); (void) idmap_fini(ih); /* @@ -1903,7 +2222,7 @@ idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) return (rc); rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, - &is_user, &is_wuser, gid, NULL, NULL); + &is_user, &is_wuser, gid, NULL, NULL, NULL); (void) idmap_fini(ih); /* @@ -1934,7 +2253,7 @@ idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) return (rc); rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, NULL, - NULL, &winname, &windomain, NULL); + NULL, &winname, &windomain, NULL, NULL); (void) idmap_fini(ih); /* Return on error */ diff --git a/usr/src/lib/libidmap/common/idmap_impl.h b/usr/src/lib/libidmap/common/idmap_impl.h index b33ac3e4da..ee44aefd18 100644 --- a/usr/src/lib/libidmap/common/idmap_impl.h +++ b/usr/src/lib/libidmap/common/idmap_impl.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -82,6 +82,7 @@ typedef struct idmap_get_res { char **sidprefix; idmap_rid_t *rid; idmap_stat *stat; + idmap_info *info; } idmap_get_res_t; struct idmap_get_handle { diff --git a/usr/src/lib/libidmap/common/idmap_priv.h b/usr/src/lib/libidmap/common/idmap_priv.h index 8e92c21763..617921bf81 100644 --- a/usr/src/lib/libidmap/common/idmap_priv.h +++ b/usr/src/lib/libidmap/common/idmap_priv.h @@ -57,7 +57,6 @@ typedef struct idmap_udt_handle idmap_udt_handle_t; /* Opaque iterator */ typedef struct idmap_iter idmap_iter_t; - /* * Update API */ @@ -100,12 +99,13 @@ extern idmap_stat idmap_udt_flush_namerules(idmap_udt_handle_t *); */ /* Create a iterator to get SID to UID/GID mappings */ -extern idmap_stat idmap_iter_mappings(idmap_handle_t *, idmap_iter_t **); +extern idmap_stat idmap_iter_mappings(idmap_handle_t *, idmap_iter_t **, + int flag); /* Iterate through the SID to UID/GID mappings */ extern idmap_stat idmap_iter_next_mapping(idmap_iter_t *, char **, idmap_rid_t *, uid_t *, char **, char **, char **, boolean_t *, - boolean_t *, int *); + boolean_t *, int *, idmap_info *); /* Create a iterator to get name-based mapping rules */ extern idmap_stat idmap_iter_namerules(idmap_handle_t *, const char *, @@ -127,11 +127,11 @@ extern void idmap_iter_destroy(idmap_iter_t *); */ extern idmap_stat idmap_get_w2u_mapping(idmap_handle_t *, const char *, idmap_rid_t *, const char *, const char *, int, int *, int *, - uid_t *, char **, int *); + uid_t *, char **, int *, idmap_info *); extern idmap_stat idmap_get_u2w_mapping(idmap_handle_t *, uid_t *, const char *, int, int, int *, char **, idmap_rid_t *, char **, - char **, int *); + char **, int *, idmap_info *); /* @@ -147,6 +147,42 @@ extern idmap_stat idmap_stat4prot(idmap_stat); /* copy idmap_namerule including strings */ extern idmap_stat idmap_namerule_cpy(idmap_namerule *, idmap_namerule *); +/* copy idmap_info info including strings */ +extern idmap_stat idmap_info_cpy(idmap_info *to, idmap_info *from); + +/* Move idmap_info info including strings */ +extern idmap_stat idmap_info_mov(idmap_info *to, idmap_info *from); + +/* free idmap_info info from user supplied struct */ +extern void idmap_info_free(idmap_info *); + + +/* + * Extended API to batch SID to UID/GID mapping requests + */ + +/* Given SID, get UID */ +extern idmap_stat idmap_getext_uidbysid(idmap_get_handle_t *, char *, + idmap_rid_t, int, uid_t *, idmap_info *, idmap_stat *); + +/* Given SID, get GID */ +extern idmap_stat idmap_getext_gidbysid(idmap_get_handle_t *, char *, + idmap_rid_t, int, gid_t *, idmap_info *, idmap_stat *); + +/* Given SID, get UID or GID */ +extern idmap_stat idmap_getext_pidbysid(idmap_get_handle_t *, char *, + idmap_rid_t, int, uid_t *, int *, idmap_info *, idmap_stat *); + +/* Given UID, get SID */ +extern idmap_stat idmap_getext_sidbyuid(idmap_get_handle_t *, uid_t, int, + char **, idmap_rid_t *, idmap_info *, idmap_stat *); + +/* Given GID, get SID */ +extern idmap_stat idmap_getext_sidbygid(idmap_get_handle_t *, gid_t, int, + char **, idmap_rid_t *, idmap_info *, idmap_stat *); + + + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libidmap/common/mapfile-vers b/usr/src/lib/libidmap/common/mapfile-vers index 6712b9eb1f..a49a8246c9 100644 --- a/usr/src/lib/libidmap/common/mapfile-vers +++ b/usr/src/lib/libidmap/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -74,6 +74,14 @@ SUNWprivate { idmap_getuidbywinname; idmap_getgidbywinname; idmap_namerule_cpy; + idmap_info_free; + idmap_info_cpy; + idmap_info_mov; + idmap_getext_sidbygid; + idmap_getext_uidbysid; + idmap_getext_pidbysid; + idmap_getext_gidbysid; + idmap_getext_sidbyuid; local: *; }; diff --git a/usr/src/uts/common/sys/idmap.h b/usr/src/uts/common/sys/idmap.h index a42da84766..71fe14a61b 100644 --- a/usr/src/uts/common/sys/idmap.h +++ b/usr/src/uts/common/sys/idmap.h @@ -64,9 +64,10 @@ #define IDMAP_ERR_W2U_NAMERULE_CONFLICT -9970 #define IDMAP_ERR_U2W_NAMERULE_CONFLICT -9969 #define IDMAP_ERR_BAD_UTF8 -9968 +#define IDMAP_ERR_NONEGENERATED -9967 /* Reserved GIDs for some well-known SIDs */ -#define IDMAP_WK_LOCAL_SYSTEM_GID 2147483648U +#define IDMAP_WK_LOCAL_SYSTEM_GID 2147483648U /* 0x80000000 */ #define IDMAP_WK_CREATOR_GROUP_GID 2147483649U #define IDMAP_WK__MAX_GID 2147483649U |