]>
Commit | Line | Data |
---|---|---|
9b2d9078 LP |
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 (hashed_password_valid(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 | ||
ed30170e LP |
109 | int nss_group_record_by_name( |
110 | const char *name, | |
111 | bool with_shadow, | |
112 | GroupRecord **ret) { | |
113 | ||
9b2d9078 LP |
114 | _cleanup_free_ char *buf = NULL, *sbuf = NULL; |
115 | struct group grp, *result; | |
116 | bool incomplete = false; | |
117 | size_t buflen = 4096; | |
ed30170e | 118 | struct sgrp sgrp, *sresult = NULL; |
9b2d9078 LP |
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 | ||
ed30170e LP |
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); | |
9b2d9078 LP |
159 | if (r < 0) |
160 | return r; | |
161 | ||
162 | (*ret)->incomplete = incomplete; | |
163 | return 0; | |
164 | } | |
165 | ||
ed30170e LP |
166 | int nss_group_record_by_gid( |
167 | gid_t gid, | |
168 | bool with_shadow, | |
169 | GroupRecord **ret) { | |
170 | ||
9b2d9078 LP |
171 | _cleanup_free_ char *buf = NULL, *sbuf = NULL; |
172 | struct group grp, *result; | |
173 | bool incomplete = false; | |
174 | size_t buflen = 4096; | |
ed30170e | 175 | struct sgrp sgrp, *sresult = NULL; |
9b2d9078 LP |
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 | ||
ed30170e LP |
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); | |
9b2d9078 LP |
214 | if (r < 0) |
215 | return r; | |
216 | ||
217 | (*ret)->incomplete = incomplete; | |
218 | return 0; | |
219 | } |