ipwd.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#define _POSIX_PTHREAD_SEMANTICS /* for Solaris */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "lib.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "ipwd.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen#include <unistd.h>
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#define PWBUF_MIN_SIZE 128
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen#define GRBUF_MIN_SIZE 128
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstatic void *pwbuf = NULL, *grbuf = NULL;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainenstatic size_t pwbuf_size, grbuf_size;
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic void pw_init(void)
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen{
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen size_t old_pwbuf_size = pwbuf_size;
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (pwbuf == NULL || errno == ERANGE) {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen pwbuf_size = nearest_power(old_pwbuf_size + 1);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (pwbuf_size < PWBUF_MIN_SIZE)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen pwbuf_size = PWBUF_MIN_SIZE;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen pwbuf = i_realloc(pwbuf, old_pwbuf_size, pwbuf_size);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstatic void gr_init(void)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen size_t old_grbuf_size = grbuf_size;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen if (grbuf == NULL || errno == ERANGE) {
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen grbuf_size = nearest_power(old_grbuf_size + 1);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (grbuf_size < PWBUF_MIN_SIZE)
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen grbuf_size = PWBUF_MIN_SIZE;
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen grbuf = i_realloc(grbuf, old_grbuf_size, grbuf_size);
22535a9e685e29214082878e37a267157044618eTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen}
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenvoid ipwd_deinit(void)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen i_free_and_null(pwbuf);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen i_free_and_null(grbuf);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenint i_getpwnam(const char *name, struct passwd *pwd_r)
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen{
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen struct passwd *result;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen errno = 0;
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen do {
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen pw_init();
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen errno = getpwnam_r(name, pwd_r, pwbuf, pwbuf_size, &result);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen } while (errno == ERANGE);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (result != NULL)
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen return 1;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen if (errno == EINVAL) {
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen /* FreeBSD fails here when name="user@domain" */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen return 0;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen }
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen return errno == 0 ? 0 : -1;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen}
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenint i_getpwuid(uid_t uid, struct passwd *pwd_r)
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen{
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen struct passwd *result;
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen errno = 0;
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen do {
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen pw_init();
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen errno = getpwuid_r(uid, pwd_r, pwbuf, pwbuf_size, &result);
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen } while (errno == ERANGE);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (result != NULL)
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen return 1;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return errno == 0 ? 0 : -1;
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainenint i_getgrnam(const char *name, struct group *grp_r)
0af3274706d337b2930bd34f0377f2cc2dbcd18aTimo Sirainen{
157bce86d0a01477bb8ebd0d380e6b2297f326f7Timo Sirainen struct group *result;
157bce86d0a01477bb8ebd0d380e6b2297f326f7Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen errno = 0;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen do {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen gr_init();
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen errno = getgrnam_r(name, grp_r, grbuf, grbuf_size, &result);
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen } while (errno == ERANGE);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen 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;
}