1 /*
2 *
3 ***** BEGIN LICENSE BLOCK *****
4
5 Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
6
7 This file is part of CLIXON.
8
9 Licensed under the Apache License, Version 2.0 (the "License");
10 you may not use this file except in compliance with the License.
11 You may obtain a copy of the License at
12
13 http://www.apache.org/licenses/LICENSE-2.0
14
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
20
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 3 or later (the "GPL"),
23 in which case the provisions of the GPL are applicable instead
24 of those above. If you wish to allow use of your version of this file only
25 under the terms of the GPL, and not to allow others to
26 use your version of this file under the terms of Apache License version 2,
27 indicate your decision by deleting the provisions above and replace them with
28 the notice and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this file under
30 the terms of any one of the Apache License version 2 or the GPL.
31
32 ***** END LICENSE BLOCK *****
33
34 * uid, gid, privileges
35 */
36
37 #ifdef HAVE_CONFIG_H
38 #include "clixon_config.h" /* generated by config & autoconf */
39 #endif
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #define _GNU_SOURCE
45 #define __USE_GNU
46 #include <unistd.h> /* For setresuid */
47 #undef _GNU_SOURCE
48 #undef __USE_GNU
49 #include <stdarg.h>
50 #include <signal.h>
51 #include <syslog.h>
52 #include <errno.h>
53 #include <grp.h>
54 #include <pwd.h>
55
56 /* clicon */
57 #include "clixon_err.h"
58 #include "clixon_log.h"
59 #include "clixon_uid.h"
60
61 /*! Translate group name to gid. Return -1 if error or not found.
62 * @param[in] name Name of group
63 * @param[out] gid Group id
64 * @retval 0 OK
65 * @retval -1 Error. or not found
66 */
67 int
group_name2gid(const char * name,gid_t * gid)68 group_name2gid(const char *name,
69 gid_t *gid)
70 {
71 int retval = -1;
72 char buf[1024];
73 struct group g0;
74 struct group *gr = &g0;
75 struct group *gtmp;
76
77 gr = &g0;
78 /* This leaks memory in ubuntu */
79 if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){
80 clicon_err(OE_UNIX, errno, "getgrnam_r(%s)", name);
81 goto done;
82 }
83 if (gtmp == NULL){
84 clicon_err(OE_UNIX, 0, "No such group: %s", name);
85 goto done;
86 }
87 if (gid)
88 *gid = gr->gr_gid;
89 retval = 0;
90 done:
91 return retval;
92 }
93
94 /*! Translate user name to uid. Return -1 if error or not found.
95 * @param[in] name Name of user
96 * @param[out] uid User id
97 * @retval 0 OK
98 * @retval -1 Error. or not found
99 */
100 int
name2uid(const char * name,uid_t * uid)101 name2uid(const char *name,
102 uid_t *uid)
103 {
104 int retval = -1;
105 char buf[1024];
106 struct passwd pwbuf;
107 struct passwd *pwbufp = NULL;
108
109 if (getpwnam_r(name, &pwbuf, buf, sizeof(buf), &pwbufp) != 0){
110 clicon_err(OE_UNIX, errno, "getpwnam_r(%s)", name);
111 goto done;
112 }
113 if (pwbufp == NULL){
114 clicon_err(OE_UNIX, 0, "No such user: %s", name);
115 goto done;
116 }
117 if (uid)
118 *uid = pwbufp->pw_uid;
119 retval = 0;
120 done:
121 return retval;
122 }
123
124 /*! Translate uid to user name
125 * @param[in] uid User id
126 * @param[out] name User name (Malloced, need to be freed)
127 * @retval 0 OK
128 * @retval -1 Error. or not found
129 */
130 int
uid2name(const uid_t uid,char ** name)131 uid2name(const uid_t uid,
132 char **name)
133 {
134 int retval = -1;
135 char buf[1024];
136 struct passwd pwbuf = {0,};
137 struct passwd *pwbufp = NULL;
138
139 if (getpwuid_r(uid, &pwbuf, buf, sizeof(buf), &pwbufp) != 0){
140 clicon_err(OE_UNIX, errno, "getpwuid_r(%u)", uid);
141 goto done;
142 }
143 if (pwbufp == NULL){
144 clicon_err(OE_UNIX, ENOENT, "No such user: %u", uid);
145 goto done;
146 }
147
148 if (name){
149 if ((*name = strdup(pwbufp->pw_name)) == NULL){
150 clicon_err(OE_UNIX, errno, "strdup");
151 goto done;
152 }
153 }
154 retval = 0;
155 done:
156 return retval;
157 }
158
159 /* Privileges drop perm, temp and restore
160 * @see https://www.usenix.org/legacy/events/sec02/full_papers/chen/chen.pdf
161 */
162 /*! Temporarily drop privileges
163 * @param[in] new_uid
164 */
165 int
drop_priv_temp(uid_t new_uid)166 drop_priv_temp(uid_t new_uid)
167 {
168 int retval = -1;
169
170 /* XXX: implicit declaration of function 'setresuid' on travis */
171 if (setresuid(-1, new_uid, geteuid()) < 0){
172 clicon_err(OE_UNIX, errno, "setresuid");
173 goto done;
174 }
175 if (geteuid() != new_uid){
176 clicon_err(OE_UNIX, errno, "geteuid");
177 goto done;
178 }
179 retval = 0;
180 done:
181 return retval;
182 }
183
184 /*! Permanently drop privileges
185 * @param[in] new_uid
186 */
187 int
drop_priv_perm(uid_t new_uid)188 drop_priv_perm(uid_t new_uid)
189 {
190 int retval = -1;
191 uid_t ruid;
192 uid_t euid;
193 uid_t suid;
194
195 if (setresuid(new_uid, new_uid, new_uid) < 0){
196 clicon_err(OE_UNIX, errno, "setresuid");
197 goto done;
198 }
199 if (getresuid(&ruid, &euid, &suid) < 0){
200 clicon_err(OE_UNIX, errno, "getresuid");
201 goto done;
202 }
203 if (ruid != new_uid ||
204 euid != new_uid ||
205 suid != new_uid){
206 clicon_err(OE_UNIX, EINVAL, "Non-matching uid");
207 goto done;
208 }
209 retval = 0;
210 done:
211 return retval;
212 }
213
214 /*! Restore privileges to saved level */
215 int
restore_priv(void)216 restore_priv(void)
217 {
218 int retval = -1;
219 uid_t ruid;
220 uid_t euid;
221 uid_t suid;
222
223 if (getresuid(&ruid, &euid, &suid) < 0){
224 clicon_err(OE_UNIX, errno, "setresuid");
225 goto done;
226 }
227 if (setresuid(-1, suid, -1) < 0){
228 clicon_err(OE_UNIX, errno, "setresuid");
229 goto done;
230 }
231 if (geteuid() != suid){
232 clicon_err(OE_UNIX, EINVAL, "Non-matching uid");
233 goto done;
234 }
235 retval = 0;
236 done:
237 return retval;
238 }
239