]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/pwd.c
logging: Make the legacy logger configurable
[people/ms/pakfire.git] / src / libpakfire / pwd.c
CommitLineData
ce389fc8
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2021 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
2cdf5a9b 21#include <errno.h>
f7bcda59 22#include <grp.h>
097b6ca6 23#include <linux/limits.h>
ce389fc8
MT
24#include <pwd.h>
25#include <stdio.h>
26#include <stdlib.h>
27
ffaa6362
MT
28#ifdef HAVE_SUBID
29#include <shadow/subid.h>
30#endif
31
517708c8
MT
32// Enable legacy logging
33#define PAKFIRE_LEGACY_LOGGING
34
41c76557 35#include <pakfire/logging.h>
ce389fc8
MT
36#include <pakfire/pakfire.h>
37#include <pakfire/pwd.h>
d973a13d 38#include <pakfire/string.h>
41c76557
MT
39#include <pakfire/util.h>
40
41#define ETC_SUBUID "/etc/subuid"
42#define ETC_SUBGID "/etc/subgid"
ce389fc8 43
ac4c607b 44static struct passwd* pakfire_getpwent(struct pakfire* pakfire,
ce389fc8
MT
45 int(*cmp)(struct passwd* entry, const void* value), const void* value) {
46 struct passwd* entry = NULL;
097b6ca6 47 char path[PATH_MAX];
77e26129 48 int r;
ce389fc8
MT
49
50 // Get path to /etc/passwd
77e26129
MT
51 r = pakfire_path(pakfire, path, "%s", "/etc/passwd");
52 if (r)
ce389fc8
MT
53 return NULL;
54
55 FILE* f = fopen(path, "r");
56 if (!f)
57 goto END;
58
59 for (;;) {
60 // Parse entry
61 entry = fgetpwent(f);
62 if (!entry)
63 goto END;
64
65 // Check if this is what we are looking for
66 if (cmp(entry, value))
67 break;
68 else
69 entry = NULL;
70 }
71
72END:
ce389fc8
MT
73 if (f)
74 fclose(f);
75
76 return entry;
77}
78
79static int __pakfire_getpwnam(struct passwd* entry, const void* value) {
80 const char* name = (const char*)value;
81
82 if (strcmp(entry->pw_name, name) == 0)
83 return 1;
84
85 return 0;
86}
87
ac4c607b 88struct passwd* pakfire_getpwnam(struct pakfire* pakfire, const char* name) {
ce389fc8
MT
89 return pakfire_getpwent(pakfire, __pakfire_getpwnam, name);
90}
91
92static int __pakfire_getpwuid(struct passwd* entry, const void* value) {
93 uid_t* uid = (uid_t*)value;
94
95 if (entry->pw_uid == *uid)
96 return 1;
97
98 return 0;
99}
100
ac4c607b 101struct passwd* pakfire_getpwuid(struct pakfire* pakfire, uid_t uid) {
ce389fc8
MT
102 return pakfire_getpwent(pakfire, __pakfire_getpwuid, &uid);
103}
f7bcda59 104
ac4c607b 105static struct group* pakfire_getgrent(struct pakfire* pakfire,
f7bcda59
MT
106 int(*cmp)(struct group* entry, const void* value), const void* value) {
107 struct group* entry = NULL;
097b6ca6 108 char path[PATH_MAX];
77e26129 109 int r;
f7bcda59
MT
110
111 // Get path to /etc/group
77e26129
MT
112 r = pakfire_path(pakfire, path, "%s", "/etc/group");
113 if (r)
f7bcda59
MT
114 return NULL;
115
116 FILE* f = fopen(path, "r");
117 if (!f)
118 goto END;
119
120 for (;;) {
121 // Parse entry
122 entry = fgetgrent(f);
123 if (!entry)
124 goto END;
125
126 // Check if this is what we are looking for
127 if (cmp(entry, value))
128 break;
129 else
130 entry = NULL;
131 }
132
133END:
f7bcda59
MT
134 if (f)
135 fclose(f);
136
137 return entry;
138}
139
140static int __pakfire_getgrnam(struct group* entry, const void* value) {
141 const char* name = (const char*)value;
142
143 if (strcmp(entry->gr_name, name) == 0)
144 return 1;
145
146 return 0;
147}
148
ac4c607b 149struct group* pakfire_getgrnam(struct pakfire* pakfire, const char* name) {
f7bcda59
MT
150 return pakfire_getgrent(pakfire, __pakfire_getgrnam, name);
151}
152
153static int __pakfire_getgrgid(struct group* entry, const void* value) {
154 gid_t* gid = (gid_t*)value;
155
156 if (entry->gr_gid == *gid)
157 return 1;
158
159 return 0;
160}
161
ac4c607b 162struct group* pakfire_getgrgid(struct pakfire* pakfire, gid_t gid) {
f7bcda59
MT
163 return pakfire_getgrent(pakfire, __pakfire_getgrgid, &gid);
164}
41c76557
MT
165
166// SUBUID/SUBGID
167
ffaa6362
MT
168#ifdef HAVE_SUBID
169
170static int pakfire_getsubid(struct pakfire* pakfire, const char* owner,
171 struct pakfire_subid* subid, int (callback)(const char* owner, struct subid_range** ranges)) {
172 struct subid_range* ranges = NULL;
173 int count;
174 int r = -1;
175
176 if (!subid_init(PACKAGE_NAME, stderr)) {
177 ERROR(pakfire, "Could not setup subid: %m\n");
178 return 1;
179 }
180
181 count = callback(owner, &ranges);
182 if (count < 0) {
183 ERROR(pakfire, "Could not fetch subids for %s: %m\n", owner);
184 goto ERROR;
185 }
186
187 // Store the result
188 for (int i = 0; i < count; i++) {
189 subid->id = ranges[i].start;
190 subid->length = ranges[i].count;
191 r = 0;
192 break;
193 }
194
195ERROR:
196 if (ranges)
197 free(ranges);
198
199 return r;
200}
201
202int pakfire_getsubuid(struct pakfire* pakfire, const char* owner, struct pakfire_subid* subid) {
203 return pakfire_getsubid(pakfire, owner, subid, subid_get_uid_ranges);
204}
205
206int pakfire_getsubgid(struct pakfire* pakfire, const char* owner, struct pakfire_subid* subid) {
207 return pakfire_getsubid(pakfire, owner, subid, subid_get_gid_ranges);
208}
209
210# else /* Our own implementation */
211
2cdf5a9b 212static int pakfire_fgetsubid(struct pakfire* pakfire, struct pakfire_subid* subid, FILE* f) {
41c76557
MT
213 int r;
214
215 char* line = NULL;
216 size_t length = 0;
217 char* p = NULL;
218
219 // Read the next line
220 while (1) {
221 r = getline(&line, &length, f);
222 if (r < 0)
223 goto ERROR;
224
225 // Try reading the next line if this one was empty
226 else if (r == 0)
227 continue;
228
229 // Fall through
230 else
231 break;
232 }
233
41c76557
MT
234 int i = 0;
235
236 char* token = strtok_r(line, ":", &p);
237 while (token) {
238 switch (i++) {
239 // First field has the name
240 case 0:
2cdf5a9b 241 pakfire_string_set(subid->name, token);
41c76557
MT
242 break;
243
a1ff2863 244 // Second field has the ID
41c76557 245 case 1:
2cdf5a9b 246 subid->id = strtoul(token, NULL, 10);
41c76557
MT
247 break;
248
249 // Third field has the length
250 case 2:
2cdf5a9b 251 subid->length = strtoul(token, NULL, 10);
41c76557
MT
252 break;
253 }
254
255 token = strtok_r(NULL, ":", &p);
256 }
257
1251d1f0 258 // Check if length is greater than zero
2cdf5a9b 259 if (subid->length == 0) {
1251d1f0
MT
260 DEBUG(pakfire, "Length equals zero: %s\n", line);
261 r = 1;
2cdf5a9b 262 goto ERROR;
1251d1f0
MT
263 }
264
2cdf5a9b
MT
265 // Reset r
266 r = 0;
267
41c76557
MT
268ERROR:
269 if (line)
270 free(line);
271
2cdf5a9b 272 if (!r)
a8a41064 273 DEBUG(pakfire, "Parsed SUBID entry: name=%s, id=%u, length=%zu\n",
2cdf5a9b 274 subid->name, subid->id, subid->length);
41c76557 275
2cdf5a9b 276 return r;
41c76557
MT
277}
278
c54bafa7
MT
279/*
280 This function searches for a SUBUID/SUBGID entry for the given user.
281
282 If something is found, subid is configured accordingly and the function returns 0.
283 If nothing was found, the function returns 1.
284 If there was an error, the function may return something else.
285*/
9b50d885 286static int pakfire_getsubid(struct pakfire* pakfire, const char* path, const char* owner,
74a3d0c7 287 struct pakfire_subid* subid) {
2cdf5a9b 288 struct pakfire_subid entry;
c54bafa7 289 int r;
1e494258 290
c54bafa7
MT
291 // Do not lookup root
292 if (!owner)
293 return 1;
1e494258 294
9b50d885 295 DEBUG(pakfire, "Fetching SUBID from %s for %s\n", path, owner);
41c76557
MT
296
297 // Open /etc/subuid
74a3d0c7 298 FILE* f = fopen(path, "r");
41c76557 299 if (!f) {
c54bafa7
MT
300 switch (errno) {
301 case ENOENT:
302 break;
303
304 default:
305 ERROR(pakfire, "Could not open %s: %m\n", path);
306 break;
307 }
308
309 // Nothing found
2cdf5a9b
MT
310 r = 1;
311 goto END;
41c76557
MT
312 }
313
314 // Walk through all entries
315 while (1) {
2cdf5a9b 316 r = pakfire_fgetsubid(pakfire, &entry, f);
c54bafa7
MT
317 switch (r) {
318 case 0:
319 break;
320
321 case EOF:
322 r = 1;
323 goto END;
324
325 default:
326 goto END;
327 }
41c76557 328
41c76557 329 // Check for match
9b50d885 330 if (strcmp(entry.name, owner) == 0) {
2cdf5a9b
MT
331 subid->id = entry.id;
332 subid->length = entry.length;
41c76557 333
c54bafa7 334 r = 0;
2cdf5a9b 335 goto END;
41c76557
MT
336 }
337 }
338
2cdf5a9b 339 // No match found
c54bafa7 340 DEBUG(pakfire, "No match found for %s\n", owner);
2cdf5a9b
MT
341 r = 1;
342
343END:
41c76557
MT
344 if (f)
345 fclose(f);
346
347 return r;
348}
9b50d885
MT
349
350int pakfire_getsubuid(struct pakfire* pakfire, const char* owner, struct pakfire_subid* subid) {
351 return pakfire_getsubid(pakfire, ETC_SUBUID, owner, subid);
352}
353
354int pakfire_getsubgid(struct pakfire* pakfire, const char* owner, struct pakfire_subid* subid) {
355 return pakfire_getsubid(pakfire, ETC_SUBGID, owner, subid);
356}
357
358#endif