1 /* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
2
3 #define _POSIX_PTHREAD_SEMANTICS /* for Solaris */
4 #include "lib.h"
5 #include "ipwd.h"
6
7 #include <unistd.h>
8
9 #define PWBUF_MIN_SIZE 128
10 #define GRBUF_MIN_SIZE 128
11
12 static void *pwbuf = NULL, *grbuf = NULL;
13 static size_t pwbuf_size, grbuf_size;
14
pw_init(void)15 static void pw_init(void)
16 {
17 size_t old_pwbuf_size = pwbuf_size;
18
19 if (pwbuf == NULL || errno == ERANGE) {
20 pwbuf_size = nearest_power(old_pwbuf_size + 1);
21 if (pwbuf_size < PWBUF_MIN_SIZE)
22 pwbuf_size = PWBUF_MIN_SIZE;
23 pwbuf = i_realloc(pwbuf, old_pwbuf_size, pwbuf_size);
24 }
25 }
26
gr_init(void)27 static void gr_init(void)
28 {
29 size_t old_grbuf_size = grbuf_size;
30
31 if (grbuf == NULL || errno == ERANGE) {
32 grbuf_size = nearest_power(old_grbuf_size + 1);
33 if (grbuf_size < PWBUF_MIN_SIZE)
34 grbuf_size = PWBUF_MIN_SIZE;
35 grbuf = i_realloc(grbuf, old_grbuf_size, grbuf_size);
36 }
37 }
38
ipwd_deinit(void)39 void ipwd_deinit(void)
40 {
41 i_free_and_null(pwbuf);
42 i_free_and_null(grbuf);
43 }
44
i_getpwnam(const char * name,struct passwd * pwd_r)45 int i_getpwnam(const char *name, struct passwd *pwd_r)
46 {
47 struct passwd *result;
48
49 errno = 0;
50 do {
51 pw_init();
52 errno = getpwnam_r(name, pwd_r, pwbuf, pwbuf_size, &result);
53 } while (errno == ERANGE);
54 if (result != NULL)
55 return 1;
56 if (errno == EINVAL) {
57 /* FreeBSD fails here when name="user@domain" */
58 return 0;
59 }
60 return errno == 0 ? 0 : -1;
61 }
62
i_getpwuid(uid_t uid,struct passwd * pwd_r)63 int i_getpwuid(uid_t uid, struct passwd *pwd_r)
64 {
65 struct passwd *result;
66
67 errno = 0;
68 do {
69 pw_init();
70 errno = getpwuid_r(uid, pwd_r, pwbuf, pwbuf_size, &result);
71 } while (errno == ERANGE);
72 if (result != NULL)
73 return 1;
74 return errno == 0 ? 0 : -1;
75 }
76
i_getgrnam(const char * name,struct group * grp_r)77 int i_getgrnam(const char *name, struct group *grp_r)
78 {
79 struct group *result;
80
81 errno = 0;
82 do {
83 gr_init();
84 errno = getgrnam_r(name, grp_r, grbuf, grbuf_size, &result);
85 } while (errno == ERANGE);
86 if (result != NULL)
87 return 1;
88 return errno == 0 ? 0 : -1;
89 }
90
i_getgrgid(gid_t gid,struct group * grp_r)91 int i_getgrgid(gid_t gid, struct group *grp_r)
92 {
93 struct group *result;
94
95 errno = 0;
96 do {
97 gr_init();
98 errno = getgrgid_r(gid, grp_r, grbuf, grbuf_size, &result);
99 } while (errno == ERANGE);
100 if (result != NULL)
101 return 1;
102 return errno == 0 ? 0 : -1;
103 }
104