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 return STATUS_SUCCESS; 166 } 167 168 /* Check if a node exists */ 169 int sepol_node_exists(sepol_handle_t * handle, 170 const sepol_policydb_t * p, 171 const sepol_node_key_t * key, int *response) 172 { 173 174 const policydb_t *policydb = &p->p; 175 ocontext_t *c, *head; 176 177 int proto; 178 const char *addr, *mask; 179 sepol_node_key_unpack(key, &addr, &mask, &proto); 180 181 switch (proto) { 182 183 case SEPOL_PROTO_IP4: 184 { 185 head = policydb->ocontexts[OCON_NODE]; 186 for (c = head; c; c = c->next) { 187 unsigned int *addr2 = &c->u.node.addr; 188 unsigned int *mask2 = &c->u.node.mask; 189 190 if (!memcmp(addr, addr2, 4) && 191 !memcmp(mask, mask2, 4)) { 192 193 *response = 1; 194 return STATUS_SUCCESS; 195 } 196 } 197 break; 198 } 199 case SEPOL_PROTO_IP6: 200 { 201 head = policydb->ocontexts[OCON_NODE6]; 202 for (c = head; c; c = c->next) { 203 unsigned int *addr2 = c->u.node6.addr; 204 unsigned int *mask2 = c->u.node6.mask; 205 206 if (!memcmp(addr, addr2, 16) && 207 !memcmp(mask, mask2, 16)) { 208 *response = 1; 209 return STATUS_SUCCESS; 210 } 211 } 212 break; 213 } 214 default: 215 ERR(handle, "unsupported protocol %u", proto); 216 goto err; 217 } 218 219 *response = 0; 220 return STATUS_SUCCESS; 221 222 err: 223 ERR(handle, "could not check if node %s/%s (%s) exists", 224 addr, mask, sepol_node_get_proto_str(proto)); 225 return STATUS_ERR; 226 } 227 228 /* Query a node */ 229 int sepol_node_query(sepol_handle_t * handle, 230 const sepol_policydb_t * p, 231 const sepol_node_key_t * key, sepol_node_t ** response) 232 { 233 234 const policydb_t *policydb = &p->p; 235 ocontext_t *c, *head; 236 237 int proto; 238 const char *addr, *mask; 239 sepol_node_key_unpack(key, &addr, &mask, &proto); 240 241 switch (proto) { 242 243 case SEPOL_PROTO_IP4: 244 { 245 head = policydb->ocontexts[OCON_NODE]; 246 for (c = head; c; c = c->next) { 247 unsigned int *addr2 = &c->u.node.addr; 248 unsigned int *mask2 = &c->u.node.mask; 249 250 if (!memcmp(addr, addr2, 4) && 251 !memcmp(mask, mask2, 4)) { 252 253 if (node_to_record(handle, policydb, 254 c, SEPOL_PROTO_IP4, 255 response) < 0) 256 goto err; 257 return STATUS_SUCCESS; 258 } 259 } 260 break; 261 } 262 case SEPOL_PROTO_IP6: 263 { 264 head = policydb->ocontexts[OCON_NODE6]; 265 for (c = head; c; c = c->next) { 266 unsigned int *addr2 = c->u.node6.addr; 267 unsigned int *mask2 = c->u.node6.mask; 268 269 if (!memcmp(addr, addr2, 16) && 270 !memcmp(mask, mask2, 16)) { 271 272 if (node_to_record(handle, policydb, 273 c, SEPOL_PROTO_IP6, 274 response) < 0) 275 goto err; 276 return STATUS_SUCCESS; 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