bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
60bdf7c0422caeb08cc615c60b659d4d1ff30614Timo Sirainen#define _POSIX_PTHREAD_SEMANTICS /* for Solaris */
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen#include "lib.h"
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen#include "ipwd.h"
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen#include <unistd.h>
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen#define PWBUF_MIN_SIZE 128
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen#define GRBUF_MIN_SIZE 128
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenstatic void *pwbuf = NULL, *grbuf = NULL;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenstatic size_t pwbuf_size, grbuf_size;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenstatic void pw_init(void)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen size_t old_pwbuf_size = pwbuf_size;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen if (pwbuf == NULL || errno == ERANGE) {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen pwbuf_size = nearest_power(old_pwbuf_size + 1);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen if (pwbuf_size < PWBUF_MIN_SIZE)
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen pwbuf_size = PWBUF_MIN_SIZE;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen pwbuf = i_realloc(pwbuf, old_pwbuf_size, pwbuf_size);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen }
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenstatic void gr_init(void)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen size_t old_grbuf_size = grbuf_size;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen if (grbuf == NULL || errno == ERANGE) {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen grbuf_size = nearest_power(old_grbuf_size + 1);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen if (grbuf_size < PWBUF_MIN_SIZE)
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen grbuf_size = PWBUF_MIN_SIZE;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen grbuf = i_realloc(grbuf, old_grbuf_size, grbuf_size);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen }
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenvoid ipwd_deinit(void)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen i_free_and_null(pwbuf);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen i_free_and_null(grbuf);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenint i_getpwnam(const char *name, struct passwd *pwd_r)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen struct passwd *result;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = 0;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen do {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen pw_init();
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = getpwnam_r(name, pwd_r, pwbuf, pwbuf_size, &result);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen } while (errno == ERANGE);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen if (result != NULL)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return 1;
9a1a4c2ca1b9a8bbadd38224b15a364c78cb9938Timo Sirainen if (errno == EINVAL) {
9a1a4c2ca1b9a8bbadd38224b15a364c78cb9938Timo Sirainen /* FreeBSD fails here when name="user@domain" */
9a1a4c2ca1b9a8bbadd38224b15a364c78cb9938Timo Sirainen return 0;
9a1a4c2ca1b9a8bbadd38224b15a364c78cb9938Timo Sirainen }
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return errno == 0 ? 0 : -1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenint i_getpwuid(uid_t uid, struct passwd *pwd_r)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen struct passwd *result;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = 0;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen do {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen pw_init();
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = getpwuid_r(uid, pwd_r, pwbuf, pwbuf_size, &result);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen } while (errno == ERANGE);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen if (result != NULL)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return 1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return errno == 0 ? 0 : -1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenint i_getgrnam(const char *name, struct group *grp_r)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen struct group *result;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = 0;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen do {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen gr_init();
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = getgrnam_r(name, grp_r, grbuf, grbuf_size, &result);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen } while (errno == ERANGE);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen if (result != NULL)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return 1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return errno == 0 ? 0 : -1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainenint i_getgrgid(gid_t gid, struct group *grp_r)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen{
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen struct group *result;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = 0;
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen do {
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen gr_init();
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen errno = getgrgid_r(gid, grp_r, grbuf, grbuf_size, &result);
c8555d0f669c5732c8b9f5bece7b41fc65545f33Timo Sirainen } while (errno == ERANGE);
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen if (result != NULL)
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return 1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen return errno == 0 ? 0 : -1;
596f582a422eddef951ee445f9a0ed3d4bf14ff8Timo Sirainen}