Пример #1
0
static struct keychain *keychain_get(const char *name)
{
	struct keychain *keychain;

	keychain = keychain_lookup(name);

	if (keychain)
		return keychain;

	keychain = keychain_new();
	keychain->name = XSTRDUP(MTYPE_KEYCHAIN, name);
	keychain->key = list_new();
	keychain->key->cmp = (int (*)(void *, void *))key_cmp_func;
	keychain->key->del = (void (*)(void *))key_delete_func;
	listnode_add(keychain_list, keychain);

	return keychain;
}
Пример #2
0
/* RIP-2 simple password authentication. */
static int
rip_auth_check_password (struct rip_interface *ri, struct rip_auth_rte *auth)
{
  if (ri->auth_str)
  {
    u_int8_t padded_simple_password[RIP_AUTH_SIMPLE_SIZE] = { 0 };

    memcpy (padded_simple_password, ri->auth_str, MIN (RIP_AUTH_SIMPLE_SIZE, strlen (ri->auth_str)));
    if (! memcmp (auth->u.password, padded_simple_password, RIP_AUTH_SIMPLE_SIZE))
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("interface authentication string is configured and matches");
      return 1;
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("interface authentication string is configured, but does not match");
  }
  if (ri->key_chain)
  {
    struct keychain *keychain;
    struct key *key;

    keychain = keychain_lookup (ri->key_chain);
    if (keychain == NULL)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("key chain '%s' is configured, but does not exist", ri->key_chain);
      return 0;
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("trying configured key chain '%s'", ri->key_chain);

    key = key_match_for_accept (keychain, auth->u.password);
    if (key)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("key %u matched the packet", key->index);
      return 1;
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("no key matched the packet");
  }
  return 0;
}
Пример #3
0
/*
Check hash authentication. Assume the packet has passed rip_packet_examin()
and rip_auth_check_packet(), which implies:
1. Authentication header is the first RTE and filled in correctly.
2. Authentication trailer is present and within the buffer.
*/
static int
rip_auth_check_hash (struct rip_interface *ri, struct in_addr *from, struct rip_packet *packet)
{
  struct rip_auth_rte *hi, *hd;
  struct keychain *keychain;
  struct key *key;
  u_char received_digest[RIP_AUTH_MAX_SIZE], local_digest[RIP_AUTH_MAX_SIZE];
  u_int16_t packet_len;
  char *auth_str = NULL;
  u_int8_t local_dlen, remote_dlen;
  unsigned hash_error;
  u_int32_t peer_prev_seqno, peer_cur_seqno;

  /* setup header and trailer */
  hi = (struct rip_auth_rte *) &packet->rte;
  packet_len = ntohs (hi->u.hash_info.packet_len);
  hd = (struct rip_auth_rte *) (((caddr_t) packet) + packet_len);
  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("declared main body length is %u", packet_len);

  /* check authentication data size */
  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("interface configured for %s", LOOKUP (hash_algo_str, ri->hash_algo));
  remote_dlen = hi->u.hash_info.auth_len;
  local_dlen = hash_digest_length[ri->hash_algo];
  if
  (
    local_dlen != remote_dlen && /* basic RFC constraint */
    /* non-RFC MD5 special exception */
    (ri->hash_algo != HASH_KEYED_MD5 || remote_dlen != RIP_AUTH_MD5_COMPAT_SIZE)
  )
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("authentication data length mismatch: local %u, remote %u", local_dlen, remote_dlen);
    return 0;
  }

  /* check sequence number */
  peer_prev_seqno = rip_peer_getseqno (from);
  peer_cur_seqno = ntohl (hi->u.hash_info.sequence);
  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("crypto sequence number for %s was %u, now %u",
      inet_ntoa (*from), peer_prev_seqno, peer_cur_seqno);
  if (peer_cur_seqno < peer_prev_seqno)
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("crypto sequence number check failed");
    return 0;
  }

  /* pick local key */
  if (ri->key_chain)
  {
    if ((keychain = keychain_lookup (ri->key_chain)) == NULL)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("key chain '%s' is configured, but does not exist", ri->key_chain);
      return 0;
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("trying configured key chain '%s'", ri->key_chain);
    if ((key = key_lookup_for_accept (keychain, hi->u.hash_info.key_id)) == NULL)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("key %u lookup failed", hi->u.hash_info.key_id);
      return 0;
    }
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("using keychain '%s', key %u for receiving", ri->key_chain, key->index);
    auth_str = key->string;
  }
  else if (ri->auth_str)
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("using interface authentication string");
    auth_str = ri->auth_str;
  }
  if (auth_str == NULL)
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("authentication string lookup failed");
    return 0;
  }

  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("key is ready, calculating hash digest value %uB long", local_dlen);
  /* set aside, calculate and compare */
  memcpy (received_digest, hd->u.hash_digest, local_dlen);
  switch (ri->hash_algo)
  {
  case HASH_KEYED_MD5:
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("%s: %uB of input buffer, %zuB of key", __func__, packet_len + RIP_HEADER_SIZE, strlen (auth_str));
    hash_error = hash_make_keyed_md5 ((caddr_t) packet, packet_len + RIP_HEADER_SIZE, auth_str, strlen (auth_str), local_digest);
    break;
#ifdef HAVE_LIBGCRYPT
  case HASH_HMAC_SHA1:
  case HASH_HMAC_SHA256:
  case HASH_HMAC_SHA384:
  case HASH_HMAC_SHA512:
    {
      u_int8_t compr_auth_str[RIP_AUTH_MAX_SIZE];
      size_t compr_authlen;

      hash_key_compress_rfc4822 (ri->hash_algo, auth_str, strlen (auth_str), compr_auth_str, &compr_authlen);
      /* RFC4822 2.5: Fill Apad, process whole packet with HMAC rounds. */
      memcpy (hd->u.hash_digest, hash_apad_sha512, local_dlen);
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("%s: %uB of input buffer, %zuB of key (%zuB compressed)", __func__,
          packet_len + 4 + local_dlen, strlen (auth_str), compr_authlen);
      hash_error = hash_make_hmac (ri->hash_algo, packet,
        packet_len + 4 + local_dlen, compr_auth_str, compr_authlen, local_digest);
      memcpy (hd->u.hash_digest, received_digest, local_dlen);
      break;
    }
#endif /* HAVE_LIBGCRYPT */
  default:
    assert (0);
  }
  if (hash_error)
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("hash function returned error %u", hash_error);
    return 0;
  }

  if (memcmp (local_digest, received_digest, local_dlen))
    return 0;
  if (peer_cur_seqno > peer_prev_seqno)
  {
    if (IS_RIP_DEBUG_AUTH)
      zlog_debug ("updating crypto sequence number for %s from %u to %u",
        inet_ntoa (*from), peer_prev_seqno, peer_cur_seqno);
    rip_peer_setseqno (from, peer_cur_seqno);
  }
  return packet_len;
}
Пример #4
0
/* Take a sequence of payload (routing) RTE structures, decide on particular
 * authentication required for the given interface and build a complete RIP
 * packet in a stream structure. The packet will consist of header, optional
 * heading RTE, the payload RTEs and optional trailing data. Return the stream.
 */
int
rip_auth_make_packet
(
  struct rip_interface * ri,
  struct stream * packet,
  struct stream * rtes,
  const u_int8_t version,
  const u_int8_t command
)
{
  struct key *key = NULL;
  char *auth_str = NULL;

  if (IS_RIP_DEBUG_AUTH)
    zlog_debug ("interface auth type is '%s', inet RTEs payload size is %zuB",
      LOOKUP (rip_ffff_type_str, ri->auth_type), stream_get_endp (rtes));

  /* packet header, unconditional */
  stream_reset (packet);
  stream_putc (packet, command);
  stream_putc (packet, version);
  stream_putw (packet, 0);

  /* authentication leading RTE, conditional */
  if (version == RIPv2 && ri->auth_type != RIP_NO_AUTH)
  {
    if (ri->key_chain)
    {
      struct keychain *keychain;

      keychain = keychain_lookup (ri->key_chain);
      if (keychain)
      {
        if (IS_RIP_DEBUG_AUTH)
          zlog_debug ("trying configured key chain '%s'", ri->key_chain);
        key = key_lookup_for_send (keychain);
      }
      else
      {
        if (IS_RIP_DEBUG_AUTH)
          zlog_debug ("key chain '%s' is configured, but does not exist", ri->key_chain);
      }
    }
    /* Pick correct auth string for sends, prepare auth_str buffer for use.
     * (left justified and padded).
     *
     * presumes one of ri or key is valid, and that the auth strings they point
     * to are nul terminated. If neither are present, auth_str will be fully
     * zero padded.
     *
     */
    if (key && key->string)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("using keychain '%s', key %u for sending", ri->key_chain, key->index);
      auth_str = key->string;
    }
    else if (ri->auth_str)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("using interface authentication string");
      auth_str = ri->auth_str;
    }
    if (auth_str == NULL)
    {
      if (IS_RIP_DEBUG_AUTH)
        zlog_debug ("authentication string lookup failed");
      return -1;
    }

    rip_auth_write_leading_rte (packet, ri, key ? key->index % 256 : 1, auth_str,
      RIP_HEADER_SIZE + RIP_RTE_SIZE + stream_get_endp (rtes));
  }

  /* RTEs payload, unconditional */
  if (stream_get_endp (rtes) % RIP_RTE_SIZE)
  {
    zlog_err ("%s: malformed input RTE buffer", __func__);
    return -1;
  }
  stream_write (packet, STREAM_DATA (rtes), stream_get_endp (rtes));
  stream_reset (rtes);

  /* authentication trailing data, even more conditional */
  if (version == RIPv2 && ri->auth_type == RIP_AUTH_HASH)
    rip_auth_write_trailer (packet, ri, auth_str);

  return 0;
}