Home | History | Annotate | Download | only in src
      1 /*
      2  * Generalized labeling frontend for userspace object managers.
      3  *
      4  * Author : Eamon Walsh <ewalsh (at) 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 
     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 
     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 
     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->spec_file);
     90 		free(rec);
     91 		rec = NULL;
     92 	}
     93 
     94 out:
     95 	return rec;
     96 }
     97 
     98 static struct selabel_lookup_rec *
     99 selabel_lookup_common(struct selabel_handle *rec,
    100 		      const char *key, int type)
    101 {
    102 	struct selabel_lookup_rec *lr;
    103 	lr = rec->func_lookup(rec, key, type);
    104 	if (!lr)
    105 		return NULL;
    106 
    107 	return lr;
    108 }
    109 
    110 int selabel_lookup(struct selabel_handle *rec, char **con,
    111 		   const char *key, int type)
    112 {
    113 	struct selabel_lookup_rec *lr;
    114 
    115 	lr = selabel_lookup_common(rec, key, type);
    116 	if (!lr)
    117 		return -1;
    118 
    119 	*con = strdup(lr->ctx_raw);
    120 	return *con ? 0 : -1;
    121 }
    122 
    123 bool selabel_partial_match(struct selabel_handle *rec, const char *key)
    124 {
    125 	if (!rec->func_partial_match) {
    126 		/*
    127 		 * If the label backend does not support partial matching,
    128 		 * then assume a match is possible.
    129 		 */
    130 		return true;
    131 	}
    132 	return rec->func_partial_match(rec, key);
    133 }
    134 
    135 int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
    136 			      const char *key, const char **aliases, int type)
    137 {
    138 	struct selabel_lookup_rec *lr;
    139 
    140 	if (!rec->func_lookup_best_match) {
    141 		errno = ENOTSUP;
    142 		return -1;
    143 	}
    144 
    145 	lr = rec->func_lookup_best_match(rec, key, aliases, type);
    146 	if (!lr)
    147 		return -1;
    148 
    149 	*con = strdup(lr->ctx_raw);
    150 	return *con ? 0 : -1;
    151 }
    152 
    153 enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
    154 				    struct selabel_handle *h2)
    155 {
    156 	if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
    157 		return SELABEL_INCOMPARABLE;
    158 
    159 	return h1->func_cmp(h1, h2);
    160 }
    161 
    162 void selabel_close(struct selabel_handle *rec)
    163 {
    164 	rec->func_close(rec);
    165 	free(rec->spec_file);
    166 	free(rec);
    167 }
    168 
    169 void selabel_stats(struct selabel_handle *rec)
    170 {
    171 	rec->func_stats(rec);
    172 }
    173