int main(int argc, char *argv[]) { note("Testing static decl"); { bitstr_t bit_decl(bs, 65); /*bitstr_t *bsp = bs;*/ bit_set(bs,9); bit_set(bs,14); TEST(bit_test(bs,9), "bit 9 set"); TEST(!bit_test(bs,12), "bit 12 not set"); TEST(bit_test(bs,14), "bit 14 set" ); /*bit_free(bsp);*/ /* triggers TEST in bit_free - OK */ } note("Testing basic vixie functions"); { bitstr_t *bs = bit_alloc(16), *bs2; /*bit_set(bs, 42);*/ /* triggers TEST in bit_set - OK */ bit_set(bs,9); bit_set(bs,14); TEST(bit_test(bs,9), "bit 9 set"); TEST(!bit_test(bs,12), "bit 12 not set" ); TEST(bit_test(bs,14), "bit 14 set"); bs2 = bit_copy(bs); bit_fill_gaps(bs2); TEST(bit_ffs(bs2) == 9, "first bit set = 9 "); TEST(bit_fls(bs2) == 14, "last bit set = 14"); TEST(bit_set_count(bs2) == 6, "bitstring"); TEST(bit_test(bs2,12), "bitstring"); TEST(bit_super_set(bs,bs2) == 1, "bitstring"); TEST(bit_super_set(bs2,bs) == 0, "bitstring"); bit_clear(bs,14); TEST(!bit_test(bs,14), "bitstring"); bit_nclear(bs,9,14); TEST(!bit_test(bs,9), "bitstring"); TEST(!bit_test(bs,12), "bitstring"); TEST(!bit_test(bs,14), "bitstring"); bit_nset(bs,9,14); TEST(bit_test(bs,9), "bitstring"); TEST(bit_test(bs,12), "bitstring"); TEST(bit_test(bs,14), "bitstring"); TEST(bit_ffs(bs) == 9, "ffs"); TEST(bit_ffc(bs) == 0, "ffc"); bit_nset(bs,0,8); TEST(bit_ffc(bs) == 15, "ffc"); bit_free(bs); /*bit_set(bs,9); */ /* triggers TEST in bit_set - OK */ } note("Testing and/or/not"); { bitstr_t *bs1 = bit_alloc(128); bitstr_t *bs2 = bit_alloc(128); bit_set(bs1, 100); bit_set(bs1, 104); bit_set(bs2, 100); bit_and(bs1, bs2); TEST(bit_test(bs1, 100), "and"); TEST(!bit_test(bs1, 104), "and"); bit_set(bs2, 110); bit_set(bs2, 111); bit_set(bs2, 112); bit_or(bs1, bs2); TEST(bit_test(bs1, 100), "or"); TEST(bit_test(bs1, 110), "or"); TEST(bit_test(bs1, 111), "or"); TEST(bit_test(bs1, 112), "or"); bit_not(bs1); TEST(!bit_test(bs1, 100), "not"); TEST(bit_test(bs1, 12), "not"); bit_free(bs1); bit_free(bs2); } note("testing bit selection"); { bitstr_t *bs1 = bit_alloc(128), *bs2; bit_set(bs1, 21); bit_set(bs1, 100); bit_fill_gaps(bs1); bs2 = bit_pick_cnt(bs1,20); if (bs2) { TEST(bit_set_count(bs2) == 20, "pick"); TEST(bit_ffs(bs2) == 21, "pick"); TEST(bit_fls(bs2) == 40, "pick"); bit_free(bs2); } else TEST(0, "alloc fail"); bit_free(bs1); } note("Testing realloc"); { bitstr_t *bs = bit_alloc(1); TEST(bit_ffs(bs) == -1, "bitstring"); bit_set(bs,0); /*bit_set(bs, 1000);*/ /* triggers TEST in bit_set - OK */ bs = bit_realloc(bs,1048576); bit_set(bs,1000); bit_set(bs,1048575); TEST(bit_test(bs, 0), "bitstring"); TEST(bit_test(bs, 1000), "bitstring"); TEST(bit_test(bs, 1048575), "bitstring"); TEST(bit_set_count(bs) == 3, "bitstring"); bit_clear(bs,0); bit_clear(bs,1000); TEST(bit_set_count(bs) == 1, "bitstring"); TEST(bit_ffs(bs) == 1048575, "bitstring"); bit_free(bs); } note("Testing bit_fmt"); { char tmpstr[1024]; bitstr_t *bs = bit_alloc(1024); TEST(!strcmp(bit_fmt(tmpstr,sizeof(tmpstr),bs), ""), "bitstring"); bit_set(bs,42); TEST(!strcmp(bit_fmt(tmpstr,sizeof(tmpstr),bs), "42"), "bitstring"); bit_set(bs,102); TEST(!strcmp(bit_fmt(tmpstr,sizeof(tmpstr),bs), "42,102"), "bitstring"); bit_nset(bs,9,14); TEST(!strcmp(bit_fmt(tmpstr,sizeof(tmpstr), bs), "9-14,42,102"), "bitstring"); } note("Testing bit_nffc/bit_nffs"); { bitstr_t *bs = bit_alloc(1024); bit_set(bs, 2); bit_set(bs, 6); bit_set(bs, 7); bit_nset(bs,12,1018); TEST(bit_nffc(bs, 2) == 0, "bitstring"); TEST(bit_nffc(bs, 3) == 3, "bitstring"); TEST(bit_nffc(bs, 4) == 8, "bitstring"); TEST(bit_nffc(bs, 5) == 1019, "bitstring"); TEST(bit_nffc(bs, 6) == -1, "bitstring"); TEST(bit_nffs(bs, 1) == 2, "bitstring"); TEST(bit_nffs(bs, 2) == 6, "bitstring"); TEST(bit_nffs(bs, 100) == 12, "bitstring"); TEST(bit_nffs(bs, 1023) == -1, "bitstring"); bit_free(bs); } note("Testing bit_unfmt"); { bitstr_t *bs = bit_alloc(1024); bitstr_t *bs2 = bit_alloc(1024); char tmpstr[4096]; bit_set(bs,1); bit_set(bs,3); bit_set(bs,30); bit_nset(bs,42,64); bit_nset(bs,97,1000); bit_fmt(tmpstr, sizeof(tmpstr), bs); TEST(bit_unfmt(bs2, tmpstr) != -1, "bitstring"); TEST(bit_equal(bs, bs2), "bitstring"); } totals(); return failed; }
/* * When we are "the server", this starts SET/ACK mode * When we are "the client", this starts REQ/REPLY mode */ static int cfg_initiator_send_ATTR(struct message *msg) { struct sa *isakmp_sa = msg->isakmp_sa; struct ipsec_exch *ie = msg->exchange->data; u_int8_t *hashp = 0, *attrp, *attr; size_t attrlen, off; char *id_string, *cfg_mode, *field; struct sockaddr *sa; #define CFG_ATTR_BIT_MAX ISAKMP_CFG_ATTR_FUTURE_MIN /* XXX */ bitstr_t bit_decl(attrbits, CFG_ATTR_BIT_MAX); u_int16_t bit, length; u_int32_t life; if (msg->exchange->phase == 2) { hashp = cfg_add_hash(msg); if (!hashp) return -1; } /* We initiated this exchange, check isakmp_sa for other side. */ if (isakmp_sa->initiator) id_string = ipsec_id_string(isakmp_sa->id_r, isakmp_sa->id_r_len); else id_string = ipsec_id_string(isakmp_sa->id_i, isakmp_sa->id_i_len); if (!id_string) { log_print("cfg_initiator_send_ATTR: cannot parse ID"); goto fail; } /* Check for attribute list to send to the other side */ attrlen = 0; bit_nclear(attrbits, 0, CFG_ATTR_BIT_MAX - 1); cfg_mode = conf_get_str(id_string, "Mode"); if (!cfg_mode || strcmp(cfg_mode, "SET") == 0) { /* SET/ACK mode */ ie->cfg_type = ISAKMP_CFG_SET; LOG_DBG((LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: SET/ACK mode")); #define ATTRFIND(STR,ATTR4,LEN4,ATTR6,LEN6) do \ { \ if ((sa = conf_get_address (id_string, STR)) != NULL) \ switch (sa->sa_family) { \ case AF_INET: \ bit_set (attrbits, ATTR4); \ attrlen += ISAKMP_ATTR_SZ + LEN4; \ break; \ case AF_INET6: \ bit_set (attrbits, ATTR6); \ attrlen += ISAKMP_ATTR_SZ + LEN6; \ break; \ default: \ break; \ } \ free (sa); \ } while (0) /* * XXX We don't simultaneously support IPv4 and IPv6 * addresses. */ ATTRFIND("Address", ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS, 4, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS, 16); ATTRFIND("Netmask", ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK, 4, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK, 16); ATTRFIND("Nameserver", ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS, 4, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS, 16); ATTRFIND("WINS-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS, 4, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS, 16); ATTRFIND("DHCP-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP, 4, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP, 16); #ifdef notyet ATTRFIND("Network", ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET, 8, ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET, 17); #endif #undef ATTRFIND if (conf_get_str(id_string, "Lifetime")) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); attrlen += ISAKMP_ATTR_SZ + 4; } } else { struct conf_list *alist; struct conf_list_node *anode; ie->cfg_type = ISAKMP_CFG_REQUEST; LOG_DBG((LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: REQ/REPLY mode")); alist = conf_get_list(id_string, "Attributes"); if (alist) { for (anode = TAILQ_FIRST(&alist->fields); anode; anode = TAILQ_NEXT(anode, link)) { if (strcasecmp(anode->field, "Address") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS); bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS); attrlen += ISAKMP_ATTR_SZ * 2; } else if (strcasecmp(anode->field, "Netmask") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK); bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK); attrlen += ISAKMP_ATTR_SZ * 2; } else if (strcasecmp(anode->field, "Nameserver") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS); bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS); attrlen += ISAKMP_ATTR_SZ * 2; } else if (strcasecmp(anode->field, "WINS-server") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS); bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS); attrlen += ISAKMP_ATTR_SZ * 2; } else if (strcasecmp(anode->field, "DHCP-server") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP); bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP); attrlen += ISAKMP_ATTR_SZ * 2; } else if (strcasecmp(anode->field, "Lifetime") == 0) { bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY); attrlen += ISAKMP_ATTR_SZ; } else { log_print("cfg_initiator_send_ATTR: " "unknown attribute %.20s in " "section [%s]", anode->field, id_string); } } conf_free_list(alist); } } if (attrlen == 0) { /* No data found. */ log_print("cfg_initiator_send_ATTR: no IKECFG attributes " "found for [%s]", id_string); /* * We can continue, but this indicates a configuration error * that the user probably will want to correct. */ free(id_string); return 0; } attrlen += ISAKMP_ATTRIBUTE_SZ; attrp = calloc(1, attrlen); if (!attrp) { log_error("cfg_initiator_send_ATTR: calloc (1, %lu) failed", (unsigned long)attrlen); goto fail; } if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) { free(attrp); goto fail; } SET_ISAKMP_ATTRIBUTE_TYPE(attrp, ie->cfg_type); getrandom((u_int8_t *) & ie->cfg_id, sizeof ie->cfg_id); SET_ISAKMP_ATTRIBUTE_ID(attrp, ie->cfg_id); off = ISAKMP_ATTRIBUTE_SZ; /* * Use the bitstring built previously to collect the right * parameters for attrp. */ for (bit = 0; bit < CFG_ATTR_BIT_MAX; bit++) if (bit_test(attrbits, bit)) { attr = attrp + off; SET_ISAKMP_ATTR_TYPE(attr, bit); if (ie->cfg_type == ISAKMP_CFG_REQUEST) { off += ISAKMP_ATTR_SZ; continue; } /* All the other are similar, this is the odd one. */ if (bit == ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY) { life = conf_get_num(id_string, "Lifetime", 1200); SET_ISAKMP_ATTR_LENGTH_VALUE(attr, 4); encode_32(attr + ISAKMP_ATTR_VALUE_OFF, life); off += ISAKMP_ATTR_SZ + 4; continue; } switch (bit) { case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: length = 4; break; case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: length = 16; break; default: length = 0; /* Silence gcc. */ } switch (bit) { case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: field = "Address"; break; case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: field = "Netmask"; break; case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: field = "Nameserver"; break; case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: field = "DHCP-server"; break; case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: field = "WINS-server"; break; default: field = 0; /* Silence gcc. */ } sa = conf_get_address(id_string, field); SET_ISAKMP_ATTR_LENGTH_VALUE(attr, length); memcpy(attr + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata(sa), length); free(sa); off += ISAKMP_ATTR_SZ + length; } if (msg->exchange->phase == 2) if (cfg_finalize_hash(msg, hashp, attrp, attrlen)) goto fail; return 0; fail: free(id_string); return -1; }