1 #include <netinet/in.h> 2 #include <stdlib.h> 3 4 #include "debug.h" 5 #include "context.h" 6 #include "handle.h" 7 8 #include <sepol/ibpkey_record.h> 9 #include <sepol/policydb/policydb.h> 10 #include "ibpkey_internal.h" 11 12 /* Create a low level ibpkey structure from 13 * a high level representation 14 */ 15 static int ibpkey_from_record(sepol_handle_t *handle, 16 const policydb_t *policydb, 17 ocontext_t **ibpkey, const sepol_ibpkey_t *data) 18 { 19 ocontext_t *tmp_ibpkey = NULL; 20 context_struct_t *tmp_con = NULL; 21 char *subnet_prefix_buf = NULL; 22 int low = sepol_ibpkey_get_low(data); 23 int high = sepol_ibpkey_get_high(data); 24 25 tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); 26 if (!tmp_ibpkey) 27 goto omem; 28 29 tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); 30 31 /* Pkey range */ 32 tmp_ibpkey->u.ibpkey.low_pkey = low; 33 tmp_ibpkey->u.ibpkey.high_pkey = high; 34 if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { 35 ERR(handle, "low ibpkey %d exceeds high ibpkey %d", 36 tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); 37 goto err; 38 } 39 40 /* Context */ 41 if (context_from_record(handle, policydb, &tmp_con, 42 sepol_ibpkey_get_con(data)) < 0) 43 goto err; 44 context_cpy(&tmp_ibpkey->context[0], tmp_con); 45 context_destroy(tmp_con); 46 free(tmp_con); 47 tmp_con = NULL; 48 49 *ibpkey = tmp_ibpkey; 50 return STATUS_SUCCESS; 51 52 omem: 53 ERR(handle, "out of memory"); 54 55 err: 56 if (tmp_ibpkey) { 57 context_destroy(&tmp_ibpkey->context[0]); 58 free(tmp_ibpkey); 59 } 60 context_destroy(tmp_con); 61 free(tmp_con); 62 free(subnet_prefix_buf); 63 ERR(handle, "could not create ibpkey structure"); 64 return STATUS_ERR; 65 } 66 67 static int ibpkey_to_record(sepol_handle_t *handle, 68 const policydb_t *policydb, 69 ocontext_t *ibpkey, sepol_ibpkey_t **record) 70 { 71 context_struct_t *con = &ibpkey->context[0]; 72 sepol_context_t *tmp_con = NULL; 73 sepol_ibpkey_t *tmp_record = NULL; 74 75 if (sepol_ibpkey_create(handle, &tmp_record) < 0) 76 goto err; 77 78 sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, 79 ibpkey->u.ibpkey.subnet_prefix); 80 81 sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, 82 ibpkey->u.ibpkey.high_pkey); 83 84 if (context_to_record(handle, policydb, con, &tmp_con) < 0) 85 goto err; 86 87 if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) 88 goto err; 89 90 sepol_context_free(tmp_con); 91 *record = tmp_record; 92 return STATUS_SUCCESS; 93 94 err: 95 ERR(handle, "could not convert ibpkey to record"); 96 sepol_context_free(tmp_con); 97 sepol_ibpkey_free(tmp_record); 98 return STATUS_ERR; 99 } 100 101 /* Return the number of ibpkeys */ 102 extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), 103 const sepol_policydb_t *p, unsigned int *response) 104 { 105 unsigned int count = 0; 106 ocontext_t *c, *head; 107 const policydb_t *policydb = &p->p; 108 109 head = policydb->ocontexts[OCON_IBPKEY]; 110 for (c = head; c; c = c->next) 111 count++; 112 113 *response = count; 114 115 return STATUS_SUCCESS; 116 } 117 118 /* Check if a ibpkey exists */ 119 int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), 120 const sepol_policydb_t *p, 121 const sepol_ibpkey_key_t *key, int *response) 122 { 123 const policydb_t *policydb = &p->p; 124 ocontext_t *c, *head; 125 int low, high; 126 uint64_t subnet_prefix; 127 128 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 129 130 head = policydb->ocontexts[OCON_IBPKEY]; 131 for (c = head; c; c = c->next) { 132 uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; 133 uint16_t low2 = c->u.ibpkey.low_pkey; 134 uint16_t high2 = c->u.ibpkey.high_pkey; 135 136 if (low2 == low && 137 high2 == high && 138 subnet_prefix == subnet_prefix2) { 139 *response = 1; 140 return STATUS_SUCCESS; 141 } 142 } 143 144 *response = 0; 145 return STATUS_SUCCESS; 146 } 147 148 /* Query a ibpkey */ 149 int sepol_ibpkey_query(sepol_handle_t *handle, 150 const sepol_policydb_t *p, 151 const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) 152 { 153 const policydb_t *policydb = &p->p; 154 ocontext_t *c, *head; 155 int low, high; 156 uint64_t subnet_prefix; 157 158 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 159 160 head = policydb->ocontexts[OCON_IBPKEY]; 161 for (c = head; c; c = c->next) { 162 uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; 163 int low2 = c->u.ibpkey.low_pkey; 164 int high2 = c->u.ibpkey.high_pkey; 165 166 if (low2 == low && 167 high2 == high && 168 subnet_prefix == subnet_prefix2) { 169 if (ibpkey_to_record(handle, policydb, c, response) < 0) 170 goto err; 171 return STATUS_SUCCESS; 172 } 173 } 174 175 *response = NULL; 176 return STATUS_SUCCESS; 177 178 err: 179 ERR(handle, "could not query ibpkey subnet prefix: %#lx range %u - %u exists", 180 subnet_prefix, low, high); 181 return STATUS_ERR; 182 } 183 184 /* Load a ibpkey into policy */ 185 int sepol_ibpkey_modify(sepol_handle_t *handle, 186 sepol_policydb_t *p, 187 const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) 188 { 189 policydb_t *policydb = &p->p; 190 ocontext_t *ibpkey = NULL; 191 int low, high; 192 uint64_t subnet_prefix; 193 194 sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); 195 196 if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) 197 goto err; 198 199 /* Attach to context list */ 200 ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; 201 policydb->ocontexts[OCON_IBPKEY] = ibpkey; 202 203 return STATUS_SUCCESS; 204 205 err: 206 ERR(handle, "could not load ibpkey subnet prefix: %#lx range %u - %u exists", 207 subnet_prefix, low, high); 208 if (ibpkey) { 209 context_destroy(&ibpkey->context[0]); 210 free(ibpkey); 211 } 212 return STATUS_ERR; 213 } 214 215 int sepol_ibpkey_iterate(sepol_handle_t *handle, 216 const sepol_policydb_t *p, 217 int (*fn)(const sepol_ibpkey_t *ibpkey, 218 void *fn_arg), void *arg) 219 { 220 const policydb_t *policydb = &p->p; 221 ocontext_t *c, *head; 222 sepol_ibpkey_t *ibpkey = NULL; 223 224 head = policydb->ocontexts[OCON_IBPKEY]; 225 for (c = head; c; c = c->next) { 226 int status; 227 228 if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) 229 goto err; 230 231 /* Invoke handler */ 232 status = fn(ibpkey, arg); 233 if (status < 0) 234 goto err; 235 236 sepol_ibpkey_free(ibpkey); 237 ibpkey = NULL; 238 239 /* Handler requested exit */ 240 if (status > 0) 241 break; 242 } 243 244 return STATUS_SUCCESS; 245 246 err: 247 ERR(handle, "could not iterate over ibpkeys"); 248 sepol_ibpkey_free(ibpkey); 249 return STATUS_ERR; 250 } 251