1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2#include <unistd.h>
3#include <sys/types.h>
4#include <stdlib.h>
5#include <errno.h>
6#include "selinux_internal.h"
7#include <selinux/avc.h>
8#include "avc_internal.h"
9
10static pthread_once_t once = PTHREAD_ONCE_INIT;
11static int selinux_enabled;
12
13static void avc_init_once(void)
14{
15	selinux_enabled = is_selinux_enabled();
16	if (selinux_enabled == 1)
17		avc_open(NULL, 0);
18}
19
20int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
21	int rc;
22	security_id_t scon_id;
23	security_id_t tcon_id;
24	security_class_t sclass;
25	access_vector_t av;
26
27	__selinux_once(once, avc_init_once);
28
29	if (selinux_enabled != 1)
30		return 0;
31
32	rc = avc_context_to_sid(scon, &scon_id);
33	if (rc < 0)
34		return rc;
35
36       rc = avc_context_to_sid(tcon, &tcon_id);
37       if (rc < 0)
38	       return rc;
39
40       sclass = string_to_security_class(class);
41       if (sclass == 0) {
42	       rc = errno;
43	       avc_log(SELINUX_ERROR, "Unknown class %s", class);
44	       if (security_deny_unknown() == 0)
45		       return 0;
46	       errno = rc;
47	       return -1;
48       }
49
50       av = string_to_av_perm(sclass, perm);
51       if (av == 0) {
52	       rc = errno;
53	       avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
54	       if (security_deny_unknown() == 0)
55		       return 0;
56	       errno = rc;
57	       return -1;
58       }
59
60       return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
61}
62
63int selinux_check_passwd_access(access_vector_t requested)
64{
65	int status = -1;
66	char *user_context;
67	if (is_selinux_enabled() == 0)
68		return 0;
69	if (getprevcon_raw(&user_context) == 0) {
70		security_class_t passwd_class;
71		struct av_decision avd;
72		int retval;
73
74		passwd_class = string_to_security_class("passwd");
75		if (passwd_class == 0)
76			return 0;
77
78		retval = security_compute_av_raw(user_context,
79						     user_context,
80						     passwd_class,
81						     requested,
82						     &avd);
83
84		if ((retval == 0) && ((requested & avd.allowed) == requested)) {
85			status = 0;
86		}
87		freecon(user_context);
88	}
89
90	if (status != 0 && security_getenforce() == 0)
91		status = 0;
92
93	return status;
94}
95
96hidden_def(selinux_check_passwd_access)
97
98int checkPasswdAccess(access_vector_t requested)
99{
100	return selinux_check_passwd_access(requested);
101}
102