diff -urN -X dontdiff checkpolicy-1.8.o/checkpolicy.c checkpolicy-1.8.w/checkpolicy.c --- checkpolicy-1.8.o/checkpolicy.c 2004-02-24 08:29:22.000000000 -0500 +++ checkpolicy-1.8.w/checkpolicy.c 2004-03-19 00:30:52.782858072 -0500 @@ -7,7 +7,12 @@ * * Added conditional policy language extensions * + * Updated: James Morris + * + * Added IPv6 support. + * * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 Red Hat, Inc., James Morris * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. @@ -433,7 +438,7 @@ char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype; size_t scontext_len, pathlen; unsigned int i; - unsigned int protocol, port, addr; + unsigned int protocol, port; unsigned int binary = 0, debug = 0, output_version15 = 0; struct val_to_name v; int ret, ch, fd; @@ -850,14 +855,45 @@ printf("if_sid %d default_msg_sid %d\n", ssid, tsid); break; - case 'b': + case 'b': { + char *p; + int family, len; + struct in_addr addr4; + struct in6_addr addr6; + + printf("protocol family? "); + fgets(ans, sizeof(ans), stdin); + ans[strlen(ans) - 1] = 0; + if (!strcasecmp(ans, "ipv4")) + family = AF_INET; + else if (!strcasecmp(ans, "ipv6")) + family = AF_INET6; + else { + printf("unknown protocol family\n"); + break; + } + printf("node address? "); fgets(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; - addr = inet_addr(ans); - security_node_sid(AF_INET, &addr, sizeof addr, &ssid); + + if (family == AF_INET) { + p = (char *)&addr4; + len = sizeof(addr4); + } else { + p = (char *)&addr6; + len = sizeof(addr6); + } + + if (inet_pton(family, ans, p) < 1) { + printf("error parsing address\n"); + break; + } + + security_node_sid(family, p, len, &ssid); printf("sid %d\n", ssid); break; + } case 'c': printf("fstype? "); fgets(ans, sizeof(ans), stdin); diff -urN -X dontdiff checkpolicy-1.8.o/policydb.c checkpolicy-1.8.w/policydb.c --- checkpolicy-1.8.o/policydb.c 2004-03-03 10:02:38.000000000 -0500 +++ checkpolicy-1.8.w/policydb.c 2004-03-19 00:30:52.783857920 -0500 @@ -1280,6 +1280,20 @@ if (context_read_and_validate(&c->context[0], p, fp)) goto bad; break; + case OCON_NODE6: { + int k; + + buf = next_entry(fp, sizeof(__u32) * 8); + if (!buf) + goto bad; + for (k = 0; k < 4; k++) + c->u.node6.addr[k] = le32_to_cpu(buf[k]); + for (k = 0; k < 4; k++) + c->u.node6.mask[k] = le32_to_cpu(buf[k+4]); + if (context_read_and_validate(&c->context[0], p, fp)) + goto bad; + break; + } } } } diff -urN -X dontdiff checkpolicy-1.8.o/policydb.h checkpolicy-1.8.w/policydb.h --- checkpolicy-1.8.o/policydb.h 2004-02-04 13:21:53.000000000 -0500 +++ checkpolicy-1.8.w/policydb.h 2004-03-19 00:30:52.784857768 -0500 @@ -147,6 +147,10 @@ __u32 addr; __u32 mask; } node; /* node information */ + struct { + __u32 addr[4]; + __u32 mask[4]; + } node6; /* IPv6 node information */ } u; union { __u32 sclass; /* security class for genfs */ @@ -186,7 +190,8 @@ #define OCON_NETIF 3 /* network interfaces */ #define OCON_NODE 4 /* nodes */ #define OCON_FSUSE 5 /* fs_use */ -#define OCON_NUM 6 +#define OCON_NODE6 6 /* IPv6 nodes */ +#define OCON_NUM 7 /* The policy database */ typedef struct policydb { @@ -273,7 +278,7 @@ extern int policydb_read(policydb_t * p, struct policy_file * fp); #define PERM_SYMTAB_SIZE 32 -#define POLICYDB_VERSION 16 +#define POLICYDB_VERSION 17 #define POLICYDB_VERSION_COMPAT 15 #define POLICYDB_CONFIG_MLS 1 diff -urN -X dontdiff checkpolicy-1.8.o/policy_parse.y checkpolicy-1.8.w/policy_parse.y --- checkpolicy-1.8.o/policy_parse.y 2004-02-04 13:21:53.000000000 -0500 +++ checkpolicy-1.8.w/policy_parse.y 2004-03-19 01:11:27.879667088 -0500 @@ -80,7 +80,8 @@ static int define_fs_context(unsigned int major, unsigned int minor); static int define_port_context(unsigned int low, unsigned int high); static int define_netif_context(void); -static int define_node_context(unsigned int addr, unsigned int mask); +static int define_ipv4_node_context(unsigned int addr, unsigned int mask); +static int define_ipv6_node_context(void); %} %union { @@ -143,6 +144,7 @@ %token NUMBER %token EQUALS %token NOTEQUAL +%token IPV6_ADDR %left OR %left XOR @@ -569,7 +571,9 @@ | node_contexts node_context_def ; node_context_def : NODECON ipv4_addr_def ipv4_addr_def security_context_def - {if (define_node_context($2,$3)) return -1;} + {if (define_ipv4_node_context($2,$3)) return -1;} + | NODECON ipv6_addr ipv6_addr security_context_def + {if (define_ipv6_node_context()) return -1;} ; fs_uses : fs_use_def | fs_uses fs_use_def @@ -697,6 +701,9 @@ number : NUMBER { $$ = strtoul(yytext,NULL,0); } ; +ipv6_addr : IPV6_ADDR + { if (insert_id(yytext,0)) return -1; } + ; %% #define DEBUG 1 @@ -4314,7 +4321,7 @@ return 0; } -static int define_node_context(unsigned int addr, unsigned int mask) +static int define_ipv4_node_context(unsigned int addr, unsigned int mask) { ocontext_t *newc, *c, *l, *head; @@ -4350,6 +4357,84 @@ return 0; } +static int define_ipv6_node_context(void) +{ + char *id; + int rc = 0; + struct in6_addr addr, mask; + ocontext_t *newc, *c, *l, *head; + + if (pass == 1) { + free(queue_remove(id_queue)); + free(queue_remove(id_queue)); + parse_security_context(NULL); + goto out; + } + + id = queue_remove(id_queue); + if (!id) { + yyerror("failed to read ipv6 address"); + rc = -1; + goto out; + } + + rc = inet_pton(AF_INET6, id, &addr); + free (id); + if (rc < 1) { + yyerror("failed to parse ipv6 address"); + if (rc == 0) + rc = -1; + goto out; + } + + id = queue_remove(id_queue); + if (!id) { + yyerror("failed to read ipv6 address"); + rc = -1; + goto out; + } + + rc = inet_pton(AF_INET6, id, &mask); + free(id); + if (rc < 1) { + yyerror("failed to parse ipv6 mask"); + if (rc == 0) + rc = -1; + goto out; + } + + newc = malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + rc = -1; + goto out; + } + + memset(newc, 0, sizeof(ocontext_t)); + memcpy(&newc->u.node6.addr[0], &addr.s6_addr32[0], 16); + memcpy(&newc->u.node6.mask[0], &mask.s6_addr32[0], 16); + + if (parse_security_context(&newc->context[0])) { + free(newc); + rc = -1; + goto out; + } + + /* Place this at the end of the list, to retain + the matching order specified in the configuration. */ + head = policydbp->ocontexts[OCON_NODE6]; + for (l = NULL, c = head; c; l = c, c = c->next); + + if (l) + l->next = newc; + else + policydbp->ocontexts[OCON_NODE6] = newc; + + rc = 0; +out: + return rc; +} + static int define_fs_use(int behavior) { ocontext_t *newc, *c, *head; diff -urN -X dontdiff checkpolicy-1.8.o/policy_scan.l checkpolicy-1.8.w/policy_scan.l --- checkpolicy-1.8.o/policy_scan.l 2004-02-04 13:21:53.000000000 -0500 +++ checkpolicy-1.8.w/policy_scan.l 2004-03-19 00:30:52.789857008 -0500 @@ -32,6 +32,7 @@ %array letter [A-Za-z] digit [0-9] +hexval [0-9A-Fa-f] %% \n.* { strncpy(linebuf[lno], yytext+1, 255); linebuf[lno][254] = 0; @@ -159,6 +160,7 @@ {letter}({letter}|{digit}|_)* { return(IDENTIFIER); } {letter}({letter}|{digit}|_|"."|"-")* { return(USER_IDENTIFIER); } {digit}{digit}* { return(NUMBER); } +{hexval}{0,4}":"{hexval}{0,4}":"({hexval}|":"|".")* { return(IPV6_ADDR); } #line[ ]1[ ]\"[^\n]*\" { source_lineno = 1; strncpy(source_file, yytext+9, 255); source_file[strlen(source_file)-1] = '\0'; } #line[ ]{digit}{digit}* { source_lineno = atoi(yytext+6)-1; } #[^\n]* { /* delete comments */ } diff -urN -X dontdiff checkpolicy-1.8.o/services.c checkpolicy-1.8.w/services.c --- checkpolicy-1.8.o/services.c 2004-02-04 13:21:53.000000000 -0500 +++ checkpolicy-1.8.w/services.c 2004-03-19 00:30:52.791856704 -0500 @@ -1159,6 +1159,18 @@ return rc; } +static int match_ipv6_addrmask(__u32 *input, __u32 *addr, __u32 *mask) +{ + int i, fail = 0; + + for(i = 0; i < 4; i++) + if(addr[i] != (input[i] & mask[i])) { + fail = 1; + break; + } + + return !fail; +} /* * Return the SID of the node specified by the address @@ -1172,22 +1184,48 @@ security_id_t *out_sid) { int rc = 0; - __u32 addr; ocontext_t *c; POLICY_RDLOCK; - if (domain != AF_INET || addrlen != sizeof(__u32)) { - *out_sid = SECINITSID_NODE; - goto out; + switch (domain) { + case AF_INET: { + __u32 addr; + + if (addrlen != sizeof(__u32)) { + rc = -EINVAL; + goto out; + } + + addr = *((__u32 *)addrp); + + c = policydb.ocontexts[OCON_NODE]; + while (c) { + if (c->u.node.addr == (addr & c->u.node.mask)) + break; + c = c->next; + } + break; } - addr = *((__u32 *)addrp); + + case AF_INET6: + if (addrlen != sizeof(__u64) * 2) { + rc = -EINVAL; + goto out; + } + + c = policydb.ocontexts[OCON_NODE6]; + while (c) { + if (match_ipv6_addrmask(addrp, c->u.node6.addr, + c->u.node6.mask)) + break; + c = c->next; + } + break; - c = policydb.ocontexts[OCON_NODE]; - while (c) { - if (c->u.node.addr == (addr & c->u.node.mask)) - break; - c = c->next; + default: + *out_sid = SECINITSID_NODE; + goto out; } if (c) { diff -urN -X dontdiff checkpolicy-1.8.o/write.c checkpolicy-1.8.w/write.c --- checkpolicy-1.8.o/write.c 2004-03-03 10:02:38.000000000 -0500 +++ checkpolicy-1.8.w/write.c 2004-03-19 00:30:52.792856552 -0500 @@ -870,6 +870,17 @@ if (context_write(&c->context[0], fp)) return -1; break; + case OCON_NODE6: + for (j = 0; j < 4; j++) + buf[j] = cpu_to_le32(c->u.node6.addr[j]); + for (j = 0; j < 4; j++) + buf[j+4] = cpu_to_le32(c->u.node6.mask[j]); + items = fwrite(buf, sizeof(__u32), 8, fp); + if (items != 8) + return -1; + if (context_write(&c->context[0], fp)) + return -1; + break; } } }