diff options
Diffstat (limited to 'src/lib/ipwd.c')
-rw-r--r-- | src/lib/ipwd.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/lib/ipwd.c b/src/lib/ipwd.c new file mode 100644 index 0000000..8ac81fa --- /dev/null +++ b/src/lib/ipwd.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ + +#define _POSIX_PTHREAD_SEMANTICS /* for Solaris */ +#include "lib.h" +#include "ipwd.h" + +#include <unistd.h> + +#define PWBUF_MIN_SIZE 128 +#define GRBUF_MIN_SIZE 128 + +static void *pwbuf = NULL, *grbuf = NULL; +static size_t pwbuf_size, grbuf_size; + +static void pw_init(void) +{ + size_t old_pwbuf_size = pwbuf_size; + + if (pwbuf == NULL || errno == ERANGE) { + pwbuf_size = nearest_power(old_pwbuf_size + 1); + if (pwbuf_size < PWBUF_MIN_SIZE) + pwbuf_size = PWBUF_MIN_SIZE; + pwbuf = i_realloc(pwbuf, old_pwbuf_size, pwbuf_size); + } +} + +static void gr_init(void) +{ + size_t old_grbuf_size = grbuf_size; + + if (grbuf == NULL || errno == ERANGE) { + grbuf_size = nearest_power(old_grbuf_size + 1); + if (grbuf_size < PWBUF_MIN_SIZE) + grbuf_size = PWBUF_MIN_SIZE; + grbuf = i_realloc(grbuf, old_grbuf_size, grbuf_size); + } +} + +void ipwd_deinit(void) +{ + i_free_and_null(pwbuf); + i_free_and_null(grbuf); +} + +int i_getpwnam(const char *name, struct passwd *pwd_r) +{ + struct passwd *result; + + errno = 0; + do { + pw_init(); + errno = getpwnam_r(name, pwd_r, pwbuf, pwbuf_size, &result); + } while (errno == ERANGE); + if (result != NULL) + return 1; + if (errno == EINVAL) { + /* FreeBSD fails here when name="user@domain" */ + return 0; + } + return errno == 0 ? 0 : -1; +} + +int i_getpwuid(uid_t uid, struct passwd *pwd_r) +{ + struct passwd *result; + + errno = 0; + do { + pw_init(); + errno = getpwuid_r(uid, pwd_r, pwbuf, pwbuf_size, &result); + } while (errno == ERANGE); + if (result != NULL) + return 1; + return errno == 0 ? 0 : -1; +} + +int i_getgrnam(const char *name, struct group *grp_r) +{ + struct group *result; + + errno = 0; + do { + gr_init(); + errno = getgrnam_r(name, grp_r, grbuf, grbuf_size, &result); + } while (errno == ERANGE); + if (result != NULL) + return 1; + return errno == 0 ? 0 : -1; +} + +int i_getgrgid(gid_t gid, struct group *grp_r) +{ + struct group *result; + + errno = 0; + do { + gr_init(); + errno = getgrgid_r(gid, grp_r, grbuf, grbuf_size, &result); + } while (errno == ERANGE); + if (result != NULL) + return 1; + return errno == 0 ? 0 : -1; +} |