1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #if !defined(_GNU_SOURCE)
26*1c60b9acSAndroid Build Coastguard Worker #define _GNU_SOURCE
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
29*1c60b9acSAndroid Build Coastguard Worker
30*1c60b9acSAndroid Build Coastguard Worker #include <pwd.h>
31*1c60b9acSAndroid Build Coastguard Worker #include <grp.h>
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
34*1c60b9acSAndroid Build Coastguard Worker static void
_lws_plat_apply_caps(unsigned int mode,const cap_value_t * cv,int count)35*1c60b9acSAndroid Build Coastguard Worker _lws_plat_apply_caps(unsigned int mode, const cap_value_t *cv, int count)
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker cap_t caps;
38*1c60b9acSAndroid Build Coastguard Worker
39*1c60b9acSAndroid Build Coastguard Worker if (!count)
40*1c60b9acSAndroid Build Coastguard Worker return;
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker caps = cap_get_proc();
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard Worker cap_set_flag(caps, (cap_flag_t)mode, count, cv, CAP_SET);
45*1c60b9acSAndroid Build Coastguard Worker cap_set_proc(caps);
46*1c60b9acSAndroid Build Coastguard Worker prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
47*1c60b9acSAndroid Build Coastguard Worker cap_free(caps);
48*1c60b9acSAndroid Build Coastguard Worker }
49*1c60b9acSAndroid Build Coastguard Worker #endif
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker int
lws_plat_user_colon_group_to_ids(const char * u_colon_g,uid_t * puid,gid_t * pgid)52*1c60b9acSAndroid Build Coastguard Worker lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid)
53*1c60b9acSAndroid Build Coastguard Worker {
54*1c60b9acSAndroid Build Coastguard Worker char *colon = strchr(u_colon_g, ':'), u[33];
55*1c60b9acSAndroid Build Coastguard Worker struct group *g;
56*1c60b9acSAndroid Build Coastguard Worker struct passwd *p;
57*1c60b9acSAndroid Build Coastguard Worker size_t ulen;
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker if (!colon)
60*1c60b9acSAndroid Build Coastguard Worker return 1;
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker ulen = (size_t)(unsigned int)lws_ptr_diff(colon, u_colon_g);
63*1c60b9acSAndroid Build Coastguard Worker if (ulen < 2 || ulen > sizeof(u) - 1)
64*1c60b9acSAndroid Build Coastguard Worker return 1;
65*1c60b9acSAndroid Build Coastguard Worker
66*1c60b9acSAndroid Build Coastguard Worker memcpy(u, u_colon_g, ulen);
67*1c60b9acSAndroid Build Coastguard Worker u[ulen] = '\0';
68*1c60b9acSAndroid Build Coastguard Worker
69*1c60b9acSAndroid Build Coastguard Worker colon++;
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETGRNAM_R)
72*1c60b9acSAndroid Build Coastguard Worker {
73*1c60b9acSAndroid Build Coastguard Worker struct group gr;
74*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker if (getgrnam_r(colon, &gr, strs, sizeof(strs), &g) || !g) {
77*1c60b9acSAndroid Build Coastguard Worker #else
78*1c60b9acSAndroid Build Coastguard Worker {
79*1c60b9acSAndroid Build Coastguard Worker g = getgrnam(colon);
80*1c60b9acSAndroid Build Coastguard Worker if (!g) {
81*1c60b9acSAndroid Build Coastguard Worker #endif
82*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unknown group '%s'\n", __func__, colon);
83*1c60b9acSAndroid Build Coastguard Worker
84*1c60b9acSAndroid Build Coastguard Worker return 1;
85*1c60b9acSAndroid Build Coastguard Worker }
86*1c60b9acSAndroid Build Coastguard Worker *pgid = g->gr_gid;
87*1c60b9acSAndroid Build Coastguard Worker }
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETPWNAM_R)
90*1c60b9acSAndroid Build Coastguard Worker {
91*1c60b9acSAndroid Build Coastguard Worker struct passwd pr;
92*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker if (getpwnam_r(u, &pr, strs, sizeof(strs), &p) || !p) {
95*1c60b9acSAndroid Build Coastguard Worker #else
96*1c60b9acSAndroid Build Coastguard Worker {
97*1c60b9acSAndroid Build Coastguard Worker p = getpwnam(u);
98*1c60b9acSAndroid Build Coastguard Worker if (!p) {
99*1c60b9acSAndroid Build Coastguard Worker #endif
100*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unknown user '%s'\n", __func__, u);
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker return 1;
103*1c60b9acSAndroid Build Coastguard Worker }
104*1c60b9acSAndroid Build Coastguard Worker *puid = p->pw_uid;
105*1c60b9acSAndroid Build Coastguard Worker }
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker return 0;
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker
110*1c60b9acSAndroid Build Coastguard Worker int
111*1c60b9acSAndroid Build Coastguard Worker lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop)
112*1c60b9acSAndroid Build Coastguard Worker {
113*1c60b9acSAndroid Build Coastguard Worker struct passwd *p;
114*1c60b9acSAndroid Build Coastguard Worker struct group *g;
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker /* if he gave us the groupname, align gid to match it */
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker if (context->groupname) {
119*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETGRNAM_R)
120*1c60b9acSAndroid Build Coastguard Worker struct group gr;
121*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker if (!getgrnam_r(context->groupname, &gr, strs, sizeof(strs), &g) && g) {
124*1c60b9acSAndroid Build Coastguard Worker #else
125*1c60b9acSAndroid Build Coastguard Worker g = getgrnam(context->groupname);
126*1c60b9acSAndroid Build Coastguard Worker if (g) {
127*1c60b9acSAndroid Build Coastguard Worker #endif
128*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "group %s -> gid %u",
129*1c60b9acSAndroid Build Coastguard Worker context->groupname, g->gr_gid);
130*1c60b9acSAndroid Build Coastguard Worker context->gid = g->gr_gid;
131*1c60b9acSAndroid Build Coastguard Worker } else {
132*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "unknown groupname '%s'",
133*1c60b9acSAndroid Build Coastguard Worker context->groupname);
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker return 1;
136*1c60b9acSAndroid Build Coastguard Worker }
137*1c60b9acSAndroid Build Coastguard Worker }
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker /* if he gave us the username, align uid to match it */
140*1c60b9acSAndroid Build Coastguard Worker
141*1c60b9acSAndroid Build Coastguard Worker if (context->username) {
142*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETPWNAM_R)
143*1c60b9acSAndroid Build Coastguard Worker struct passwd pr;
144*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker if (!getpwnam_r(context->username, &pr, strs, sizeof(strs), &p) && p) {
147*1c60b9acSAndroid Build Coastguard Worker #else
148*1c60b9acSAndroid Build Coastguard Worker p = getpwnam(context->username);
149*1c60b9acSAndroid Build Coastguard Worker if (p) {
150*1c60b9acSAndroid Build Coastguard Worker #endif
151*1c60b9acSAndroid Build Coastguard Worker context->uid = p->pw_uid;
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "username %s -> uid %u",
154*1c60b9acSAndroid Build Coastguard Worker context->username, (unsigned int)p->pw_uid);
155*1c60b9acSAndroid Build Coastguard Worker } else {
156*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "unknown username %s",
157*1c60b9acSAndroid Build Coastguard Worker context->username);
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker return 1;
160*1c60b9acSAndroid Build Coastguard Worker }
161*1c60b9acSAndroid Build Coastguard Worker }
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker if (!actually_drop)
164*1c60b9acSAndroid Build Coastguard Worker return 0;
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker /* if he gave us the gid or we have it from the groupname, set it */
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker if (context->gid && context->gid != (gid_t)-1l) {
169*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETGRGID_R)
170*1c60b9acSAndroid Build Coastguard Worker struct group gr;
171*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker if (getgrgid_r(context->gid, &gr, strs, sizeof(strs), &g) || !g) {
174*1c60b9acSAndroid Build Coastguard Worker #else
175*1c60b9acSAndroid Build Coastguard Worker g = getgrgid(context->gid);
176*1c60b9acSAndroid Build Coastguard Worker if (!g) {
177*1c60b9acSAndroid Build Coastguard Worker #endif
178*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "cannot find name for gid %d",
179*1c60b9acSAndroid Build Coastguard Worker context->gid);
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker return 1;
182*1c60b9acSAndroid Build Coastguard Worker }
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker if (setgid(context->gid)) {
185*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "setgid: %s failed",
186*1c60b9acSAndroid Build Coastguard Worker strerror(LWS_ERRNO));
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker return 1;
189*1c60b9acSAndroid Build Coastguard Worker }
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, "effective group '%s'", g->gr_name);
192*1c60b9acSAndroid Build Coastguard Worker } else
193*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "not changing group");
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker
196*1c60b9acSAndroid Build Coastguard Worker /* if he gave us the uid or we have it from the username, set it */
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker if (context->uid && context->uid != (uid_t)-1l) {
199*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GETPWUID_R)
200*1c60b9acSAndroid Build Coastguard Worker struct passwd pr;
201*1c60b9acSAndroid Build Coastguard Worker char strs[1024];
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker if (getpwuid_r(context->uid, &pr, strs, sizeof(strs), &p) || !p) {
204*1c60b9acSAndroid Build Coastguard Worker #else
205*1c60b9acSAndroid Build Coastguard Worker p = getpwuid(context->uid);
206*1c60b9acSAndroid Build Coastguard Worker if (!p) {
207*1c60b9acSAndroid Build Coastguard Worker #endif
208*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "getpwuid: unable to find uid %d",
209*1c60b9acSAndroid Build Coastguard Worker context->uid);
210*1c60b9acSAndroid Build Coastguard Worker return 1;
211*1c60b9acSAndroid Build Coastguard Worker }
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
214*1c60b9acSAndroid Build Coastguard Worker _lws_plat_apply_caps(CAP_PERMITTED, context->caps,
215*1c60b9acSAndroid Build Coastguard Worker context->count_caps);
216*1c60b9acSAndroid Build Coastguard Worker #endif
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker if (initgroups(p->pw_name,
219*1c60b9acSAndroid Build Coastguard Worker #if defined(__APPLE__)
220*1c60b9acSAndroid Build Coastguard Worker (int)
221*1c60b9acSAndroid Build Coastguard Worker #endif
222*1c60b9acSAndroid Build Coastguard Worker context->gid))
223*1c60b9acSAndroid Build Coastguard Worker return 1;
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker if (setuid(context->uid)) {
226*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "setuid: %s failed",
227*1c60b9acSAndroid Build Coastguard Worker strerror(LWS_ERRNO));
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker return 1;
230*1c60b9acSAndroid Build Coastguard Worker } else
231*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, "effective user '%s'",
232*1c60b9acSAndroid Build Coastguard Worker p->pw_name);
233*1c60b9acSAndroid Build Coastguard Worker
234*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
235*1c60b9acSAndroid Build Coastguard Worker _lws_plat_apply_caps(CAP_EFFECTIVE, context->caps,
236*1c60b9acSAndroid Build Coastguard Worker context->count_caps);
237*1c60b9acSAndroid Build Coastguard Worker
238*1c60b9acSAndroid Build Coastguard Worker if (context->count_caps) {
239*1c60b9acSAndroid Build Coastguard Worker int n;
240*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < context->count_caps; n++)
241*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, " RETAINING CAP %d",
242*1c60b9acSAndroid Build Coastguard Worker (int)context->caps[n]);
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker #endif
245*1c60b9acSAndroid Build Coastguard Worker } else
246*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "not changing user");
247*1c60b9acSAndroid Build Coastguard Worker
248*1c60b9acSAndroid Build Coastguard Worker return 0;
249*1c60b9acSAndroid Build Coastguard Worker }
250