xref: /unit/src/test/nxt_clone_test.c (revision 1306)
1*1306St.nateldemoura@f5.com /*
2*1306St.nateldemoura@f5.com  * Copyright (C) NGINX, Inc.
3*1306St.nateldemoura@f5.com  * Copyright (C) Valentin V. Bartenev
4*1306St.nateldemoura@f5.com  */
5*1306St.nateldemoura@f5.com 
6*1306St.nateldemoura@f5.com #include <nxt_main.h>
7*1306St.nateldemoura@f5.com #include <nxt_conf.h>
8*1306St.nateldemoura@f5.com #include "nxt_tests.h"
9*1306St.nateldemoura@f5.com 
10*1306St.nateldemoura@f5.com 
11*1306St.nateldemoura@f5.com #define UIDMAP 1
12*1306St.nateldemoura@f5.com #define GIDMAP 2
13*1306St.nateldemoura@f5.com 
14*1306St.nateldemoura@f5.com 
15*1306St.nateldemoura@f5.com typedef struct {
16*1306St.nateldemoura@f5.com     nxt_int_t         map_type;
17*1306St.nateldemoura@f5.com     nxt_str_t         map_data;
18*1306St.nateldemoura@f5.com     nxt_int_t         setid;
19*1306St.nateldemoura@f5.com     nxt_credential_t  creds;
20*1306St.nateldemoura@f5.com     nxt_uid_t         unit_euid;
21*1306St.nateldemoura@f5.com     nxt_gid_t         unit_egid;
22*1306St.nateldemoura@f5.com     nxt_int_t         result;
23*1306St.nateldemoura@f5.com     nxt_str_t         errmsg;
24*1306St.nateldemoura@f5.com } nxt_clone_creds_testcase_t;
25*1306St.nateldemoura@f5.com 
26*1306St.nateldemoura@f5.com typedef struct {
27*1306St.nateldemoura@f5.com     nxt_clone_creds_testcase_t  *tc;
28*1306St.nateldemoura@f5.com } nxt_clone_creds_ctx_t;
29*1306St.nateldemoura@f5.com 
30*1306St.nateldemoura@f5.com 
31*1306St.nateldemoura@f5.com nxt_int_t nxt_clone_test_mappings(nxt_task_t *task, nxt_mp_t *mp,
32*1306St.nateldemoura@f5.com     nxt_clone_creds_ctx_t *ctx, nxt_clone_creds_testcase_t *tc);
33*1306St.nateldemoura@f5.com void nxt_cdecl nxt_clone_test_log_handler(nxt_uint_t level, nxt_log_t *log,
34*1306St.nateldemoura@f5.com     const char *fmt, ...);
35*1306St.nateldemoura@f5.com nxt_int_t nxt_clone_test_map_assert(nxt_task_t *task,
36*1306St.nateldemoura@f5.com     nxt_clone_creds_testcase_t *tc, nxt_clone_credential_map_t *map);
37*1306St.nateldemoura@f5.com static nxt_int_t nxt_clone_test_parse_map(nxt_task_t *task,
38*1306St.nateldemoura@f5.com     nxt_str_t *map_str, nxt_clone_credential_map_t *map);
39*1306St.nateldemoura@f5.com 
40*1306St.nateldemoura@f5.com 
41*1306St.nateldemoura@f5.com nxt_log_t *test_log;
42*1306St.nateldemoura@f5.com 
43*1306St.nateldemoura@f5.com static nxt_gid_t gids[] = {1000, 10000, 60000};
44*1306St.nateldemoura@f5.com 
45*1306St.nateldemoura@f5.com static nxt_clone_creds_testcase_t testcases[] = {
46*1306St.nateldemoura@f5.com     {
47*1306St.nateldemoura@f5.com         /*
48*1306St.nateldemoura@f5.com          * Unprivileged unit
49*1306St.nateldemoura@f5.com          *
50*1306St.nateldemoura@f5.com          * if no uid mapping and app creds and unit creds are the same,
51*1306St.nateldemoura@f5.com          * then we automatically add a map for the creds->uid.
52*1306St.nateldemoura@f5.com          * Then, child process can safely setuid(creds->uid) in
53*1306St.nateldemoura@f5.com          * the new namespace.
54*1306St.nateldemoura@f5.com          */
55*1306St.nateldemoura@f5.com         UIDMAP,
56*1306St.nateldemoura@f5.com         nxt_string(""),
57*1306St.nateldemoura@f5.com         0,
58*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
59*1306St.nateldemoura@f5.com         1000, 1000,
60*1306St.nateldemoura@f5.com         NXT_OK,
61*1306St.nateldemoura@f5.com         nxt_string("")
62*1306St.nateldemoura@f5.com     },
63*1306St.nateldemoura@f5.com     {
64*1306St.nateldemoura@f5.com         UIDMAP,
65*1306St.nateldemoura@f5.com         nxt_string(""),
66*1306St.nateldemoura@f5.com         0,
67*1306St.nateldemoura@f5.com         {"johndoe", 10000, 10000, 0, NULL},
68*1306St.nateldemoura@f5.com         1000, 1000,
69*1306St.nateldemoura@f5.com         NXT_OK,
70*1306St.nateldemoura@f5.com         nxt_string("")
71*1306St.nateldemoura@f5.com     },
72*1306St.nateldemoura@f5.com     {
73*1306St.nateldemoura@f5.com         UIDMAP,
74*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"),
75*1306St.nateldemoura@f5.com         0,
76*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
77*1306St.nateldemoura@f5.com         1000, 1000,
78*1306St.nateldemoura@f5.com         NXT_OK,
79*1306St.nateldemoura@f5.com         nxt_string("")
80*1306St.nateldemoura@f5.com     },
81*1306St.nateldemoura@f5.com     {
82*1306St.nateldemoura@f5.com         UIDMAP,
83*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"),
84*1306St.nateldemoura@f5.com         0,
85*1306St.nateldemoura@f5.com         {"root", 0, 0, 0, NULL},
86*1306St.nateldemoura@f5.com         1000, 1000,
87*1306St.nateldemoura@f5.com         NXT_OK,
88*1306St.nateldemoura@f5.com         nxt_string("")
89*1306St.nateldemoura@f5.com     },
90*1306St.nateldemoura@f5.com     {
91*1306St.nateldemoura@f5.com         UIDMAP,
92*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"),
93*1306St.nateldemoura@f5.com         0,
94*1306St.nateldemoura@f5.com         {"nobody", 65534, 0, 0, NULL},
95*1306St.nateldemoura@f5.com         1000, 1000,
96*1306St.nateldemoura@f5.com         NXT_OK,
97*1306St.nateldemoura@f5.com         nxt_string("")
98*1306St.nateldemoura@f5.com     },
99*1306St.nateldemoura@f5.com     {
100*1306St.nateldemoura@f5.com         UIDMAP,
101*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1},"
102*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"),
103*1306St.nateldemoura@f5.com         0,
104*1306St.nateldemoura@f5.com         {"root", 0, 0, 0, NULL},
105*1306St.nateldemoura@f5.com         1000, 1000,
106*1306St.nateldemoura@f5.com         NXT_ERROR,
107*1306St.nateldemoura@f5.com         nxt_string("\"uidmap\" field has 2 entries but unprivileged unit has "
108*1306St.nateldemoura@f5.com                    "a maximum of 1 map.")
109*1306St.nateldemoura@f5.com     },
110*1306St.nateldemoura@f5.com     {
111*1306St.nateldemoura@f5.com         UIDMAP,
112*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1},"
113*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"),
114*1306St.nateldemoura@f5.com         1, /* privileged */
115*1306St.nateldemoura@f5.com         {"root", 0, 0, 0, NULL},
116*1306St.nateldemoura@f5.com         1000, 1000,
117*1306St.nateldemoura@f5.com         NXT_OK,
118*1306St.nateldemoura@f5.com         nxt_string("")
119*1306St.nateldemoura@f5.com     },
120*1306St.nateldemoura@f5.com     {
121*1306St.nateldemoura@f5.com         UIDMAP,
122*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000},"
123*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"),
124*1306St.nateldemoura@f5.com         1, /* privileged */
125*1306St.nateldemoura@f5.com         {"johndoe", 500, 0, 0, NULL},
126*1306St.nateldemoura@f5.com         1000, 1000,
127*1306St.nateldemoura@f5.com         NXT_OK,
128*1306St.nateldemoura@f5.com         nxt_string("")
129*1306St.nateldemoura@f5.com     },
130*1306St.nateldemoura@f5.com     {
131*1306St.nateldemoura@f5.com         UIDMAP,
132*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000},"
133*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"),
134*1306St.nateldemoura@f5.com         1, /* privileged */
135*1306St.nateldemoura@f5.com         {"johndoe", 1000, 0, 0, NULL},
136*1306St.nateldemoura@f5.com         1000, 1000,
137*1306St.nateldemoura@f5.com         NXT_OK,
138*1306St.nateldemoura@f5.com         nxt_string("")
139*1306St.nateldemoura@f5.com     },
140*1306St.nateldemoura@f5.com     {
141*1306St.nateldemoura@f5.com         UIDMAP,
142*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000},"
143*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"),
144*1306St.nateldemoura@f5.com         1, /* privileged */
145*1306St.nateldemoura@f5.com         {"johndoe", 1500, 0, 0, NULL},
146*1306St.nateldemoura@f5.com         1000, 1000,
147*1306St.nateldemoura@f5.com         NXT_OK,
148*1306St.nateldemoura@f5.com         nxt_string("")
149*1306St.nateldemoura@f5.com     },
150*1306St.nateldemoura@f5.com     {
151*1306St.nateldemoura@f5.com         UIDMAP,
152*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000},"
153*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"),
154*1306St.nateldemoura@f5.com         1, /* privileged */
155*1306St.nateldemoura@f5.com         {"johndoe", 1999, 0, 0, NULL},
156*1306St.nateldemoura@f5.com         1000, 1000,
157*1306St.nateldemoura@f5.com         NXT_OK,
158*1306St.nateldemoura@f5.com         nxt_string("")
159*1306St.nateldemoura@f5.com     },
160*1306St.nateldemoura@f5.com     {
161*1306St.nateldemoura@f5.com         UIDMAP,
162*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000},"
163*1306St.nateldemoura@f5.com                    " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"),
164*1306St.nateldemoura@f5.com         1, /* privileged */
165*1306St.nateldemoura@f5.com         {"johndoe", 2000, 0, 0, NULL},
166*1306St.nateldemoura@f5.com         1000, 1000,
167*1306St.nateldemoura@f5.com         NXT_ERROR,
168*1306St.nateldemoura@f5.com         nxt_string("\"uidmap\" field has no \"container\" entry for user "
169*1306St.nateldemoura@f5.com                    "\"johndoe\" (uid 2000)")
170*1306St.nateldemoura@f5.com     },
171*1306St.nateldemoura@f5.com     {
172*1306St.nateldemoura@f5.com         /*
173*1306St.nateldemoura@f5.com          * Unprivileged unit
174*1306St.nateldemoura@f5.com          *
175*1306St.nateldemoura@f5.com          * if no gid mapping and app creds and unit creds are the same,
176*1306St.nateldemoura@f5.com          * then we automatically add a map for the creds->base_gid.
177*1306St.nateldemoura@f5.com          * Then, child process can safely setgid(creds->base_gid) in
178*1306St.nateldemoura@f5.com          * the new namespace.
179*1306St.nateldemoura@f5.com          */
180*1306St.nateldemoura@f5.com         GIDMAP,
181*1306St.nateldemoura@f5.com         nxt_string("[]"),
182*1306St.nateldemoura@f5.com         0,
183*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
184*1306St.nateldemoura@f5.com         1000, 1000,
185*1306St.nateldemoura@f5.com         NXT_OK,
186*1306St.nateldemoura@f5.com         nxt_string("")
187*1306St.nateldemoura@f5.com     },
188*1306St.nateldemoura@f5.com     {
189*1306St.nateldemoura@f5.com         /*
190*1306St.nateldemoura@f5.com          * Unprivileged unit
191*1306St.nateldemoura@f5.com          *
192*1306St.nateldemoura@f5.com          * Inside the new namespace, we can have any gid but it
193*1306St.nateldemoura@f5.com          * should map to parent gid (in this case 1000) in parent
194*1306St.nateldemoura@f5.com          * namespace.
195*1306St.nateldemoura@f5.com          */
196*1306St.nateldemoura@f5.com         GIDMAP,
197*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"),
198*1306St.nateldemoura@f5.com         0,
199*1306St.nateldemoura@f5.com         {"root", 0, 0, 0, NULL},
200*1306St.nateldemoura@f5.com         1000, 1000,
201*1306St.nateldemoura@f5.com         NXT_OK,
202*1306St.nateldemoura@f5.com         nxt_string("")
203*1306St.nateldemoura@f5.com     },
204*1306St.nateldemoura@f5.com     {
205*1306St.nateldemoura@f5.com         GIDMAP,
206*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"),
207*1306St.nateldemoura@f5.com         0,
208*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
209*1306St.nateldemoura@f5.com         1000, 1000,
210*1306St.nateldemoura@f5.com         NXT_OK,
211*1306St.nateldemoura@f5.com         nxt_string("")
212*1306St.nateldemoura@f5.com     },
213*1306St.nateldemoura@f5.com     {
214*1306St.nateldemoura@f5.com         /*
215*1306St.nateldemoura@f5.com          * Unprivileged unit
216*1306St.nateldemoura@f5.com          *
217*1306St.nateldemoura@f5.com          * There's no mapping for "johndoe" (gid 1000) inside the namespace.
218*1306St.nateldemoura@f5.com          */
219*1306St.nateldemoura@f5.com         GIDMAP,
220*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 65535, \"host\": 1000, \"size\": 1}]"),
221*1306St.nateldemoura@f5.com         0,
222*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
223*1306St.nateldemoura@f5.com         1000, 1000,
224*1306St.nateldemoura@f5.com         NXT_ERROR,
225*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has no \"container\" entry for "
226*1306St.nateldemoura@f5.com                     "gid 1000.")
227*1306St.nateldemoura@f5.com     },
228*1306St.nateldemoura@f5.com     {
229*1306St.nateldemoura@f5.com         GIDMAP,
230*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 2}]"),
231*1306St.nateldemoura@f5.com         0,
232*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
233*1306St.nateldemoura@f5.com         1000, 1000,
234*1306St.nateldemoura@f5.com         NXT_ERROR,
235*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has an entry with \"size\": 2, but "
236*1306St.nateldemoura@f5.com                     "for unprivileged unit it must be 1.")
237*1306St.nateldemoura@f5.com     },
238*1306St.nateldemoura@f5.com     {
239*1306St.nateldemoura@f5.com         GIDMAP,
240*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 1001, \"size\": 1}]"),
241*1306St.nateldemoura@f5.com         0,
242*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
243*1306St.nateldemoura@f5.com         1000, 1000,
244*1306St.nateldemoura@f5.com         NXT_ERROR,
245*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has an entry for host gid 1001 but "
246*1306St.nateldemoura@f5.com                     "unprivileged unit can only map itself (gid 1000) "
247*1306St.nateldemoura@f5.com                     "into child namespaces.")
248*1306St.nateldemoura@f5.com     },
249*1306St.nateldemoura@f5.com     {
250*1306St.nateldemoura@f5.com         GIDMAP,
251*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"),
252*1306St.nateldemoura@f5.com         0,
253*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
254*1306St.nateldemoura@f5.com         1000, 1000,
255*1306St.nateldemoura@f5.com         NXT_ERROR,
256*1306St.nateldemoura@f5.com         nxt_string("unprivileged unit disallow supplementary groups for "
257*1306St.nateldemoura@f5.com                     "new namespace (user \"johndoe\" has 3 groups).")
258*1306St.nateldemoura@f5.com     },
259*1306St.nateldemoura@f5.com 
260*1306St.nateldemoura@f5.com     /* privileged unit */
261*1306St.nateldemoura@f5.com 
262*1306St.nateldemoura@f5.com     /* not root with capabilities */
263*1306St.nateldemoura@f5.com     {
264*1306St.nateldemoura@f5.com         GIDMAP,
265*1306St.nateldemoura@f5.com         nxt_string("[]"),
266*1306St.nateldemoura@f5.com         1,
267*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
268*1306St.nateldemoura@f5.com         1000, 1000,
269*1306St.nateldemoura@f5.com         NXT_OK,
270*1306St.nateldemoura@f5.com         nxt_string("")
271*1306St.nateldemoura@f5.com     },
272*1306St.nateldemoura@f5.com     {
273*1306St.nateldemoura@f5.com         GIDMAP,
274*1306St.nateldemoura@f5.com         nxt_string(""),
275*1306St.nateldemoura@f5.com         1,
276*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 0, NULL},
277*1306St.nateldemoura@f5.com         1000, 1000,
278*1306St.nateldemoura@f5.com         NXT_OK,
279*1306St.nateldemoura@f5.com         nxt_string("")
280*1306St.nateldemoura@f5.com     },
281*1306St.nateldemoura@f5.com     {
282*1306St.nateldemoura@f5.com         /* missing gid of {"user": "nobody"} */
283*1306St.nateldemoura@f5.com         GIDMAP,
284*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"),
285*1306St.nateldemoura@f5.com         1,
286*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
287*1306St.nateldemoura@f5.com         1000, 1000,
288*1306St.nateldemoura@f5.com         NXT_ERROR,
289*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has no \"container\" entry for "
290*1306St.nateldemoura@f5.com                     "gid 65534.")
291*1306St.nateldemoura@f5.com     },
292*1306St.nateldemoura@f5.com     {
293*1306St.nateldemoura@f5.com         /* solves the previous by mapping 65534 gids */
294*1306St.nateldemoura@f5.com         GIDMAP,
295*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 65535}]"),
296*1306St.nateldemoura@f5.com         1,
297*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
298*1306St.nateldemoura@f5.com         1000, 1000,
299*1306St.nateldemoura@f5.com         NXT_OK,
300*1306St.nateldemoura@f5.com         nxt_string("")
301*1306St.nateldemoura@f5.com     },
302*1306St.nateldemoura@f5.com     {
303*1306St.nateldemoura@f5.com         /* solves by adding a separate mapping */
304*1306St.nateldemoura@f5.com         GIDMAP,
305*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1},"
306*1306St.nateldemoura@f5.com                    " {\"container\": 65534, \"host\": 1000, \"size\": 1}]"),
307*1306St.nateldemoura@f5.com         1,
308*1306St.nateldemoura@f5.com         {"nobody", 65534, 65534, 0, NULL},
309*1306St.nateldemoura@f5.com         1000, 1000,
310*1306St.nateldemoura@f5.com         NXT_OK,
311*1306St.nateldemoura@f5.com         nxt_string("")
312*1306St.nateldemoura@f5.com     },
313*1306St.nateldemoura@f5.com     {
314*1306St.nateldemoura@f5.com         /*
315*1306St.nateldemoura@f5.com          * Map a big range
316*1306St.nateldemoura@f5.com          */
317*1306St.nateldemoura@f5.com         GIDMAP,
318*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 0, \"size\": 200000}]"),
319*1306St.nateldemoura@f5.com         1,
320*1306St.nateldemoura@f5.com         {"johndoe", 100000, 100000, 0, NULL},
321*1306St.nateldemoura@f5.com         1000, 1000,
322*1306St.nateldemoura@f5.com         NXT_OK,
323*1306St.nateldemoura@f5.com         nxt_string("")
324*1306St.nateldemoura@f5.com     },
325*1306St.nateldemoura@f5.com     {
326*1306St.nateldemoura@f5.com         /*
327*1306St.nateldemoura@f5.com          * Validate if supplementary groups are mapped
328*1306St.nateldemoura@f5.com          */
329*1306St.nateldemoura@f5.com         GIDMAP,
330*1306St.nateldemoura@f5.com         nxt_string("[]"),
331*1306St.nateldemoura@f5.com         1,
332*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
333*1306St.nateldemoura@f5.com         1000, 1000,
334*1306St.nateldemoura@f5.com         NXT_ERROR,
335*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has no entries but user \"johndoe\" "
336*1306St.nateldemoura@f5.com                    "has 3 suplementary groups."),
337*1306St.nateldemoura@f5.com     },
338*1306St.nateldemoura@f5.com     {
339*1306St.nateldemoura@f5.com         GIDMAP,
340*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 0, \"host\": 0, \"size\": 1}]"),
341*1306St.nateldemoura@f5.com         1,
342*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
343*1306St.nateldemoura@f5.com         1000, 1000,
344*1306St.nateldemoura@f5.com         NXT_ERROR,
345*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has no \"container\" entry for "
346*1306St.nateldemoura@f5.com                    "gid 1000."),
347*1306St.nateldemoura@f5.com     },
348*1306St.nateldemoura@f5.com     {
349*1306St.nateldemoura@f5.com         GIDMAP,
350*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 0, \"size\": 1}]"),
351*1306St.nateldemoura@f5.com         1,
352*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
353*1306St.nateldemoura@f5.com         1000, 1000,
354*1306St.nateldemoura@f5.com         NXT_ERROR,
355*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has missing suplementary gid mappings "
356*1306St.nateldemoura@f5.com                    "(found 1 out of 3)."),
357*1306St.nateldemoura@f5.com     },
358*1306St.nateldemoura@f5.com     {
359*1306St.nateldemoura@f5.com         GIDMAP,
360*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 0, \"size\": 1},"
361*1306St.nateldemoura@f5.com                    " {\"container\": 10000, \"host\": 10000, \"size\": 1}]"),
362*1306St.nateldemoura@f5.com         1,
363*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
364*1306St.nateldemoura@f5.com         1000, 1000,
365*1306St.nateldemoura@f5.com         NXT_ERROR,
366*1306St.nateldemoura@f5.com         nxt_string("\"gidmap\" field has missing suplementary gid mappings "
367*1306St.nateldemoura@f5.com                    "(found 2 out of 3)."),
368*1306St.nateldemoura@f5.com     },
369*1306St.nateldemoura@f5.com     {
370*1306St.nateldemoura@f5.com         /*
371*1306St.nateldemoura@f5.com          * Fix all mappings
372*1306St.nateldemoura@f5.com          */
373*1306St.nateldemoura@f5.com         GIDMAP,
374*1306St.nateldemoura@f5.com         nxt_string("[{\"container\": 1000, \"host\": 0, \"size\": 1},"
375*1306St.nateldemoura@f5.com                    "{\"container\": 10000, \"host\": 10000, \"size\": 1},"
376*1306St.nateldemoura@f5.com                    " {\"container\": 60000, \"host\": 60000, \"size\": 1}]"),
377*1306St.nateldemoura@f5.com         1,
378*1306St.nateldemoura@f5.com         {"johndoe", 1000, 1000, 3, gids},
379*1306St.nateldemoura@f5.com         1000, 1000,
380*1306St.nateldemoura@f5.com         NXT_OK,
381*1306St.nateldemoura@f5.com         nxt_string(""),
382*1306St.nateldemoura@f5.com     },
383*1306St.nateldemoura@f5.com };
384*1306St.nateldemoura@f5.com 
385*1306St.nateldemoura@f5.com 
386*1306St.nateldemoura@f5.com void nxt_cdecl
387*1306St.nateldemoura@f5.com nxt_clone_test_log_handler(nxt_uint_t level, nxt_log_t *log,
388*1306St.nateldemoura@f5.com     const char *fmt, ...)
389*1306St.nateldemoura@f5.com {
390*1306St.nateldemoura@f5.com     u_char                      *p, *end;
391*1306St.nateldemoura@f5.com     va_list                     args;
392*1306St.nateldemoura@f5.com     nxt_clone_creds_ctx_t       *ctx;
393*1306St.nateldemoura@f5.com     nxt_clone_creds_testcase_t  *tc;
394*1306St.nateldemoura@f5.com     u_char                      msg[NXT_MAX_ERROR_STR];
395*1306St.nateldemoura@f5.com 
396*1306St.nateldemoura@f5.com     p = msg;
397*1306St.nateldemoura@f5.com     end = msg + NXT_MAX_ERROR_STR;
398*1306St.nateldemoura@f5.com 
399*1306St.nateldemoura@f5.com     ctx = log->ctx;
400*1306St.nateldemoura@f5.com     tc = ctx->tc;
401*1306St.nateldemoura@f5.com 
402*1306St.nateldemoura@f5.com     va_start(args, fmt);
403*1306St.nateldemoura@f5.com     p = nxt_vsprintf(p, end, fmt, args);
404*1306St.nateldemoura@f5.com     va_end(args);
405*1306St.nateldemoura@f5.com 
406*1306St.nateldemoura@f5.com     *p++ = '\0';
407*1306St.nateldemoura@f5.com 
408*1306St.nateldemoura@f5.com     if (tc->result == NXT_OK && level == NXT_LOG_DEBUG) {
409*1306St.nateldemoura@f5.com         return;
410*1306St.nateldemoura@f5.com     }
411*1306St.nateldemoura@f5.com 
412*1306St.nateldemoura@f5.com     if (tc->errmsg.length == 0) {
413*1306St.nateldemoura@f5.com         nxt_log_error(NXT_LOG_ERR, &nxt_main_log, "unexpected log: %s", msg);
414*1306St.nateldemoura@f5.com         return;
415*1306St.nateldemoura@f5.com     }
416*1306St.nateldemoura@f5.com 
417*1306St.nateldemoura@f5.com     if (!nxt_str_eq(&tc->errmsg, msg, (nxt_uint_t) (p - msg - 1))) {
418*1306St.nateldemoura@f5.com         nxt_log_error(NXT_LOG_ERR, &nxt_main_log,
419*1306St.nateldemoura@f5.com                       "error log mismatch: got [%s] but wants [%V]",
420*1306St.nateldemoura@f5.com                       msg, &tc->errmsg);
421*1306St.nateldemoura@f5.com         return;
422*1306St.nateldemoura@f5.com     }
423*1306St.nateldemoura@f5.com }
424*1306St.nateldemoura@f5.com 
425*1306St.nateldemoura@f5.com 
426*1306St.nateldemoura@f5.com nxt_int_t
427*1306St.nateldemoura@f5.com nxt_clone_creds_test(nxt_thread_t *thr)
428*1306St.nateldemoura@f5.com {
429*1306St.nateldemoura@f5.com     nxt_mp_t               *mp;
430*1306St.nateldemoura@f5.com     nxt_int_t              ret;
431*1306St.nateldemoura@f5.com     nxt_uint_t             count, i;
432*1306St.nateldemoura@f5.com     nxt_task_t             *task;
433*1306St.nateldemoura@f5.com     nxt_runtime_t          rt;
434*1306St.nateldemoura@f5.com     nxt_clone_creds_ctx_t  ctx;
435*1306St.nateldemoura@f5.com 
436*1306St.nateldemoura@f5.com     nxt_log_t nxt_clone_creds_log = {
437*1306St.nateldemoura@f5.com         NXT_LOG_INFO,
438*1306St.nateldemoura@f5.com         0,
439*1306St.nateldemoura@f5.com         nxt_clone_test_log_handler,
440*1306St.nateldemoura@f5.com         NULL,
441*1306St.nateldemoura@f5.com         &ctx
442*1306St.nateldemoura@f5.com     };
443*1306St.nateldemoura@f5.com 
444*1306St.nateldemoura@f5.com     nxt_thread_time_update(thr);
445*1306St.nateldemoura@f5.com 
446*1306St.nateldemoura@f5.com     thr->runtime = &rt;
447*1306St.nateldemoura@f5.com 
448*1306St.nateldemoura@f5.com     task = thr->task;
449*1306St.nateldemoura@f5.com 
450*1306St.nateldemoura@f5.com     mp = nxt_mp_create(1024, 128, 256, 32);
451*1306St.nateldemoura@f5.com     if (mp == NULL) {
452*1306St.nateldemoura@f5.com         return NXT_ERROR;
453*1306St.nateldemoura@f5.com     }
454*1306St.nateldemoura@f5.com 
455*1306St.nateldemoura@f5.com     rt.mem_pool = mp;
456*1306St.nateldemoura@f5.com 
457*1306St.nateldemoura@f5.com     test_log = task->log;
458*1306St.nateldemoura@f5.com     task->log = &nxt_clone_creds_log;
459*1306St.nateldemoura@f5.com     task->thread = thr;
460*1306St.nateldemoura@f5.com 
461*1306St.nateldemoura@f5.com     count = sizeof(testcases)/sizeof(nxt_clone_creds_testcase_t);
462*1306St.nateldemoura@f5.com 
463*1306St.nateldemoura@f5.com     for (i = 0; i < count; i++) {
464*1306St.nateldemoura@f5.com         ret = nxt_clone_test_mappings(task, mp, &ctx, &testcases[i]);
465*1306St.nateldemoura@f5.com 
466*1306St.nateldemoura@f5.com         if (ret != NXT_OK) {
467*1306St.nateldemoura@f5.com             goto fail;
468*1306St.nateldemoura@f5.com         }
469*1306St.nateldemoura@f5.com     }
470*1306St.nateldemoura@f5.com 
471*1306St.nateldemoura@f5.com     ret = NXT_OK;
472*1306St.nateldemoura@f5.com 
473*1306St.nateldemoura@f5.com     nxt_log_error(NXT_LOG_NOTICE, test_log, "clone creds test passed");
474*1306St.nateldemoura@f5.com 
475*1306St.nateldemoura@f5.com fail:
476*1306St.nateldemoura@f5.com     task->log = test_log;
477*1306St.nateldemoura@f5.com     nxt_mp_destroy(mp);
478*1306St.nateldemoura@f5.com 
479*1306St.nateldemoura@f5.com     return ret;
480*1306St.nateldemoura@f5.com }
481*1306St.nateldemoura@f5.com 
482*1306St.nateldemoura@f5.com 
483*1306St.nateldemoura@f5.com nxt_int_t
484*1306St.nateldemoura@f5.com nxt_clone_test_mappings(nxt_task_t *task, nxt_mp_t *mp,
485*1306St.nateldemoura@f5.com     nxt_clone_creds_ctx_t *ctx, nxt_clone_creds_testcase_t *tc)
486*1306St.nateldemoura@f5.com {
487*1306St.nateldemoura@f5.com     nxt_int_t                   ret;
488*1306St.nateldemoura@f5.com     nxt_runtime_t               *rt;
489*1306St.nateldemoura@f5.com     nxt_clone_credential_map_t  map;
490*1306St.nateldemoura@f5.com 
491*1306St.nateldemoura@f5.com     rt = task->thread->runtime;
492*1306St.nateldemoura@f5.com 
493*1306St.nateldemoura@f5.com     map.size = 0;
494*1306St.nateldemoura@f5.com 
495*1306St.nateldemoura@f5.com     if (tc->map_data.length > 0) {
496*1306St.nateldemoura@f5.com         ret = nxt_clone_test_parse_map(task, &tc->map_data, &map);
497*1306St.nateldemoura@f5.com         if (ret != NXT_OK) {
498*1306St.nateldemoura@f5.com             return NXT_ERROR;
499*1306St.nateldemoura@f5.com         }
500*1306St.nateldemoura@f5.com     }
501*1306St.nateldemoura@f5.com 
502*1306St.nateldemoura@f5.com     rt->capabilities.setid = tc->setid;
503*1306St.nateldemoura@f5.com 
504*1306St.nateldemoura@f5.com     nxt_euid = tc->unit_euid;
505*1306St.nateldemoura@f5.com     nxt_egid = tc->unit_egid;
506*1306St.nateldemoura@f5.com 
507*1306St.nateldemoura@f5.com     ctx->tc = tc;
508*1306St.nateldemoura@f5.com 
509*1306St.nateldemoura@f5.com     if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) {
510*1306St.nateldemoura@f5.com         return NXT_ERROR;
511*1306St.nateldemoura@f5.com     }
512*1306St.nateldemoura@f5.com 
513*1306St.nateldemoura@f5.com     if (tc->setid && nxt_euid != 0) {
514*1306St.nateldemoura@f5.com         /*
515*1306St.nateldemoura@f5.com          * Running as root should have the same behavior as
516*1306St.nateldemoura@f5.com          * passing Linux capabilities.
517*1306St.nateldemoura@f5.com          */
518*1306St.nateldemoura@f5.com 
519*1306St.nateldemoura@f5.com         nxt_euid = 0;
520*1306St.nateldemoura@f5.com         nxt_egid = 0;
521*1306St.nateldemoura@f5.com 
522*1306St.nateldemoura@f5.com         if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) {
523*1306St.nateldemoura@f5.com             return NXT_ERROR;
524*1306St.nateldemoura@f5.com         }
525*1306St.nateldemoura@f5.com     }
526*1306St.nateldemoura@f5.com 
527*1306St.nateldemoura@f5.com     return NXT_OK;
528*1306St.nateldemoura@f5.com }
529*1306St.nateldemoura@f5.com 
530*1306St.nateldemoura@f5.com 
531*1306St.nateldemoura@f5.com nxt_int_t
532*1306St.nateldemoura@f5.com nxt_clone_test_map_assert(nxt_task_t *task, nxt_clone_creds_testcase_t *tc,
533*1306St.nateldemoura@f5.com     nxt_clone_credential_map_t *map)
534*1306St.nateldemoura@f5.com {
535*1306St.nateldemoura@f5.com     nxt_int_t ret;
536*1306St.nateldemoura@f5.com 
537*1306St.nateldemoura@f5.com     if (tc->map_type == UIDMAP) {
538*1306St.nateldemoura@f5.com         ret = nxt_clone_vldt_credential_uidmap(task, map, &tc->creds);
539*1306St.nateldemoura@f5.com     } else {
540*1306St.nateldemoura@f5.com         ret = nxt_clone_vldt_credential_gidmap(task, map, &tc->creds);
541*1306St.nateldemoura@f5.com     }
542*1306St.nateldemoura@f5.com 
543*1306St.nateldemoura@f5.com     if (ret != tc->result) {
544*1306St.nateldemoura@f5.com         nxt_log_error(NXT_LOG_ERR, &nxt_main_log,
545*1306St.nateldemoura@f5.com                       "return %d instead of %d (map: %V)", ret, tc->result,
546*1306St.nateldemoura@f5.com                       &tc->map_data);
547*1306St.nateldemoura@f5.com 
548*1306St.nateldemoura@f5.com         return NXT_ERROR;
549*1306St.nateldemoura@f5.com     }
550*1306St.nateldemoura@f5.com 
551*1306St.nateldemoura@f5.com     return NXT_OK;
552*1306St.nateldemoura@f5.com }
553*1306St.nateldemoura@f5.com 
554*1306St.nateldemoura@f5.com 
555*1306St.nateldemoura@f5.com static nxt_int_t
556*1306St.nateldemoura@f5.com nxt_clone_test_parse_map(nxt_task_t *task, nxt_str_t *map_str,
557*1306St.nateldemoura@f5.com     nxt_clone_credential_map_t *map)
558*1306St.nateldemoura@f5.com {
559*1306St.nateldemoura@f5.com     nxt_uint_t        i;
560*1306St.nateldemoura@f5.com     nxt_runtime_t     *rt;
561*1306St.nateldemoura@f5.com     nxt_conf_value_t  *array, *obj, *value;
562*1306St.nateldemoura@f5.com 
563*1306St.nateldemoura@f5.com     static nxt_str_t  host_name = nxt_string("host");
564*1306St.nateldemoura@f5.com     static nxt_str_t  cont_name = nxt_string("container");
565*1306St.nateldemoura@f5.com     static nxt_str_t  size_name = nxt_string("size");
566*1306St.nateldemoura@f5.com 
567*1306St.nateldemoura@f5.com     rt = task->thread->runtime;
568*1306St.nateldemoura@f5.com 
569*1306St.nateldemoura@f5.com     array = nxt_conf_json_parse_str(rt->mem_pool, map_str);
570*1306St.nateldemoura@f5.com     if (array == NULL) {
571*1306St.nateldemoura@f5.com         return NXT_ERROR;
572*1306St.nateldemoura@f5.com     }
573*1306St.nateldemoura@f5.com 
574*1306St.nateldemoura@f5.com     map->size = nxt_conf_array_elements_count(array);
575*1306St.nateldemoura@f5.com 
576*1306St.nateldemoura@f5.com     if (map->size == 0) {
577*1306St.nateldemoura@f5.com         return NXT_OK;
578*1306St.nateldemoura@f5.com     }
579*1306St.nateldemoura@f5.com 
580*1306St.nateldemoura@f5.com     map->map = nxt_mp_alloc(rt->mem_pool,
581*1306St.nateldemoura@f5.com                             map->size * sizeof(nxt_clone_map_entry_t));
582*1306St.nateldemoura@f5.com 
583*1306St.nateldemoura@f5.com     if (map->map == NULL) {
584*1306St.nateldemoura@f5.com         return NXT_ERROR;
585*1306St.nateldemoura@f5.com     }
586*1306St.nateldemoura@f5.com 
587*1306St.nateldemoura@f5.com     for (i = 0; i < map->size; i++) {
588*1306St.nateldemoura@f5.com         obj = nxt_conf_get_array_element(array, i);
589*1306St.nateldemoura@f5.com 
590*1306St.nateldemoura@f5.com         value = nxt_conf_get_object_member(obj, &host_name, NULL);
591*1306St.nateldemoura@f5.com         map->map[i].host = nxt_conf_get_integer(value);
592*1306St.nateldemoura@f5.com 
593*1306St.nateldemoura@f5.com         value = nxt_conf_get_object_member(obj, &cont_name, NULL);
594*1306St.nateldemoura@f5.com         map->map[i].container = nxt_conf_get_integer(value);
595*1306St.nateldemoura@f5.com 
596*1306St.nateldemoura@f5.com         value = nxt_conf_get_object_member(obj, &size_name, NULL);
597*1306St.nateldemoura@f5.com         map->map[i].size = nxt_conf_get_integer(value);
598*1306St.nateldemoura@f5.com     }
599*1306St.nateldemoura@f5.com 
600*1306St.nateldemoura@f5.com     return NXT_OK;
601*1306St.nateldemoura@f5.com }
602