1 #include <netinet/in.h> 2 #include <arpa/inet.h> 3 #include <stdlib.h> 4 5 #include "debug.h" 6 #include "context.h" 7 #include "handle.h" 8 9 #include <sepol/policydb/policydb.h> 10 #include "node_internal.h" 11 12 /* Create a low level node structure from 13 * a high level representation */ 14 static int node_from_record(sepol_handle_t * handle, 15 const policydb_t * policydb, 16 ocontext_t ** node, const sepol_node_t * data) 17 { 18 19 ocontext_t *tmp_node = NULL; 20 context_struct_t *tmp_con = NULL; 21 char *addr_buf = NULL, *mask_buf = NULL; 22 23 tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t)); 24 if (!tmp_node) 25 goto omem; 26 27 size_t addr_bsize, mask_bsize; 28 29 /* Address and netmask */ 30 if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0) 31 goto err; 32 if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0) 33 goto err; 34 35 int proto = sepol_node_get_proto(data); 36 37 switch (proto) { 38 case SEPOL_PROTO_IP4: 39 memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize); 40 memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize); 41 break; 42 case SEPOL_PROTO_IP6: 43 memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize); 44 memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize); 45 break; 46 default: 47 ERR(handle, "unsupported protocol %u", proto); 48 goto err; 49 } 50 free(addr_buf); 51 free(mask_buf); 52 addr_buf = NULL; 53 mask_buf = NULL; 54 55 /* Context */ 56 if (context_from_record(handle, policydb, &tmp_con, 57 sepol_node_get_con(data)) < 0) 58 goto err; 59 context_cpy(&tmp_node->context[0], tmp_con); 60 context_destroy(tmp_con); 61 free(tmp_con); 62 tmp_con = NULL; 63 64 *node = tmp_node; 65 return STATUS_SUCCESS; 66 67 omem: 68 ERR(handle, "out of memory"); 69 70 err: 71 if (tmp_node != NULL) { 72 context_destroy(&tmp_node->context[0]); 73 free(tmp_node); 74 } 75 context_destroy(tmp_con); 76 free(tmp_con); 77 free(addr_buf); 78 free(mask_buf); 79 ERR(handle, "could not create node structure"); 80 return STATUS_ERR; 81 } 82 83 static int node_to_record(sepol_handle_t * handle, 84 const policydb_t * policydb, 85 ocontext_t * node, int proto, sepol_node_t ** record) 86 { 87 88 context_struct_t *con = &node->context[0]; 89 90 sepol_context_t *tmp_con = NULL; 91 sepol_node_t *tmp_record = NULL; 92 93 if (sepol_node_create(handle, &tmp_record) < 0) 94 goto err; 95 96 sepol_node_set_proto(tmp_record, proto); 97 98 switch (proto) { 99 100 case SEPOL_PROTO_IP4: 101 if (sepol_node_set_addr_bytes(handle, tmp_record, 102 (const char *)&node->u.node.addr, 103 4) < 0) 104 goto err; 105 106 if (sepol_node_set_mask_bytes(handle, tmp_record, 107 (const char *)&node->u.node.mask, 108 4) < 0) 109 goto err; 110 break; 111 112 case SEPOL_PROTO_IP6: 113 if (sepol_node_set_addr_bytes(handle, tmp_record, 114 (const char *)&node->u.node6.addr, 115 16) < 0) 116 goto err; 117 118 if (sepol_node_set_mask_bytes(handle, tmp_record, 119 (const char *)&node->u.node6.mask, 120 16) < 0) 121 goto err; 122 break; 123 124 default: 125 ERR(handle, "unsupported protocol %u", proto); 126 goto err; 127 } 128 129 if (context_to_record(handle, policydb, con, &tmp_con) < 0) 130 goto err; 131 132 if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0) 133 goto err; 134 135 sepol_context_free(tmp_con); 136 *record = tmp_record; 137 return STATUS_SUCCESS; 138 139 err: 140 ERR(handle, "could not convert node to record"); 141 sepol_context_free(tmp_con); 142 sepol_node_free(tmp_record); 143 return STATUS_ERR; 144 } 145 146 /* Return the number of nodes */ 147 extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)), 148 const sepol_policydb_t * p, unsigned int *response) 149 { 150 151 unsigned int count = 0; 152 ocontext_t *c, *head; 153 const policydb_t *policydb = &p->p; 154 155 head = policydb->ocontexts[OCON_NODE]; 156 for (c = head; c != NULL; c = c->next) 157 count++; 158 159 head = policydb->ocontexts[OCON_NODE6]; 160 for (c = head; c != NULL; c = c->next) 161 count++; 162 163 *response = count; 164 165 handle = NULL; 166 return STATUS_SUCCESS; 167 } 168 169 /* Check if a node exists */ 170 int sepol_node_exists(sepol_handle_t * handle, 171 const sepol_policydb_t * p, 172 const sepol_node_key_t * key, int *response) 173 { 174 175 const policydb_t *policydb = &p->p; 176 ocontext_t *c, *head; 177 178 int proto; 179 const char *addr, *mask; 180 sepol_node_key_unpack(key, &addr, &mask, &proto); 181 182 switch (proto) { 183 184 case SEPOL_PROTO_IP4: 185 { 186 head = policydb->ocontexts[OCON_NODE]; 187 for (c = head; c; c = c->next) { 188 unsigned int *addr2 = &c->u.node.addr; 189 unsigned int *mask2 = &c->u.node.mask; 190 191 if (!memcmp(addr, addr2, 4) && 192 !memcmp(mask, mask2, 4)) { 193 194 *response = 1; 195 return STATUS_SUCCESS; 196 } 197 } 198 break; 199 } 200 case SEPOL_PROTO_IP6: 201 { 202 head = policydb->ocontexts[OCON_NODE6]; 203 for (c = head; c; c = c->next) { 204 unsigned int *addr2 = c->u.node6.addr; 205 unsigned int *mask2 = c->u.node6.mask; 206 207 if (!memcmp(addr, addr2, 16) && 208 !memcmp(mask, mask2, 16)) { 209 *response = 1; 210 return STATUS_SUCCESS; 211 } 212 } 213 break; 214 } 215 default: 216 ERR(handle, "unsupported protocol %u", proto); 217 goto err; 218 } 219 220 *response = 0; 221 return STATUS_SUCCESS; 222 223 err: 224 ERR(handle, "could not check if node %s/%s (%s) exists", 225 addr, mask, sepol_node_get_proto_str(proto)); 226 return STATUS_ERR; 227 } 228 229 /* Query a node */ 230 int sepol_node_query(sepol_handle_t * handle, 231 const sepol_policydb_t * p, 232 const sepol_node_key_t * key, sepol_node_t ** response) 233 { 234 235 const policydb_t *policydb = &p->p; 236 ocontext_t *c, *head; 237 238 int proto; 239 const char *addr, *mask; 240 sepol_node_key_unpack(key, &addr, &mask, &proto); 241 242 switch (proto) { 243 244 case SEPOL_PROTO_IP4: 245 { 246 head = policydb->ocontexts[OCON_NODE]; 247 for (c = head; c; c = c->next) { 248 unsigned int *addr2 = &c->u.node.addr; 249 unsigned int *mask2 = &c->u.node.mask; 250 251 if (!memcmp(addr, addr2, 4) && 252 !memcmp(mask, mask2, 4)) { 253 254 if (node_to_record(handle, policydb, 255 c, SEPOL_PROTO_IP4, 256 response) < 0) 257 goto err; 258 return STATUS_SUCCESS; 259 } 260 } 261 break; 262 } 263 case SEPOL_PROTO_IP6: 264 { 265 head = policydb->ocontexts[OCON_NODE6]; 266 for (c = head; c; c = c->next) { 267 unsigned int *addr2 = c->u.node6.addr; 268 unsigned int *mask2 = c->u.node6.mask; 269 270 if (!memcmp(addr, addr2, 16) && 271 !memcmp(mask, mask2, 16)) { 272 273 if (node_to_record(handle, policydb, 274 c, SEPOL_PROTO_IP6, 275 response) < 0) 276 goto err; 277 } 278 } 279 break; 280 } 281 default: 282 ERR(handle, "unsupported protocol %u", proto); 283 goto err; 284 } 285 *response = NULL; 286 return STATUS_SUCCESS; 287 288 err: 289 ERR(handle, "could not query node %s/%s (%s)", 290 addr, mask, sepol_node_get_proto_str(proto)); 291 return STATUS_ERR; 292 293 } 294 295 /* Load a node into policy */ 296 int sepol_node_modify(sepol_handle_t * handle, 297 sepol_policydb_t * p, 298 const sepol_node_key_t * key, const sepol_node_t * data) 299 { 300 301 policydb_t *policydb = &p->p; 302 ocontext_t *node = NULL; 303 304 int proto; 305 const char *addr, *mask; 306 307 sepol_node_key_unpack(key, &addr, &mask, &proto); 308 309 if (node_from_record(handle, policydb, &node, data) < 0) 310 goto err; 311 312 switch (proto) { 313 314 case SEPOL_PROTO_IP4: 315 { 316 /* Attach to context list */ 317 node->next = policydb->ocontexts[OCON_NODE]; 318 policydb->ocontexts[OCON_NODE] = node; 319 break; 320 } 321 case SEPOL_PROTO_IP6: 322 { 323 /* Attach to context list */ 324 node->next = policydb->ocontexts[OCON_NODE6]; 325 policydb->ocontexts[OCON_NODE6] = node; 326 break; 327 } 328 default: 329 ERR(handle, "unsupported protocol %u", proto); 330 goto err; 331 } 332 333 return STATUS_SUCCESS; 334 335 err: 336 ERR(handle, "could not load node %s/%s (%s)", 337 addr, mask, sepol_node_get_proto_str(proto)); 338 if (node != NULL) { 339 context_destroy(&node->context[0]); 340 free(node); 341 } 342 return STATUS_ERR; 343 } 344 345 int sepol_node_iterate(sepol_handle_t * handle, 346 const sepol_policydb_t * p, 347 int (*fn) (const sepol_node_t * node, 348 void *fn_arg), void *arg) 349 { 350 351 const policydb_t *policydb = &p->p; 352 ocontext_t *c, *head; 353 sepol_node_t *node = NULL; 354 int status; 355 356 head = policydb->ocontexts[OCON_NODE]; 357 for (c = head; c; c = c->next) { 358 if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node) 359 < 0) 360 goto err; 361 362 /* Invoke handler */ 363 status = fn(node, arg); 364 if (status < 0) 365 goto err; 366 367 sepol_node_free(node); 368 node = NULL; 369 370 /* Handler requested exit */ 371 if (status > 0) 372 break; 373 } 374 375 head = policydb->ocontexts[OCON_NODE6]; 376 for (c = head; c; c = c->next) { 377 if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node) 378 < 0) 379 goto err; 380 381 /* Invoke handler */ 382 status = fn(node, arg); 383 if (status < 0) 384 goto err; 385 386 sepol_node_free(node); 387 node = NULL; 388 389 /* Handler requested exit */ 390 if (status > 0) 391 break; 392 } 393 394 return STATUS_SUCCESS; 395 396 err: 397 ERR(handle, "could not iterate over nodes"); 398 sepol_node_free(node); 399 return STATUS_ERR; 400 } 401