Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142089979
D47147.id144971.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D47147.id144971.diff
View Options
diff --git a/include/nsswitch.h b/include/nsswitch.h
--- a/include/nsswitch.h
+++ b/include/nsswitch.h
@@ -190,7 +190,8 @@
enum nss_lookup_type {
nss_lt_name = 1,
nss_lt_id = 2,
- nss_lt_all = 3
+ nss_lt_all = 3,
+ nss_lt_pivot= 4
};
#ifdef _NS_PRIVATE
diff --git a/usr.sbin/nscd/agents/group.c b/usr.sbin/nscd/agents/group.c
--- a/usr.sbin/nscd/agents/group.c
+++ b/usr.sbin/nscd/agents/group.c
@@ -28,20 +28,84 @@
#include <sys/param.h>
#include <assert.h>
+#include <errno.h>
#include <grp.h>
#include <nsswitch.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "../debug.h"
#include "group.h"
+#define GROUP_STORAGE_INITIAL (1 << 10)
+#define GROUP_STORAGE_MAX (1 << 20)
+
+typedef struct key {
+ char *name;
+ gid_t gid;
+} st_key;
+
+static int wrap_getgrnam_r(st_key, struct group *, char *, size_t,
+ struct group **);
+static int wrap_getgrgid_r(st_key, struct group *, char *, size_t,
+ struct group **);
+static int wrap_getgrent_r(st_key, struct group *, char *, size_t,
+ struct group **);
+static char *wrap_getgrouplist(st_key, size_t *);
+static char *getgr(int (*)(st_key, struct group *, char *, size_t,
+ struct group **), st_key, size_t *);
+
static int group_marshal_func(struct group *, char *, size_t *);
+static int grouplist_marshal_func(gid_t *, int, char *, size_t *);
static int group_lookup_func(const char *, size_t, char **, size_t *);
static void *group_mp_init_func(void);
static int group_mp_lookup_func(char **, size_t *, void *);
static void group_mp_destroy_func(void *);
+static int
+wrap_getgrnam_r(st_key skey, struct group *group, char *buffer, size_t size,
+ struct group **result)
+{
+ return (getgrnam_r(skey.name, group, buffer, size, result));
+}
+
+static int
+wrap_getgrgid_r(st_key skey, struct group *group, char *buffer, size_t size,
+ struct group **result)
+{
+ return (getgrgid_r(skey.gid, group, buffer, size, result));
+}
+
+static int
+wrap_getgrent_r(st_key skey __unused, struct group *group, char *buffer,
+ size_t size, struct group **result)
+{
+ return (getgrent_r(group, buffer, size, result));
+}
+
+static int
+grouplist_marshal_func(gid_t *gids, int ngids, char *buffer,
+ size_t* buffer_size)
+{
+ size_t desired_size;
+ TRACE_IN(grouplist_marshal_func);
+
+ desired_size = sizeof(int) + (ngids * sizeof(gid_t));
+ if (buffer == NULL || desired_size > *buffer_size) {
+ *buffer_size = desired_size;
+ TRACE_OUT(grouplist_marshal_func);
+
+ return NS_RETURN;
+ }
+ *buffer_size = desired_size;
+ memcpy(buffer, &ngids, sizeof(ngids));
+ memcpy(buffer + sizeof(ngids), gids, sizeof(gid_t) * ngids);
+ TRACE_OUT(grouplist_marshal_func);
+
+ return (NS_SUCCESS);
+}
+
static int
group_marshal_func(struct group *grp, char *buffer, size_t *buffer_size)
{
@@ -119,15 +183,14 @@
size_t *buffer_size)
{
enum nss_lookup_type lookup_type;
- char *name;
+ st_key stkey;
size_t size;
- gid_t gid;
-
- struct group *result;
+ int gr_errno;
TRACE_IN(group_lookup_func);
assert(buffer != NULL);
assert(buffer_size != NULL);
+ *buffer_size = 0;
if (key_size < sizeof(enum nss_lookup_type)) {
TRACE_OUT(group_lookup_func);
@@ -137,48 +200,67 @@
switch (lookup_type) {
case nss_lt_name:
- size = key_size - sizeof(enum nss_lookup_type) + 1;
- name = calloc(1, size);
- assert(name != NULL);
- memcpy(name, key + sizeof(enum nss_lookup_type), size - 1);
+ if (key_size < sizeof(enum nss_lookup_type) + 2) {
+ TRACE_OUT(group_lookup_func);
+
+ return (NS_UNAVAIL);
+ }
+
+ size = key_size - sizeof(enum nss_lookup_type);
+ stkey.name = malloc(size);
+ assert(stkey.name != NULL);
+
+ memcpy(stkey.name, key + sizeof(enum nss_lookup_type), size);
+ stkey.name[size-1] = 0x00;
+
+ TRACE_STR(stkey.name);
+ errno = 0;
+ *buffer = getgr(wrap_getgrnam_r, stkey, buffer_size);
+ gr_errno = errno;
+ free(stkey.name);
+
break;
case nss_lt_id:
if (key_size < sizeof(enum nss_lookup_type) +
sizeof(gid_t)) {
- TRACE_OUT(passwd_lookup_func);
+ TRACE_OUT(group_lookup_func);
+
return (NS_UNAVAIL);
}
+ memcpy(&(stkey.gid), key + sizeof(enum nss_lookup_type), sizeof(gid_t));
+ errno=0;
+ *buffer = getgr(wrap_getgrgid_r, stkey, buffer_size);
+ gr_errno = errno;
- memcpy(&gid, key + sizeof(enum nss_lookup_type), sizeof(gid_t));
break;
- default:
- TRACE_OUT(group_lookup_func);
- return (NS_UNAVAIL);
- }
+ case nss_lt_pivot:
+ if (key_size < sizeof(enum nss_lookup_type) + 2
+ + sizeof(gid_t)) {
+ TRACE_OUT(group_lookup_func);
+ return (NS_UNAVAIL);
+ }
+ size = key_size - sizeof(enum nss_lookup_type) - sizeof(gid_t);
+ stkey.name = malloc(size);
+ assert(stkey.name != NULL);
+ memcpy(stkey.name, key + sizeof(enum nss_lookup_type), size);
+ stkey.name[size-1]=0x00;
+
+ memcpy (&(stkey.gid), key + sizeof(enum nss_lookup_type) + size, sizeof(gid_t));
+
+ errno = 0;
+ *buffer = wrap_getgrouplist(stkey, buffer_size);
+ gr_errno = errno;
- switch (lookup_type) {
- case nss_lt_name:
- TRACE_STR(name);
- result = getgrnam(name);
- free(name);
- break;
- case nss_lt_id:
- result = getgrgid(gid);
break;
default:
- /* SHOULD NOT BE REACHED */
- break;
- }
-
- if (result != NULL) {
- group_marshal_func(result, NULL, buffer_size);
- *buffer = malloc(*buffer_size);
- assert(*buffer != NULL);
- group_marshal_func(result, *buffer, buffer_size);
+ TRACE_OUT(group_lookup_func);
+ return (NS_UNAVAIL);
}
TRACE_OUT(group_lookup_func);
- return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+ return (*buffer == NULL ?
+ (gr_errno == 0 ? NS_NOTFOUND : NS_UNAVAIL) :
+ NS_SUCCESS);
}
static void *
@@ -194,19 +276,20 @@
static int
group_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
{
- struct group *result;
+ st_key stkey;
TRACE_IN(group_mp_lookup_func);
- result = getgrent();
- if (result != NULL) {
- group_marshal_func(result, NULL, buffer_size);
- *buffer = malloc(*buffer_size);
- assert(*buffer != NULL);
- group_marshal_func(result, *buffer, buffer_size);
- }
+ assert(buffer != NULL);
+ assert(buffer_size != NULL);
+ *buffer_size = 0;
+ errno = 0;
+ stkey.name = NULL;
+ *buffer = getgr(wrap_getgrent_r, stkey, buffer_size);
TRACE_OUT(group_mp_lookup_func);
- return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+ return (*buffer == NULL ?
+ (errno == 0 ? NS_NOTFOUND : NS_UNAVAIL) :
+ NS_SUCCESS);
}
static void
@@ -255,3 +338,83 @@
TRACE_OUT(init_group_mp_agent);
return ((struct agent *)retval);
}
+
+static char *wrap_getgrouplist(st_key skey, size_t *buffer_size)
+{
+ int return_value;
+ gid_t *gids = NULL;
+ int ngids = 0;
+ char *buffer;
+
+ errno = 0;
+ return_value = getgrouplist(skey.name, skey.gid, gids, &ngids);
+
+ while (return_value == -1 && errno == 0) {
+ gids = realloc(gids, ngids * sizeof(gid_t));
+ assert (gids != NULL);
+ errno=0;
+ return_value=getgrouplist(skey.name, skey.gid, gids, &ngids);
+ }
+
+ if (errno != 0) {
+ free (gids);
+ return (NULL);
+ }
+
+ grouplist_marshal_func(gids, ngids, NULL, buffer_size);
+ buffer = malloc(*buffer_size);
+ assert(buffer != NULL);
+ grouplist_marshal_func(gids, ngids, buffer, buffer_size);
+ free(gids);
+
+ return (buffer);
+}
+
+static char *
+getgr(int (*fn)(st_key, struct group *, char *, size_t, struct group **),
+ st_key skey, size_t *buffer_size)
+{
+ int return_value;
+ struct group group, *result;
+ char *group_storage, *buffer;
+ size_t group_storage_size = GROUP_STORAGE_INITIAL;
+
+ group_storage = malloc(group_storage_size);
+ if (group_storage == NULL) {
+
+ return (NULL);
+ }
+ do {
+ return_value = fn(skey, &group, group_storage, group_storage_size, &result);
+ if (result == NULL && return_value == ERANGE) {
+ free(group_storage);
+ group_storage = NULL;
+ group_storage_size <<= 1;
+ if (group_storage_size > GROUP_STORAGE_MAX) {
+ errno = ERANGE;
+
+ return (NULL);
+ }
+ group_storage = malloc(group_storage_size);
+ if (group_storage == NULL) {
+
+ return (NULL);
+ }
+ }
+ } while (result == NULL && return_value == ERANGE);
+ errno = return_value;
+ if (return_value != 0 || result == NULL) {
+ free(group_storage);
+
+ return (NULL);
+ }
+
+ group_marshal_func(&group, NULL, buffer_size);
+ buffer = malloc(*buffer_size);
+ assert(buffer != NULL);
+ group_marshal_func(&group, buffer, buffer_size);
+
+ free(group_storage);
+
+ return (buffer);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 16, 11:12 PM (8 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27672627
Default Alt Text
D47147.id144971.diff (8 KB)
Attached To
Mode
D47147: nscd step5
Attached
Detach File
Event Timeline
Log In to Comment