]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/group-record-nss.c
test-json: add function headers
[thirdparty/systemd.git] / src / shared / group-record-nss.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "errno-util.h"
4 #include "group-record-nss.h"
5 #include "libcrypt-util.h"
6 #include "strv.h"
7
8 int nss_group_to_group_record(
9 const struct group *grp,
10 const struct sgrp *sgrp,
11 GroupRecord **ret) {
12
13 _cleanup_(group_record_unrefp) GroupRecord *g = NULL;
14 int r;
15
16 assert(grp);
17 assert(ret);
18
19 if (isempty(grp->gr_name))
20 return -EINVAL;
21
22 if (sgrp && !streq_ptr(sgrp->sg_namp, grp->gr_name))
23 return -EINVAL;
24
25 g = group_record_new();
26 if (!g)
27 return -ENOMEM;
28
29 g->group_name = strdup(grp->gr_name);
30 if (!g->group_name)
31 return -ENOMEM;
32
33 g->members = strv_copy(grp->gr_mem);
34 if (!g->members)
35 return -ENOMEM;
36
37 g->gid = grp->gr_gid;
38
39 if (sgrp) {
40 if (looks_like_hashed_password(sgrp->sg_passwd)) {
41 g->hashed_password = strv_new(sgrp->sg_passwd);
42 if (!g->hashed_password)
43 return -ENOMEM;
44 }
45
46 r = strv_extend_strv(&g->members, sgrp->sg_mem, 1);
47 if (r < 0)
48 return r;
49
50 g->administrators = strv_copy(sgrp->sg_adm);
51 if (!g->administrators)
52 return -ENOMEM;
53 }
54
55 r = json_build(&g->json, JSON_BUILD_OBJECT(
56 JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(g->group_name)),
57 JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(g->gid)),
58 JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->members), "members", JSON_BUILD_STRV(g->members)),
59 JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->hashed_password), "privileged", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRV(g->hashed_password)))),
60 JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->administrators), "administrators", JSON_BUILD_STRV(g->administrators))));
61 if (r < 0)
62 return r;
63
64 g->mask = USER_RECORD_REGULAR |
65 (!strv_isempty(g->hashed_password) ? USER_RECORD_PRIVILEGED : 0);
66
67 *ret = TAKE_PTR(g);
68 return 0;
69 }
70
71 int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer) {
72 size_t buflen = 4096;
73 int r;
74
75 assert(grp);
76 assert(ret_sgrp);
77 assert(ret_buffer);
78
79 for (;;) {
80 _cleanup_free_ char *buf = NULL;
81 struct sgrp sgrp, *result;
82
83 buf = malloc(buflen);
84 if (!buf)
85 return -ENOMEM;
86
87 r = getsgnam_r(grp->gr_name, &sgrp, buf, buflen, &result);
88 if (r == 0) {
89 if (!result)
90 return -ESRCH;
91
92 *ret_sgrp = *result;
93 *ret_buffer = TAKE_PTR(buf);
94 return 0;
95 }
96 if (r < 0)
97 return -EIO; /* Weird, this should not return negative! */
98 if (r != ERANGE)
99 return -r;
100
101 if (buflen > SIZE_MAX / 2)
102 return -ERANGE;
103
104 buflen *= 2;
105 buf = mfree(buf);
106 }
107 }
108
109 int nss_group_record_by_name(
110 const char *name,
111 bool with_shadow,
112 GroupRecord **ret) {
113
114 _cleanup_free_ char *buf = NULL, *sbuf = NULL;
115 struct group grp, *result;
116 bool incomplete = false;
117 size_t buflen = 4096;
118 struct sgrp sgrp, *sresult = NULL;
119 int r;
120
121 assert(name);
122 assert(ret);
123
124 for (;;) {
125 buf = malloc(buflen);
126 if (!buf)
127 return -ENOMEM;
128
129 r = getgrnam_r(name, &grp, buf, buflen, &result);
130 if (r == 0) {
131 if (!result)
132 return -ESRCH;
133
134 break;
135 }
136
137 if (r < 0)
138 return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrnam_r() returned a negative value");
139 if (r != ERANGE)
140 return -r;
141 if (buflen > SIZE_MAX / 2)
142 return -ERANGE;
143
144 buflen *= 2;
145 buf = mfree(buf);
146 }
147
148 if (with_shadow) {
149 r = nss_sgrp_for_group(result, &sgrp, &sbuf);
150 if (r < 0) {
151 log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name);
152 incomplete = ERRNO_IS_PRIVILEGE(r);
153 } else
154 sresult = &sgrp;
155 } else
156 incomplete = true;
157
158 r = nss_group_to_group_record(result, sresult, ret);
159 if (r < 0)
160 return r;
161
162 (*ret)->incomplete = incomplete;
163 return 0;
164 }
165
166 int nss_group_record_by_gid(
167 gid_t gid,
168 bool with_shadow,
169 GroupRecord **ret) {
170
171 _cleanup_free_ char *buf = NULL, *sbuf = NULL;
172 struct group grp, *result;
173 bool incomplete = false;
174 size_t buflen = 4096;
175 struct sgrp sgrp, *sresult = NULL;
176 int r;
177
178 assert(ret);
179
180 for (;;) {
181 buf = malloc(buflen);
182 if (!buf)
183 return -ENOMEM;
184
185 r = getgrgid_r(gid, &grp, buf, buflen, &result);
186 if (r == 0) {
187 if (!result)
188 return -ESRCH;
189 break;
190 }
191
192 if (r < 0)
193 return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrgid_r() returned a negative value");
194 if (r != ERANGE)
195 return -r;
196 if (buflen > SIZE_MAX / 2)
197 return -ERANGE;
198
199 buflen *= 2;
200 buf = mfree(buf);
201 }
202
203 if (with_shadow) {
204 r = nss_sgrp_for_group(result, &sgrp, &sbuf);
205 if (r < 0) {
206 log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name);
207 incomplete = ERRNO_IS_PRIVILEGE(r);
208 } else
209 sresult = &sgrp;
210 } else
211 incomplete = true;
212
213 r = nss_group_to_group_record(result, sresult, ret);
214 if (r < 0)
215 return r;
216
217 (*ret)->incomplete = incomplete;
218 return 0;
219 }