diff --git a/SOURCES/libnfsidmap-0.2-memleak.patch b/SOURCES/libnfsidmap-0.2-memleak.patch new file mode 100644 index 00000000..67001c6b --- /dev/null +++ b/SOURCES/libnfsidmap-0.2-memleak.patch @@ -0,0 +1,21 @@ +commit c7edb02d52d048e9e82c0431a3256df3675668ac +Author: Steve Dickson +Date: Wed Aug 17 14:57:01 2016 -0400 + + Fixed a memory leak nss_name_to_gid() + + Signed-off-by: Steve Dickson + +diff --git a/nss.c b/nss.c +index 47c6b14..0f12351 100644 +--- a/nss.c ++++ b/nss.c +@@ -242,7 +242,7 @@ static int nss_name_to_gid(char *name, gid_t *gid) + + err = -ENOMEM; + if (buflen > UINT_MAX) +- goto out; ++ goto out_name; + + do { + buf = malloc(buflen); diff --git a/SOURCES/libnfsidmap-0.2-negativerets.patch b/SOURCES/libnfsidmap-0.2-negativerets.patch new file mode 100644 index 00000000..8626fde5 --- /dev/null +++ b/SOURCES/libnfsidmap-0.2-negativerets.patch @@ -0,0 +1,34 @@ +diff -up libnfsidmap-0.25/nss.c.save libnfsidmap-0.25/nss.c +--- libnfsidmap-0.25/nss.c.save 2016-08-17 14:09:18.797550853 -0400 ++++ libnfsidmap-0.25/nss.c 2016-08-17 14:09:39.021905256 -0400 +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + #include "nfsidmap.h" + #include "nfsidmap_internal.h" + #include "cfg.h" +@@ -171,6 +172,9 @@ static struct passwd *nss_getpwnam(const + char *localname; + int err = ENOMEM; + ++ if (buflen > UINT_MAX) ++ goto err; ++ + buf = malloc(sizeof(*buf) + buflen); + if (buf == NULL) + goto err; +@@ -236,8 +240,11 @@ static int nss_name_to_gid(char *name, g + if (!localname) + goto out; + ++ err = -ENOMEM; ++ if (buflen > UINT_MAX) ++ goto out; ++ + do { +- err = -ENOMEM; + buf = malloc(buflen); + if (!buf) + goto out_name; diff --git a/SOURCES/libnfsidmap-0.2-stripnewlines.patch b/SOURCES/libnfsidmap-0.2-stripnewlines.patch new file mode 100644 index 00000000..fb94e5f4 --- /dev/null +++ b/SOURCES/libnfsidmap-0.2-stripnewlines.patch @@ -0,0 +1,806 @@ +commit 6fc893187db3fceb66129a3fd8437f663a5e33d0 +Author: Jeff Layton +Date: Tue Sep 8 11:59:25 2015 -0400 + + Strip newlines out of IDMAP_LOG messages + + When logging to syslog, they aren't needed (or desirable) and when + logging to stderr the logging function generally adds it itself. + + Note that I did not change gums.c since it defaults to using printf() + as a logging function. + + Signed-off-by: Jeff Layton + Signed-off-by: Steve Dickson + +diff --git a/libnfsidmap.c b/libnfsidmap.c +index a8a9229..2db4d13 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -141,20 +141,20 @@ static int load_translation_plugin(char *method, struct mapping_plugin *plgn) + + dl = dlopen(plgname, RTLD_NOW | RTLD_LOCAL); + if (dl == NULL) { +- IDMAP_LOG(1, ("libnfsidmap: Unable to load plugin: %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: Unable to load plugin: %s", + dlerror())); + return -1; + } + init_func = (libnfsidmap_plugin_init_t) dlsym(dl, PLUGIN_INIT_FUNC); + if (init_func == NULL) { +- IDMAP_LOG(1, ("libnfsidmap: Unable to get init function: %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: Unable to get init function: %s", + dlerror())); + dlclose(dl); + return -1; + } + trans = init_func(); + if (trans == NULL) { +- IDMAP_LOG(1, ("libnfsidmap: Failed to initialize plugin %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: Failed to initialize plugin %s", + PLUGIN_INIT_FUNC, plgname)); + dlclose(dl); + return -1; +@@ -163,14 +163,14 @@ static int load_translation_plugin(char *method, struct mapping_plugin *plgn) + ret = trans->init(); + if (ret) { + IDMAP_LOG(1, ("libnfsidmap: Failed in %s's init(), " +- "returned %d\n", plgname, ret)); ++ "returned %d", plgname, ret)); + dlclose(dl); + return -1; + } + } + plgn->dl_handle = dl; + plgn->trans = trans; +- IDMAP_LOG(1, ("libnfsidmap: loaded plugin %s for method %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: loaded plugin %s for method %s", + plgname, method)); + + return 0; +@@ -182,7 +182,7 @@ static void unload_plugins(struct mapping_plugin **plgns) + for (i = 0; plgns[i] != NULL; i++) { + if (plgns[i]->dl_handle && dlclose(plgns[i]->dl_handle)) + IDMAP_LOG(1, ("libnfsidmap: failed to " +- "unload plugin for method = %s\n", ++ "unload plugin for method = %s", + plgns[i]->trans->name)); + free(plgns[i]); + } +@@ -207,7 +207,7 @@ static int load_plugins(struct conf_list *methods, + goto out; + if (load_translation_plugin(m->field, plgns[i]) == -1) { + IDMAP_LOG(0, ("libnfsidmap: requested translation " +- "method, '%s', is not available\n", ++ "method, '%s', is not available", + m->field)); + goto out; + } +@@ -251,7 +251,7 @@ int nfs4_init_name_mapping(char *conffile) + IDMAP_LOG(1, ("libnfsidmap: Unable to determine " + "the NFSv4 domain; Using '%s' as the NFSv4 domain " + "which means UIDs will be mapped to the 'Nobody-User' " +- "user defined in %s\n", ++ "user defined in %s", + IDMAPD_DEFAULT_DOMAIN, PATH_IDMAPDCONF)); + default_domain = IDMAPD_DEFAULT_DOMAIN; + } +@@ -344,11 +344,11 @@ int nfs4_init_name_mapping(char *conffile) + if (err == 0 && pw != NULL) + nobody_uid = pw->pw_uid; + else +- IDMAP_LOG(1, ("libnfsidmap: Nobody-User (%s) not found: %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: Nobody-User (%s) not found: %s", + nobody_user, strerror(errno))); + free(buf); + } else +- IDMAP_LOG(0,("libnfsidmap: Nobody-User: no memory : %s\n", ++ IDMAP_LOG(0,("libnfsidmap: Nobody-User: no memory : %s", + nobody_user, strerror(errno))); + } + +@@ -365,11 +365,11 @@ int nfs4_init_name_mapping(char *conffile) + if (err == 0 && gr != NULL) + nobody_gid = gr->gr_gid; + else +- IDMAP_LOG(1, ("libnfsidmap: Nobody-Group (%s) not found: %s\n", ++ IDMAP_LOG(1, ("libnfsidmap: Nobody-Group (%s) not found: %s", + nobody_group, strerror(errno))); + free(buf); + } else +- IDMAP_LOG(0,("libnfsidmap: Nobody-Group: no memory : %s\n", ++ IDMAP_LOG(0,("libnfsidmap: Nobody-Group: no memory : %s", + nobody_group, strerror(errno))); + } + +@@ -395,7 +395,7 @@ char * get_default_domain(void) + ret = domain_from_dns(&default_domain); + if (ret) { + IDMAP_LOG(0, ("Unable to determine a default nfsv4 domain; " +- " consider specifying one in idmapd.conf\n")); ++ " consider specifying one in idmapd.conf")); + default_domain = ""; + } + return default_domain; +@@ -444,12 +444,12 @@ nfs4_get_default_domain(char *server, char *domain, size_t len) + if (plgns[i]->trans->funcname == NULL) \ + continue; \ + \ +- IDMAP_LOG(4, ("%s: calling %s->%s\n", __func__, \ ++ IDMAP_LOG(4, ("%s: calling %s->%s", __func__, \ + plgns[i]->trans->name, #funcname)); \ + \ + ret = plgns[i]->trans->funcname(args); \ + \ +- IDMAP_LOG(4, ("%s: %s->%s returned %d\n", \ ++ IDMAP_LOG(4, ("%s: %s->%s returned %d", \ + __func__, plgns[i]->trans->name, \ + #funcname, ret)); \ + \ +@@ -458,7 +458,7 @@ nfs4_get_default_domain(char *server, char *domain, size_t len) + \ + break; \ + } \ +- IDMAP_LOG(4, ("%s: final return value is %d\n", \ ++ IDMAP_LOG(4, ("%s: final return value is %d", \ + __func__, ret)); \ + return ret; \ + } while (0) +diff --git a/nss.c b/nss.c +index b3fef5a..ffe3333 100644 +--- a/nss.c ++++ b/nss.c +@@ -178,10 +178,10 @@ static struct passwd *nss_getpwnam(const char *name, const char *domain, int *er + err = EINVAL; + localname = strip_domain(name, domain); + IDMAP_LOG(4, ("nss_getpwnam: name '%s' domain '%s': " +- "resulting localname '%s'\n", name, domain, localname)); ++ "resulting localname '%s'", name, domain, localname)); + if (localname == NULL) { + IDMAP_LOG(0, ("nss_getpwnam: name '%s' does not map " +- "into domain '%s'\n", name, ++ "into domain '%s'", name, + domain ? domain : "")); + goto err_free_buf; + } +@@ -189,7 +189,7 @@ static struct passwd *nss_getpwnam(const char *name, const char *domain, int *er + err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw); + if (pw == NULL && domain != NULL) + IDMAP_LOG(0, +- ("nss_getpwnam: name '%s' not found in domain '%s'\n", ++ ("nss_getpwnam: name '%s' not found in domain '%s'", + localname, domain)); + free(localname); + if (err == 0 && pw != NULL) { +diff --git a/static.c b/static.c +index ec04057..9f587af 100644 +--- a/static.c ++++ b/static.c +@@ -124,13 +124,13 @@ again: + if (err == 0) + err = ENOENT; + +- IDMAP_LOG(0, ("static_getpwnam: localname '%s' for '%s' not found\n", ++ IDMAP_LOG(0, ("static_getpwnam: localname '%s' for '%s' not found", + localname, name)); + + goto err_free_buf; + } + +- IDMAP_LOG(4, ("static_getpwnam: name '%s' mapped to '%s'\n", ++ IDMAP_LOG(4, ("static_getpwnam: name '%s' mapped to '%s'", + name, localname)); + + *err_p = 0; +@@ -174,13 +174,13 @@ again: + if (err == 0) + err = ENOENT; + +- IDMAP_LOG(0, ("static_getgrnam: local group '%s' for '%s' not found\n", ++ IDMAP_LOG(0, ("static_getgrnam: local group '%s' for '%s' not found", + localgroup, name)); + + goto err_free_buf; + } + +- IDMAP_LOG(4, ("static_getgrnam: group '%s' mapped to '%s'\n", ++ IDMAP_LOG(4, ("static_getgrnam: group '%s' mapped to '%s'", + name, localgroup)); + + *err_p = 0; +diff --git a/umich_ldap.c b/umich_ldap.c +index b527c5d..886fa0c 100644 +--- a/umich_ldap.c ++++ b/umich_ldap.c +@@ -160,7 +160,7 @@ ldap_init_and_bind(LDAP **pld, + */ + if ((lerr = ldap_initialize(&ld, server_url)) != LDAP_SUCCESS) { + IDMAP_LOG(0, ("ldap_init_and_bind: ldap_initialize() failed " +- "to [%s]: %s (%d)\n", server_url, ++ "to [%s]: %s (%d)", server_url, + ldap_err2string(lerr), lerr)); + goto out; + } +@@ -168,7 +168,7 @@ ldap_init_and_bind(LDAP **pld, + if ((ldap_set_option(ld, LDAP_OPT_DEBUG_LEVEL, &debug_level) + != LDAP_SUCCESS)) { + IDMAP_LOG(0, ("ldap_init_and_bind: error setting ldap " +- "library debugging level\n")); ++ "library debugging level")); + goto out; + } + +@@ -179,7 +179,7 @@ ldap_init_and_bind(LDAP **pld, + ldap_get_option(ld, LDAP_OPT_API_INFO, &apiinfo); + if (apiinfo.ldapai_info_version != LDAP_API_INFO_VERSION) { + IDMAP_LOG(0, ("ldap_init_and_bind: APIInfo version mismatch: " +- "library %d, header %d\n", ++ "library %d, header %d", + apiinfo.ldapai_info_version, LDAP_API_INFO_VERSION)); + goto out; + } +@@ -189,7 +189,7 @@ ldap_init_and_bind(LDAP **pld, + new_version = LDAP_VERSION3; + IDMAP_LOG(4, ("ldap_init_and_bind: version mismatch between " + "API information and protocol version. Setting " +- "protocol version to %d\n", new_version)); ++ "protocol version to %d", new_version)); + ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &new_version); + } + +@@ -212,7 +212,7 @@ ldap_init_and_bind(LDAP **pld, + lerr = ldap_set_option(ld, LDAP_OPT_X_TLS, &tls_type); + if (lerr != LDAP_SUCCESS) { + IDMAP_LOG(2, ("ldap_init_and_bind: setting SSL " +- "failed : %s (%d)\n", ++ "failed : %s (%d)", + ldap_err2string(lerr), lerr)); + goto out; + } +@@ -220,7 +220,7 @@ ldap_init_and_bind(LDAP **pld, + linfo->ca_cert); + if (lerr != LDAP_SUCCESS) { + IDMAP_LOG(2, ("ldap_init_and_bind: setting CA " +- "certificate file failed : %s (%d)\n", ++ "certificate file failed : %s (%d)", + ldap_err2string(lerr), lerr)); + goto out; + } +@@ -242,24 +242,24 @@ retry_bind: + IDMAP_LOG(2, ("ldap_init_and_bind: " + "got protocol error while attempting " + "bind with protocol version %d, " +- "trying protocol version %d\n", ++ "trying protocol version %d", + current_version, new_version)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("ldap_init_and_bind: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + goto retry_bind; + } + IDMAP_LOG(2, ("ldap_init_and_bind: ldap_simple_bind_s " +- "to [%s] as user '%s': %s (%d)\n", ++ "to [%s] as user '%s': %s (%d)", + server_url, linfo->user_dn, + ldap_err2string(lerr), lerr)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL)&& (*errmsg != '\0')) { + IDMAP_LOG(2, ("ldap_init_and_bind: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + goto out; +@@ -272,12 +272,12 @@ retry_bind: + char *errmsg; + + IDMAP_LOG(2, ("ldap_init_and_bind: ldap_simple_bind_s " +- "to [%s] as anonymous: %s (%d)\n", server_url, ++ "to [%s] as anonymous: %s (%d)", server_url, + ldap_err2string(lerr), lerr)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("ldap_init_and_bind: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + goto out; +@@ -323,7 +323,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + attrtype, name)) + == LDAP_FILT_MAXSIZ) { + IDMAP_LOG(0, ("ERROR: umich_name_to_ids: filter " +- "too long!\n")); ++ "too long!")); + goto out; + } + base = linfo->people_tree; +@@ -335,13 +335,13 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + attrtype, name)) + == LDAP_FILT_MAXSIZ) { + IDMAP_LOG(0, ("ERROR: umich_name_to_ids: filter " +- "too long!\n")); ++ "too long!")); + goto out; + } + base = linfo->group_tree; + } + else { +- IDMAP_LOG(0, ("ERROR: umich_name_to_ids: invalid idtype (%d)\n", ++ IDMAP_LOG(0, ("ERROR: umich_name_to_ids: invalid idtype (%d)", + idtype)); + goto out; + } +@@ -360,12 +360,12 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + char *errmsg; + + IDMAP_LOG(2, ("umich_name_to_ids: ldap_search_st for " +- "base '%s', filter '%s': %s (%d)\n", ++ "base '%s', filter '%s': %s (%d)", + base, filter, ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_name_to_ids: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + err = -ENOENT; +@@ -381,7 +381,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + if (!(entry = ldap_first_entry(ld, result))) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_name_to_ids: ldap_first_entry: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + +@@ -402,7 +402,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + if ((idstr = ldap_get_values(ld, result, attr_res)) == NULL) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_name_to_ids: ldap_get_values: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_memfree; + } + if (strcasecmp(attr_res, ldap_map.NFSv4_uid_attr) == 0) { +@@ -411,7 +411,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + if (tmp_uid != tmp_u || + (errno == ERANGE && tmp_u == ULONG_MAX)) { + IDMAP_LOG(0, ("ERROR: umich_name_to_ids: " +- "uidNumber too long converting '%s'\n", ++ "uidNumber too long converting '%s'", + *idstr)); + ldap_memfree(attr_res); + ldap_value_free(idstr); +@@ -424,7 +424,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + if (tmp_gid != tmp_g || + (errno == ERANGE && tmp_g == ULONG_MAX)) { + IDMAP_LOG(0, ("ERROR: umich_name_to_ids: " +- "gidNumber too long converting '%s'\n", ++ "gidNumber too long converting '%s'", + *idstr)); + ldap_memfree(attr_res); + ldap_value_free(idstr); +@@ -433,7 +433,7 @@ umich_name_to_ids(char *name, int idtype, uid_t *uid, gid_t *gid, + *gid = tmp_gid; + } else { + IDMAP_LOG(0, ("umich_name_to_ids: received attr " +- "'%s' ???\n", attr_res)); ++ "'%s' ???", attr_res)); + ldap_memfree(attr_res); + ldap_value_free(idstr); + goto out_memfree; +@@ -485,7 +485,7 @@ umich_id_to_name(uid_t id, int idtype, char **name, size_t len, + ldap_map.NFSv4_uid_attr, idstr)) + == LDAP_FILT_MAXSIZ) { + IDMAP_LOG(0, ("ERROR: umich_id_to_name: " +- "uid filter too long!\n")); ++ "uid filter too long!")); + goto out; + } + base = linfo->people_tree; +@@ -496,12 +496,12 @@ umich_id_to_name(uid_t id, int idtype, char **name, size_t len, + ldap_map.NFSv4_gid_attr,idstr)) + == LDAP_FILT_MAXSIZ) { + IDMAP_LOG(0, ("ERROR: umich_id_to_name: " +- "gid filter too long!\n")); ++ "gid filter too long!")); + goto out; + } + base = linfo->group_tree; + } else { +- IDMAP_LOG(0, ("ERROR: umich_id_to_name: invalid idtype (%d)\n", ++ IDMAP_LOG(0, ("ERROR: umich_id_to_name: invalid idtype (%d)", + idtype)); + err = -EINVAL; + goto out; +@@ -523,12 +523,12 @@ umich_id_to_name(uid_t id, int idtype, char **name, size_t len, + char * errmsg; + + IDMAP_LOG(2, ("umich_id_to_name: ldap_search_st for " +- "base '%s, filter '%s': %s (%d)\n", base, filter, ++ "base '%s, filter '%s': %s (%d)", base, filter, + ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_id_to_name: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + +@@ -544,21 +544,21 @@ umich_id_to_name(uid_t id, int idtype, char **name, size_t len, + if (!(entry = ldap_first_entry(ld, result))) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_id_to_name: ldap_first_entry: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + + if (!(attr_res = ldap_first_attribute(ld, result, &ber))) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_id_to_name: ldap_first_attribute: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + + if ((names = ldap_get_values(ld, result, attr_res)) == NULL) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_id_to_name: ldap_get_values: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_memfree; + } + +@@ -571,7 +571,7 @@ umich_id_to_name(uid_t id, int idtype, char **name, size_t len, + if (strlen(names[0]) >= len) { + /* not enough space to return the name */ + IDMAP_LOG(1, ("umich_id_to_name: output buffer size (%d) " +- "too small to return string, '%s', of length %d\n", ++ "too small to return string, '%s', of length %d", + len, names[0], strlen(names[0]))); + goto out_memfree; + } +@@ -625,7 +625,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + ldap_map.GSS_principal_attr, principal)) + == LDAP_FILT_MAXSIZ) { + IDMAP_LOG(0, ("ERROR: umich_gss_princ_to_grouplist: " +- "filter too long!\n")); ++ "filter too long!")); + goto out; + } + +@@ -638,13 +638,13 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + char *errmsg; + + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_search_st " +- "for tree '%s, filter '%s': %s (%d)\n", ++ "for tree '%s, filter '%s': %s (%d)", + linfo->people_tree, filter, + ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + err = -ENOENT; +@@ -655,7 +655,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + count = ldap_count_entries(ld, result); + if (count != 1) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "ldap account lookup of gssauthname %s returned %d accounts\n", ++ "ldap account lookup of gssauthname %s returned %d accounts", + principal,count)); + goto out_unbind; + } +@@ -663,14 +663,14 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + if (!(entry = ldap_first_entry(ld, result))) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_first_entry: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + + if ((names = ldap_get_values(ld, result, attrs[0])) == NULL) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_get_values: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + +@@ -685,7 +685,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + ldap_map.NFSv4_acctname_attr, + names[0])) == LDAP_FILT_MAXSIZ ) { + IDMAP_LOG(2, ("ERROR: umich_gss_princ_to_grouplist: " +- "filter too long!\n")); ++ "filter too long!")); + ldap_value_free(names); + goto out_unbind; + } +@@ -702,13 +702,13 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + char *errmsg; + + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_search_st " +- "for tree '%s, filter '%s': %s (%d)\n", ++ "for tree '%s, filter '%s': %s (%d)", + linfo->people_tree, filter, + ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) + && (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + err = -ENOENT; +@@ -720,7 +720,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + count = ldap_count_entries(ld, result); + if (count != 1) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "ldap group member lookup of gssauthname %s returned %d multiple entries\n", ++ "ldap group member lookup of gssauthname %s returned %d multiple entries", + principal,count)); + goto out_unbind; + } +@@ -728,14 +728,14 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + if (!(entry = ldap_first_entry(ld, result))) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_first_entry: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + + if ((names = ldap_get_values(ld, result, attrs[0])) == NULL) { + lerr = ldap_result2error(ld, result, 0); + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_get_values: " +- "%s (%d)\n", ldap_err2string(lerr), lerr)); ++ "%s (%d)", ldap_err2string(lerr), lerr)); + goto out_unbind; + } + +@@ -747,7 +747,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + ldap_value_free(names); + err = -EINVAL; + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: User %s, " +- "number of groups %d, exceeds requested number %d\n", ++ "number of groups %d, exceeds requested number %d", + principal, i, *ngroups)); + *ngroups = i; + goto out_unbind; +@@ -780,7 +780,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + + if ( f_len == LDAP_FILT_MAXSIZ ) { + IDMAP_LOG(2, ("ERROR: umich_gss_princ_to_grouplist: " +- "filter too long!\n")); ++ "filter too long!")); + ldap_value_free(names); + goto out_unbind; + } +@@ -793,14 +793,14 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + char *errmsg; + + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_search_st " +- "for tree '%s, filter '%s': %s (%d)\n", ++ "for tree '%s, filter '%s': %s (%d)", + linfo->group_tree, filter, + ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg)==LDAP_SUCCESS) + && + (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + continue; +@@ -822,7 +822,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + /* There should be only one gidNumber attribute per group */ + if ((valcount = ldap_count_values(vals)) != 1) { + IDMAP_LOG(2, ("DB problem getting gidNumber of " +- "posixGroup! (count was %d)\n", valcount)); ++ "posixGroup! (count was %d)", valcount)); + ldap_value_free(vals); + continue; + } +@@ -832,7 +832,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + if (tmp_gid != tmp_g || + (errno == ERANGE && tmp_g == ULONG_MAX)) { + IDMAP_LOG(2, ("ERROR: umich_gss_princ_to_grouplist: " +- "gidNumber too long converting '%s'\n", ++ "gidNumber too long converting '%s'", + vals[0])); + ldap_value_free(vals); + continue; +@@ -867,7 +867,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + + if ( f_len == LDAP_FILT_MAXSIZ ) { + IDMAP_LOG(0, ("ERROR: umich_gss_princ_to_grouplist: " +- "filter too long!\n")); ++ "filter too long!")); + ldap_value_free(names); + goto out_unbind; + } +@@ -884,13 +884,13 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + char *errmsg; + + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: ldap_search_st " +- "for tree '%s, filter '%s': %s (%d)\n", ++ "for tree '%s, filter '%s': %s (%d)", + linfo->group_tree, filter, + ldap_err2string(err), err)); + if ((ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &errmsg) == LDAP_SUCCESS) && + (errmsg != NULL) && (*errmsg != '\0')) { + IDMAP_LOG(2, ("umich_gss_princ_to_grouplist: " +- "Additional info: %s\n", errmsg)); ++ "Additional info: %s", errmsg)); + ldap_memfree(errmsg); + } + err = -ENOENT; +@@ -938,7 +938,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + /* There should be only one gidNumber attribute per group */ + if ((valcount = ldap_count_values(vals)) != 1) { + IDMAP_LOG(0, ("DB problem getting gidNumber of " +- "posixGroup! (count was %d)\n", valcount)); ++ "posixGroup! (count was %d)", valcount)); + goto out_unbind; + } + tmp_g = strtoul(vals[0], (char **)NULL, 10); +@@ -946,7 +946,7 @@ umich_gss_princ_to_grouplist(char *principal, gid_t *groups, int *ngroups, + if (tmp_gid != tmp_g || + (errno == ERANGE && tmp_g == ULONG_MAX)) { + IDMAP_LOG(0, ("ERROR: umich_gss_princ_to_grouplist: " +- "gidNumber too long converting '%s'\n", ++ "gidNumber too long converting '%s'", + vals[0])); + ldap_value_free(vals); + goto out_unbind; +@@ -978,7 +978,7 @@ umichldap_gss_princ_to_ids(char *secname, char *principal, + + if ((strcmp(secname, "krb5") != 0) && (strcmp(secname, "spkm3") != 0)) { + IDMAP_LOG(0, ("ERROR: umichldap_gss_princ_to_ids: " +- "invalid secname '%s'\n", secname)); ++ "invalid secname '%s'", secname)); + return err; + } + +@@ -1031,7 +1031,7 @@ umichldap_gss_princ_to_grouplist(char *secname, char *principal, + + if ((strcmp(secname, "krb5") != 0) && (strcmp(secname, "spkm3") != 0)) { + IDMAP_LOG(0, ("ERROR: umichldap_gss_princ_to_grouplist: " +- "invalid secname '%s'\n", secname)); ++ "invalid secname '%s'", secname)); + return err; + } + +@@ -1068,11 +1068,11 @@ get_canonical_hostname(const char *inname) + msg = gai_strerror(aierr); + break; + } +- IDMAP_LOG(1, ("%s: '%s': %s\n", __FUNCTION__, inname, msg)); ++ IDMAP_LOG(1, ("%s: '%s': %s", __FUNCTION__, inname, msg)); + goto out_err; + } + if (ap == 0) { +- IDMAP_LOG(1, ("%s: no addresses for host '%s'?\n", ++ IDMAP_LOG(1, ("%s: no addresses for host '%s'?", + __FUNCTION__, inname)); + goto out_err; + } +@@ -1080,7 +1080,7 @@ get_canonical_hostname(const char *inname) + error = getnameinfo (ap->ai_addr, ap->ai_addrlen, tmphost, + sizeof(tmphost), NULL, 0, 0); + if (error) { +- IDMAP_LOG(1, ("%s: getnameinfo for host '%s' failed (%d)\n", ++ IDMAP_LOG(1, ("%s: getnameinfo for host '%s' failed (%d)", + __FUNCTION__, inname)); + goto out_free; + } +@@ -1125,7 +1125,7 @@ umichldap_init(void) + strncat(missing_msg, "LDAP_base ", sizeof(missing_msg)); + if (strlen(missing_msg) != 0) { + IDMAP_LOG(0, ("umichldap_init: Missing required information: " +- "%s\n", missing_msg)); ++ "%s", missing_msg)); + goto fail; + } + +@@ -1137,7 +1137,7 @@ umichldap_init(void) + canon_name = get_canonical_hostname(server_in); + if (canon_name == NULL) + IDMAP_LOG(0, ("umichldap_init: Warning! Unable to " +- "canonicalize server name '%s' as requested.\n", ++ "canonicalize server name '%s' as requested.", + server_in)); + else + ldap_info.server = canon_name; +@@ -1226,56 +1226,56 @@ umichldap_init(void) + + if (ldap_info.use_ssl && ldap_info.ca_cert == NULL) { + IDMAP_LOG(0, ("umichldap_init: You must specify LDAP_ca_cert " +- "with LDAP_use_ssl=yes\n")); ++ "with LDAP_use_ssl=yes")); + goto fail; + } + + + /* print out some good debugging info */ +- IDMAP_LOG(1, ("umichldap_init: canonicalize_name: %s\n", ++ IDMAP_LOG(1, ("umichldap_init: canonicalize_name: %s", + canonicalize)); +- IDMAP_LOG(1, ("umichldap_init: server : %s (from config value '%s')\n", ++ IDMAP_LOG(1, ("umichldap_init: server : %s (from config value '%s')", + ldap_info.server, server_in)); +- IDMAP_LOG(1, ("umichldap_init: port : %d\n", ldap_info.port)); +- IDMAP_LOG(1, ("umichldap_init: people : %s\n", ldap_info.people_tree)); +- IDMAP_LOG(1, ("umichldap_init: groups : %s\n", ldap_info.group_tree)); ++ IDMAP_LOG(1, ("umichldap_init: port : %d", ldap_info.port)); ++ IDMAP_LOG(1, ("umichldap_init: people : %s", ldap_info.people_tree)); ++ IDMAP_LOG(1, ("umichldap_init: groups : %s", ldap_info.group_tree)); + +- IDMAP_LOG(1, ("umichldap_init: user_dn : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: user_dn : %s", + (ldap_info.user_dn && strlen(ldap_info.user_dn) != 0) + ? ldap_info.user_dn : "")); + /* Don't print actual password into the log. */ +- IDMAP_LOG(1, ("umichldap_init: passwd : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: passwd : %s", + (ldap_info.passwd && strlen(ldap_info.passwd) != 0) ? + "" : "")); +- IDMAP_LOG(1, ("umichldap_init: use_ssl : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: use_ssl : %s", + ldap_info.use_ssl ? "yes" : "no")); +- IDMAP_LOG(1, ("umichldap_init: ca_cert : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: ca_cert : %s", + ldap_info.ca_cert ? ldap_info.ca_cert : "")); +- IDMAP_LOG(1, ("umichldap_init: use_memberof_for_groups : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: use_memberof_for_groups : %s", + ldap_info.memberof_for_groups ? "yes" : "no")); + +- IDMAP_LOG(1, ("umichldap_init: NFSv4_person_objectclass : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_person_objectclass : %s", + ldap_map.NFSv4_person_objcls)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_nfsname_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_nfsname_attr : %s", + ldap_map.NFSv4_nfsname_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_acctname_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_acctname_attr : %s", + ldap_map.NFSv4_acctname_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_uid_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_uid_attr : %s", + ldap_map.NFSv4_uid_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_group_objectclass : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_group_objectclass : %s", + ldap_map.NFSv4_group_objcls)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_gid_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_gid_attr : %s", + ldap_map.NFSv4_gid_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_group_nfsname_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_group_nfsname_attr : %s", + ldap_map.NFSv4_group_nfsname_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_member_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_member_attr : %s", + ldap_map.NFSv4_member_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_member_of_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_member_of_attr : %s", + ldap_map.NFSv4_member_of_attr)); +- IDMAP_LOG(1, ("umichldap_init: NFSv4_grouplist_filter : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: NFSv4_grouplist_filter : %s", + ldap_map.NFSv4_grouplist_filter ? + ldap_map.NFSv4_grouplist_filter : "")); +- IDMAP_LOG(1, ("umichldap_init: GSS_principal_attr : %s\n", ++ IDMAP_LOG(1, ("umichldap_init: GSS_principal_attr : %s", + ldap_map.GSS_principal_attr)); + return 0; + fail: diff --git a/SOURCES/libnfsidmap-0.25-dns-resolved.patch b/SOURCES/libnfsidmap-0.25-dns-resolved.patch new file mode 100644 index 00000000..36746ebf --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-dns-resolved.patch @@ -0,0 +1,149 @@ +diff --git a/configure.ac b/configure.ac +index 5179e96..db1cee2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -13,6 +13,8 @@ AC_PROG_CC + + # Checks for libraries. + ++AC_CHECK_LIB([resolv], [__res_querydomain], , AC_MSG_ERROR(res_querydomain needed)) ++ + AC_ARG_ENABLE([ldap], + [AS_HELP_STRING([--disable-ldap],[Disable support for LDAP @<:@default=detect@:>@])]) + if test "x$enable_ldap" != "xno" ; then +diff --git a/libnfsidmap.c b/libnfsidmap.c +index b9c0db3..d484101 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -53,6 +53,10 @@ + #include + #include + #include ++#include ++#include ++#include ++ + #include "nfsidmap.h" + #include "nfsidmap_internal.h" + #include "cfg.h" +@@ -81,6 +85,11 @@ gid_t nobody_gid = (gid_t)-1; + #define IDMAPD_DEFAULT_DOMAIN "localdomain" + #endif + ++#ifndef NFS4DNSTXTREC ++#define NFS4DNSTXTREC "_nfsv4idmapdomain" ++#endif ++ ++ + /* Default logging fuction */ + static void default_logger(const char *fmt, ...) + { +@@ -116,6 +125,93 @@ static int id_as_chars(char *name, uid_t *id) + return 1; + } + ++static int dns_txt_query(char *domain, char **nfs4domain) ++{ ++ char *txtname = NFS4DNSTXTREC; ++ char *msg, *answ, *eom, *mptr; ++ int len, status = -1; ++ HEADER *hdr; ++ ++ msg = calloc(1, NS_MAXMSG); ++ if (msg == NULL) ++ return -1; ++ ++ answ = calloc(1, NS_MAXMSG); ++ if (answ == NULL) { ++ free(msg); ++ return -1; ++ } ++ ++ if (res_init() < 0) { ++ IDMAP_LOG(2, ("libnfsidmap: res_init() failed for %s.%s: %s\n", ++ txtname, domain, hstrerror(h_errno))); ++ goto freemem; ++ } ++ len = res_querydomain(txtname, domain, C_IN, T_TXT, msg, NS_MAXMSG); ++ if (len < 0) { ++ IDMAP_LOG(2, ("libnfsidmap: res_querydomain() failed for %s.%s: %s\n", ++ txtname, domain, hstrerror(h_errno))); ++ goto freemem; ++ } ++ hdr = (HEADER *)msg; ++ ++ /* See if there is an answer */ ++ if (ntohs(hdr->ancount) < 1) { ++ IDMAP_LOG(2, ("libnfsidmap: No TXT record for %s.%s\n", ++ txtname, domain)); ++ goto freemem; ++ } ++ /* find the EndOfMessage */ ++ eom = msg + len; ++ ++ /* skip header */ ++ mptr = &msg[HFIXEDSZ]; ++ ++ /* skip name field in question section */ ++ mptr += dn_skipname(mptr, eom) + QFIXEDSZ; ++ ++ /* read in the question */ ++ len = dn_expand(msg, eom, mptr, answ, NS_MAXDNAME); ++ if (len < 0) { /* does this really matter?? */ ++ IDMAP_LOG(2, ("libnfsidmap: No question section for %s.%s: %s\n", ++ txtname, domain, hstrerror(h_errno))); ++ goto freemem; ++ } ++ ++ /* ++ * Now, dissect the answer section, Note: if there ++ * are more than one answer only the first ++ * one will be used. ++ */ ++ ++ /* skip passed the name field */ ++ mptr += dn_skipname(mptr, eom); ++ /* skip pass the type class and ttl fields */ ++ mptr += 2 + 2 + 4; ++ ++ /* make sure there is some data */ ++ GETSHORT(len, mptr); ++ if (len < 0) { ++ IDMAP_LOG(2, ("libnfsidmap: No data in answer for %s.%s\n", ++ txtname, domain)); ++ goto freemem; ++ } ++ /* get the lenght field */ ++ len = (int)*mptr++; ++ /* copy the data */ ++ memcpy(answ, mptr, len); ++ answ[len] = '\0'; ++ ++ *nfs4domain = strdup(answ); ++ status = 0; ++ ++freemem: ++ free(msg); ++ free(answ); ++ ++ return (status); ++} ++ + static int domain_from_dns(char **domain) + { + struct hostent *he; +@@ -127,7 +223,13 @@ static int domain_from_dns(char **domain) + return -1; + if ((c = strchr(he->h_name, '.')) == NULL || *++c == '\0') + return -1; +- *domain = strdup(c); ++ /* ++ * Query DNS to see if the _nfsv4idmapdomain TXT record exists ++ * If so use it... ++ */ ++ if (dns_txt_query(c, domain) < 0) ++ *domain = strdup(c); ++ + return 0; + } + diff --git a/SOURCES/libnfsidmap-0.25-multidomain.patch b/SOURCES/libnfsidmap-0.25-multidomain.patch new file mode 100644 index 00000000..66d81653 --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-multidomain.patch @@ -0,0 +1,409 @@ +diff -up libnfsidmap-0.25/idmapd.conf.5.orig libnfsidmap-0.25/idmapd.conf.5 +--- libnfsidmap-0.25/idmapd.conf.5.orig 2017-01-10 13:30:28.696901000 -0500 ++++ libnfsidmap-0.25/idmapd.conf.5 2017-01-10 13:32:44.241316000 -0500 +@@ -63,6 +63,30 @@ The local NFSv4 domain name. An NFSv4 d + a unique username<->UID and groupname<->GID mapping. + (Default: Host's fully-qualified DNS domain name) + .TP ++.B No-Strip ++In multi-domain environments, some NFS servers will append the identity ++management domain to the owner and owner_group in lieu of a true NFSv4 ++domain. This option can facilitate lookups in such environments. If ++set to a value other than "none", the nsswitch plugin will first pass ++the name to the password/group lookup function without stripping the ++domain off. If that mapping fails then the plugin will try again using ++the old method (comparing the domain in the string to the Domain value, ++stripping it if it matches, and passing the resulting short name to the ++lookup function). Valid values are "user", "group", "both", and ++"none". ++(Default: "none") ++.TP ++.B Reformat-Group ++Winbind has a quirk whereby doing a group lookup in UPN format ++(e.g. staff@americas.example.com) will cause the group to be ++displayed prefixed with the full domain in uppercase ++(e.g. AMERICAS.EXAMPLE.COM\\staff) instead of in the familiar netbios ++name format (e.g. AMERICAS\\staff). Setting this option to true ++causes the name to be reformatted before passing it to the group ++lookup function in order to work around this. This setting is ++ignored unless No-Strip is set to either "both" or "group". ++(Default: "false") ++.TP + .B Local-Realms + A comma-separated list of Kerberos realm names that may be considered equivalent to the + local realm name. For example, users juser@ORDER.EDU and juser@MAIL.ORDER.EDU +diff -up libnfsidmap-0.25/idmapd.conf.orig libnfsidmap-0.25/idmapd.conf +--- libnfsidmap-0.25/idmapd.conf.orig 2011-12-05 15:28:10.000000000 -0500 ++++ libnfsidmap-0.25/idmapd.conf 2017-01-10 13:32:44.235315000 -0500 +@@ -4,6 +4,29 @@ + # The default is the host's DNS domain name. + #Domain = local.domain.edu + ++# In multi-domain environments, some NFS servers will append the identity ++# management domain to the owner and owner_group in lieu of a true NFSv4 ++# domain. This option can facilitate lookups in such environments. If ++# set to a value other than "none", the nsswitch plugin will first pass ++# the name to the password/group lookup function without stripping the ++# domain off. If that mapping fails then the plugin will try again using ++# the old method (comparing the domain in the string to the Domain value, ++# stripping it if it matches, and passing the resulting short name to the ++# lookup function). Valid values are "user", "group", "both", and ++# "none". The default is "none". ++#No-Strip = none ++ ++# Winbind has a quirk whereby doing a group lookup in UPN format ++# (e.g. staff@americas.example.com) will cause the group to be ++# displayed prefixed with the full domain in uppercase ++# (e.g. AMERICAS.EXAMPLE.COM\staff) instead of in the familiar netbios ++# name format (e.g. AMERICAS\staff). Setting this option to true ++# causes the name to be reformatted before passing it to the group ++# lookup function in order to work around this. This setting is ++# ignored unless No-Strip is set to either "both" or "group". ++# The default is "false". ++#Reformat-Group = false ++ + # The following is a comma-separated list of Kerberos realm + # names that should be considered to be equivalent to the + # local realm, such that @REALM.A can be assumed to +diff -up libnfsidmap-0.25/libnfsidmap.c.orig libnfsidmap-0.25/libnfsidmap.c +--- libnfsidmap-0.25/libnfsidmap.c.orig 2017-01-10 13:30:28.837901000 -0500 ++++ libnfsidmap-0.25/libnfsidmap.c 2017-01-10 13:32:44.247315000 -0500 +@@ -60,6 +60,8 @@ + static char *default_domain; + static struct conf_list *local_realms; + int idmap_verbosity = 0; ++int no_strip = 0; ++int reformat_group = 0; + static struct mapping_plugin **nfs4_plugins = NULL; + static struct mapping_plugin **gss_plugins = NULL; + uid_t nobody_uid = (uid_t)-1; +@@ -234,6 +236,8 @@ int nfs4_init_name_mapping(char *conffil + int dflt = 0; + struct conf_list *nfs4_methods, *gss_methods; + char *nobody_user, *nobody_group; ++ char *nostrip; ++ char *reformatgroup; + + /* XXX: need to be able to reload configurations... */ + if (nfs4_plugins) /* already succesfully initialized */ +@@ -306,6 +310,26 @@ int nfs4_init_name_mapping(char *conffil + IDMAP_LOG(1, ("libnfsidmap: Realms list: ")); + } + ++ nostrip = conf_get_str_with_def("General", "No-Strip", "none"); ++ if (strcasecmp(nostrip, "both") == 0) ++ no_strip = IDTYPE_USER|IDTYPE_GROUP; ++ else if (strcasecmp(nostrip, "group") == 0) ++ no_strip = IDTYPE_GROUP; ++ else if (strcasecmp(nostrip, "user") == 0) ++ no_strip = IDTYPE_USER; ++ else ++ no_strip = 0; ++ ++ if (no_strip & IDTYPE_GROUP) { ++ reformatgroup = conf_get_str_with_def("General", "Reformat-Group", "false"); ++ if ((strcasecmp(reformatgroup, "true") == 0) || ++ (strcasecmp(reformatgroup, "on") == 0) || ++ (strcasecmp(reformatgroup, "yes") == 0)) ++ reformat_group = 1; ++ else ++ reformat_group = 0; ++ } ++ + nfs4_methods = conf_get_list("Translation", "Method"); + if (nfs4_methods) { + IDMAP_LOG(1, ("libnfsidmap: processing 'Method' list")); +diff -up libnfsidmap-0.25/nfsidmap_internal.h.orig libnfsidmap-0.25/nfsidmap_internal.h +--- libnfsidmap-0.25/nfsidmap_internal.h.orig 2011-12-05 15:28:10.000000000 -0500 ++++ libnfsidmap-0.25/nfsidmap_internal.h 2017-01-10 13:32:44.253315000 -0500 +@@ -63,6 +63,8 @@ typedef enum { + IDTYPE_GROUP = 2 + } idtypes; + ++extern int no_strip; ++extern int reformat_group; + extern int idmap_verbosity; + extern nfs4_idmap_log_function_t idmap_log_func; + /* Level zero always prints, others print depending on verbosity level */ +diff -up libnfsidmap-0.25/nss.c.orig libnfsidmap-0.25/nss.c +--- libnfsidmap-0.25/nss.c.orig 2017-01-10 13:30:28.892903000 -0500 ++++ libnfsidmap-0.25/nss.c 2017-01-10 13:32:44.259316000 -0500 +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include "nfsidmap.h" + #include "nfsidmap_internal.h" + #include "cfg.h" +@@ -58,14 +59,20 @@ + * and ignore the domain entirely when looking up a name. + */ + +-static int write_name(char *dest, char *localname, char *domain, size_t len) ++static int write_name(char *dest, char *localname, char *domain, size_t len, ++ int doappend) + { +- if (strlen(localname) + 1 + strlen(domain) + 1 > len) { +- return -ENOMEM; /* XXX: Is there an -ETOOLONG? */ ++ if (doappend || !strchr(localname,'@')) { ++ if (strlen(localname) + 1 + strlen(domain) + 1 > len) ++ return -ENOMEM; /* XXX: Is there an -ETOOLONG? */ ++ strcpy(dest, localname); ++ strcat(dest, "@"); ++ strcat(dest, domain); ++ } else { ++ if (strlen(localname) + 1 > len) ++ return -ENOMEM; ++ strcpy(dest, localname); + } +- strcpy(dest, localname); +- strcat(dest, "@"); +- strcat(dest, domain); + return 0; + } + +@@ -87,7 +94,10 @@ static int nss_uid_to_name(uid_t uid, ch + err = -ENOENT; + if (err) + goto out_buf; +- err = write_name(name, pw->pw_name, domain, len); ++ if (no_strip & IDTYPE_USER) ++ err = write_name(name, pw->pw_name, domain, len, 0); ++ else ++ err = write_name(name, pw->pw_name, domain, len, 1); + out_buf: + free(buf); + out: +@@ -121,7 +131,10 @@ static int nss_gid_to_name(gid_t gid, ch + + if (err) + goto out_buf; +- err = write_name(name, gr->gr_name, domain, len); ++ if (no_strip & IDTYPE_GROUP) ++ err = write_name(name, gr->gr_name, domain, len, 0); ++ else ++ err = write_name(name, gr->gr_name, domain, len, 1); + out_buf: + free(buf); + out: +@@ -164,7 +177,8 @@ struct pwbuf { + char buf[1]; + }; + +-static struct passwd *nss_getpwnam(const char *name, const char *domain, int *err_p) ++static struct passwd *nss_getpwnam(const char *name, const char *domain, ++ int *err_p, int dostrip) + { + struct passwd *pw; + struct pwbuf *buf; +@@ -180,22 +194,29 @@ static struct passwd *nss_getpwnam(const + goto err; + + err = EINVAL; +- localname = strip_domain(name, domain); +- IDMAP_LOG(4, ("nss_getpwnam: name '%s' domain '%s': " +- "resulting localname '%s'", name, domain, localname)); +- if (localname == NULL) { +- IDMAP_LOG(0, ("nss_getpwnam: name '%s' does not map " +- "into domain '%s'", name, +- domain ? domain : "")); +- goto err_free_buf; +- } ++ if (dostrip) { ++ localname = strip_domain(name, domain); ++ IDMAP_LOG(4, ("nss_getpwnam: name '%s' domain '%s': " ++ "resulting localname '%s'", name, domain, localname)); ++ if (localname == NULL) { ++ IDMAP_LOG(0, ("nss_getpwnam: name '%s' does not map " ++ "into domain '%s'", name, ++ domain ? domain : "")); ++ goto err_free_buf; ++ } + +- err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw); +- if (pw == NULL && domain != NULL) +- IDMAP_LOG(0, +- ("nss_getpwnam: name '%s' not found in domain '%s'", +- localname, domain)); +- free(localname); ++ err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw); ++ if (pw == NULL && domain != NULL) ++ IDMAP_LOG(1, ++ ("nss_getpwnam: name '%s' not found in domain '%s'", ++ localname, domain)); ++ free(localname); ++ } else { ++ err = getpwnam_r(name, &buf->pwbuf, buf->buf, buflen, &pw); ++ if (pw == NULL) ++ IDMAP_LOG(1, ++ ("nss_getpwnam: name '%s' not found (domain not stripped)", name)); ++ } + if (err == 0 && pw != NULL) { + *err_p = 0; + return pw; +@@ -217,28 +238,83 @@ static int nss_name_to_uid(char *name, u + int err = -ENOENT; + + domain = get_default_domain(); +- pw = nss_getpwnam(name, domain, &err); ++ if (no_strip & IDTYPE_USER) { ++ pw = nss_getpwnam(name, domain, &err, 0); ++ if (pw != NULL) ++ goto out_uid; ++ } ++ pw = nss_getpwnam(name, domain, &err, 1); + if (pw == NULL) + goto out; ++out_uid: + *uid = pw->pw_uid; ++ IDMAP_LOG(4, ("nss_name_to_uid: name '%s' uid %u", name, *uid)); + free(pw); + err = 0; + out: + return err; + } + +-static int nss_name_to_gid(char *name, gid_t *gid) ++static char *reformat_name(const char *name) ++{ ++ const char *domain; ++ const char *c; ++ const char *d; ++ char *l = NULL; ++ int len; ++ int dlen = 0; ++ int i; ++ ++ c = strchr(name, '@'); ++ if (c == NULL) ++ goto out; ++ len = c - name; ++ domain = ++c; ++ d = strchr(domain, '.'); ++ if (d == NULL) ++ goto out; ++ dlen = d - domain; ++ l = malloc(dlen + 1 + len + 1); ++ if (l == NULL) ++ goto out; ++ for (i = 0; i < dlen; i++) ++ l[i] = toupper(domain[i]); ++ l[dlen] = '\\'; ++ memcpy(l + dlen + 1, name, len); ++ l[dlen + 1 + len] = '\0'; ++out: ++ return l; ++} ++ ++static int _nss_name_to_gid(char *name, gid_t *gid, int dostrip) + { + struct group *gr = NULL; + struct group grbuf; +- char *buf, *localname, *domain; ++ char *buf, *domain; + size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + int err = -EINVAL; ++ char *localname = NULL; ++ char *ref_name = NULL; + + domain = get_default_domain(); +- localname = strip_domain(name, domain); +- if (!localname) +- goto out; ++ if (dostrip) { ++ localname = strip_domain(name, domain); ++ IDMAP_LOG(4, ("nss_name_to_gid: name '%s' domain '%s': " ++ "resulting localname '%s'", name, domain, localname)); ++ if (!localname) { ++ IDMAP_LOG(0, ("nss_name_to_gid: name '%s' does not map " ++ "into domain '%s'", name, domain)); ++ goto out; ++ } ++ } else if (reformat_group) { ++ ref_name = reformat_name(name); ++ if (ref_name == NULL) { ++ IDMAP_LOG(1, ("nss_name_to_gid: failed to reformat name '%s'", ++ name)); ++ err = -ENOENT; ++ goto out; ++ } ++ } + + err = -ENOMEM; + if (buflen > UINT_MAX) +@@ -248,9 +324,24 @@ static int nss_name_to_gid(char *name, g + buf = malloc(buflen); + if (!buf) + goto out_name; +- err = -getgrnam_r(localname, &grbuf, buf, buflen, &gr); +- if (gr == NULL && !err) ++ if (dostrip) ++ err = -getgrnam_r(localname, &grbuf, buf, buflen, &gr); ++ else if (reformat_group) ++ err = -getgrnam_r(ref_name, &grbuf, buf, buflen, &gr); ++ else ++ err = -getgrnam_r(name, &grbuf, buf, buflen, &gr); ++ if (gr == NULL && !err) { ++ if (dostrip) ++ IDMAP_LOG(1, ("nss_name_to_gid: name '%s' not found " ++ "in domain '%s'", localname, domain)); ++ else if (reformat_group) ++ IDMAP_LOG(1, ("nss_name_to_gid: name '%s' not found " ++ "(reformatted)", ref_name)); ++ else ++ IDMAP_LOG(1, ("nss_name_to_gid: name '%s' not found " ++ "(domain not stripped)", name)); + err = -ENOENT; ++ } + if (err == -ERANGE) { + buflen *= 2; + free(buf); +@@ -260,10 +351,28 @@ static int nss_name_to_gid(char *name, g + if (err) + goto out_buf; + *gid = gr->gr_gid; ++ IDMAP_LOG(4, ("nss_name_to_gid: name '%s' gid %u", name, *gid)); + out_buf: + free(buf); + out_name: +- free(localname); ++ if (dostrip) ++ free(localname); ++ if (reformat_group) ++ free(ref_name); ++out: ++ return err; ++} ++ ++static int nss_name_to_gid(char *name, gid_t *gid) ++{ ++ int err = 0; ++ ++ if (no_strip & IDTYPE_GROUP) { ++ err = _nss_name_to_gid(name, gid, 0); ++ if (!err) ++ goto out; ++ } ++ err = _nss_name_to_gid(name, gid, 1); + out: + return err; + } +@@ -306,7 +415,7 @@ static int nss_gss_princ_to_ids(char *se + return -ENOENT; + } + /* XXX: this should call something like getgssauthnam instead? */ +- pw = nss_getpwnam(princ, NULL, &err); ++ pw = nss_getpwnam(princ, NULL, &err, 0); + if (pw == NULL) { + err = -ENOENT; + goto out; +@@ -329,7 +438,7 @@ int nss_gss_princ_to_grouplist(char *sec + goto out; + /* XXX: not quite right? Need to know default realm? */ + /* XXX: this should call something like getgssauthnam instead? */ +- pw = nss_getpwnam(princ, NULL, &ret); ++ pw = nss_getpwnam(princ, NULL, &ret, 0); + if (pw == NULL) { + ret = -ENOENT; + goto out; diff --git a/SOURCES/libnfsidmap-0.25-nobody.patch b/SOURCES/libnfsidmap-0.25-nobody.patch new file mode 100644 index 00000000..22a9f508 --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-nobody.patch @@ -0,0 +1,108 @@ +commit f139de79d91e7773b5b98fe5aca5570f77c7aee9 +Author: Christian Seiler +Date: Wed Aug 13 12:42:14 2014 -0400 + + libnfsidmap: respect Nobody-User/Nobody-Group + + Previous behavior of libnfsidmap was to do a name lookup of + nobody@DEFAULTDOMAIN (for both user and group), which does not match + the behavior of rpc.idmapd. + + This patch makes libnfsidmap respect Nobody-User/Nobody-Group for + lookups, thus making the nfsidmap utility properly handle the case if + nobody@DEFAULTDOMAIN does not directly map to any user/group on the + system. + + Signed-off-by: Christian Seiler + Signed-off-by: Steve Dickson + +diff --git a/libnfsidmap.c b/libnfsidmap.c +index 92bc493..ec5c141 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -62,6 +62,8 @@ static struct conf_list *local_realms; + int idmap_verbosity = 0; + static struct mapping_plugin **nfs4_plugins = NULL; + static struct mapping_plugin **gss_plugins = NULL; ++uid_t nobody_uid = (uid_t)-1; ++gid_t nobody_gid = (gid_t)-1; + + #ifndef PATH_PLUGINS + #define PATH_PLUGINS "/usr/lib/libnfsidmap" +@@ -228,6 +230,7 @@ int nfs4_init_name_mapping(char *conffile) + int ret = -ENOENT; + int dflt = 0; + struct conf_list *nfs4_methods, *gss_methods; ++ char *nobody_user, *nobody_group; + + /* XXX: need to be able to reload configurations... */ + if (nfs4_plugins) /* already succesfully initialized */ +@@ -324,6 +327,49 @@ int nfs4_init_name_mapping(char *conffile) + if (load_plugins(gss_methods, &gss_plugins) == -1) + goto out; + } ++ ++ nobody_user = conf_get_str("Mapping", "Nobody-User"); ++ if (nobody_user) { ++ size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); ++ struct passwd *buf; ++ struct passwd *pw = NULL; ++ int err; ++ ++ buf = malloc(sizeof(*buf) + buflen); ++ if (buf) { ++ err = getpwnam_r(nobody_user, buf, ((char *)buf) + sizeof(*buf), buflen, &pw); ++ if (err == 0 && pw != NULL) ++ nobody_uid = pw->pw_uid; ++ else ++ IDMAP_LOG(1, ("libnfsidmap: Nobody-User (%s) not found: %s\n", ++ nobody_user, strerror(errno))); ++ free(buf); ++ } else ++ IDMAP_LOG(0,("libnfsidmap: Nobody-User: no memory : %s\n", ++ nobody_user, strerror(errno))); ++ } ++ ++ nobody_group = conf_get_str("Mapping", "Nobody-Group"); ++ if (nobody_group) { ++ size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); ++ struct group *buf; ++ struct group *gr = NULL; ++ int err; ++ ++ buf = malloc(sizeof(*buf) + buflen); ++ if (buf) { ++ err = getgrnam_r(nobody_group, buf, ((char *)buf) + sizeof(*buf), buflen, &gr); ++ if (err == 0 && gr != NULL) ++ nobody_gid = gr->gr_gid; ++ else ++ IDMAP_LOG(1, ("libnfsidmap: Nobody-Group (%s) not found: %s\n", ++ nobody_group, strerror(errno))); ++ free(buf); ++ } else ++ IDMAP_LOG(0,("libnfsidmap: Nobody-Group: no memory : %s\n", ++ nobody_group, strerror(errno))); ++ } ++ + ret = 0; + out: + if (ret) { +@@ -453,6 +499,18 @@ static int set_id_to_nobody(int *id, int is_uid) + int rc = 0; + const char name[] = "nobody@"; + char nobody[strlen(name) + strlen(get_default_domain()) + 1]; ++ ++ /* First try to see whether a Nobody-User/Nobody-Group was ++ * configured, before we try to do a full lookup for the ++ * NFS nobody user. */ ++ if (is_uid && nobody_uid != (uid_t)-1) { ++ *id = (int)nobody_uid; ++ return 0; ++ } else if (!is_uid && nobody_gid != (gid_t)-1) { ++ *id = (int)nobody_gid; ++ return 0; ++ } ++ + strcpy(nobody, name); + strcat(nobody, get_default_domain()); + diff --git a/SOURCES/libnfsidmap-0.25-nssgssprinc.patch b/SOURCES/libnfsidmap-0.25-nssgssprinc.patch new file mode 100644 index 00000000..e4c2c1ce --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-nssgssprinc.patch @@ -0,0 +1,40 @@ +nss_gss_princ_to_ids() and nss_gss_princ_to_grouplist() must strip the realm + +nss_gss_princ_to_ids() and nss_gss_princ_to_grouplist() were hard-coded +to call nss_getpwnam with the 'dostrip' arg set to 0, which is the +opposite of what they should have had. Note: there's no point making +the decision to strip or not to strip configurable in these two +functions. Ideally both of these functions should be taking a +gss_name_t instead of a char * for the principal, calling +gss_localname() on that, and passing the result to nss_getpwnam... but +that would require changes in both rpc.svcgssd and libgssglue (both of +which have been deprecated for a while). + +Fixes: 4db1bb1 (libnfsidmap: add options to aid id mapping in multi domain environments) +Signed-off-by: Scott Mayhew +--- + nss.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/nss.c b/nss.c +index 67e657a..82799ce 100644 +--- a/nss.c ++++ b/nss.c +@@ -415,7 +415,7 @@ static int nss_gss_princ_to_ids(char *secname, char *princ, + return -ENOENT; + } + /* XXX: this should call something like getgssauthnam instead? */ +- pw = nss_getpwnam(princ, NULL, &err, 0); ++ pw = nss_getpwnam(princ, NULL, &err, 1); + if (pw == NULL) { + err = -ENOENT; + goto out; +@@ -438,7 +438,7 @@ int nss_gss_princ_to_grouplist(char *secname, char *princ, + goto out; + /* XXX: not quite right? Need to know default realm? */ + /* XXX: this should call something like getgssauthnam instead? */ +- pw = nss_getpwnam(princ, NULL, &ret, 0); ++ pw = nss_getpwnam(princ, NULL, &ret, 1); + if (pw == NULL) { + ret = -ENOENT; + goto out; diff --git a/SOURCES/libnfsidmap-0.25-nullnames.patch b/SOURCES/libnfsidmap-0.25-nullnames.patch new file mode 100644 index 00000000..0fb07cca --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-nullnames.patch @@ -0,0 +1,42 @@ +commit 82718594eb8e6afabc572cea2da1caab69e9a720 +Author: Steve Dickson +Date: Thu Apr 30 13:55:32 2015 -0400 + + Handle NULL names better + + Detect when an application passes in NULL names + and fail gracefully instead of crashing hard. + + Signed-off-by: Steve Dickson + +diff --git a/libnfsidmap.c b/libnfsidmap.c +index 833f94c..a8a9229 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -100,8 +100,11 @@ static char * toupper_str(char *s) + + static int id_as_chars(char *name, uid_t *id) + { +- long int value = strtol(name, NULL, 10); ++ long int value; + ++ if (name == NULL) ++ return 0; ++ value = strtol(name, NULL, 10); + if (value == 0) { + /* zero value ids are valid */ + if (strcmp(name, "0") != 0) +diff --git a/nss.c b/nss.c +index f8129fe..b3fef5a 100644 +--- a/nss.c ++++ b/nss.c +@@ -135,6 +135,9 @@ static char *strip_domain(const char *name, const char *domain) + char *l = NULL; + int len; + ++ if (name == NULL) ++ goto out; ++ + c = strrchr(name, '@'); + if (c == NULL && domain != NULL) + goto out; diff --git a/SOURCES/libnfsidmap-0.25-strrchr.patch b/SOURCES/libnfsidmap-0.25-strrchr.patch new file mode 100644 index 00000000..7b1e7a2d --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-strrchr.patch @@ -0,0 +1,22 @@ +commit 309a89975a50bf53c408233a1bb5b10fd579ca30 +Author: Signed-off-by: Shijoe Panjikkaran +Date: Wed Apr 30 13:19:34 2014 -0400 + + nss: use strrchr() instead of strchr() to get the last occurrence of "@" + + Signed-off-by: Shijoe Panjikkaran + Signed-off-by: Steve Dickson + +diff --git a/nss.c b/nss.c +index b2b1227..f8129fe 100644 +--- a/nss.c ++++ b/nss.c +@@ -135,7 +135,7 @@ static char *strip_domain(const char *name, const char *domain) + char *l = NULL; + int len; + +- c = strchr(name, '@'); ++ c = strrchr(name, '@'); + if (c == NULL && domain != NULL) + goto out; + if (c == NULL && domain == NULL) { diff --git a/SOURCES/libnfsidmap-0.25-txt-bigrec.patch b/SOURCES/libnfsidmap-0.25-txt-bigrec.patch new file mode 100644 index 00000000..ac05e1c4 --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-txt-bigrec.patch @@ -0,0 +1,13 @@ +diff -up libnfsidmap-0.25/libnfsidmap.c.orig libnfsidmap-0.25/libnfsidmap.c +--- libnfsidmap-0.25/libnfsidmap.c.orig 2017-11-15 10:35:56.897700293 -0500 ++++ libnfsidmap-0.25/libnfsidmap.c 2017-11-15 10:38:57.655082342 -0500 +@@ -128,7 +128,8 @@ static int id_as_chars(char *name, uid_t + static int dns_txt_query(char *domain, char **nfs4domain) + { + char *txtname = NFS4DNSTXTREC; +- char *msg, *answ, *eom, *mptr; ++ unsigned char *msg, *eom, *mptr; ++ char *answ; + int len, status = -1; + HEADER *hdr; + diff --git a/SOURCES/libnfsidmap-0.25-warnings.patch b/SOURCES/libnfsidmap-0.25-warnings.patch new file mode 100644 index 00000000..223a6893 --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-warnings.patch @@ -0,0 +1,253 @@ +diff -up libnfsidmap-0.25/configure.ac.orig libnfsidmap-0.25/configure.ac +--- libnfsidmap-0.25/configure.ac.orig 2014-10-21 10:56:09.384577000 -0400 ++++ libnfsidmap-0.25/configure.ac 2014-10-21 10:56:09.382575000 -0400 +@@ -0,0 +1,67 @@ ++# -*- Autoconf -*- ++# Process this file with autoconf to produce a configure script. ++ ++AC_PREREQ([2.68]) ++AC_INIT([libnfsidmap],[0.25],[linux-nfs@vger.kernel.org]) ++AC_CONFIG_SRCDIR([nfsidmap.h]) ++AC_CONFIG_MACRO_DIR([m4]) ++AM_INIT_AUTOMAKE ++LT_INIT ++ ++# Checks for programs. ++AC_PROG_CC ++ ++# Checks for libraries. ++ ++AC_ARG_ENABLE([ldap], ++ [AS_HELP_STRING([--disable-ldap],[Disable support for LDAP @<:@default=detect@:>@])]) ++if test "x$enable_ldap" != "xno" ; then ++ AC_CHECK_HEADER([ldap.h], ++ [AC_CHECK_LIB([ldap], [ldap_initialize], ++ [have_ldap="yes"],[have_ldap="no"])], ++ [have_ldap="no"]) ++ if test "x$have_ldap" = "xyes" ; then ++ AC_DEFINE([ENABLE_LDAP], 1, [Enable LDAP Support]) ++ elif test "x$enable_ldap$have_ldap" = "xyesno" ; then ++ AC_MSG_ERROR(LDAP support not found!) ++ fi ++fi ++AM_CONDITIONAL(ENABLE_LDAP, test "x$have_ldap" = "xyes") ++ ++# Should we build gums mapping library? ++AC_ARG_ENABLE([gums], ++ [AS_HELP_STRING([--enable-gums],[Enable support for the GUMS mapping library @<:@default=false@:>@])]) ++if test "x$enable_gums" = "xyes" ; then ++ AC_DEFINE([ENABLE_GUMS], 1, [Enable GUMS mapping library support]) ++fi ++AM_CONDITIONAL(ENABLE_GUMS, test "x$enable_gums" = "xyes") ++ ++#Where do the Plugins live ++AC_ARG_WITH(pluginpath, ++ [AS_HELP_STRING([--with-pluginpath=/foo],[Causes the library to look in /foo instead of /usr/lib/libnfsidmap for plugins ++ ])], ++ path_plugins=$withval, ++ path_plugins="" ++ ) ++if test -n "$path_plugins" ; then ++ AC_DEFINE_UNQUOTED(PATH_PLUGINS, "$path_plugins", ++ [Define this to change the plugins path]) ++fi ++AM_CONDITIONAL(PATH_PLUGINS, test -n "$path_plugins") ++ ++AC_CONFIG_HEADERS([./config.h]) ++# Checks for header files. ++AC_HEADER_STDC ++AC_CHECK_HEADERS([stdlib.h string.h unistd.h errno.h]) ++ ++# Checks for typedefs, structures, and compiler characteristics. ++AC_TYPE_UID_T ++AC_TYPE_SIZE_T ++ ++# Checks for library functions. ++AC_FUNC_MALLOC ++AC_CHECK_FUNCS([strchr strdup]) ++ ++AC_CONFIG_FILES([Makefile]) ++AC_CONFIG_FILES([libnfsidmap.pc]) ++AC_OUTPUT +diff -up libnfsidmap-0.25/configure.in.orig libnfsidmap-0.25/configure.in +--- libnfsidmap-0.25/configure.in.orig 2011-12-05 15:48:54.000000000 -0500 ++++ libnfsidmap-0.25/configure.in 2014-10-21 10:56:09.388579000 -0400 +@@ -1,67 +0,0 @@ +-# -*- Autoconf -*- +-# Process this file with autoconf to produce a configure script. +- +-AC_PREREQ([2.68]) +-AC_INIT([libnfsidmap],[0.25],[linux-nfs@vger.kernel.org]) +-AC_CONFIG_SRCDIR([nfsidmap.h]) +-AC_CONFIG_MACRO_DIR([m4]) +-AM_INIT_AUTOMAKE +-LT_INIT +- +-# Checks for programs. +-AC_PROG_CC +- +-# Checks for libraries. +- +-AC_ARG_ENABLE([ldap], +- [AS_HELP_STRING([--disable-ldap],[Disable support for LDAP @<:@default=detect@:>@])]) +-if test "x$enable_ldap" != "xno" ; then +- AC_CHECK_HEADER([ldap.h], +- [AC_CHECK_LIB([ldap], [ldap_initialize], +- [have_ldap="yes"],[have_ldap="no"])], +- [have_ldap="no"]) +- if test "x$have_ldap" = "xyes" ; then +- AC_DEFINE([ENABLE_LDAP], 1, [Enable LDAP Support]) +- elif test "x$enable_ldap$have_ldap" = "xyesno" ; then +- AC_MSG_ERROR(LDAP support not found!) +- fi +-fi +-AM_CONDITIONAL(ENABLE_LDAP, test "x$have_ldap" = "xyes") +- +-# Should we build gums mapping library? +-AC_ARG_ENABLE([gums], +- [AS_HELP_STRING([--enable-gums],[Enable support for the GUMS mapping library @<:@default=false@:>@])]) +-if test "x$enable_gums" = "xyes" ; then +- AC_DEFINE([ENABLE_GUMS], 1, [Enable GUMS mapping library support]) +-fi +-AM_CONDITIONAL(ENABLE_GUMS, test "x$enable_gums" = "xyes") +- +-#Where do the Plugins live +-AC_ARG_WITH(pluginpath, +- [AS_HELP_STRING([--with-pluginpath=/foo],[Causes the library to look in /foo instead of /usr/lib/libnfsidmap for plugins +- ])], +- path_plugins=$withval, +- path_plugins="" +- ) +-if test -n "$path_plugins" ; then +- AC_DEFINE_UNQUOTED(PATH_PLUGINS, "$path_plugins", +- [Define this to change the plugins path]) +-fi +-AM_CONDITIONAL(PATH_PLUGINS, test -n "$path_plugins") +- +-AC_CONFIG_HEADERS([./config.h]) +-# Checks for header files. +-AC_HEADER_STDC +-AC_CHECK_HEADERS([stdlib.h string.h unistd.h errno.h]) +- +-# Checks for typedefs, structures, and compiler characteristics. +-AC_TYPE_UID_T +-AC_TYPE_SIZE_T +- +-# Checks for library functions. +-AC_FUNC_MALLOC +-AC_CHECK_FUNCS([strchr strdup]) +- +-AC_CONFIG_FILES([Makefile]) +-AC_CONFIG_FILES([libnfsidmap.pc]) +-AC_OUTPUT +diff -up libnfsidmap-0.25/libnfsidmap.c.orig libnfsidmap-0.25/libnfsidmap.c +--- libnfsidmap-0.25/libnfsidmap.c.orig 2014-10-21 10:55:29.626400000 -0400 ++++ libnfsidmap-0.25/libnfsidmap.c 2014-10-21 10:56:21.180926000 -0400 +@@ -98,7 +98,7 @@ static char * toupper_str(char *s) + return s; + } + +-static int id_as_chars(char *name, int *id) ++static int id_as_chars(char *name, uid_t *id) + { + long int value = strtol(name, NULL, 10); + +@@ -494,7 +494,7 @@ int nfs4_name_to_gid(char *name, gid_t * + RUN_TRANSLATIONS(name_to_gid, 0, name, gid); + } + +-static int set_id_to_nobody(int *id, int is_uid) ++static int set_id_to_nobody(uid_t *id, uid_t is_uid) + { + int rc = 0; + const char name[] = "nobody@"; +@@ -504,10 +504,10 @@ static int set_id_to_nobody(int *id, int + * configured, before we try to do a full lookup for the + * NFS nobody user. */ + if (is_uid && nobody_uid != (uid_t)-1) { +- *id = (int)nobody_uid; ++ *id = (uid_t)nobody_uid; + return 0; + } else if (!is_uid && nobody_gid != (gid_t)-1) { +- *id = (int)nobody_gid; ++ *id = (uid_t)nobody_gid; + return 0; + } + +@@ -542,7 +542,7 @@ int nfs4_group_owner_to_gid(char *name, + if (rc && id_as_chars(name, gid)) + rc = 0; + else if (rc) +- rc = set_id_to_nobody(gid, 0); ++ rc = set_id_to_nobody((uid_t *)gid, 0); + return rc; + } + +diff -up libnfsidmap-0.25/static.c.orig libnfsidmap-0.25/static.c +--- libnfsidmap-0.25/static.c.orig 2014-10-21 10:55:29.588399000 -0400 ++++ libnfsidmap-0.25/static.c 2014-10-21 10:56:21.186926000 -0400 +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #include "queue.h" + #include "cfg.h" +@@ -268,7 +269,6 @@ static int static_name_to_gid(char *name + + static int static_uid_to_name(uid_t uid, char *domain, char *name, size_t len) + { +- struct passwd *pw; + struct uid_mapping * um; + + for (um = LIST_FIRST (&uid_mappings[uid_hash (uid)]); um; +@@ -284,7 +284,6 @@ static int static_uid_to_name(uid_t uid, + + static int static_gid_to_name(gid_t gid, char *domain, char *name, size_t len) + { +- struct group *gr; + struct gid_mapping * gm; + + for (gm = LIST_FIRST (&gid_mappings[gid_hash (gid)]); gm; +@@ -305,7 +304,6 @@ static int static_gid_to_name(gid_t gid, + + static int static_init() { + int err; +- uid_t uid; + struct conf_list * princ_list = NULL; + struct conf_list_node * cln, *next; + struct uid_mapping * unode; +@@ -367,7 +365,7 @@ static int static_init() { + next = TAILQ_NEXT (cln, link); + + gr = static_getgrnam(cln->field, NULL, &err); +- if (!pw) { ++ if (!gr) { + continue; + } + +@@ -376,19 +374,19 @@ static int static_init() { + { + warnx("static_init: calloc (1, %lu) failed", + (unsigned long)sizeof *gnode); +- free(pw); ++ free(gr); + return -ENOMEM; + } +- gnode->gid = pw->pw_uid; ++ gnode->gid = gr->gr_gid; + gnode->principal = strdup(cln->field); + + gnode->localgroup = conf_get_str("Static", cln->field); + if (!gnode->localgroup) { +- free(pw); ++ free(gr); + return -ENOENT; + } + +- free(pw); ++ free(gr); + + LIST_INSERT_HEAD (&gid_mappings[gid_hash(gnode->gid)], gnode, link); + } diff --git a/SOURCES/libnfsidmap-0.25-whitspaces.patch b/SOURCES/libnfsidmap-0.25-whitspaces.patch new file mode 100644 index 00000000..d0fd67cb --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-whitspaces.patch @@ -0,0 +1,148 @@ +diff -up libnfsidmap-0.25/cfg.c.orig libnfsidmap-0.25/cfg.c +--- libnfsidmap-0.25/cfg.c.orig 2011-12-05 15:28:10.000000000 -0500 ++++ libnfsidmap-0.25/cfg.c 2017-11-17 12:01:56.756692437 -0500 +@@ -210,69 +210,98 @@ static void + conf_parse_line (int trans, char *line, size_t sz) + { + char *val; +- size_t i; +- int j; ++ char *ptr; + static char *section = 0; + static int ln = 0; + + ln++; + ++ /* Strip off any leading blanks */ ++ while (isblank(*line)) ++ line++; ++ ++ + /* Lines starting with '#' or ';' are comments. */ + if (*line == '#' || *line == ';') + return; + + /* '[section]' parsing... */ +- if (*line == '[') +- { +- for (i = 1; i < sz; i++) +- if (line[i] == ']') +- break; +- if (section) +- free (section); +- if (i == sz) +- { +- warnx("conf_parse_line: %d:" +- "non-matched ']', ignoring until next section", ln); +- section = 0; +- return; ++ if (*line == '[') { ++ line++; ++ ++ if (section) free(section); ++ ++ while (isblank(*line)) line++; ++ ++ /* find the closing ] */ ++ ptr = strchr(line, ']'); ++ ++ if (ptr == NULL) { ++ warnx("conf_parse_line: %d:" ++ "non-matched ']', ignoring until next section", ln); ++ section = NULL; ++ return; + } +- section = malloc (i); +- if (!section) +- { +- warnx("conf_parse_line: %d: malloc (%lu) failed", ln, +- (unsigned long)i); +- return; ++ ++ /* just ignore everything after the closing ] */ ++ *(ptr--) = '\0'; ++ ++ /* strip off any blanks before ']' */ ++ while (ptr >= line && isblank(*ptr)) ++ *(ptr--) = '\0'; ++ ++ section = strdup(line); ++ if (!section) { ++ warnx("conf_parse_line: %d: malloc failed", ln); ++ + } +- strlcpy (section, line + 1, i); +- return; +- } ++ return; ++ } + + /* Deal with assignments. */ +- for (i = 0; i < sz; i++) +- if (line[i] == '=') +- { +- /* If no section, we are ignoring the lines. */ +- if (!section) +- { ++ ptr = strchr(line, '='); ++ ++ /* not an assignment line */ ++ if (ptr == NULL) { ++ /* and not just whitespace either, weird */ ++ if (line[strspn(line, " \t")]) ++ warnx("conf_parse_line: %d: syntax error", ln); ++ return; ++ } ++ ++ /* If no section, we are ignoring the lines. */ ++ if (!section) { + warnx("conf_parse_line: %d: ignoring line due to no section", ln); + return; +- } +- line[strcspn (line, " \t=")] = '\0'; +- val = line + i + 1 + strspn (line + i + 1, " \t"); +- /* Skip trailing whitespace, if any */ +- for (j = sz - (val - line) - 1; j > 0 && isspace (val[j]); j--) +- val[j] = '\0'; +- /* XXX Perhaps should we not ignore errors? */ +- conf_set (trans, section, line, val, 0, 0); +- return; +- } +- +- /* Other non-empty lines are weird. */ +- i = strspn (line, " \t"); +- if (line[i]) +- warnx("conf_parse_line: %d: syntax error", ln); ++ } + +- return; ++ val = ptr + 1; ++ *(ptr--) = '\0'; ++ ++ /* strip spaces before and after the = */ ++ while (ptr >= line && isblank(*ptr)) ++ *(ptr--) = '\0'; ++ while (*val != '\0' && isblank(*val)) ++ val++; ++ ++ /* trim any trailing spaces or comments */ ++ if ((ptr=strchr(val, '#'))!=NULL) *ptr = '\0'; ++ if ((ptr=strchr(val, ';'))!=NULL) *ptr = '\0'; ++ ptr = val + strlen(val) - 1; ++ while (ptr > val && isspace(*ptr)) ++ *(ptr--) = '\0'; ++ ++ if (*line == '\0') { ++ warnx("conf_parse_line: %d: missing tag in assignment", ln); ++ return; ++ } ++ if (*val == '\0') { ++ warnx("conf_parse_line: %d: missing value in assignment", ln); ++ return; ++ } ++ ++ /* XXX Perhaps should we not ignore errors? */ ++ conf_set (trans, section, line, val, 0, 0); + } + + /* Parse the mapped configuration file. */ diff --git a/SOURCES/libnfsidmap-0.25-zero-ids.patch b/SOURCES/libnfsidmap-0.25-zero-ids.patch new file mode 100644 index 00000000..a037570c --- /dev/null +++ b/SOURCES/libnfsidmap-0.25-zero-ids.patch @@ -0,0 +1,30 @@ +commit 3226c06989186d9cd60ba146df4e2898fee5047b +Author: Steve Dickson +Date: Wed Apr 30 11:14:22 2014 -0400 + + libnfsidmap: id_as_chars() fails zero value ids. + + Root has a zero value id which is valid and + should not be mapped to nfsnobody + + Signed-off-by: Steve Dickson + +diff --git a/libnfsidmap.c b/libnfsidmap.c +index 641d766..92bc493 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -99,8 +99,12 @@ static char * toupper_str(char *s) + static int id_as_chars(char *name, int *id) + { + long int value = strtol(name, NULL, 10); +- if (value == 0) +- return 0; ++ ++ if (value == 0) { ++ /* zero value ids are valid */ ++ if (strcmp(name, "0") != 0) ++ return 0; ++ } + *id = (int)value; + return 1; + } diff --git a/SOURCES/libnfsidmap-0.26-rc3.patch b/SOURCES/libnfsidmap-0.26-rc3.patch new file mode 100644 index 00000000..35eb9f28 --- /dev/null +++ b/SOURCES/libnfsidmap-0.26-rc3.patch @@ -0,0 +1,438 @@ +diff --git a/.gitignore b/.gitignore +index 6244609..d24d727 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -17,18 +17,13 @@ libnfsidmap.pc + libtool + .libs/ + libnfsidmap.la +-libnfsidmap_la-cfg.lo +-libnfsidmap_la-libnfsidmap.lo +-libnfsidmap_la-strlcpy.lo +-nss.lo + nsswitch.la + static.la +-static.lo + umich_ldap.la +-umich_ldap.lo + configure.in~ + m4/ + *.o ++*.lo + cscope.* + config.h + config.h.in +diff --git a/autogen.sh b/autogen.sh +index ee89987..c17f6be 100755 +--- a/autogen.sh ++++ b/autogen.sh +@@ -37,5 +37,6 @@ fi + + aclocal + libtoolize --force --copy +-autoupdate ++autoheader ++automake --add-missing --copy --gnu + autoreconf -vi -Wall +diff --git a/idmapd.conf.5 b/idmapd.conf.5 +index 9c7f1ae..de1bfa9 100644 +--- a/idmapd.conf.5 ++++ b/idmapd.conf.5 +@@ -31,7 +31,7 @@ + .\" + .TH idmapd.conf 5 "19 Nov 2008" + .SH NAME +-idmapd.conf ++idmapd.conf \- configuration file for libnfsidmap + .SH SYNOPSIS + Configuration file for libnfsidmap. Used by idmapd and svcgssd to map NFSv4 name to and from ids. + .SH DESCRIPTION +@@ -234,7 +234,6 @@ Number of seconds before timing out an LDAP request + .\" ------------------------------------------------------------------- + .\" + .SH EXAMPLES +-." + An example + .I /etc/idmapd.conf + file: +@@ -266,7 +265,7 @@ johndoe@OTHER.DOMAIN.ORG = johnny + LDAP_server = ldap.domain.org + LDAP_base = dc=org,dc=domain + +-.fo ++.fi + .\" + .\" ------------------------------------------------------------------- + .\" Additional sections +@@ -275,11 +274,11 @@ LDAP_base = dc=org,dc=domain + .SH SEE ALSO + .BR idmapd (8) + .BR svcgssd (8) +-.".SH COMPATIBILITY +-.".SH STANDARDS +-.".SH ACKNOWLEDGEMENTS +-.".SH AUTHORS +-.".SH HISTORY ++.\".SH COMPATIBILITY ++.\".SH STANDARDS ++.\".SH ACKNOWLEDGEMENTS ++.\".SH AUTHORS ++.\".SH HISTORY + .SH BUGS + Report bugs to +-.".SH CAVEATS ++.\".SH CAVEATS +diff --git a/libnfsidmap.c b/libnfsidmap.c +index 57bb6c3..641d766 100644 +--- a/libnfsidmap.c ++++ b/libnfsidmap.c +@@ -285,8 +285,9 @@ int nfs4_init_name_mapping(char *conffile) + } + buf = malloc(siz); + if (buf) { ++ *buf = 0; + TAILQ_FOREACH(r, &local_realms->fields, link) { +- sprintf(buf, "'%s' ", r->field); ++ sprintf(buf+strlen(buf), "'%s' ", r->field); + } + IDMAP_LOG(1, ("libnfsidmap: Realms list: %s", buf)); + free(buf); +diff --git a/static.c b/static.c +index fffd458..8be87e8 100644 +--- a/static.c ++++ b/static.c +@@ -40,6 +40,7 @@ + #include + #include + ++#include "queue.h" + #include "cfg.h" + #include "nfsidmap.h" + #include "nfsidmap_internal.h" +@@ -57,6 +58,40 @@ struct pwbuf { + char buf[1]; + }; + ++struct grbuf { ++ struct group grbuf; ++ char buf[1]; ++}; ++ ++struct uid_mapping { ++ LIST_ENTRY (uid_mapping) link; ++ uid_t uid; ++ char * principal; ++ char * localname; ++}; ++ ++struct gid_mapping { ++ LIST_ENTRY (gid_mapping) link; ++ gid_t gid; ++ char * principal; ++ char * localgroup; ++}; ++ ++static __inline__ u_int8_t uid_hash (uid_t uid) ++{ ++ return uid % 256; ++} ++ ++static __inline__ u_int8_t gid_hash (gid_t gid) ++{ ++ return gid % 256; ++} ++ ++//Hash tables of uid and guids to principals mappings. ++//We reuse some queue/hash functions from cfg.c. ++LIST_HEAD (uid_mappings, uid_mapping) uid_mappings[256]; ++LIST_HEAD (gid_mappings, gid_mapping) gid_mappings[256]; ++ + static struct passwd *static_getpwnam(const char *name, const char *domain, + int *err_p) + { +@@ -75,12 +110,9 @@ static struct passwd *static_getpwnam(const char *name, const char *domain, + localname = conf_get_str("Static", (char *)name); + if (!localname) { + err = ENOENT; +- goto err; ++ goto err_free_buf; + } + +- IDMAP_LOG(4, ("static_getpwnam: name '%s' mapped to '%s'\n", +- name, localname)); +- + again: + err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw); + +@@ -91,12 +123,15 @@ again: + if (err == 0) + err = ENOENT; + +- IDMAP_LOG(0, ("static_getpwnam: name '%s' not found\n", +- localname)); ++ IDMAP_LOG(0, ("static_getpwnam: localname '%s' for '%s' not found\n", ++ localname, name)); + + goto err_free_buf; + } + ++ IDMAP_LOG(4, ("static_getpwnam: name '%s' mapped to '%s'\n", ++ name, localname)); ++ + *err_p = 0; + return pw; + +@@ -107,6 +142,56 @@ err: + return NULL; + } + ++static struct group *static_getgrnam(const char *name, const char *domain, ++ int *err_p) ++{ ++ struct group *gr; ++ struct grbuf *buf; ++ size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); ++ char *localgroup; ++ int err; ++ ++ buf = malloc(sizeof(*buf) + buflen); ++ if (!buf) { ++ err = ENOMEM; ++ goto err; ++ } ++ ++ localgroup = conf_get_str("Static", (char *)name); ++ if (!localgroup) { ++ err = ENOENT; ++ goto err_free_buf; ++ } ++ ++again: ++ err = getgrnam_r(localgroup, &buf->grbuf, buf->buf, buflen, &gr); ++ ++ if (err == EINTR) ++ goto again; ++ ++ if (!gr) { ++ if (err == 0) ++ err = ENOENT; ++ ++ IDMAP_LOG(0, ("static_getgrnam: local group '%s' for '%s' not found\n", ++ localgroup, name)); ++ ++ goto err_free_buf; ++ } ++ ++ IDMAP_LOG(4, ("static_getgrnam: group '%s' mapped to '%s'\n", ++ name, localgroup)); ++ ++ *err_p = 0; ++ return gr; ++ ++err_free_buf: ++ free(buf); ++err: ++ *err_p = err; ++ return NULL; ++} ++ + static int static_gss_princ_to_ids(char *secname, char *princ, + uid_t *uid, uid_t *gid, + extra_mapping_params **ex) +@@ -151,14 +236,173 @@ static int static_gss_princ_to_grouplist(char *secname, char *princ, + return -err; + } + ++static int static_name_to_uid(char *name, uid_t *uid) ++{ ++ struct passwd *pw; ++ int err; ++ ++ pw = static_getpwnam(name, NULL, &err); ++ ++ if (pw) { ++ *uid = pw->pw_uid; ++ free(pw); ++ } ++ ++ return -err; ++} ++ ++static int static_name_to_gid(char *name, gid_t *gid) ++{ ++ struct group *gr; ++ int err; ++ ++ gr = static_getgrnam(name, NULL, &err); ++ ++ if (gr) { ++ *gid = gr->gr_gid; ++ free(gr); ++ } ++ ++ return -err; ++} ++ ++static int static_uid_to_name(uid_t uid, char *domain, char *name, size_t len) ++{ ++ struct passwd *pw; ++ struct uid_mapping * um; ++ ++ for (um = LIST_FIRST (&uid_mappings[uid_hash (uid)]); um; ++ um = LIST_NEXT (um, link)) { ++ if (um->uid == uid) { ++ strcpy(name, um->principal); ++ return 0; ++ } ++ } ++ ++ return -ENOENT; ++} ++ ++static int static_gid_to_name(gid_t gid, char *domain, char *name, size_t len) ++{ ++ struct group *gr; ++ struct gid_mapping * gm; ++ ++ for (gm = LIST_FIRST (&gid_mappings[gid_hash (gid)]); gm; ++ gm = LIST_NEXT (gm, link)) { ++ if (gm->gid == gid) { ++ strcpy(name, gm->principal); ++ return 0; ++ } ++ } ++ ++ return -ENOENT; ++} ++ ++/* ++ * We buffer all UID's for which static mappings is defined in advance, so the ++ * uid_to_name functions will be fast enough. ++ */ ++ ++static int static_init() { ++ int err; ++ uid_t uid; ++ struct conf_list * princ_list = NULL; ++ struct conf_list_node * cln, *next; ++ struct uid_mapping * unode; ++ struct gid_mapping * gnode; ++ struct passwd * pw = NULL; ++ struct group * gr = NULL; ++ unsigned int i; ++ ++ //init hash_table first ++ for (i = 0; i < sizeof uid_mappings / sizeof uid_mappings[0]; i++) ++ LIST_INIT (&uid_mappings[i]); ++ ++ //get all principals for which we have mappings ++ princ_list = conf_get_tag_list("Static"); ++ ++ if (!princ_list) { ++ return -ENOENT; ++ } ++ ++ /* As we can not distinguish between mappings for users and groups, we try to ++ * resolve all mappings for both cases. ++ */ ++ ++ //resolve uid of localname account for all such principals and cache it ++ for (cln = TAILQ_FIRST (&princ_list->fields); cln; cln = next) ++ { ++ next = TAILQ_NEXT (cln, link); ++ ++ pw = static_getpwnam(cln->field, NULL, &err); ++ if (!pw) { ++ continue; ++ } ++ ++ unode = calloc (1, sizeof *unode); ++ if (!unode) ++ { ++ warnx("static_init: calloc (1, %lu) failed", ++ (unsigned long)sizeof *unode); ++ free(pw); ++ return -ENOMEM; ++ } ++ unode->uid = pw->pw_uid; ++ unode->principal = strdup(cln->field); ++ ++ unode->localname = conf_get_str("Static", cln->field); ++ if (!unode->localname) { ++ free(pw); ++ return -ENOENT; ++ } ++ ++ free(pw); ++ ++ LIST_INSERT_HEAD (&uid_mappings[uid_hash(unode->uid)], unode, link); ++ } ++ ++ //resolve gid of localgroup accounts and cache it ++ for (cln = TAILQ_FIRST (&princ_list->fields); cln; cln = next) ++ { ++ next = TAILQ_NEXT (cln, link); ++ ++ gr = static_getgrnam(cln->field, NULL, &err); ++ if (!pw) { ++ continue; ++ } ++ ++ gnode = calloc (1, sizeof *gnode); ++ if (!gnode) ++ { ++ warnx("static_init: calloc (1, %lu) failed", ++ (unsigned long)sizeof *gnode); ++ free(pw); ++ return -ENOMEM; ++ } ++ gnode->gid = pw->pw_uid; ++ gnode->principal = strdup(cln->field); ++ ++ gnode->localgroup = conf_get_str("Static", cln->field); ++ if (!gnode->localgroup) { ++ free(pw); ++ return -ENOENT; ++ } ++ ++ free(pw); ++ ++ LIST_INSERT_HEAD (&gid_mappings[gid_hash(gnode->gid)], gnode, link); ++ } ++ return 0; ++} ++ + + struct trans_func static_trans = { + .name = "static", +- .init = NULL, +- .name_to_uid = NULL, +- .name_to_gid = NULL, +- .uid_to_name = NULL, +- .gid_to_name = NULL, ++ .init = static_init, ++ .name_to_uid = static_name_to_uid, ++ .name_to_gid = static_name_to_gid, ++ .uid_to_name = static_uid_to_name, ++ .gid_to_name = static_gid_to_name, + .princ_to_ids = static_gss_princ_to_ids, + .gss_princ_to_grouplist = static_gss_princ_to_grouplist, + }; +diff --git a/umich_ldap.c b/umich_ldap.c +index f482b0a..b527c5d 100644 +--- a/umich_ldap.c ++++ b/umich_ldap.c +@@ -32,8 +32,6 @@ + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-#ifdef ENABLE_LDAP +- + #include + #include + #include +@@ -1302,4 +1300,3 @@ struct trans_func *libnfsidmap_plugin_init() + { + return (&umichldap_trans); + } +-#endif diff --git a/SPECS/libnfsidmap.spec b/SPECS/libnfsidmap.spec new file mode 100644 index 00000000..9a3aad79 --- /dev/null +++ b/SPECS/libnfsidmap.spec @@ -0,0 +1,230 @@ +%define _root_libdir /%{_lib} + +Summary: NFSv4 User and Group ID Mapping Library +Name: libnfsidmap +Version: 0.25 +Release: 19%{?dist} +Provides: libnfsidmap +Obsoletes: nfs-utils-lib +URL: http://www.citi.umich.edu/projects/nfsv4/linux/ +License: BSD + +Source0: http://www.citi.umich.edu/projects/nfsv4/linux/libnfsidmap/%{name}-%{version}.tar.gz + +Patch001: libnfsidmap-0.26-rc3.patch +Patch002: libnfsidmap-0.25-zero-ids.patch +Patch003: libnfsidmap-0.25-nobody.patch +Patch004: libnfsidmap-0.25-strrchr.patch +Patch005: libnfsidmap-0.25-warnings.patch +# +# RHEL7.2 +# +Patch006: libnfsidmap-0.25-nullnames.patch +# +# RHEL7.3 +# +Patch007: libnfsidmap-0.2-stripnewlines.patch +Patch008: libnfsidmap-0.2-negativerets.patch +Patch009: libnfsidmap-0.2-memleak.patch +# +# RHEL7.4 +# +Patch010: libnfsidmap-0.25-multidomain.patch +Patch011: libnfsidmap-0.25-dns-resolved.patch +Patch012: libnfsidmap-0.25-nssgssprinc.patch +# +# RHEL7.5 +# +Patch013: libnfsidmap-0.25-txt-bigrec.patch +Patch014: libnfsidmap-0.25-whitspaces.patch + +Group: System Environment/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-root +BuildRequires: pkgconfig, openldap-devel +BuildRequires: automake, libtool +Requires(postun): /sbin/ldconfig +Requires(pre): /sbin/ldconfig +Requires: openldap + +%description +Library that handles mapping between names and ids for NFSv4. + +%package devel +Summary: Development files for the libnfsidmap library +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + +%description devel +This package includes header files and libraries necessary for +developing programs which use the libnfsidmap library. + +%prep +%setup -q + +%patch001 -p1 + +# +# RHEL7.1 +# +# 1093093 - chown does not respect NFSv4 no_root_squash +%patch002 -p1 +# 1129790 - libnfsidmap: respect Nobody-User/Nobody-Group +%patch003 -p1 +# 1114053 - RFE: Make rpcidmap and NFS accept full qualified usernames as a user. +%patch004 -p1 +# 1152658 - A large number of warning occur when the source is compiled +%patch005 -p1 +# 1214882 - libnfsidmap: crash due to not checking argument +%patch006 -p1 +# 1261124 - libnfsidmap: strip newlines out of IDMAP_LOG messages +%patch007 -p1 +# 1271449 - "Covscan test" failures in errata RHBA-2015:20444-05.... +%patch008 -p1 +%patch009 -p1 +# 1378557 - NFSv4 id mapping issues in multi-domain environments +%patch010 -p1 +# 980925 - rpc.idmapd should support getting the NFSv4 ID Domains from DNS +%patch011 -p1 +# 1420352 - Cannot create file in it's directory using kerberos.... +%patch012 -p1 +# 1498210 - domain lookup by TXT record can crash idmapd if the... +%patch013 -p1 +# 1455923 - Static IP mapping does not allow to map groups with... +%patch014 -p1 + +rm -f configure.in + +%build +./autogen.sh +%configure --disable-static --with-pluginpath=%{_root_libdir}/%name +make %{?_smp_mflags} all + +%install +rm -rf %{buildroot} +make install DESTDIR=%{buildroot} \ + libdir=%{_root_libdir} pkgconfigdir=%{_libdir}/pkgconfig + +mkdir -p %{buildroot}%{_sysconfdir} +mkdir -p %{buildroot}%{_mandir}/man5 + +install -m 644 idmapd.conf %{buildroot}%{_sysconfdir}/idmapd.conf + +# Delete unneeded libtool libs +rm -rf %{buildroot}%{_root_libdir}/*.{a,la} +rm -rf %{buildroot}%{_root_libdir}/%{name}/*.{a,la} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%doc AUTHORS ChangeLog NEWS README COPYING +%config(noreplace) %{_sysconfdir}/idmapd.conf +%{_root_libdir}/*.so.* +%{_root_libdir}/%{name}/*.so +%{_mandir}/*/* + +%files devel +%defattr(0644,root,root,755) +%{_libdir}/pkgconfig/libnfsidmap.pc +%{_includedir}/nfsidmap.h +%{_root_libdir}/*.so + +%changelog +* Fri Nov 17 2017 Steve Dickson 0.25-19 +- Fixed patch for bz 1455923 + +* Wed Nov 15 2017 Steve Dickson 0.25-18 +- Enlarge the TXT record to lager than 127 characters (bz 1498210) +- Allow white spaces in static IP mapping (bz 1455923) + +* Fri Feb 17 2017 Steve Dickson 0.25-17 +- Fixed stripping realm problem in nss_gss_princ routines (bz 1420352) + +* Tue Jan 10 2017 Steve Dickson 0.25-16 +- Add options to aid id mapping in multi domain environments (bz 1378557) +- Query DNS for the the NFSv4 domain (bz 980925) + +* Wed Aug 17 2016 Steve Dickson 0.25-15 +- nss_getpwnam: correctly check for negative values (bz 1271449) +- Fixed a memory leak in nss_name_to_gid() (bz 1271449) + +* Thu Apr 7 2016 Steve Dickson 0.25-13 +- Strip newlines out of IDMAP_LOG messages (bz 1261124) +- Fixed some NEGATIVE_RETURNS that a Covscan scan found (bz 1271449) + +* Mon May 4 2015 Steve Dickson 0.25-12 +- Handle NULL names better (bz 1214882) + +* Tue Oct 21 2014 Steve Dickson 0.25-11 +- Accept full qualified usernames a a user (bz 1114053) +- Removed a number of warnings (bz 1152658) + +* Wed Sep 17 2014 Steve Dickson 0.25-10 +- id_as_chars() fails zero value ids (bz 1093093) +- respect Nobody-User/Nobody-Group (bz 1129790) + +* Fri Jan 24 2014 Daniel Mach - 0.25-9 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.25-8 +- Mass rebuild 2013-12-27 + +* Mon Aug 19 2013 Ville Skyttä - 0.25-7 +- Updated to latest rc release: libnfsidmap-0-26-rc3 + +* Fri Jul 26 2013 Ville Skyttä - 0.25-6 +- Drop unnecessary doc dir references from specfile. +- Fix bogus dates in %%changelog. + +* Thu Feb 14 2013 Fedora Release Engineering - 0.25-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Thu Jul 19 2012 Fedora Release Engineering - 0.25-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jun 19 2012 Steve Dickson 0.20-3 +- Updated to latest rc release: libnfsidmap-0-26-rc1 + +* Mon Mar 19 2012 Steve Dickson 0.20-2 +- Fixed Local-Realms debugging (bz 804152) + +* Fri Jan 13 2012 Fedora Release Engineering - 0.25-1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Dec 6 2011 Steve Dickson 0.20-0 +- Updated to latest release: libnfsidmap-0.25 + +* Mon Nov 14 2011 Steve Dickson 0.24-7 +- Updated to latest rc release: libnfsidmap-0-25-rc3 (bz 753930) + +* Mon Mar 7 2011 Steve Dickson 0.24-6 +- Updated to latest rc release: libnfsidmap-0-25-rc2 + +* Tue Feb 08 2011 Fedora Release Engineering - 0.24-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Jan 14 2011 Steve Dickson 0.24-4 +- Updated to latest rc release: libnfsidmap-0-25-rc1 + +* Wed Dec 22 2010 Steve Dickson 0.24-3 +- Used the newly added --with-pluginpath config flag to + redefine where the plugins live (bz 664641). + +* Fri Dec 10 2010 Steve Dickson 0.24-2 +- Removed the versions from the Provides: and Obsoletes: lines + +* Wed Dec 8 2010 Steve Dickson 0.24-1 +- Updated to latest upstream release: 0.24 +- Obsoleted nfs-utils-lib + +* Tue Dec 7 2010 Steve Dickson 0.23-3 +- Maded corrections in spec per review comments. + +* Fri Dec 3 2010 Steve Dickson 0.23-2 +- Initial commit