16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Generalized labeling frontend for userspace object managers.
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <sys/types.h>
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <ctype.h>
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <errno.h>
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h>
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdlib.h>
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <string.h>
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <selinux/selinux.h>
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "callbacks.h"
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "label_internal.h"
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef int (*selabel_initfunc)(struct selabel_handle *rec,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				const struct selinux_opt *opts,
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				unsigned nopts);
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic selabel_initfunc initfuncs[] = {
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	&selabel_file_init,
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	NULL,
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	NULL,
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	NULL,
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	&selabel_property_init,
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Validation functions
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline int selabel_is_validate_set(const struct selinux_opt *opts,
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					  unsigned n)
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	while (n--)
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (opts[n].type == SELABEL_OPT_VALIDATE)
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			return !!opts[n].value;
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return 0;
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_validate(struct selabel_handle *rec,
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     struct selabel_lookup_rec *contexts)
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	int rc = 0;
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!rec->validating || contexts->validated)
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		goto out;
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rc = selinux_validate(&contexts->ctx_raw);
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (rc < 0)
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		goto out;
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	contexts->validated = 1;
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennout:
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return rc;
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Public API
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct selabel_handle *selabel_open(unsigned int backend,
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				    const struct selinux_opt *opts,
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				    unsigned nopts)
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct selabel_handle *rec = NULL;
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (backend >= ARRAY_SIZE(initfuncs)) {
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		errno = EINVAL;
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		goto out;
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (initfuncs[backend] == NULL)
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		goto out;
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rec = (struct selabel_handle *)malloc(sizeof(*rec));
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!rec)
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		goto out;
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	memset(rec, 0, sizeof(*rec));
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rec->backend = backend;
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rec->validating = selabel_is_validate_set(opts, nopts);
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if ((*initfuncs[backend])(rec, opts, nopts)) {
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		free(rec);
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		rec = NULL;
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennout:
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return rec;
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic struct selabel_lookup_rec *
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennselabel_lookup_common(struct selabel_handle *rec,
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		      const char *key, int type)
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct selabel_lookup_rec *lr;
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	lr = rec->func_lookup(rec, key, type);
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!lr)
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return NULL;
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return lr;
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_lookup(struct selabel_handle *rec, char **con,
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   const char *key, int type)
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct selabel_lookup_rec *lr;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	lr = selabel_lookup_common(rec, key, type);
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!lr)
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return -1;
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	*con = strdup(lr->ctx_raw);
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return *con ? 0 : -1;
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool selabel_partial_match(struct selabel_handle *rec, const char *key)
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!rec->func_partial_match) {
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		/*
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		 * If the label backend does not support partial matching,
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		 * then assume a match is possible.
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		 */
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return true;
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return rec->func_partial_match(rec, key);
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint selabel_lookup_best_match(struct selabel_handle *rec, char **con,
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			      const char *key, const char **aliases, int type)
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct selabel_lookup_rec *lr;
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!rec->func_lookup_best_match) {
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		errno = ENOTSUP;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return -1;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	lr = rec->func_lookup_best_match(rec, key, aliases, type);
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!lr)
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return -1;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	*con = strdup(lr->ctx_raw);
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return *con ? 0 : -1;
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid selabel_close(struct selabel_handle *rec)
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rec->func_close(rec);
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	free(rec);
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid selabel_stats(struct selabel_handle *rec)
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rec->func_stats(rec);
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn