bool cert_VerifySubjectAltName(const CERTCertificate *cert, const char *name) { SECStatus rv; SECItem subAltName; PLArenaPool *arena = NULL; CERTGeneralName *nameList = NULL; CERTGeneralName *current = NULL; bool san_ip = FALSE; unsigned int len = strlen(name); ip_address myip; rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, &subAltName); if (rv != SECSuccess) { DBG(DBG_X509, DBG_log("certificate contains no subjectAltName extension")); return FALSE; } if (tnatoaddr(name, 0, AF_UNSPEC, &myip) == NULL) san_ip = TRUE; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); passert(arena != NULL); nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName); passert(current != NULL); do { switch (current->type) { case certDNSName: case certRFC822Name: if (san_ip) break; if (current->name.other.len == len) { if (memcmp(current->name.other.data, name, len) == 0) { DBG(DBG_X509, DBG_log("subjectAltname %s found in certificate", name)); PORT_FreeArena(arena, PR_FALSE); return TRUE; } } if (current->name.other.len != 0 && current->name.other.len < IDTOA_BUF) { char osan[IDTOA_BUF]; memcpy(osan,current->name.other.data, current->name.other.len); osan[current->name.other.len] = '\0'; DBG(DBG_X509, DBG_log("subjectAltname (len=%d) %s not match %s", current->name.other.len, osan, name)); } else { DBG(DBG_X509, DBG_log("subjectAltname <TOO BIG TO PRINT> does not match %s", name)); } break; case certIPAddress: if (!san_ip) break; if ((current->name.other.len == 4) && (addrtypeof(&myip) == AF_INET)) { if (memcmp(current->name.other.data, &myip.u.v4.sin_addr.s_addr, 4) == 0) { DBG(DBG_X509, DBG_log("subjectAltname IPv4 matches %s", name)); PORT_FreeArena(arena, PR_FALSE); return TRUE; } else { DBG(DBG_X509, DBG_log("subjectAltname IPv4 does not match %s", name)); break; } } if ((current->name.other.len == 16) && (addrtypeof(&myip) == AF_INET6)) { if (memcmp(current->name.other.data, &myip.u.v6.sin6_addr.s6_addr, 16) == 0) { DBG(DBG_X509, DBG_log("subjectAltname IPv6 matches %s", name)); PORT_FreeArena(arena, PR_FALSE); return TRUE; } else { DBG(DBG_X509, DBG_log("subjectAltname IPv6 does not match %s", name)); break; } } DBG(DBG_X509, DBG_log("subjectAltnamea IP address family mismatch for %s", name)); break; default: break; } current = CERT_GetNextGeneralName(current); } while (current != nameList); loglog(RC_LOG_SERIOUS, "No matching subjectAltName found"); /* Don't free nameList, it's part of the arena. */ PORT_FreeArena(arena, PR_FALSE); return FALSE; }
/* * See if left->addr or left->next is %defaultroute and change it to IP. * * Returns: * -1: failure * 0: done * 1: please call again: more to do */ static int resolve_defaultroute_one(struct starter_end *host, struct starter_end *peer) { /* * "left=" == host->addrtype and host->addr * "leftnexthop=" == host->nexttype and host->nexthop */ /* What kind of result are we seeking? */ bool seeking_src = (host->addrtype == KH_DEFAULTROUTE); bool seeking_gateway = (host->nexttype == KH_DEFAULTROUTE); char msgbuf[RTNL_BUFSIZE]; bool has_dst = FALSE; int query_again = 0; if (!seeking_src && !seeking_gateway) return 0; /* this end already figured out */ /* Fill netlink request */ netlink_query_init(msgbuf, host->addr_family); if (host->nexttype == KH_IPADDR) { /* * My nexthop (gateway) is specified. * We need to figure out our source IP to get there. */ netlink_query_add(msgbuf, RTA_DST, &host->nexthop); has_dst = TRUE; } else if (peer->addrtype == KH_IPADDR) { /* * Peer IP is specified. * We may need to figure out source IP * and gateway IP to get there. */ netlink_query_add(msgbuf, RTA_DST, &peer->addr); has_dst = TRUE; if (seeking_src && seeking_gateway && host->addr_family == AF_INET) { /* * If we have only peer IP and no gateway/src we must * do two queries: * 1) find out gateway for dst * 2) find out src for that gateway * Doing both in one query returns src for dst. * * (IPv6 returns link-local for gateway so we can and * do seek both in one query.) */ seeking_src = FALSE; query_again = 1; } } if (has_dst && host->addrtype == KH_IPADDR) { /* SRC works only with DST */ netlink_query_add(msgbuf, RTA_SRC, &host->addr); } /* * If we have for example host=%defaultroute + peer=%any * (no destination) the netlink reply will be full routing table. * We must do two queries: * 1) find out default gateway * 2) find out src for that default gateway */ if (!has_dst) { if (seeking_src && seeking_gateway) { seeking_src = FALSE; query_again = 1; } } if (seeking_gateway) { struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; nlmsg->nlmsg_flags |= NLM_F_DUMP; } if (verbose) printf("\nseeking_src = %d, seeking_gateway = %d, has_dst = %d\n", seeking_src, seeking_gateway, has_dst); /* Send netlink get_route request */ ssize_t len = netlink_query(msgbuf); if (len < 0) return -1; /* Parse reply */ struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; for (; NLMSG_OK(nlmsg, len); nlmsg = NLMSG_NEXT(nlmsg, len)) { struct rtmsg *rtmsg; struct rtattr *rtattr; int rtlen; char r_interface[IF_NAMESIZE+1]; char r_source[ADDRTOT_BUF]; char r_gateway[ADDRTOT_BUF]; char r_destination[ADDRTOT_BUF]; bool ignore; if (nlmsg->nlmsg_type == NLMSG_DONE) break; if (nlmsg->nlmsg_type == NLMSG_ERROR) { printf("netlink error\n"); return -1; break; } /* ignore all but IPv4 and IPv6 */ rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6) continue; /* Parse one route entry */ r_interface[0] = r_interface[IF_NAMESIZE] = r_source[0] = r_gateway[0] = r_destination[0] = '\0'; rtattr = (struct rtattr *) RTM_RTA(rtmsg); rtlen = RTM_PAYLOAD(nlmsg); for (; RTA_OK(rtattr, rtlen); rtattr = RTA_NEXT(rtattr, rtlen)) { switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), r_interface); break; case RTA_PREFSRC: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_source, sizeof(r_source)); break; case RTA_GATEWAY: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_gateway, sizeof(r_gateway)); break; case RTA_DST: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_destination, sizeof(r_destination)); break; } } /* * Ignore if not main table. * Ignore ipsecX or mastX interfaces. */ ignore = rtmsg->rtm_table != RT_TABLE_MAIN || startswith(r_interface, "ipsec") || startswith(r_interface, "mast"); if (verbose) { printf("dst %s via %s dev %s src %s table %d%s\n", r_destination, r_gateway, r_interface, r_source, rtmsg->rtm_table, ignore ? "" : " (ignored)"); } if (ignore) continue; if (seeking_src && r_source[0] != '\0') { err_t err = tnatoaddr(r_source, 0, rtmsg->rtm_family, &host->addr); if (err == NULL) { host->addrtype = KH_IPADDR; seeking_src = FALSE; if (verbose) printf("set addr: %s\n", r_source); } else if (verbose) { printf("unknown source results from kernel (%s): %s\n", r_source, err); } } if (seeking_gateway && r_destination[0] == '\0' && (has_dst || r_source[0] == '\0')) { if (r_gateway[0] == '\0' && r_interface[0] != '\0') { /* * Point-to-Point default gw without "via IP" * Attempt to find r_gateway as the IP address * on the interface. */ resolve_ppp_peer(r_interface, host->addr_family, r_gateway); } if (r_gateway[0] != '\0') { err_t err = tnatoaddr(r_gateway, 0, rtmsg->rtm_family, &host->nexthop); if (err != NULL) { printf("unknown gateway results from kernel: %s\n", err); } else { /* Note: Use first even if multiple */ host->nexttype = KH_IPADDR; seeking_gateway = FALSE; if (verbose) printf("set nexthop: %s\n", r_gateway); } } } } return query_again; }
static bool validate_end(struct ub_ctx *dnsctx , #endif struct starter_conn *conn_st, struct starter_end *end, const char *leftright, bool resolvip UNUSED, err_t *perr) { err_t er = NULL; char *err_str = NULL; int family = conn_st->options[KBF_CONNADDRFAMILY]; bool err = FALSE; # define ERR_FOUND(...) { err |= error_append(&err_str, __VA_ARGS__); } if (!end->options_set[KNCF_IP]) conn_st->state = STATE_INCOMPLETE; end->addrtype = end->options[KNCF_IP]; end->addr_family = family; /* validate the KSCF_IP/KNCF_IP */ switch (end->addrtype) { case KH_ANY: anyaddr(family, &(end->addr)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright); break; case KH_IPADDR: assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0] == '%') { pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (!starter_iface_find(end->iface, family, &end->addr, &end->nexthop)) conn_st->state = STATE_INVALID; /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr)); if (er != NULL) { /* not numeric, so set the type to the string type */ end->addrtype = KH_IPHOSTNAME; } if (end->id == NULL) { ipstr_buf b; end->id = clone_str(ipstr(&end->addr, &b), "end if"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPORTUNISTIC; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IPHOSTNAME", leftright); break; case KH_DEFAULTROUTE: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_DEFAULTROUTE", leftright); break; case KH_NOTSET: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright); break; } /* validate the KSCF_SUBNET */ if (end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if (end->strings_set[KSCF_ADDRESSPOOL]) { ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); } if (startswith(value, "vhost:") || startswith(value, "vnet:")) { er = NULL; end->virt = clone_str(value, "validate_end item"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, family, &(end->subnet)); } if (er != NULL) ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright, value, er); } /* set nexthop address to something consistent, by default */ anyaddr(family, &end->nexthop); anyaddr(addrtypeof(&end->addr), &end->nexthop); /* validate the KSCF_NEXTHOP */ if (end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if (strcaseeq(value, "%defaultroute")) { end->nexttype = KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_INET, &(end->nexthop)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->nexthop)) != NULL) { #ifdef DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %snexthop value", leftright); if (!unbound_resolve(dnsctx, value, strlen(value), AF_INET, &(end->nexthop)) && !unbound_resolve(dnsctx, value, strlen(value), AF_INET6, &(end->nexthop))) ERR_FOUND("bad value for %snexthop=%s\n", leftright, value); #else er = ttoaddr(value, 0, family, &(end->nexthop)); if (er != NULL) ERR_FOUND("bad value for %snexthop=%s [%s]", leftright, value, er); #endif } end->nexttype = KH_IPADDR; } } else { #if 0 if (conn_st->policy & POLICY_OPPORTUNISTIC) end->nexttype = KH_DEFAULTROUTE; #endif anyaddr(family, &end->nexthop); if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } } /* validate the KSCF_ID */ if (end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); } if (end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch (end->options[KSCF_RSAKEY1]) { case PUBKEY_DNS: case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if (end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1"); } if (end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if (end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) { #ifdef DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %ssourceip value", leftright); if (!unbound_resolve(dnsctx, value, strlen(value), AF_INET, &(end->sourceip)) && !unbound_resolve(dnsctx, value, strlen(value), AF_INET6, &(end->sourceip))) ERR_FOUND("bad value for %ssourceip=%s\n", leftright, value); #else er = ttoaddr(value, 0, family, &(end->sourceip)); if (er != NULL) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); #endif } else { er = tnatoaddr(value, 0, family, &(end->sourceip)); if (er != NULL) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if (!end->has_client) { starter_log(LOG_LEVEL_INFO, "%ssourceip= used but not %ssubnet= defined, defaulting %ssubnet to %s", leftright, leftright, leftright, value); er = addrtosubnet(&end->sourceip, &end->subnet); if (er != NULL) { ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); } end->has_client = TRUE; end->has_client_wildcard = FALSE; } } /* copy certificate path name */ if (end->strings_set[KSCF_CERT]) end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); if (end->strings_set[KSCF_CA]) end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); if (end->strings_set[KSCF_UPDOWN]) end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); if (end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh != NULL) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->strings_set[KSCF_ADDRESSPOOL]) { char *addresspool = end->strings[KSCF_ADDRESSPOOL]; if (end->strings_set[KSCF_SUBNET]) ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); starter_log(LOG_LEVEL_DEBUG, "connection's %saddresspool set to: %s", leftright, end->strings[KSCF_ADDRESSPOOL] ); er = ttorange(addresspool, 0, AF_INET, &end->pool_range, TRUE); if (er != NULL) ERR_FOUND("bad %saddresspool=%s [%s]", leftright, addresspool, er); } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) conn_st->policy |= POLICY_XAUTH; /* KSCF_SUBNETWITHIN --- not sure what to do with it. KSCF_ESPENCKEY --- todo (manual keying) KSCF_ESPAUTHKEY --- todo (manual keying) KSCF_SOURCEIP = 16, KSCF_MAX = 19 */ if (err) *perr = err_str; return err; # undef ERR_FOUND }
/* * See if left->addr or left->next is %defaultroute and change it to IP. */ int resolve_defaultroute_one(struct starter_end *left, struct starter_end *right) { /* TODO: this will probably not work with Point-to-Point links */ /* "left=" == left->addrtype + left->addr * "leftnexthop=" == left->nexttype + left->nexthop */ /* What kind of result we want to parse? */ int parse_src = (left->addrtype == KH_DEFAULTROUTE); int parse_gateway = (left->nexttype == KH_DEFAULTROUTE); if (parse_src == 0 && parse_gateway == 0) return 0; /* Fill netlink request */ char msgbuf[RTNL_BUFSIZE]; int has_dst = 0; netlink_query_init(msgbuf, left->addr_family); if (left->nexttype == KH_IPADDR) { /* My nexthop is specified */ netlink_query_add(msgbuf, RTA_DST, &left->nexthop); has_dst = 1; } else if (right->addrtype == KH_IPADDR) { /* Peer IP is specified */ netlink_query_add(msgbuf, RTA_DST, &right->addr); has_dst = 1; } if (has_dst && left->addrtype == KH_IPADDR) /* SRC works only with DST */ netlink_query_add(msgbuf, RTA_SRC, &left->addr); /* If we have for example left=%defaultroute + right=%any, the netlink * reply will be full routing table. We just want default gateway for the * first run. */ if (has_dst == 0) { struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; nlmsg->nlmsg_flags |= NLM_F_DUMP; if (parse_gateway) parse_src = 0; } if (verbose) printf("\nparse_src = %d, parse_gateway = %d, has_dst = %d\n", parse_src, parse_gateway, has_dst); /* Send netlink get_route request */ int len = netlink_query(msgbuf); if (len < 0) return -1; /* Parse reply */ struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf; for (; NLMSG_OK(nlmsg, len); nlmsg = NLMSG_NEXT(nlmsg, len)) { struct rtmsg *rtmsg; struct rtattr *rtattr; int rtlen; char r_interface[IF_NAMESIZE]; char r_source[ADDRTOT_BUF]; char r_gateway[ADDRTOT_BUF]; char r_destination[ADDRTOT_BUF]; /* Check for IPv4 / IPv6 */ rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg); if (rtmsg->rtm_family != AF_INET && rtmsg->rtm_family != AF_INET6) continue; /* Parse one route entry */ *r_interface = *r_source = *r_gateway = *r_destination = 0; rtattr = (struct rtattr *) RTM_RTA(rtmsg); rtlen = RTM_PAYLOAD(nlmsg); for (; RTA_OK(rtattr, rtlen); rtattr = RTA_NEXT(rtattr, rtlen)) { switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), r_interface); break; case RTA_PREFSRC: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_source, sizeof(r_source)); break; case RTA_GATEWAY: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_gateway, sizeof(r_gateway)); break; case RTA_DST: inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr), r_destination, sizeof(r_destination)); break; } } if (verbose) printf("dst %s via %s dev %s src %s\n", r_destination, r_gateway, r_interface, r_source); err_t err; if (parse_src && *r_source != 0) { err = tnatoaddr(r_source, 0, rtmsg->rtm_family, &left->addr); if (err == NULL) { left->addrtype = KH_IPADDR; parse_src = 0; if (verbose) printf("set addr: %s\n", r_source); } else if (verbose) printf("unknown source results from kernel: %s\n", err); } if (parse_gateway && *r_gateway != 0 && (has_dst || *r_source == 0)) { err = tnatoaddr(r_gateway, 0, rtmsg->rtm_family, &left->nexthop); if (err == NULL) { left->nexttype = KH_IPADDR; parse_gateway = 0; /* Use first if multiple */ if (verbose) printf("set nexthop: %s\n", r_gateway); } else if (verbose) printf("unknown gateway results from kernel: %s\n", err); } } /* If we parsed and found default_gateway, we must do the request again * to find out the source IP for that gateway. */ return has_dst == 0 && parse_gateway == 0; }
/* synchronous blocking resolving - simple replacement of ttoaddr() * src_len 0 means "apply strlen" * af 0 means "try both families */ int unbound_resolve(struct ub_ctx *dnsctx, char *src, size_t srclen, int af, ip_address *ipaddr) { const int qtype = (af == AF_INET6) ? 28 : 1; /* 28 = AAAA record, 1 = A record */ struct ub_result *result; passert(dnsctx != NULL); if (srclen == 0) { srclen = strlen(src); if (srclen == 0) { libreswan_log("empty hostname in host lookup\n"); ub_resolve_free(result); return 0; } } { int ugh = ub_resolve(dnsctx, src, qtype, 1 /* CLASS IN */, &result); if(ugh != 0) { libreswan_log("unbound error: %s", ub_strerror(ugh)); ub_resolve_free(result); return 0; } } if(result->bogus) { libreswan_log("ERROR: %s failed DNSSEC valdation!\n", result->qname); ub_resolve_free(result); return 0; } if(!result->havedata) { if(result->secure) { DBG(DBG_DNS,DBG_log("Validated reply proves '%s' does not exist\n", src)); } else { DBG(DBG_DNS,DBG_log("Failed to resolve '%s' (%s)\n", src, (result->bogus) ? "BOGUS" : "insecure")); } ub_resolve_free(result); return 0; } else if(!result->bogus) { if(!result->secure) { DBG(DBG_DNS,DBG_log("warning: %s lookup was not protected by DNSSEC!\n", result->qname)); } } #if 0 { int i = 0; DBG_log("The result has:\n"); DBG_log("qname: %s\n", result->qname); DBG_log("qtype: %d\n", result->qtype); DBG_log("qclass: %d\n", result->qclass); if(result->canonname) DBG_log("canonical name: %s\n", result->canonname); DBG_log("DNS rcode: %d\n", result->rcode); for(i=0; result->data[i] != NULL; i++) { DBG_log("result data element %d has length %d\n", i, result->len[i]); } DBG_log("result has %d data element(s)\n", i); } #endif /* XXX: for now pick the first one and return that */ passert(result->data[0] != NULL); { char dst[INET6_ADDRSTRLEN]; err_t err = tnatoaddr(inet_ntop(af, result->data[0], dst , (af==AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN) , 0, af, ipaddr); ub_resolve_free(result); if(err == NULL) { DBG(DBG_DNS,DBG_log("success for %s lookup", (af==AF_INET) ? "IPv4" : "IPv6")); return 1; } else { libreswan_log("tnatoaddr failed in unbound_resolve()"); return 0; } } }
/** * Validate that yes in fact we are one side of the tunnel * * The function checks that IP addresses are valid, nexthops are * present (if needed) as well as policies, and sets the leftID * from the left= if it isn't set. * * @param conn_st a connection definition * @param end a connection end * @param left boolean (are we 'left'? 1 = yes, 0 = no) * @param perr pointer to char containing error value * @return bool TRUE if failed */ static bool validate_end(struct starter_conn *conn_st , struct starter_end *end , bool left , bool resolvip UNUSED , err_t *perr) { err_t er = NULL; char *err_str = NULL; const char *leftright=(left ? "left" : "right"); int family = conn_st->options[KBF_CONNADDRFAMILY]; bool err = FALSE; #define ERR_FOUND(args...) do { err += error_append(&err_str, ##args); } while(0) if(!end->options_set[KNCF_IP]) { conn_st->state = STATE_INCOMPLETE; } end->addrtype=end->options[KNCF_IP]; end->addr_family = family; /* validate the KSCF_IP/KNCF_IP */ switch(end->addrtype) { case KH_ANY: anyaddr(family, &(end->addr)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ break; case KH_IPADDR: /* right=/left= */ assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0]=='%') { if (end->iface) pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (starter_iface_find(end->iface, family, &(end->addr), &(end->nexthop)) == -1) { conn_st->state = STATE_INVALID; } /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr)); if(er) { /* not numeric, so set the type to the string type */ end->addrtype = KH_IPHOSTNAME; } if(end->id == NULL) { char idbuf[ADDRTOT_BUF]; addrtot(&end->addr, 0, idbuf, sizeof(idbuf)); end->id= clone_str(idbuf, "end id"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPO; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPO|POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* XXX */ break; case KH_DEFAULTROUTE: break; case KH_NOTSET: break; } /* validate the KSCF_SUBNET */ if(end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if ( ((strlen(value)>=6) && (strncmp(value,"vhost:",6)==0)) || ((strlen(value)>=5) && (strncmp(value,"vnet:",5)==0)) ) { er = NULL; end->virt = clone_str(value, "end->virt"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, 0, &(end->subnet)); } if (er) ERR_FOUND("bad subnet %ssubnet=%s [%s] family=%s", leftright, value, er, family2str(family)); } /* set nexthop address to something consistent, by default */ anyaddr(family, &end->nexthop); anyaddr(addrtypeof(&end->addr), &end->nexthop); /* validate the KSCF_NEXTHOP */ if(end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if(strcasecmp(value, "%defaultroute")==0) { end->nexttype=KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_INET, &(end->nexthop)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->nexthop)) != NULL) { er = ttoaddr(value, 0, family, &(end->nexthop)); if (er) ERR_FOUND("bad addr %snexthop=%s [%s]", leftright, value, er); } end->nexttype = KH_IPADDR; } } else { if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } anyaddr(family, &end->nexthop); } /* validate the KSCF_ID */ if(end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); } if(end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch(end->rsakey1_type) { case PUBKEY_DNS: case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if(end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1"); } if(end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if(end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) { er = ttoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); } else { er = tnatoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if(!end->has_client) { starter_log(LOG_LEVEL_INFO, "defaulting %ssubnet to %s\n", leftright, value); er = addrtosubnet(&end->sourceip, &end->subnet); if (er) ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); end->has_client = TRUE; end->has_client_wildcard = FALSE; } } /* copy certificate path name */ if(end->strings_set[KSCF_CERT]) { end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); } if(end->strings_set[KSCF_CA]) { end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); } if(end->strings_set[KSCF_UPDOWN]) { end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); } if(end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) { conn_st->policy |= POLICY_XAUTH; } /* KSCF_SUBNETWITHIN --- not sure what to do with it. KSCF_ESPENCKEY --- todo (manual keying) KSCF_ESPAUTHKEY --- todo (manual keying) KSCF_SOURCEIP = 16, KSCF_MAX = 19 */ if(err) *perr = err_str; return err; # undef ERR_FOUND }