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 19typedef int (*selabel_initfunc)(struct selabel_handle *rec, 20 const struct selinux_opt *opts, 21 unsigned nopts); 22 23static 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 35static 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 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, 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 94out: 95 return rec; 96} 97 98static struct selabel_lookup_rec * 99selabel_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 110int 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 123bool 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 135int 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 153enum 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 162void selabel_close(struct selabel_handle *rec) 163{ 164 rec->func_close(rec); 165 free(rec->spec_file); 166 free(rec); 167} 168 169void selabel_stats(struct selabel_handle *rec) 170{ 171 rec->func_stats(rec); 172} 173