1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/* ISC license. */
#include <sys/types.h>
#include <stdint.h>
#include <skalibs/posixplz.h>
#include <skalibs/bytestr.h>
#include <skalibs/types.h>
#include <skalibs/env.h>
#include <skalibs/strerr2.h>
#include <skalibs/djbunix.h>
#include <skalibs/cdb.h>
#include <s6/accessrules.h>
#include "clientrules.h"
static unsigned int rulestype = 0 ;
static char const *rules = 0 ;
static int cdbfd = -1 ;
static struct cdb cdbmap = CDB_ZERO ;
void clientrules_init (unsigned int type, char const *s)
{
rulestype = type ;
rules = s ;
if (rulestype == 2)
{
cdbfd = open_readb(rules) ;
if (cdbfd < 0) strerr_diefu3sys(111, "open ", rules, " for reading") ;
if (cdb_init(&cdbmap, cdbfd) < 0)
strerr_diefu2sys(111, "cdb_init ", rules) ;
}
}
void clientrules_reload ()
{
int fd ;
struct cdb c = CDB_ZERO ;
if (rulestype != 2) break ;
fd = open_readb(rules) ;
if (fd < 0) break ;
if (cdb_init(&c, fd) < 0)
{
fd_close(fd) ;
break ;
}
cdb_free(&cdbmap) ;
fd_close(cdbfd) ;
cdbfd = fd ;
cdbmap = c ;
}
static inline uint8_t parse_env (char const *const *envp)
{
uint8_t perms = 0 ;
for (; *envp ; envp++)
{
if (str_start(*envp, "query=")) perms |= 1 ;
if (str_start(*envp, "monitor=")) perms |= 2 ;
if (str_start(*envp, "change=")) perms |= 4 ;
if (str_start(*envp, "event=")) perms |= 8 ;
if (str_start(*envp, "admin=")) perms |= 16 ;
}
return perms ;
}
int clientrules_check (int fd, uint8_t *perms)
{
s6_accessrules_params_t params = S6_ACCESSRULES_PARAMS_ZERO ;
s6_accessrules_result_t result = S6_ACCESSRULES_ERROR ;
uid_t uid ;
gid_t gid ;
if (getpeereid(fd, &uid, &gid) < 0)
{
if (verbosity) strerr_warnwu1sys("getpeereid") ;
return 0 ;
}
switch (rulestype)
{
case 1 :
result = s6_accessrules_uidgid_fs(uid, gid, rules, ¶ms) ; break ;
case 2 :
result = s6_accessrules_uidgid_cdb(uid, gid, &cdbmap, ¶ms) ; break ;
default : break ;
}
if (result != S6_ACCESSRULES_ALLOW)
{
if (verbosity && (result == S6_ACCESSRULES_ERROR))
strerr_warnw1sys("error while checking rules") ;
return 0 ;
}
if (params.exec.len && verbosity)
{
char fmtuid[UID_FMT] ;
char fmtgid[GID_FMT] ;
fmtuid[uid_fmt(fmtuid, uid)] = 0 ;
fmtgid[gid_fmt(fmtgid, gid)] = 0 ;
strerr_warnw4x("unused exec string in rules for uid ", fmtuid, " gid ", fmtgid) ;
}
if (params.env.s)
{
size_t n = byte_count(params.env.s, params.env.len, '\0') ;
char const *envp[n+1] ;
if (!env_make(envp, n, params.env.s, params.env.len))
{
if (verbosity) strerr_warnwu1sys("env_make") ;
s6_accessrules_params_free(¶ms) ;
return 0 ;
}
envp[n] = 0 ;
*perms = parse_env(envp, perms) ;
}
s6_accessrules_params_free(¶ms) ;
return !!perms ;
}
|