示例#1
0
/*
 * As "the server", this ends REQ/REPLY mode.
 * As "the client", this ends SET/ACK mode.
 */
static int
cfg_responder_send_ATTR(struct message *msg)
{
	struct ipsec_exch *ie = msg->exchange->data;
	struct sa      *isakmp_sa = msg->isakmp_sa;
	u_int8_t       *hashp = 0, *attrp;
	u_int16_t       attrlen;
	char           *id_string;

	if (msg->exchange->phase == 2) {
		hashp = cfg_add_hash(msg);
		if (!hashp)
			return -1;
	}
	/* We are responder, check isakmp_sa for other side.  */
	if (isakmp_sa->initiator ^ (ie->cfg_type == ISAKMP_CFG_REQUEST))
		id_string = ipsec_id_string(isakmp_sa->id_i,
		    isakmp_sa->id_i_len);
	else
		id_string = ipsec_id_string(isakmp_sa->id_r,
		    isakmp_sa->id_r_len);
	if (!id_string) {
		log_print("cfg_responder_send_ATTR: cannot parse client's ID");
		return -1;
	}
	if (cfg_encode_attributes(&ie->attrs, (ie->cfg_type == ISAKMP_CFG_SET ?
	    ISAKMP_CFG_ACK : ISAKMP_CFG_REPLY), ie->cfg_id, id_string, &attrp,
	    &attrlen)) {
		free(id_string);
		return -1;
	}
	free(id_string);

	if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen,
	    1)) {
		free(attrp);
		return -1;
	}
	if (msg->exchange->phase == 2)
		if (cfg_finalize_hash(msg, hashp, attrp, attrlen))
			return -1;

	return 0;
}
示例#2
0
/*
 * 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;
}
示例#3
0
文件: ike_auth.c 项目: ebichu/dd-wrt
static int
get_raw_key_from_file (int type, u_int8_t *id, size_t id_len, RSA **rsa)
{
  char filename[FILENAME_MAX];
  char *fstr;
  struct stat st;
  BIO *bio;

  if (type != IKE_AUTH_RSA_SIG) /* XXX More types? */
    {
      LOG_DBG ((LOG_NEGOTIATION, 20, "get_raw_key_from_file: "
		"invalid auth type %d\n", type));
      return -1;
    }

  *rsa = 0;

  fstr = conf_get_str ("General", "Pubkey-directory");
  if (!fstr)
    fstr = CONF_DFLT_PUBKEY_DIR;

  if (snprintf (filename, sizeof filename, "%s/", fstr) > sizeof filename - 1)
    return -1;

  fstr = ipsec_id_string (id, id_len);
  if (!fstr)
    {
      LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: "
		"ipsec_id_string failed"));
      return -1;
    }
  strlcat (filename, fstr, sizeof filename - strlen (filename));
  free (fstr);

  /* If the file does not exist, fail silently.  */
  if (stat (filename, &st) == 0)
    {
      bio = BIO_new (BIO_s_file ());
      if (!bio)
	{
	  log_error ("get_raw_key_from_file: could not initialize BIO");
	  return -1;
	}
      if (BIO_read_filename (bio, filename) <= 0)
	{
	  LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: "
		    "BIO_read_filename(bio, \"%s\") failed", filename));
	  BIO_free (bio);
	  return -1;
	}
      LOG_DBG ((LOG_NEGOTIATION, 80, "get_raw_key_from_file: reading file %s",
		filename));
      *rsa = PEM_read_bio_RSA_PUBKEY (bio, NULL, NULL, NULL);
      BIO_free (bio);
    }
  else
    LOG_DBG ((LOG_NEGOTIATION, 50, "get_raw_key_from_file: file %s not found",
	      filename));

  return (*rsa ? 0 : -1);
}