blob: 84cee512e3e39d29d368823aefda7545e4caf316 [file] [log] [blame]
Stephen Smalleyf0740362012-01-04 12:30:47 -05001/*
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
19typedef int (*selabel_initfunc)(struct selabel_handle *rec,
Stephen Smalleya2e47cd2012-06-11 13:35:34 -040020 const struct selinux_opt *opts,
21 unsigned nopts);
Stephen Smalleyf0740362012-01-04 12:30:47 -050022
23static selabel_initfunc initfuncs[] = {
24 &selabel_file_init,
Stephen Smalley35b01082012-04-04 10:06:13 -040025 NULL,
26 NULL,
27 NULL,
28 &selabel_property_init,
Stephen Smalleyf0740362012-01-04 12:30:47 -050029};
30
31/*
32 * Validation functions
33 */
34
Stephen Smalleya2e47cd2012-06-11 13:35:34 -040035static inline int selabel_is_validate_set(const struct selinux_opt *opts,
36 unsigned n)
Stephen Smalleyf0740362012-01-04 12:30:47 -050037{
38 while (n--)
39 if (opts[n].type == SELABEL_OPT_VALIDATE)
40 return !!opts[n].value;
41
42 return 0;
43}
44
45int 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;
58out:
59 return rc;
60}
61
62/*
63 * Public API
64 */
65
66struct selabel_handle *selabel_open(unsigned int backend,
Stephen Smalleya2e47cd2012-06-11 13:35:34 -040067 const struct selinux_opt *opts,
68 unsigned nopts)
Stephen Smalleyf0740362012-01-04 12:30:47 -050069{
70 struct selabel_handle *rec = NULL;
71
72 if (backend >= ARRAY_SIZE(initfuncs)) {
73 errno = EINVAL;
74 goto out;
75 }
76
Stephen Smalley35b01082012-04-04 10:06:13 -040077 if (initfuncs[backend] == NULL)
78 goto out;
79
Stephen Smalleyf0740362012-01-04 12:30:47 -050080 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
93out:
94 return rec;
95}
96
97static struct selabel_lookup_rec *
Nick Kralevichb1ae15a2013-07-11 17:35:53 -070098selabel_lookup_common(struct selabel_handle *rec,
Stephen Smalleyf0740362012-01-04 12:30:47 -050099 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
Stephen Smalleyab40ea92014-02-19 09:16:17 -0500109int selabel_lookup(struct selabel_handle *rec, char **con,
Stephen Smalleyf0740362012-01-04 12:30:47 -0500110 const char *key, int type)
111{
112 struct selabel_lookup_rec *lr;
113
Nick Kralevichb1ae15a2013-07-11 17:35:53 -0700114 lr = selabel_lookup_common(rec, key, type);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500115 if (!lr)
116 return -1;
117
118 *con = strdup(lr->ctx_raw);
119 return *con ? 0 : -1;
120}
121
Stephen Smalley0e7340f2014-04-30 15:13:30 -0700122bool 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
Stephen Smalleybe7f5e82014-06-12 12:21:13 -0400134int 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
Stephen Smalley8b40b9c2015-08-05 11:35:23 -0400152enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
153 struct selabel_handle *h2)
154{
155 if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
156 return SELABEL_INCOMPARABLE;
157
158 return h1->func_cmp(h1, h2);
159}
160
Stephen Smalleyf0740362012-01-04 12:30:47 -0500161void selabel_close(struct selabel_handle *rec)
162{
163 rec->func_close(rec);
164 free(rec);
165}
166
167void selabel_stats(struct selabel_handle *rec)
168{
169 rec->func_stats(rec);
170}