c5b1265d5b6428ab8adbc599abb5806527ed0e97
[platform/core/system/dlog.git] / src / logger / logger_privileges.c
1 /* Copyright (c) 2020, Samsung Electronics Co., Ltd. All rights reserved.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *              http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License. */
14
15 #include "logger_privileges.h"
16
17 // POSIX
18 #include <grp.h>
19 #include <pwd.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22
23 // C
24 #include <assert.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 /**
31  * @brief Parse permissions
32  * @details Parse a string representation of permissions to the internal integral one
33  * @param[in] str The string representation
34  * @return The integer representation
35  */
36 int parse_permissions(const char *str)
37 {
38         int ret, parsed;
39         char *parse_safety;
40
41         if (!str)
42                 return S_IWUSR | S_IWGRP | S_IWOTH; // 0222: everyone can write
43
44         parsed = strtol(str, & parse_safety, 8); // note, rights are octal
45         if (parse_safety != (str + strlen(str)))
46                 return 0;
47
48         ret = 0;
49
50         // note that R and X are pretty useless, only W makes sense
51         if (parsed & 00001) ret |= S_IXOTH;
52         if (parsed & 00002) ret |= S_IWOTH;
53         if (parsed & 00004) ret |= S_IROTH;
54         if (parsed & 00010) ret |= S_IXGRP;
55         if (parsed & 00020) ret |= S_IWGRP;
56         if (parsed & 00040) ret |= S_IRGRP;
57         if (parsed & 00100) ret |= S_IXUSR;
58         if (parsed & 00200) ret |= S_IWUSR;
59         if (parsed & 00400) ret |= S_IRUSR;
60         if (parsed & 01000) ret |= S_ISVTX;
61         if (parsed & 02000) ret |= S_ISGID;
62         if (parsed & 04000) ret |= S_ISUID;
63
64         if (parsed & ~07777)
65                 printf("Warning: useless bits in permissions %s!", str);
66
67         return ret;
68 }
69
70 /**
71  * @brief Get numerical ids for specified user and group
72  * @details Converts user and group strings to proper uid and gid identifiers
73  * @param[in] user The new user
74  * @param[in] group The new group
75  * @param[out] uid The uid for user
76  * @param[out] gid The numerical gid for group
77  * @return 0 on success, else -errno
78  */
79 int usergr2id(const char *user, const char *group, uid_t *uid, gid_t *gid)
80 {
81         struct passwd pwd, *ppwd;
82         struct group  grp, *pgrp;
83         int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
84
85         assert(user);
86         assert(group);
87
88         if (bufsize == -1)
89                 bufsize = 1024;
90
91         char *const buffer = (char *)alloca(bufsize);
92
93         if (getgrnam_r(user, &grp, buffer, bufsize, &pgrp))
94                 return -errno;
95         if (!pgrp)
96                 return -ENOENT;
97
98         if (getpwnam_r(group, &pwd, buffer, bufsize, &ppwd))
99                 return -errno;
100         if (!ppwd)
101                 return -ENOENT;
102
103         *uid = pwd.pw_uid;
104         *gid = grp.gr_gid;
105
106         return 0;
107 }
108
109 /**
110  * @brief Reset privileges
111  * @details Resets privileges to those specified at build-time
112  * @return 0 on success, else -errno
113  */
114 int reset_self_privileges()
115 {
116         uid_t uid;
117         gid_t gid;
118
119         int r = usergr2id(DLOG_SERVER_USER, DLOG_SERVER_GROUP, &uid, &gid);
120         if (r < 0)
121                 return r;
122
123         if (getegid() != gid && setgid(gid) < 0)
124                 return -errno;
125         if (geteuid() != uid && setuid(uid) < 0)
126                 return -errno; // should never happen
127
128         return 0;
129 }