1 /*
2 * Generalized labeling frontend for userspace object managers.
3 *
4 * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
5 */
6
7 #include <sys/types.h>
8 #include <ctype.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <selinux/selinux.h>
14 #include "callbacks.h"
15 #include "label_internal.h"
16
17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18
19 typedef int (*selabel_initfunc)(struct selabel_handle *rec,
20 const struct selinux_opt *opts,
21 unsigned nopts);
22
23 static selabel_initfunc initfuncs[] = {
24 &selabel_file_init,
25 NULL,
26 NULL,
27 NULL,
28 &selabel_property_init,
29 };
30
31 /*
32 * Validation functions
33 */
34
selabel_is_validate_set(const struct selinux_opt * opts,unsigned n)35 static inline int selabel_is_validate_set(const struct selinux_opt *opts,
36 unsigned n)
37 {
38 while (n--)
39 if (opts[n].type == SELABEL_OPT_VALIDATE)
40 return !!opts[n].value;
41
42 return 0;
43 }
44
selabel_validate(struct selabel_handle * rec,struct selabel_lookup_rec * contexts)45 int selabel_validate(struct selabel_handle *rec,
46 struct selabel_lookup_rec *contexts)
47 {
48 int rc = 0;
49
50 if (!rec->validating || contexts->validated)
51 goto out;
52
53 rc = selinux_validate(&contexts->ctx_raw);
54 if (rc < 0)
55 goto out;
56
57 contexts->validated = 1;
58 out:
59 return rc;
60 }
61
62 /*
63 * Public API
64 */
65
selabel_open(unsigned int backend,const struct selinux_opt * opts,unsigned nopts)66 struct selabel_handle *selabel_open(unsigned int backend,
67 const struct selinux_opt *opts,
68 unsigned nopts)
69 {
70 struct selabel_handle *rec = NULL;
71
72 if (backend >= ARRAY_SIZE(initfuncs)) {
73 errno = EINVAL;
74 goto out;
75 }
76
77 if (initfuncs[backend] == NULL)
78 goto out;
79
80 rec = (struct selabel_handle *)malloc(sizeof(*rec));
81 if (!rec)
82 goto out;
83
84 memset(rec, 0, sizeof(*rec));
85 rec->backend = backend;
86 rec->validating = selabel_is_validate_set(opts, nopts);
87
88 if ((*initfuncs[backend])(rec, opts, nopts)) {
89 free(rec);
90 rec = NULL;
91 }
92
93 out:
94 return rec;
95 }
96
97 static struct selabel_lookup_rec *
selabel_lookup_common(struct selabel_handle * rec,const char * key,int type)98 selabel_lookup_common(struct selabel_handle *rec,
99 const char *key, int type)
100 {
101 struct selabel_lookup_rec *lr;
102 lr = rec->func_lookup(rec, key, type);
103 if (!lr)
104 return NULL;
105
106 return lr;
107 }
108
selabel_lookup(struct selabel_handle * rec,char ** con,const char * key,int type)109 int selabel_lookup(struct selabel_handle *rec, char **con,
110 const char *key, int type)
111 {
112 struct selabel_lookup_rec *lr;
113
114 lr = selabel_lookup_common(rec, key, type);
115 if (!lr)
116 return -1;
117
118 *con = strdup(lr->ctx_raw);
119 return *con ? 0 : -1;
120 }
121
selabel_partial_match(struct selabel_handle * rec,const char * key)122 bool selabel_partial_match(struct selabel_handle *rec, const char *key)
123 {
124 if (!rec->func_partial_match) {
125 /*
126 * If the label backend does not support partial matching,
127 * then assume a match is possible.
128 */
129 return true;
130 }
131 return rec->func_partial_match(rec, key);
132 }
133
selabel_lookup_best_match(struct selabel_handle * rec,char ** con,const char * key,const char ** aliases,int type)134 int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
135 const char *key, const char **aliases, int type)
136 {
137 struct selabel_lookup_rec *lr;
138
139 if (!rec->func_lookup_best_match) {
140 errno = ENOTSUP;
141 return -1;
142 }
143
144 lr = rec->func_lookup_best_match(rec, key, aliases, type);
145 if (!lr)
146 return -1;
147
148 *con = strdup(lr->ctx_raw);
149 return *con ? 0 : -1;
150 }
151
selabel_close(struct selabel_handle * rec)152 void selabel_close(struct selabel_handle *rec)
153 {
154 rec->func_close(rec);
155 free(rec);
156 }
157
selabel_stats(struct selabel_handle * rec)158 void selabel_stats(struct selabel_handle *rec)
159 {
160 rec->func_stats(rec);
161 }
162