OLD | NEW |
1 #include <pthread.h> | 1 #include <pthread.h> |
2 #include <byteswap.h> | 2 #include <byteswap.h> |
3 #include <string.h> | 3 #include <string.h> |
4 #include <unistd.h> | 4 #include <unistd.h> |
5 #include "pwf.h" | 5 #include "pwf.h" |
6 #include "nscd.h" | 6 #include "nscd.h" |
7 | 7 |
8 static char *itoa(char *p, uint32_t x) | 8 static char* itoa(char* p, uint32_t x) { |
9 { | 9 // number of digits in a uint32_t + NUL |
10 » // number of digits in a uint32_t + NUL | 10 p += 11; |
11 » p += 11; | 11 *--p = 0; |
12 » *--p = 0; | 12 do { |
13 » do { | 13 *--p = '0' + x % 10; |
14 » » *--p = '0' + x % 10; | 14 x /= 10; |
15 » » x /= 10; | 15 } while (x); |
16 » } while (x); | 16 return p; |
17 » return p; | |
18 } | 17 } |
19 | 18 |
20 int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t
*size, char ***mem, size_t *nmem, struct group **res) | 19 int __getgr_a(const char* name, |
21 { | 20 gid_t gid, |
22 » FILE *f; | 21 struct group* gr, |
23 » int rv = 0; | 22 char** buf, |
24 » int cs; | 23 size_t* size, |
| 24 char*** mem, |
| 25 size_t* nmem, |
| 26 struct group** res) { |
| 27 FILE* f; |
| 28 int rv = 0; |
| 29 int cs; |
25 | 30 |
26 » *res = 0; | 31 *res = 0; |
27 | 32 |
28 » pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); | 33 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); |
29 » f = fopen("/etc/group", "rbe"); | 34 f = fopen("/etc/group", "rbe"); |
30 » if (!f) { | 35 if (!f) { |
31 » » rv = errno; | 36 rv = errno; |
32 » » goto done; | 37 goto done; |
33 » } | 38 } |
34 | 39 |
35 » while (!(rv = __getgrent_a(f, gr, buf, size, mem, nmem, res)) && *res) { | 40 while (!(rv = __getgrent_a(f, gr, buf, size, mem, nmem, res)) && *res) { |
36 » » if ((name && !strcmp(name, (*res)->gr_name)) | 41 if ((name && !strcmp(name, (*res)->gr_name)) || |
37 » » || (!name && (*res)->gr_gid == gid)) { | 42 (!name && (*res)->gr_gid == gid)) { |
38 » » » break; | 43 break; |
39 » » } | 44 } |
40 » } | 45 } |
41 » fclose(f); | 46 fclose(f); |
42 | 47 |
43 » if (!*res && (rv == 0 || rv == ENOENT || rv == ENOTDIR)) { | 48 if (!*res && (rv == 0 || rv == ENOENT || rv == ENOTDIR)) { |
44 » » int32_t req = name ? GETGRBYNAME : GETGRBYGID; | 49 int32_t req = name ? GETGRBYNAME : GETGRBYGID; |
45 » » int32_t i; | 50 int32_t i; |
46 » » const char *key; | 51 const char* key; |
47 » » int32_t groupbuf[GR_LEN] = {0}; | 52 int32_t groupbuf[GR_LEN] = {0}; |
48 » » size_t len = 0; | 53 size_t len = 0; |
49 » » size_t grlist_len = 0; | 54 size_t grlist_len = 0; |
50 » » char gidbuf[11] = {0}; | 55 char gidbuf[11] = {0}; |
51 » » int swap = 0; | 56 int swap = 0; |
52 » » char *ptr; | 57 char* ptr; |
53 | 58 |
54 » » if (name) { | 59 if (name) { |
55 » » » key = name; | 60 key = name; |
56 » » } else { | 61 } else { |
57 » » » if (gid > UINT32_MAX) { | 62 if (gid > UINT32_MAX) { |
58 » » » » rv = 0; | 63 rv = 0; |
59 » » » » goto done; | 64 goto done; |
60 » » » } | 65 } |
61 » » » key = itoa(gidbuf, gid); | 66 key = itoa(gidbuf, gid); |
62 » » } | 67 } |
63 | 68 |
64 » » f = __nscd_query(req, key, groupbuf, sizeof groupbuf, &swap); | 69 f = __nscd_query(req, key, groupbuf, sizeof groupbuf, &swap); |
65 » » if (!f) { rv = errno; goto done; } | 70 if (!f) { |
| 71 rv = errno; |
| 72 goto done; |
| 73 } |
66 | 74 |
67 » » if (!groupbuf[GRFOUND]) { rv = 0; goto cleanup_f; } | 75 if (!groupbuf[GRFOUND]) { |
| 76 rv = 0; |
| 77 goto cleanup_f; |
| 78 } |
68 | 79 |
69 » » if (!groupbuf[GRNAMELEN] || !groupbuf[GRPASSWDLEN]) { | 80 if (!groupbuf[GRNAMELEN] || !groupbuf[GRPASSWDLEN]) { |
70 » » » rv = EIO; | 81 rv = EIO; |
71 » » » goto cleanup_f; | 82 goto cleanup_f; |
72 » » } | 83 } |
73 | 84 |
74 » » if (groupbuf[GRNAMELEN] > SIZE_MAX - groupbuf[GRPASSWDLEN]) { | 85 if (groupbuf[GRNAMELEN] > SIZE_MAX - groupbuf[GRPASSWDLEN]) { |
75 » » » rv = ENOMEM; | 86 rv = ENOMEM; |
76 » » » goto cleanup_f; | 87 goto cleanup_f; |
77 » » } | 88 } |
78 » » len = groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN]; | 89 len = groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN]; |
79 | 90 |
80 » » for (i = 0; i < groupbuf[GRMEMCNT]; i++) { | 91 for (i = 0; i < groupbuf[GRMEMCNT]; i++) { |
81 » » » uint32_t name_len; | 92 uint32_t name_len; |
82 » » » if (fread(&name_len, sizeof name_len, 1, f) < 1) { | 93 if (fread(&name_len, sizeof name_len, 1, f) < 1) { |
83 » » » » rv = ferror(f) ? errno : EIO; | 94 rv = ferror(f) ? errno : EIO; |
84 » » » » goto cleanup_f; | 95 goto cleanup_f; |
85 » » » } | 96 } |
86 » » » if (swap) { | 97 if (swap) { |
87 » » » » name_len = bswap_32(name_len); | 98 name_len = bswap_32(name_len); |
88 » » » } | 99 } |
89 » » » if (name_len > SIZE_MAX - grlist_len | 100 if (name_len > SIZE_MAX - grlist_len || name_len > SIZE_MAX - len) { |
90 » » » || name_len > SIZE_MAX - len) { | 101 rv = ENOMEM; |
91 » » » » rv = ENOMEM; | 102 goto cleanup_f; |
92 » » » » goto cleanup_f; | 103 } |
93 » » » } | 104 len += name_len; |
94 » » » len += name_len; | 105 grlist_len += name_len; |
95 » » » grlist_len += name_len; | 106 } |
96 » » } | |
97 | 107 |
98 » » if (len > *size || !*buf) { | 108 if (len > *size || !*buf) { |
99 » » » char *tmp = realloc(*buf, len); | 109 char* tmp = realloc(*buf, len); |
100 » » » if (!tmp) { | 110 if (!tmp) { |
101 » » » » rv = errno; | 111 rv = errno; |
102 » » » » goto cleanup_f; | 112 goto cleanup_f; |
103 » » » } | 113 } |
104 » » » *buf = tmp; | 114 *buf = tmp; |
105 » » » *size = len; | 115 *size = len; |
106 » » } | 116 } |
107 | 117 |
108 » » if (!fread(*buf, len, 1, f)) { | 118 if (!fread(*buf, len, 1, f)) { |
109 » » » rv = ferror(f) ? errno : EIO; | 119 rv = ferror(f) ? errno : EIO; |
110 » » » goto cleanup_f; | 120 goto cleanup_f; |
111 » » } | 121 } |
112 | 122 |
113 » » if (groupbuf[GRMEMCNT] + 1 > *nmem) { | 123 if (groupbuf[GRMEMCNT] + 1 > *nmem) { |
114 » » » if (groupbuf[GRMEMCNT] + 1 > SIZE_MAX/sizeof(char*)) { | 124 if (groupbuf[GRMEMCNT] + 1 > SIZE_MAX / sizeof(char*)) { |
115 » » » » rv = ENOMEM; | 125 rv = ENOMEM; |
116 » » » » goto cleanup_f; | 126 goto cleanup_f; |
117 » » » } | 127 } |
118 » » » char **tmp = realloc(*mem, (groupbuf[GRMEMCNT]+1)*sizeof
(char*)); | 128 char** tmp = realloc(*mem, (groupbuf[GRMEMCNT] + 1) * sizeof(char*)); |
119 » » » if (!tmp) { | 129 if (!tmp) { |
120 » » » » rv = errno; | 130 rv = errno; |
121 » » » » goto cleanup_f; | 131 goto cleanup_f; |
122 » » » } | 132 } |
123 » » » *mem = tmp; | 133 *mem = tmp; |
124 » » » *nmem = groupbuf[GRMEMCNT] + 1; | 134 *nmem = groupbuf[GRMEMCNT] + 1; |
125 » » } | 135 } |
126 | 136 |
127 » » if (groupbuf[GRMEMCNT]) { | 137 if (groupbuf[GRMEMCNT]) { |
128 » » » mem[0][0] = *buf + groupbuf[GRNAMELEN] + groupbuf[GRPASS
WDLEN]; | 138 mem[0][0] = *buf + groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN]; |
129 » » » for (ptr = mem[0][0], i = 0; ptr != mem[0][0]+grlist_len
; ptr++) | 139 for (ptr = mem[0][0], i = 0; ptr != mem[0][0] + grlist_len; ptr++) |
130 » » » » if (!*ptr) mem[0][++i] = ptr+1; | 140 if (!*ptr) |
131 » » » mem[0][i] = 0; | 141 mem[0][++i] = ptr + 1; |
| 142 mem[0][i] = 0; |
132 | 143 |
133 » » » if (i != groupbuf[GRMEMCNT]) { | 144 if (i != groupbuf[GRMEMCNT]) { |
134 » » » » rv = EIO; | 145 rv = EIO; |
135 » » » » goto cleanup_f; | 146 goto cleanup_f; |
136 » » » } | 147 } |
137 » » } else { | 148 } else { |
138 » » » mem[0][0] = 0; | 149 mem[0][0] = 0; |
139 » » } | 150 } |
140 | 151 |
141 » » gr->gr_name = *buf; | 152 gr->gr_name = *buf; |
142 » » gr->gr_passwd = gr->gr_name + groupbuf[GRNAMELEN]; | 153 gr->gr_passwd = gr->gr_name + groupbuf[GRNAMELEN]; |
143 » » gr->gr_gid = groupbuf[GRGID]; | 154 gr->gr_gid = groupbuf[GRGID]; |
144 » » gr->gr_mem = *mem; | 155 gr->gr_mem = *mem; |
145 | 156 |
146 » » if (gr->gr_passwd[-1] | 157 if (gr->gr_passwd[-1] || gr->gr_passwd[groupbuf[GRPASSWDLEN] - 1]) { |
147 » » || gr->gr_passwd[groupbuf[GRPASSWDLEN]-1]) { | 158 rv = EIO; |
148 » » » rv = EIO; | 159 goto cleanup_f; |
149 » » » goto cleanup_f; | 160 } |
150 » » } | |
151 | 161 |
152 » » if ((name && strcmp(name, gr->gr_name)) | 162 if ((name && strcmp(name, gr->gr_name)) || (!name && gid != gr->gr_gid)) { |
153 » » || (!name && gid != gr->gr_gid)) { | 163 rv = EIO; |
154 » » » rv = EIO; | 164 goto cleanup_f; |
155 » » » goto cleanup_f; | 165 } |
156 » » } | |
157 | 166 |
158 » » *res = gr; | 167 *res = gr; |
159 | 168 |
160 cleanup_f: | 169 cleanup_f: |
161 » » fclose(f); | 170 fclose(f); |
162 » » goto done; | 171 goto done; |
163 » } | 172 } |
164 | 173 |
165 done: | 174 done: |
166 » pthread_setcancelstate(cs, 0); | 175 pthread_setcancelstate(cs, 0); |
167 » if (rv) errno = rv; | 176 if (rv) |
168 » return rv; | 177 errno = rv; |
| 178 return rv; |
169 } | 179 } |
OLD | NEW |