| 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 |