Page MenuHomeFreeBSD

D47146.diff
No OneTemporary

D47146.diff

diff --git a/usr.sbin/nscd/agents/passwd.c b/usr.sbin/nscd/agents/passwd.c
--- a/usr.sbin/nscd/agents/passwd.c
+++ b/usr.sbin/nscd/agents/passwd.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <assert.h>
+#include <errno.h>
#include <nsswitch.h>
#include <pwd.h>
#include <stdlib.h>
@@ -36,12 +37,88 @@
#include "../debug.h"
#include "passwd.h"
+#define PASSWD_STORAGE_INITIAL (1<<10)
+#define PASSWD_STORAGE_MAX (1<<20)
+
+typedef union key {
+ char *login;
+ uid_t uid;
+} u_key;
+
static int passwd_marshal_func(struct passwd *, char *, size_t *);
static int passwd_lookup_func(const char *, size_t, char **, size_t *);
static void *passwd_mp_init_func(void);
static int passwd_mp_lookup_func(char **, size_t *, void *);
static void passwd_mp_destroy_func(void *mdata);
+static char *getpw(int (*)(u_key, struct passwd *, char *, size_t,
+ struct passwd **), u_key, size_t *);
+static int wrap_getpwnam_r(u_key, struct passwd *, char *, size_t,
+ struct passwd **);
+static int wrap_getpwuid_r(u_key, struct passwd *, char *, size_t,
+ struct passwd **);
+static int wrap_getpwent_r(u_key, struct passwd *, char *, size_t,
+ struct passwd **);
+
+static char *
+getpw(int (*fn)(u_key, struct passwd *, char *, size_t, struct passwd **),
+ u_key ukey, size_t *buffer_size)
+{
+ int return_value;
+ struct passwd passwd, *result;
+ char *passwd_storage = NULL, *buffer;
+ size_t passwd_storage_size = PASSWD_STORAGE_INITIAL;
+
+ do {
+ passwd_storage =
+ realloc(passwd_storage, passwd_storage_size);
+ if (passwd_storage == NULL) {
+ return (NULL);
+ }
+ return_value = fn(ukey, &passwd, passwd_storage,
+ passwd_storage_size, &result);
+ passwd_storage_size <<= 1;
+ } while (result == NULL &&
+ return_value == ERANGE &&
+ passwd_storage_size < PASSWD_STORAGE_MAX);
+ if (return_value != 0 || result == NULL) {
+ free(passwd_storage);
+ errno = return_value;
+ return (NULL);
+ }
+
+ *buffer_size = 0;
+ passwd_marshal_func(&passwd, NULL, buffer_size);
+ buffer = malloc(*buffer_size);
+ assert(buffer != NULL);
+ passwd_marshal_func(&passwd, buffer, buffer_size);
+
+ free(passwd_storage);
+ errno = return_value;
+ return (buffer);
+}
+
+static int
+wrap_getpwnam_r(u_key ukey, struct passwd *pwd, char *buffer, size_t bufsize,
+ struct passwd **res)
+{
+ return (getpwnam_r(ukey.login, pwd, buffer, bufsize, res));
+}
+
+static int
+wrap_getpwuid_r(u_key ukey, struct passwd *pwd, char *buffer, size_t bufsize,
+ struct passwd **res)
+{
+ return (getpwuid_r(ukey.uid, pwd, buffer, bufsize, res));
+}
+
+static int
+wrap_getpwent_r(u_key ukey __unused, struct passwd *pwd, char *buffer,
+ size_t bufsize, struct passwd **res)
+{
+ return (getpwent_r(pwd, buffer, bufsize, res));
+}
+
static int
passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size)
{
@@ -128,15 +205,14 @@
size_t *buffer_size)
{
enum nss_lookup_type lookup_type;
- char *login;
+ u_key ukey;
size_t size;
- uid_t uid;
-
- struct passwd *result;
+ int pw_errno;
TRACE_IN(passwd_lookup_func);
assert(buffer != NULL);
assert(buffer_size != NULL);
+ *buffer_size = 0;
if (key_size < sizeof(enum nss_lookup_type)) {
TRACE_OUT(passwd_lookup_func);
@@ -146,10 +222,24 @@
switch (lookup_type) {
case nss_lt_name:
- size = key_size - sizeof(enum nss_lookup_type) + 1;
- login = calloc(1, size);
- assert(login != NULL);
- memcpy(login, key + sizeof(enum nss_lookup_type), size - 1);
+ if (key_size < sizeof(enum nss_lookup_type) + 2) {
+ TRACE_OUT(passwd_lookup_func);
+ return (NS_UNAVAIL);
+ }
+
+ size = key_size - sizeof(enum nss_lookup_type);
+ ukey.login = malloc(size);
+ assert(ukey.login != NULL);
+
+ memcpy(ukey.login, key + sizeof(enum nss_lookup_type), size);
+ ukey.login[size - 1] = 0;
+
+ TRACE_STR(ukey.login);
+ errno = 0;
+ *buffer = getpw(wrap_getpwnam_r, ukey, buffer_size);
+ pw_errno = errno;
+ free(ukey.login);
+
break;
case nss_lt_id:
if (key_size < sizeof(enum nss_lookup_type) +
@@ -158,35 +248,22 @@
return (NS_UNAVAIL);
}
- memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t));
+ memcpy(&ukey.uid, key + sizeof(enum nss_lookup_type),
+ sizeof(uid_t));
+ errno = 0;
+ *buffer = getpw(wrap_getpwuid_r, ukey, buffer_size);
+ pw_errno = errno;
+
break;
default:
TRACE_OUT(passwd_lookup_func);
return (NS_UNAVAIL);
}
- switch (lookup_type) {
- case nss_lt_name:
- result = getpwnam(login);
- free(login);
- break;
- case nss_lt_id:
- result = getpwuid(uid);
- break;
- default:
- /* SHOULD NOT BE REACHED */
- break;
- }
-
- if (result != NULL) {
- passwd_marshal_func(result, NULL, buffer_size);
- *buffer = malloc(*buffer_size);
- assert(*buffer != NULL);
- passwd_marshal_func(result, *buffer, buffer_size);
- }
-
TRACE_OUT(passwd_lookup_func);
- return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+ return (*buffer == NULL ?
+ (pw_errno == 0 ? NS_NOTFOUND : NS_UNAVAIL) :
+ NS_SUCCESS);
}
static void *
@@ -195,26 +272,26 @@
TRACE_IN(passwd_mp_init_func);
setpwent();
TRACE_OUT(passwd_mp_init_func);
-
return (NULL);
}
static int
passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
{
- struct passwd *result;
+ u_key ukey;
TRACE_IN(passwd_mp_lookup_func);
- result = getpwent();
- if (result != NULL) {
- passwd_marshal_func(result, NULL, buffer_size);
- *buffer = malloc(*buffer_size);
- assert(*buffer != NULL);
- passwd_marshal_func(result, *buffer, buffer_size);
- }
+ assert(buffer != NULL);
+ assert(buffer_size != NULL);
+ *buffer_size = 0;
+ errno = 0;
+ ukey.uid = 0;
+ *buffer = getpw(wrap_getpwent_r, ukey, buffer_size);
TRACE_OUT(passwd_mp_lookup_func);
- return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+ return (*buffer == NULL ?
+ (errno == 0 ? NS_NOTFOUND : NS_UNAVAIL) :
+ NS_SUCCESS);
}
static void

File Metadata

Mime Type
text/plain
Expires
Thu, May 14, 8:35 PM (6 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33059779
Default Alt Text
D47146.diff (5 KB)

Event Timeline