예제 #1
0
const char    *
val_get_ns_string(struct sockaddr *serv, char *dst, size_t size)
{
    struct sockaddr_in *sin;
#ifdef VAL_IPV6
    struct sockaddr_in6 *sin6;
#endif
    struct sockaddr_storage *server;
    const char *addr = NULL;

    if ((serv == NULL) || (dst == NULL))
        return NULL;

    server = (struct sockaddr_storage *) serv;

    switch (server->ss_family) {
    case AF_INET:
        sin = (struct sockaddr_in *) server;
        INET_NTOP(AF_INET, ((struct sockaddr *)sin), 
            sizeof(struct sockaddr_in), dst, size, addr);
        return addr;
#ifdef VAL_IPV6
    case AF_INET6:
        sin6 = (struct sockaddr_in6 *) server;
        INET_NTOP(AF_INET6, ((struct sockaddr *)sin6), 
            sizeof(struct sockaddr_in), dst, size, addr);
        return addr;
#endif
    }
    return NULL;
}
예제 #2
0
static int
SPF_i_match_ip6(SPF_server_t *spf_server,
			SPF_request_t *spf_request,
			SPF_mech_t *mech,
			struct in6_addr ipv6 )
{
	char		src_ip6_buf[ INET6_ADDRSTRLEN ];
	char		dst_ip6_buf[ INET6_ADDRSTRLEN ];

	struct in6_addr		src_ipv6;
	int				cidr, cidr_save, mask;
	int				i;
	int				match;

	if ( spf_request->client_ver != AF_INET6 )
		return FALSE;

	src_ipv6 = spf_request->ipv6;

	cidr = SPF_i_mech_cidr(spf_request, mech);
	if ( cidr == 0 )
		cidr = 128;
	cidr_save = cidr;

	match = TRUE;
	for( i = 0; i < array_elem( ipv6.s6_addr ) && match; i++ )
	{
		if ( cidr > 8 )
			mask = 0xff;
		else if ( cidr > 0 )
			mask = (0xff << (8 - cidr)) & 0xff;
		else
			break;
		cidr -= 8;

		match = (src_ipv6.s6_addr[i] & mask) == (ipv6.s6_addr[i] & mask);
	}

	if (spf_server->debug) {
		INET_NTOP(AF_INET6, &src_ipv6.s6_addr,
							src_ip6_buf, sizeof(src_ip6_buf));
		INET_NTOP(AF_INET6, &ipv6.s6_addr,
							dst_ip6_buf, sizeof(dst_ip6_buf));
		SPF_debugf( "ip_match:  %s == %s  (/%d):  %d",
				src_ip6_buf, dst_ip6_buf, cidr_save, match );
	}

	return match;
}
예제 #3
0
// #define addrfmt(x, s) x.fmt(s, sizeof(s))
cstr PackedSockAddr::fmt(str s, size_t len) const
{
	memset(s, 0, len);
	const byte family = get_family();
	str i;
	if (family == AF_INET) {
		INET_NTOP(family, (uint32*)&_sin4, s, len);
		i = s;
		while (*++i) {}
	} else {
		i = s;
		*i++ = '[';
		INET_NTOP(family, (in6_addr*)&_in._in6addr, i, len-1);
		while (*++i) {}
		*i++ = ']';
	}
	snprintf(i, len - (i-s), ":%u", _port);
	return s;
}
예제 #4
0
static int
SPF_i_match_ip4(SPF_server_t *spf_server,
			SPF_request_t *spf_request,
			SPF_mech_t *mech,
			struct in_addr ipv4 )
{
	char		src_ip4_buf[ INET_ADDRSTRLEN ];
	char		dst_ip4_buf[ INET_ADDRSTRLEN ];
	char		mask_ip4_buf[ INET_ADDRSTRLEN ];

	struct in_addr		src_ipv4;
	int				cidr, mask;


	if ( spf_request->client_ver != AF_INET )
		return FALSE;

	src_ipv4 = spf_request->ipv4;

	cidr = SPF_i_mech_cidr( spf_request, mech );
	if ( cidr == 0 )
		cidr = 32;
	mask = 0xffffffff << (32 - cidr);
	mask = htonl(mask);

	if (spf_server->debug) {
		INET_NTOP(AF_INET, &src_ipv4.s_addr,
						src_ip4_buf, sizeof(src_ip4_buf));
		INET_NTOP(AF_INET, &ipv4.s_addr,
						dst_ip4_buf, sizeof(dst_ip4_buf));
		INET_NTOP(AF_INET, &mask,
						mask_ip4_buf, sizeof(mask_ip4_buf));
		SPF_debugf( "ip_match:  %s == %s  (/%d %s):  %d",
				src_ip4_buf, dst_ip4_buf, cidr, mask_ip4_buf,
				(src_ipv4.s_addr & mask) == (ipv4.s_addr & mask));
	}

	return (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask);
}
예제 #5
0
static int add_multicast_group(SOCKET sock, const struct sockaddr *psa) {

#if defined(WIN32)

  LOG(X_ERROR("Multicast not implemented on this system type"));
  return -1;

#else

  if(psa->sa_family == AF_INET6) {
    LOG(X_ERROR("IPv6 multicast group addition not implemented"));
    return -1;
  }

  struct ip_mreq mcip;
  char tmp[128];

  memset(&mcip, 0, sizeof(mcip));

  mcip.imr_multiaddr.s_addr = ((const struct sockaddr_in *) psa)->sin_addr.s_addr;
  mcip.imr_interface.s_addr = INADDR_ANY;

  if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mcip, 
     sizeof(mcip)) < 0) {

    LOG(X_ERROR("Unable to add multicast membership for %s"), INET_NTOP(*psa, tmp, sizeof(tmp)));
    return -1;
  }

  LOG(X_DEBUG("Subscribed to multicast membership for %s"), INET_NTOP(*psa, tmp, sizeof(tmp)));

  return 0;

#endif // WIN32

}
예제 #6
0
int sdputil_init(SDP_DESCR_T *pSdp,
                 uint8_t payloadType,
                 unsigned int clockRateHz,
                 XC_CODEC_TYPE_T codecType,
                 const char *pDstHost,
                 uint16_t dstPort,
                 uint16_t dstPortRtcp,
                 const SRTP_CTXT_T *pSrtp,
                 const DTLS_CFG_T *pDtlsCfg,
                 const STUN_REQUESTOR_CFG_T *pStunCfg,
                 const SDP_CODEC_PARAM_T *pCodecSpecific,
                 const FRAME_RATE_T *pFps,
                 const VID_ENCODER_FBREQUEST_T *pFbReq) {

  int rc = 0;
  char tmp[128];
  struct sockaddr_storage connectip;

  if(!pSdp || payloadType > 0x7f || !pDstHost) {
    return -1;
  }

  memset(&connectip, 0, sizeof(connectip));
  if(!net_isipv4(pDstHost) && !net_isipv6(pDstHost)) {
    //
    // INADDR_NONE
    //
    pDstHost = "0.0.0.0";
  }

  net_getaddress(pDstHost, &connectip);
  if(INET_ADDR_VALID(connectip) && INET_IS_MULTICAST(connectip)) {
    pSdp->c.ttl = 64;
  } else if(INET_ADDR_VALID(connectip) && INET_ADDR_LOCALHOST(connectip)) {
    pSdp->c.ttl = 0;
  } else {
    //connectip.s_addr = net_getlocalip();

    //
    // For remote unicast destinations, leave the remote ip into the 'c=' field
    // which may be contrary to RFC4566
    //
    //connectip.s_addr = INADDR_ANY;

    pSdp->c.ttl = 0;
  }

  pSdp->c.ip_family = connectip.ss_family;
  strncpy(pSdp->c.iphost, INET_NTOP(connectip, tmp, sizeof(tmp)), sizeof(pSdp->c.iphost));

  //
  // Only write the RTCP port attribute in the SDP if using a non-default port
  //
  if(dstPortRtcp == RTCP_PORT_FROM_RTP(dstPort)) {
    dstPortRtcp = 0;   
  } 

  if(pFps && pFps->clockHz > 0 && pFps->frameDeltaHz > 0) {
    memcpy(&pSdp->vid.fps, pFps, sizeof(pSdp->vid.fps));
  }
  switch(codecType) {

    case XC_CODEC_TYPE_H264:
    case XC_CODEC_TYPE_MPEG4V:
    case XC_CODEC_TYPE_H263:
    case XC_CODEC_TYPE_H263_PLUS:
    case XC_CODEC_TYPE_VP8:
      pSdp->vid.common.available = 1;
      pSdp->vid.common.codecType = codecType;
      pSdp->vid.common.payloadType = payloadType;
      pSdp->vid.common.port = dstPort;
      pSdp->vid.common.portRtcp = dstPortRtcp;
      pSdp->vid.common.clockHz = clockRateHz;
      pSdp->vid.common.transType = SDP_TRANS_TYPE_RTP_UDP;

      if(pDtlsCfg) {
        if(pDtlsCfg->dtls_srtp) {
          pSdp->vid.common.transType = SDP_TRANS_TYPE_SRTP_DTLS_UDP;
        } else {
          pSdp->vid.common.transType = SDP_TRANS_TYPE_DTLS_UDP;
        }
        memcpy(&pSdp->vid.common.fingerprint, &pDtlsCfg->fingerprint, sizeof(pSdp->vid.common.fingerprint));
      }
      if(pSrtp) {
        pSdp->vid.common.transType =  SDP_TRANS_TYPE_SRTP_SDES_UDP;
        if((rc = sdputil_initsrtp(&pSdp->vid.common.srtp, pSrtp)) < 0) {
          return rc;
        }
      }
      if(pStunCfg && pStunCfg->bindingRequest) {
        if(pStunCfg->reqUsername) {
          strncpy(pSdp->vid.common.ice.ufrag, pStunCfg->reqUsername, STUN_STRING_MAX - 1);
        }
        if(pStunCfg->reqPass) {
          strncpy(pSdp->vid.common.ice.pwd, pStunCfg->reqPass, STUN_STRING_MAX - 1);
        }
      }
      
      if(codecType == XC_CODEC_TYPE_H264) {
        strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H264,
          sizeof(pSdp->vid.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_MPEG4V) {
        strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_MPEG4V,
          sizeof(pSdp->vid.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_H263) {
        strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H263,
          sizeof(pSdp->vid.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_H263_PLUS) {
        strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H263_PLUS,
          sizeof(pSdp->vid.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_VP8) {
        strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_VP8,
          sizeof(pSdp->vid.common.encodingName));
      }

      break;
    case XC_CODEC_TYPE_AAC:
    case XC_CODEC_TYPE_AMRNB:
    case XC_CODEC_TYPE_SILK:
    case XC_CODEC_TYPE_OPUS:
    case XC_CODEC_TYPE_G711_MULAW:
    case XC_CODEC_TYPE_G711_ALAW:
      pSdp->aud.common.available = 1;
      pSdp->aud.common.codecType = codecType;
      pSdp->aud.common.payloadType = payloadType;
      pSdp->aud.common.port = dstPort;
      pSdp->aud.common.portRtcp = dstPortRtcp;
      pSdp->aud.common.clockHz = clockRateHz;
      pSdp->aud.common.transType = SDP_TRANS_TYPE_RTP_UDP;

      if(pDtlsCfg) {
        if(pDtlsCfg->dtls_srtp) {
          pSdp->aud.common.transType = SDP_TRANS_TYPE_SRTP_DTLS_UDP;
        } else {
          pSdp->aud.common.transType = SDP_TRANS_TYPE_DTLS_UDP;
        }
        memcpy(&pSdp->aud.common.fingerprint, &pDtlsCfg->fingerprint, sizeof(pSdp->aud.common.fingerprint));
      }
      if(pSrtp) {
        pSdp->aud.common.transType =  SDP_TRANS_TYPE_SRTP_SDES_UDP;
        if((rc = sdputil_initsrtp(&pSdp->aud.common.srtp, pSrtp)) < 0) {
          return rc;
        }
      }

      if(pStunCfg && pStunCfg->bindingRequest) { 
        if(pStunCfg->reqUsername) {
          strncpy(pSdp->aud.common.ice.ufrag, pStunCfg->reqUsername, STUN_STRING_MAX - 1);
        }
        if(pStunCfg->reqPass) {
          strncpy(pSdp->aud.common.ice.pwd, pStunCfg->reqPass, STUN_STRING_MAX - 1);
        }
      }

      if(codecType == XC_CODEC_TYPE_AAC) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_AAC,
          sizeof(pSdp->aud.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_AMRNB) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_AMR,
          sizeof(pSdp->aud.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_SILK) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_SILK,
          sizeof(pSdp->aud.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_OPUS) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_OPUS,
          sizeof(pSdp->aud.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_G711_MULAW) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_PCMU,
          sizeof(pSdp->aud.common.encodingName));
      } else if(codecType == XC_CODEC_TYPE_G711_ALAW) {
        strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_PCMA,
          sizeof(pSdp->aud.common.encodingName));
      }

      break;
    case MEDIA_FILE_TYPE_MP2TS:
      pSdp->vid.common.available = 1;
      pSdp->vid.common.codecType = MEDIA_FILE_TYPE_MP2TS;
      pSdp->vid.common.payloadType = payloadType;
      pSdp->vid.common.port = dstPort;
      pSdp->vid.common.portRtcp = dstPortRtcp;
      pSdp->vid.common.clockHz = 90000;

      if(pSrtp) {
        pSdp->vid.common.transType =  SDP_TRANS_TYPE_SRTP_SDES_UDP;
        if((rc = sdputil_initsrtp(&pSdp->vid.common.srtp, pSrtp)) < 0) {
          return rc;
        }
      }

      strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_MP2TS,
          sizeof(pSdp->vid.common.encodingName));
      break;
    default:
      return -1;
  }
 
  //
  // Advertise any a=rtcp-fb:  SDP flags
  //
  if(pSdp->vid.common.available) {
   if(pFbReq && (pFbReq->firCfg.fir_send_from_decoder || pFbReq->firCfg.fir_send_from_local ||
                 pFbReq->firCfg.fir_send_from_remote || pFbReq->firCfg.fir_send_from_capture)) {
      pSdp->vid.common.rtcpfb.fmtidmin1 = pSdp->vid.common.payloadType + 1;
      pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_CCM | SDP_RTCPFB_TYPE_CCM_FIR;
    }
   if(pFbReq && pFbReq->nackRtpRetransmit) {
    pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_NACK | SDP_RTCPFB_TYPE_NACK_GENERIC;
   }
    //pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_TRRINT;
    //pSdp->vid.common.rtcpfb.trrIntervalMs |= 30;
  }

  //
  // Codec specific default settings
  //
  switch(codecType) {

    case XC_CODEC_TYPE_H264:

      if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_PKTZMODE)) {

        switch(pCodecSpecific->u.pktzMode) {
          case PKTZ_H264_MODE_0:
            pSdp->vid.u.h264.packetization_mode = 0;
            break;
          case PKTZ_H264_MODE_2:
            LOG(X_WARNING("H.264 NAL Packetization mode 2 not supported.  Using mode 1")); 
          case PKTZ_H264_MODE_1:
          case PKTZ_H264_MODE_NOTSET:
          default:
            pSdp->vid.u.h264.packetization_mode = 1;
            break;
       }

     }

     break;

    case XC_CODEC_TYPE_MPEG4V:

      pSdp->vid.u.mpg4v.profile_level_id = 1;
      break;

    case XC_CODEC_TYPE_VP8:
      break;

    case XC_CODEC_TYPE_AAC:
      strncpy(pSdp->aud.u.aac.mode, "AAC-hbr", sizeof(pSdp->aud.u.aac.mode));
      pSdp->aud.u.aac.sizelength = 13;
      pSdp->aud.u.aac.indexlength = 3;
      pSdp->aud.u.aac.indexdeltalength = 3;
      break;

    case XC_CODEC_TYPE_AMRNB:

      pSdp->aud.channels = 1;
      pSdp->aud.u.amr.octet_align = 1;

      break;

    case XC_CODEC_TYPE_SILK:

      if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_CHANNELS)) {
        pSdp->aud.channels = pCodecSpecific->u.channels;
      } else {
        pSdp->aud.channels = 1;
      }

      //pSdp->aud.u.silk.dummy = 0;

      break;

    case XC_CODEC_TYPE_OPUS:

      if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_CHANNELS)) {
        pSdp->aud.channels = pCodecSpecific->u.channels;;
      } else {
        pSdp->aud.channels = 1;
      }

      break;

    case XC_CODEC_TYPE_G711_MULAW:
    case XC_CODEC_TYPE_G711_ALAW:

      pSdp->aud.channels = 1;
      break;

    default:
      break;
  }

  return rc;
}
예제 #7
0
SPF_errcode_t
SPF_record_interpret(SPF_record_t *spf_record,
			SPF_request_t *spf_request, SPF_response_t *spf_response,
			int depth)
{
	SPF_server_t	*spf_server;

	/* Temporaries */
	int				 i, j;
	int				 m;			/* Mechanism iterator */
	SPF_mech_t		*mech;
	SPF_data_t		*data;
	SPF_data_t		*data_end;	/* XXX Replace with size_t data_len */

	/* Where to insert the local policy (whitelist) */
	SPF_mech_t		*local_policy;	/* Not the local policy */
	int				 found_all;		/* A crappy temporary. */

	char			*buf = NULL;
	size_t			 buf_len = 0;
	ns_type			 fetch_ns_type;
	const char		*lookup;

	SPF_dns_rr_t	*rr_a;
	SPF_dns_rr_t	*rr_aaaa;
	SPF_dns_rr_t	*rr_ptr;
	SPF_dns_rr_t	*rr_mx;

	SPF_errcode_t	 err;

	SPF_dns_server_t*resolver;

	/* An SPF record for subrequests - replaces c_results */
	SPF_record_t	*spf_record_subr;

	SPF_response_t	*save_spf_response;
	SPF_response_t	*spf_response_subr;
	const char		*save_cur_dom;

	struct in_addr	addr4;
	struct in6_addr addr6;

	int				max_ptr;
	int				max_mx;
	int				max_exceeded;

	char			 ip4_buf[ INET_ADDRSTRLEN ];
	char			 ip6_buf[ INET6_ADDRSTRLEN ];


	/*
	 * make sure we were passed valid data to work with
	 */
	SPF_ASSERT_NOTNULL(spf_record);
	SPF_ASSERT_NOTNULL(spf_request);
	SPF_ASSERT_NOTNULL(spf_response);
	spf_server = spf_record->spf_server;
	SPF_ASSERT_NOTNULL(spf_server);

	SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);

	if (depth > 20)
		return DONE_PERMERR(SPF_E_RECURSIVE);

	if ( spf_request->client_ver != AF_INET && spf_request->client_ver != AF_INET6 )
		return DONE_PERMERR(SPF_E_NOT_CONFIG);

	if (spf_request->cur_dom == NULL)
		return DONE_PERMERR(SPF_E_NOT_CONFIG);


	/*
	 * localhost always gets a free ride
	 */

#if 0
	/* This should have been done already before we got here. */
	if ( SPF_request_is_loopback( spf_request ) )
		return DONE(SPF_RESULT_PASS,SPF_REASON_LOCALHOST,SPF_E_SUCCESS);
#endif

	/*
	 * Do some start up stuff if we haven't recursed yet
	 */

	local_policy = NULL;

	if ( spf_request->use_local_policy ) {
		/*
		 * find the location for the whitelist execution
		 *
		 * Philip Gladstone says:
		 *
		 * I think that the localpolicy should only be inserted if the
		 * final mechanism is '-all', and it should be inserted after
		 * the last mechanism which is not '-'.
		 *
		 * Thus for the case of 'v=spf1 +a +mx -all', this would be
		 * interpreted as 'v=spf1 +a +mx +localpolicy -all'. Whereas
		 * 'v=spf1 -all' would remain the same (no non-'-'
		 * mechanism). 'v=spf1 +a +mx -exists:%stuff -all' would
		 * become 'v=spf1 +a +mx +localpolicy -exists:%stuff -all'.
		 */

		if ( spf_server->local_policy ) {
			mech = spf_record->mech_first;

			found_all = FALSE;
			for(m = 0; m < spf_record->num_mech; m++)
			{
				if ( mech->mech_type == MECH_ALL
					 && (mech->prefix_type == PREFIX_FAIL
						 || mech->prefix_type == PREFIX_UNKNOWN
						 || mech->prefix_type == PREFIX_SOFTFAIL
						 )
					)
					found_all = TRUE;

				if ( mech->prefix_type != PREFIX_FAIL
					 && mech->prefix_type != PREFIX_SOFTFAIL
					)
					local_policy = mech;

				mech = SPF_mech_next( mech );
			}

			if ( !found_all )
				local_policy = NULL;
		}

	}


	/*
	 * evaluate the mechanisms
	 */

#define SPF_ADD_DNS_MECH() do { spf_response->num_dns_mech++; } while(0)

#define SPF_MAYBE_SKIP_CIDR() \
	do { \
		if ( data < data_end && data->dc.parm_type == PARM_CIDR ) \
			data = SPF_data_next( data ); \
	} while(0)

#define SPF_GET_LOOKUP_DATA() \
	do {												\
		if ( data == data_end )							\
			lookup = spf_request->cur_dom;				\
		else {											\
			err = SPF_record_expand_data( spf_server,	\
							spf_request, spf_response,	\
							data, ((char *)data_end - (char *)data),	\
							&buf, &buf_len );			\
			if (err == SPF_E_NO_MEMORY) {				\
				SPF_FREE_LOOKUP_DATA();					\
				return DONE_TEMPERR(err);				\
			}											\
			if (err) {									\
				SPF_FREE_LOOKUP_DATA();					\
				return DONE_PERMERR(err);				\
			}											\
			lookup = buf;								\
		}												\
	} while(0)
#define SPF_FREE_LOOKUP_DATA() \
	do { if (buf != NULL) { free(buf); buf = NULL; } } while(0)


	resolver = spf_server->resolver;

	mech = spf_record->mech_first;
	for (m = 0; m < spf_record->num_mech; m++) {

		/* This is as good a place as any. */
		/* XXX Rip this out and put it into a macro which can go into inner loops. */
		if (spf_response->num_dns_mech > spf_server->max_dns_mech) {
			SPF_FREE_LOOKUP_DATA();
			return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
		}

		data = SPF_mech_data(mech);
		data_end = SPF_mech_end_data(mech);

		switch (mech->mech_type) {
		case MECH_A:
			SPF_ADD_DNS_MECH();
			SPF_MAYBE_SKIP_CIDR();
			SPF_GET_LOOKUP_DATA();

			if (spf_request->client_ver == AF_INET)
				fetch_ns_type = ns_t_a;
			else
				fetch_ns_type = ns_t_aaaa;

			rr_a = SPF_dns_lookup(resolver, lookup, fetch_ns_type, TRUE);

			if (spf_server->debug)
				SPF_debugf("found %d A records for %s  (herrno: %d)",
						rr_a->num_rr, lookup, rr_a->herrno);

			if (rr_a->herrno == TRY_AGAIN) {
				SPF_dns_rr_free(rr_a);
				SPF_FREE_LOOKUP_DATA();
				return DONE_TEMPERR(SPF_E_DNS_ERROR); /* REASON_MECH */
			}

			for (i = 0; i < rr_a->num_rr; i++) {
				/* XXX Should this be hoisted? */
				if (rr_a->rr_type != fetch_ns_type)
					continue;

				if (spf_request->client_ver == AF_INET) {
					if (SPF_i_match_ip4(spf_server, spf_request, mech, rr_a->rr[i]->a)) {
						SPF_dns_rr_free(rr_a);
						SPF_FREE_LOOKUP_DATA();
						return DONE_MECH(mech->prefix_type);
					}
				}
				else {
					if (SPF_i_match_ip6(spf_server, spf_request, mech, rr_a->rr[i]->aaaa)) {
						SPF_dns_rr_free(rr_a);
						SPF_FREE_LOOKUP_DATA();
						return DONE_MECH(mech->prefix_type);
					}
				}
			}

			SPF_dns_rr_free(rr_a);
			break;

		case MECH_MX:
			SPF_ADD_DNS_MECH();
			SPF_MAYBE_SKIP_CIDR();
			SPF_GET_LOOKUP_DATA();

			rr_mx = SPF_dns_lookup(resolver, lookup, ns_t_mx, TRUE);

			if (spf_server->debug)
				SPF_debugf("found %d MX records for %s  (herrno: %d)",
						rr_mx->num_rr, lookup, rr_mx->herrno);

			if (rr_mx->herrno == TRY_AGAIN) {
				SPF_dns_rr_free(rr_mx);
				SPF_FREE_LOOKUP_DATA();
				return DONE_TEMPERR(SPF_E_DNS_ERROR);
			}

			/* The maximum number of MX records we will inspect. */
			max_mx = rr_mx->num_rr;
			max_exceeded = 0;
			if (max_mx > spf_server->max_dns_mx) {
				max_exceeded = 1;
				max_mx = SPF_server_get_max_dns_mx(spf_server);
			}

			for (j = 0; j < max_mx; j++) {
				/* XXX Should this be hoisted? */
				if (rr_mx->rr_type != ns_t_mx)
					continue;

				if (spf_request->client_ver == AF_INET)
					fetch_ns_type = ns_t_a;
				else
					fetch_ns_type = ns_t_aaaa;

				rr_a = SPF_dns_lookup(resolver, rr_mx->rr[j]->mx,
									   fetch_ns_type, TRUE );

				if (spf_server->debug)
					SPF_debugf("%d: found %d A records for %s  (herrno: %d)",
							j, rr_a->num_rr, rr_mx->rr[j]->mx, rr_a->herrno);
				if (rr_a->herrno == TRY_AGAIN) {
					SPF_dns_rr_free(rr_mx);
					SPF_dns_rr_free(rr_a);
					SPF_FREE_LOOKUP_DATA();
					return DONE_TEMPERR(SPF_E_DNS_ERROR);
				}

				for (i = 0; i < rr_a->num_rr; i++) {
					/* XXX Should this be hoisted? */
					if (rr_a->rr_type != fetch_ns_type)
						continue;

					if (spf_request->client_ver == AF_INET) {
						if (SPF_i_match_ip4(spf_server, spf_request, mech,
										rr_a->rr[i]->a)) {
							SPF_dns_rr_free(rr_mx);
							SPF_dns_rr_free(rr_a);
							SPF_FREE_LOOKUP_DATA();
							return DONE(mech->prefix_type, SPF_REASON_MECH,
										 SPF_E_SUCCESS);
						}
					}
					else {
						if (SPF_i_match_ip6(spf_server, spf_request, mech,
										rr_a->rr[i]->aaaa)) {
							SPF_dns_rr_free(rr_mx);
							SPF_dns_rr_free(rr_a);
							SPF_FREE_LOOKUP_DATA();
							return DONE(mech->prefix_type, SPF_REASON_MECH,
										 SPF_E_SUCCESS);
						}
					}
				}
				SPF_dns_rr_free(rr_a);
			}

			SPF_dns_rr_free( rr_mx );
			if (max_exceeded) {
				SPF_FREE_LOOKUP_DATA();
				return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
			}
			break;

		case MECH_PTR:
			SPF_ADD_DNS_MECH();
			SPF_GET_LOOKUP_DATA();

			if (spf_request->client_ver == AF_INET) {
				rr_ptr = SPF_dns_rlookup(resolver,
								spf_request->ipv4, ns_t_ptr, TRUE);

				if (spf_server->debug) {
					INET_NTOP(AF_INET, &spf_request->ipv4.s_addr,
										ip4_buf, sizeof(ip4_buf));
					SPF_debugf("got %d PTR records for %s (herrno: %d)",
							rr_ptr->num_rr, ip4_buf, rr_ptr->herrno);
				}

				if (rr_ptr->herrno == TRY_AGAIN) {
					SPF_dns_rr_free(rr_ptr);
					SPF_FREE_LOOKUP_DATA();
					return DONE_TEMPERR(SPF_E_DNS_ERROR);
				}


				/* The maximum number of PTR records we will inspect. */
				max_ptr = rr_ptr->num_rr;
				max_exceeded = 0;
				if (max_ptr > spf_server->max_dns_ptr) {
					max_exceeded = 1;
					max_ptr = SPF_server_get_max_dns_ptr(spf_server);
				}

				for (i = 0; i < max_ptr; i++) {
					/* XXX MX has a 'continue' case here which should be hoisted. */

					rr_a = SPF_dns_lookup(resolver,
							rr_ptr->rr[i]->ptr, ns_t_a, TRUE);

					if (spf_server->debug)
						SPF_debugf( "%d:  found %d A records for %s  (herrno: %d)",
								i, rr_a->num_rr, rr_ptr->rr[i]->ptr, rr_a->herrno );
					if (rr_a->herrno == TRY_AGAIN) {
						SPF_dns_rr_free(rr_ptr);
						SPF_dns_rr_free(rr_a);
						SPF_FREE_LOOKUP_DATA();
						return DONE_TEMPERR( SPF_E_DNS_ERROR );
					}

					for (j = 0; j < rr_a->num_rr; j++) {
						/* XXX MX has a 'continue' case here which should be hoisted. */

						if (spf_server->debug) {
							INET_NTOP(AF_INET, &rr_a->rr[j]->a.s_addr,
											ip4_buf, sizeof(ip4_buf));
							SPF_debugf("%d: %d:  found %s",
									i, j, ip4_buf);
						}

						if (rr_a->rr[j]->a.s_addr ==
										spf_request->ipv4.s_addr) {
							if (SPF_i_match_domain(spf_server,
											rr_ptr->rr[i]->ptr, lookup)) {
								SPF_dns_rr_free(rr_ptr);
								SPF_dns_rr_free(rr_a);
								SPF_FREE_LOOKUP_DATA();
								return DONE_MECH(mech->prefix_type);
							}
						}
					}
					SPF_dns_rr_free(rr_a);
				}
				SPF_dns_rr_free(rr_ptr);

				if (max_exceeded) {
					SPF_FREE_LOOKUP_DATA();
					return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
				}
			}

			else if ( spf_request->client_ver == AF_INET6 ) {
				rr_ptr = SPF_dns_rlookup6(resolver,
								spf_request->ipv6, ns_t_ptr, TRUE);

				if ( spf_server->debug ) {
					INET_NTOP( AF_INET6, &spf_request->ipv6.s6_addr,
									   ip6_buf, sizeof( ip6_buf ) );
					SPF_debugf( "found %d PTR records for %s  (herrno: %d)",
							rr_ptr->num_rr, ip6_buf, rr_ptr->herrno );
				}
				if( rr_ptr->herrno == TRY_AGAIN ) {
					SPF_dns_rr_free(rr_ptr);
					SPF_FREE_LOOKUP_DATA();
					return DONE_TEMPERR( SPF_E_DNS_ERROR );
				}


				max_ptr = rr_ptr->num_rr;
				max_exceeded = 0;
				if (max_ptr > spf_server->max_dns_ptr) {
					max_ptr = SPF_server_get_max_dns_ptr(spf_server);
					max_exceeded = 1;
				}

				for (i = 0; i < max_ptr; i++) {
					/* XXX MX has a 'continue' case here which should be hoisted. */

					rr_aaaa = SPF_dns_lookup(resolver,
							rr_ptr->rr[i]->ptr, ns_t_aaaa, TRUE);

					if ( spf_server->debug )
						SPF_debugf("%d:  found %d AAAA records for %s  (herrno: %d)",
								i, rr_aaaa->num_rr, rr_ptr->rr[i]->ptr, rr_aaaa->herrno);
					if( rr_aaaa->herrno == TRY_AGAIN ) {
						SPF_dns_rr_free(rr_ptr);
						SPF_dns_rr_free(rr_aaaa);
						SPF_FREE_LOOKUP_DATA();
						return DONE_TEMPERR( SPF_E_DNS_ERROR );
					}

					for( j = 0; j < rr_aaaa->num_rr; j++ ) {
						/* XXX MX has a 'continue' case here which should be hoisted. */
						if ( spf_server->debug ) {
							INET_NTOP(AF_INET6, &rr_aaaa->rr[j]->aaaa.s6_addr,
											ip6_buf, sizeof(ip6_buf));
							SPF_debugf( "%d: %d:  found %s",
									i, j, ip6_buf );
						}

						if (memcmp(&rr_aaaa->rr[j]->aaaa,
								&spf_request->ipv6,
								sizeof(spf_request->ipv6)) == 0) {
							if (SPF_i_match_domain(spf_server,
											rr_ptr->rr[i]->ptr, lookup)) {
								SPF_dns_rr_free( rr_ptr );
								SPF_dns_rr_free(rr_aaaa);
								SPF_FREE_LOOKUP_DATA();
								return DONE_MECH( mech->prefix_type );
							}
						}
					}
					SPF_dns_rr_free(rr_aaaa);
				}
				SPF_dns_rr_free(rr_ptr);

				if (max_exceeded) {
					SPF_FREE_LOOKUP_DATA();
					return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
				}
			}


			break;

		case MECH_INCLUDE:
		case MECH_REDIRECT:
			SPF_ADD_DNS_MECH();

			err = SPF_record_expand_data(spf_server,
					spf_request, spf_response,
					SPF_mech_data(mech), SPF_mech_data_len(mech),
					&buf, &buf_len );
			if ( err == SPF_E_NO_MEMORY ) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_TEMPERR( err );
			}
			if ( err ) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_PERMERR( err );
			}
			lookup = buf;

			/* XXX Maintain a stack depth here. Limit at 10. */
			if (strcmp(lookup, spf_request->cur_dom) == 0) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_PERMERR( SPF_E_RECURSIVE );
			}

			/*
			 * get the (compiled) SPF record
			 */

			spf_record_subr = NULL;
			/* Remember to reset this. */
			save_cur_dom = spf_request->cur_dom;
			spf_request->cur_dom = lookup;
			err = SPF_server_get_record(spf_server, spf_request,
							spf_response, &spf_record_subr);

			if ( spf_server->debug > 0 )
				SPF_debugf( "include/redirect:  got SPF record:  %s",
						SPF_strerror( err ) );

			if (err != SPF_E_SUCCESS) {
				spf_request->cur_dom = save_cur_dom;
				if (spf_record_subr)
					SPF_record_free(spf_record_subr);
				SPF_FREE_LOOKUP_DATA();
				if (err == SPF_E_DNS_ERROR)
					return DONE_TEMPERR( err );
				else
					return DONE_PERMERR( err );
			}

			SPF_ASSERT_NOTNULL(spf_record_subr);

			/*
			 * If we are a redirect which is not within the scope
			 * of any include.
			 */
			if (mech->mech_type == MECH_REDIRECT) {
				save_spf_response = NULL;
				if (spf_response->spf_record_exp == spf_record)
					spf_response->spf_record_exp = spf_record_subr;
				SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
			}
			else {
				save_spf_response = spf_response;
				spf_response = SPF_response_new(spf_request);
				if (! spf_response) {
					if (spf_record_subr)
						SPF_record_free(spf_record_subr);
					SPF_FREE_LOOKUP_DATA();
					return DONE_TEMPERR(SPF_E_NO_MEMORY);
				}
				spf_response->spf_record_exp = spf_record;
				SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
			}
			/*
			 * find out whether this configuration passes
			 */
			err = SPF_record_interpret(spf_record_subr,
							spf_request, spf_response, depth + 1);
			spf_request->cur_dom = save_cur_dom;
			/* Now, if we were a redirect, the child called done()
			 * and used spf_record_exp. In that case, we need not
			 * worry that spf_record_subr is invalid after the free.
			 * If we were not a redirect, then spf_record_subr
			 * is still the record it was in the first place.
			 * Thus we do not need to reset it now. */
			SPF_record_free(spf_record_subr);
			spf_record_subr = NULL;

			if ( spf_server->debug > 0 )
				SPF_debugf( "include/redirect:  executed SPF record:  %s  result: %s  reason: %s",
						SPF_strerror( err ),
						SPF_strresult( spf_response->result ),
						SPF_strreason( spf_response->reason ) );
			if (mech->mech_type == MECH_REDIRECT) {
				SPF_FREE_LOOKUP_DATA();
				return err;	/* One way or the other */
			}
			else { // if (spf_response->result != SPF_RESULT_INVALID) {
				/* Set everything up properly again. */
				spf_response_subr = spf_response;
				spf_response = save_spf_response;
				save_spf_response = NULL;

				/* Rewrite according to prefix of include */
				switch (SPF_response_result(spf_response_subr)) {
					case SPF_RESULT_PASS:
						/* Pass */
						SPF_FREE_LOOKUP_DATA();
						SPF_response_free(spf_response_subr);
						return DONE_MECH( mech->prefix_type );

					case SPF_RESULT_FAIL:
					case SPF_RESULT_SOFTFAIL:
					case SPF_RESULT_NEUTRAL:
						/* No match */
						SPF_response_free(spf_response_subr);
						break;

					case SPF_RESULT_TEMPERROR:
						/* Generate TempError */
						err = SPF_response_errcode(spf_response_subr);
						SPF_FREE_LOOKUP_DATA();
						SPF_response_free(spf_response_subr);
						return DONE_TEMPERR( err );

					case SPF_RESULT_NONE:
						/* Generate PermError */
						SPF_FREE_LOOKUP_DATA();
						SPF_response_free(spf_response_subr);
						return DONE_PERMERR(SPF_E_INCLUDE_RETURNED_NONE);
					case SPF_RESULT_PERMERROR:
					case SPF_RESULT_INVALID:
						/* Generate PermError */
						err = SPF_response_errcode(spf_response_subr);
						SPF_FREE_LOOKUP_DATA();
						SPF_response_free(spf_response_subr);
						return DONE_PERMERR( err );

				}
#if 0
				SPF_FREE_LOOKUP_DATA();
				return err;	/* The sub-interpret called done() */
#endif
			}

			break;

		case MECH_IP4:
			memcpy(&addr4, SPF_mech_ip4_data(mech), sizeof(addr4));
			if ( SPF_i_match_ip4( spf_server, spf_request, mech, addr4 ) ) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_MECH( mech->prefix_type );
			}
			break;

		case MECH_IP6:
			memcpy(&addr6, SPF_mech_ip6_data(mech), sizeof(addr6));
			if ( SPF_i_match_ip6( spf_server, spf_request, mech, addr6 ) ) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_MECH( mech->prefix_type );
			}
			break;

		case MECH_EXISTS:
			SPF_ADD_DNS_MECH();

			err = SPF_record_expand_data(spf_server,
							spf_request, spf_response,
							SPF_mech_data(mech),SPF_mech_data_len(mech),
							&buf, &buf_len);
			if (err != SPF_E_SUCCESS) {
				SPF_FREE_LOOKUP_DATA();
				return DONE_TEMPERR( err );
			}
			lookup = buf;

			rr_a = SPF_dns_lookup(resolver, lookup, ns_t_a, FALSE );

			if ( spf_server->debug )
				SPF_debugf( "found %d A records for %s  (herrno: %d)",
						rr_a->num_rr, lookup, rr_a->herrno );

			if( rr_a->herrno == TRY_AGAIN ) {
				SPF_dns_rr_free(rr_a);
				SPF_FREE_LOOKUP_DATA();
				return DONE_TEMPERR(SPF_E_DNS_ERROR);
			}
			if ( rr_a->num_rr > 0 ) {
				SPF_dns_rr_free(rr_a);
				SPF_FREE_LOOKUP_DATA();
				return DONE_MECH(mech->prefix_type);
			}

			SPF_dns_rr_free(rr_a);
			break;

		case MECH_ALL:
			SPF_FREE_LOOKUP_DATA();
			if (mech->prefix_type == PREFIX_UNKNOWN)
				return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
			return DONE_MECH(mech->prefix_type);
			break;

		default:
			SPF_FREE_LOOKUP_DATA();
			return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
			break;
		}

		/*
		 * execute the local policy
		 */

		if ( mech == local_policy ) {
			err = SPF_record_interpret(spf_server->local_policy,
							spf_request, spf_response, depth + 1);

			if ( spf_server->debug > 0 )
				SPF_debugf( "local_policy:  executed SPF record:  %s  result: %s  reason: %s",
							SPF_strerror( err ),
							SPF_strresult( spf_response->result ),
							SPF_strreason( spf_response->reason ) );

			if (spf_response->result != SPF_RESULT_INVALID) {
				SPF_FREE_LOOKUP_DATA();
				return err;
			}
		}

		mech = SPF_mech_next( mech );
	}

	SPF_FREE_LOOKUP_DATA();
	/* falling off the end is the same as ?all */
	return DONE( SPF_RESULT_NEUTRAL, SPF_REASON_DEFAULT, SPF_E_SUCCESS );
}
예제 #8
0
파일: getaddr.c 프로젝트: mcr/dnssec-tools
static void
print_addrinfo(int type, void *ainfo)
{
    struct sockaddr_in *s_inaddr = NULL;
    struct sockaddr_in6 *s_in6addr = NULL;
    struct addrinfo *a = (struct addrinfo *) ainfo;
    char            buf[INET6_ADDRSTRLEN];
    size_t          buflen = INET6_ADDRSTRLEN;

    while (a != NULL) {
        printf("{\n");
        printf("\tFlags:     %d [", a->ai_flags);
        if (a->ai_flags & AI_PASSIVE)
            printf("AI_PASSIVE ");
        if (a->ai_flags & AI_CANONNAME)
            printf("AI_CANONNAME ");
        if (a->ai_flags & AI_NUMERICHOST)
            printf("AI_NUMERICHOST ");
#ifdef AI_V4MAPPED
        if (a->ai_flags & AI_V4MAPPED)
            printf("AI_V4MAPPED ");
#endif
#ifdef AI_ALL
        if (a->ai_flags & AI_ALL)
            printf("AI_ALL ");
#endif
#ifdef AI_ADDRCONFIG
        if (a->ai_flags & AI_ADDRCONFIG)
            printf("AI_ADDRCONFIG ");
#endif
        //              if (a->ai_flags & AI_NUMERICSERV) printf("AI_NUMERICSERV ");
        printf("]\n");
        printf("\tFamily:    %d [%s]\n", a->ai_family,
               (a->ai_family == AF_UNSPEC) ? "AF_UNSPEC" :
               (a->ai_family == AF_INET) ? "AF_INET" :
               (a->ai_family == AF_INET6) ? "AF_INET6" : "Unknown");
        printf("\tSockType:  %d [%s]\n", a->ai_socktype,
               (a->ai_socktype == SOCK_STREAM) ? "SOCK_STREAM" :
               (a->ai_socktype == SOCK_DGRAM) ? "SOCK_DGRAM" :
               (a->ai_socktype == SOCK_RAW) ? "SOCK_RAW" : "Unknown");
        printf("\tProtocol:  %d [%s]\n", a->ai_protocol,
               (a->ai_protocol == IPPROTO_IP) ? "IPPROTO_IP" :
               (a->ai_protocol == IPPROTO_TCP) ? "IPPROTO_TCP" :
               (a->ai_protocol == IPPROTO_UDP) ? "IPPROTO_UDP" :
               "Unknown");
        printf("\tAddrLen:   %d\n", a->ai_addrlen);

        if (a->ai_addr != NULL) {
            const char *addr = NULL;
            printf("\tAddrPtr:   %p\n", a->ai_addr);
            if (a->ai_family == AF_INET) {
                s_inaddr = (struct sockaddr_in *) (a->ai_addr);
                INET_NTOP(AF_INET, ((struct sockaddr *)s_inaddr), sizeof(s_inaddr),
                          buf, buflen, addr);
                printf("\tAddr:      %s\n", addr);
            } else if (a->ai_family == AF_INET6) {
                s_in6addr = (struct sockaddr_in6 *) (a->ai_addr);
                INET_NTOP(AF_INET6, ((struct sockaddr *)s_in6addr), sizeof(s_in6addr),
                          buf, buflen, addr);
                printf("\tAddr:      %s\n", addr);
            } else
                printf
                    ("\tAddr:      Cannot parse address. Unknown protocol family\n");
        } else
            printf("\tAddr:      (null)\n");

        if (a->ai_canonname)
            printf("\tCanonName: %s\n", a->ai_canonname);
        else
            printf("\tCanonName: (null)\n");

        printf("}\n");

        a = (struct addrinfo *) (a->ai_next);
    }
}
예제 #9
0
/*
 * Function: get_hostent_from_etc_hosts
 *
 * Purpose: Read the ETC_HOSTS file and check if it contains the given name.
 *          Return the result in a hostent structure.
 *
 * Parameters:
 *              ctx -- The validation context.
 *             name -- The domain name or IP address in string form.
 *               af -- The address family: AF_INET or AF_INET6.
 *              ret -- Pointer to a hostent structure to return the result.
 *                     This parameter must not be NULL.
 *              buf -- A buffer to store auxiliary data.  This parameter must not be NULL.
 *           buflen -- Length of the buffer 'buf'.
 *           offset -- Pointer to an integer variable that contains the offset in the buffer
 *                     'buf', where data can be written.  When this function writes any data
 *                     in the auxiliary data, the offset is incremented accordingly.  This
 *                     parameter must not be NULL.
 *
 * Return value: Returns NULL on failure and 'ret' on success.
 *
 * See also: get_hostent_from_response()
 */
static struct hostent *
get_hostent_from_etc_hosts(val_context_t * ctx,
                           const char *name,
                           int af,
                           struct hostent *ret,
                           char *buf, int buflen, int *offset)
{
    int             orig_offset = 0;
    struct hosts   *hs = NULL;
    struct hosts   *h_prev = NULL;

    if ((ret == NULL) || (buf == NULL) || (offset == NULL)
        || (*offset < 0)) {
        return NULL;
    }

    /*
     * Parse the /etc/hosts file 
     */
    hs = parse_etc_hosts(name);

    orig_offset = *offset;
    memset(ret, 0, sizeof(struct hostent));

    /*
     * XXX: todo -- can hs have more than one element ? 
     */
    while (hs) {
        struct sockaddr_in sa;
#if defined( WIN32 )
        size_t addrlen4 = sizeof(struct sockaddr_in);
#endif
#ifdef VAL_IPV6
        struct sockaddr_in6 sa6;
#if defined( WIN32 )
        size_t addrlen6 = sizeof(struct sockaddr_in6);
#endif
#endif
        char            addr_buf[INET6_ADDRSTRLEN];
        int             i, alias_count;
        int             len = 0;
        const char *addr = NULL;
        size_t buflen = INET6_ADDRSTRLEN;

        if ((af == AF_INET)
            && (INET_PTON(AF_INET, hs->address, ((struct sockaddr *)&sa), &addrlen4) > 0)) {
            INET_NTOP(AF_INET, (&sa), sizeof(sa), addr_buf, buflen, addr);
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv4");
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s",
                    addr
		);
        } 
#ifdef VAL_IPV6
	else if ((af == AF_INET6)
                   && (INET_PTON(AF_INET6, hs->address, ((struct sockaddr *)&sa6), &addrlen6) > 0)) {
	    
            INET_NTOP(AF_INET6, (&sa6), sizeof(sa6), addr_buf, buflen, addr);
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv6");
            val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s",
                    addr
                  );
        } 
#endif
	else {
            /*
             * not a valid address ... skip this line 
             */
            val_log(ctx, LOG_WARNING,
                    "get_hostent_from_etc_hosts(): error in address format: %s",
                    hs->address);
            h_prev = hs;
            hs = hs->next;
            FREE_HOSTS(h_prev);
            continue;
        }

        // Name
        len =
            (hs->canonical_hostname ==
             NULL) ? 0 : strlen(hs->canonical_hostname);

        if (hs->canonical_hostname) {
            ret->h_name = (char *) bufalloc(buf, buflen, offset, len + 1);
            if (ret->h_name == NULL) {
                goto err;
            }

            memcpy(ret->h_name, hs->canonical_hostname, len + 1);
        } else {
            ret->h_name = NULL;
        }

        // Aliases
        alias_count = 0;
        while (hs->aliases[alias_count]) {
            alias_count++;
        }
        alias_count++;

        ret->h_aliases =
            (char **) bufalloc(buf, buflen, offset,
                               alias_count * sizeof(char *));

        if (ret->h_aliases == NULL) {
            goto err;
        }

        for (i = 0; i < alias_count; i++) {
            len = (hs->aliases[i] == NULL) ? 0 : strlen(hs->aliases[i]);
            if (hs->aliases[i]) {
                ret->h_aliases[i] =
                    (char *) bufalloc(buf, buflen, offset, len + 1);
                if (ret->h_aliases[i] == NULL) {
                    goto err;
                }
                memcpy(ret->h_aliases[i], hs->aliases[i], len + 1);
            } else {
                ret->h_aliases[i] = NULL;
            }
        }

        // Addresses
        ret->h_addr_list =
            (char **) bufalloc(buf, buflen, offset, 2 * sizeof(char *));
        if ((ret->h_addr_list == NULL)
            || ((af != AF_INET) && (af != AF_INET6))) {
            goto err;
        }
        if (af == AF_INET) {
            ret->h_addrtype = AF_INET;
            ret->h_length = sizeof(struct in_addr);
            ret->h_addr_list[0] =
                (char *) bufalloc(buf, buflen, offset,
                                  sizeof(struct in_addr));
            if (ret->h_addr_list[0] == NULL) {
                goto err;
            }
            memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr));
            ret->h_addr_list[1] = 0;
        } 
#ifdef VAL_IPV6
        else if (af == AF_INET6) {
            ret->h_addrtype = AF_INET6;
            ret->h_length = sizeof(struct in6_addr);
            ret->h_addr_list[0] =
                (char *) bufalloc(buf, buflen, offset,
                                  sizeof(struct in6_addr));
            if (ret->h_addr_list[0] == NULL) {
                goto err;
            }
            memcpy(ret->h_addr_list[0], &sa6.sin6_addr,
                   sizeof(struct in6_addr));
            ret->h_addr_list[1] = 0;
        }
#endif

        /*
         * clean up host list 
         */
        while (hs) {
            h_prev = hs;
            hs = hs->next;
            FREE_HOSTS(h_prev);
        }
        return ret;
    }

    return NULL;

  err:
    /*
     * clean up host list 
     */
    while (hs) {
        h_prev = hs;
        hs = hs->next;
        FREE_HOSTS(h_prev);
    }

    *offset = orig_offset;
    return NULL;

}                               /* get_hostent_from_etc_hosts() */
예제 #10
0
int
main(int argc, char *argv[])
{
    const char     *allowed_args = "hl:x:p:o:sv:i:r:V";
    char           *node = NULL;
    int             retval;
    int             async = 1;
    val_log_t      *logp;
    char           *label_str = NULL;
    struct val_daneparams daneparams;
    struct val_danestatus *danestatus = NULL;
    struct val_ssl_data *ssl_dane_data = NULL;
    int port = 443;
    int proto = DANE_PARAM_PROTO_TCP;
    val_context_t *context = NULL;
    val_status_t val_status;
    struct addrinfo *val_ainfo = NULL;
    struct addrinfo hints;
    int ret = 0;
    int dane_retval = VAL_DANE_INTERNAL_ERROR;
    int ai_retval = 0;
    int err;

    /* Parse the command line */
    while (1) {
        int             c;
#ifdef HAVE_GETOPT_LONG
        int             opt_index = 0;
#ifdef HAVE_GETOPT_LONG_ONLY
        c = getopt_long_only(argc, argv, allowed_args,
                             prog_options, &opt_index);
#else
        c = getopt_long(argc, argv, allowed_args, prog_options, &opt_index);
#endif
#else                           /* only have getopt */
        c = getopt(argc, argv, allowed_args);
#endif

        if (c == -1) {
            break;
        }

        switch (c) {
        case 'h':
            usage(argv[0]);
            return -1;
        case 'l':
            label_str = optarg;
            break;
        case 'o':
            logp = val_log_add_optarg(optarg, 1);
            if (NULL == logp) { /* err msg already logged */
                usage(argv[0]);
                return -1;
            }
            break;

        case 's':
            async = 0;
            break;

        case 'p':
            port = atoi(optarg);
            break;

        case 'x':
            if(strncmp(optarg, DANE_PARAM_PROTO_STR_TCP,
                       strlen(DANE_PARAM_PROTO_STR_TCP)))
                proto = DANE_PARAM_PROTO_TCP;
            else if (strncmp(optarg, DANE_PARAM_PROTO_STR_UDP,
                        strlen(DANE_PARAM_PROTO_STR_UDP)))
                proto = DANE_PARAM_PROTO_UDP;
            else if (strncmp(optarg, DANE_PARAM_PROTO_STR_SCTP, 
                        strlen(DANE_PARAM_PROTO_STR_SCTP)))
                proto = DANE_PARAM_PROTO_SCTP;
            else {
                usage(argv[0]);
                return -1;
            }
            break;

        case 'v':
            dnsval_conf_set(optarg);
            break;

        case 'i':
            root_hints_set(optarg);
            break;

        case 'r':
            resolv_conf_set(optarg);
            break;

        case 'V':
            version();
            return 0;
        default:
            fprintf(stderr, "Invalid option %s\n", argv[optind - 1]);
            usage(argv[0]);
            return -1;
        }
    }

    if (optind < argc) {
        node = argv[optind++];
    } else {
        fprintf(stderr, "Error: node name not specified\n");
        usage(argv[0]);
        return -1;
    }

    if (VAL_NO_ERROR != (retval = 
                val_create_context(label_str, &context))) {
        fprintf(stderr, "Cannot create context %s(%d)\n", 
                p_val_error(retval), retval);
        return -1;
    }

    daneparams.port = port;
    daneparams.proto = proto;
    memset(&hints, 0, sizeof(struct addrinfo));
#ifdef AI_ADDRCONFIG
    hints.ai_flags = AI_ADDRCONFIG;
#endif

    if (!async) {
        /* synchronous lookup and validation */
        ai_retval = val_getaddrinfo(context, node, NULL, &hints,
                                    &val_ainfo, &val_status);
        dane_retval = val_getdaneinfo(context, node, &daneparams, &danestatus); 
    }
    else {
#ifdef VAL_NO_ASYNC
        fprintf(stderr, "async support not available\n");
#else
        struct dane_cb cb_data_dane = { &dane_retval, &danestatus, 0 };
        val_dane_callback my_dane_cb = &_danecallback;
        struct timeval tv;
        val_async_status *das = NULL; /* helps us cancel the lookup if we need to */

        struct getaddr_s cb_data_ai = { &ai_retval, &val_ainfo, &val_status, 0 };
        val_gai_callback my_ai_cb = &_aicallback;
        val_gai_status *status = NULL;

        /*
         * submit requests
         */
        if (VAL_NO_ERROR != val_dane_submit(context, node, &daneparams,
                                 my_dane_cb, &cb_data_dane, &das) ||
            VAL_NO_ERROR != val_getaddrinfo_submit(context, node, NULL,
                                &hints, my_ai_cb, &cb_data_ai, 0, &status)) {
            dane_retval = VAL_DANE_INTERNAL_ERROR; 
            goto done;
        }

        /*
         * wait for it to complete
         */
#if 0
        while(0 == cb_data_dane.done ||
              0 == cb_data_ai.done) {
            tv.tv_sec = 10;
            tv.tv_usec = 0;
            val_async_check_wait(context, NULL, NULL, &tv, 0);
        }
#endif

#if 1
        while(0 == cb_data_dane.done || 
              0 == cb_data_ai.done) {
            fd_set  activefds;
            int nfds = 0;
            int ready;

            FD_ZERO(&activefds);

            tv.tv_sec = 10; /* 10 sec */
            tv.tv_usec = 0;

            val_async_select_info(context, &activefds, &nfds, &tv);
            ready = select(nfds+1, &activefds, NULL, NULL, &tv);
            if (ready < 0) {
                continue;
            } 
            val_async_check(context, &activefds, &nfds, 0);
        }
#endif

#endif
    }

done:
    if (ai_retval != 0) {
        fprintf(stderr, "Error in val_getaddrinfo(): %d\n", ai_retval);
        return -1;
    }

    if (!val_istrusted(val_status)) {
        fprintf(stderr, 
                "Address lookup information could not be validated: %s\n", 
                p_val_status(val_status));

    } else if(dane_retval == VAL_DANE_NOERROR && 
              proto == DANE_PARAM_PROTO_TCP) {

        /* Set up the SSL connection */
        SSL_library_init();
        SSL_load_error_strings();

        const SSL_METHOD *meth = SSLv23_client_method();
        SSL_CTX *sslctx = SSL_CTX_new(meth);

        struct addrinfo *ai = NULL;
        int presetup_okay;

        /*
         * OpenSSL only does protocol negotiation on SSLv23_client_method;
         * we need to set SNI to get the correct certificate from many
         * modern browsers, so we disable both SSLv2 and SSLv3 if we can.
         * That leaves (currently) TLSv1.0 TLSv1.1 TLSv1.2
         */
        long ssl_options = 0
#ifdef SSL_OP_NO_SSLv2
            | SSL_OP_NO_SSLv2
#endif
#ifdef SSL_OP_NO_SSLv3
            | SSL_OP_NO_SSLv3
#endif
            ;

        if (!SSL_CTX_set_options(sslctx, ssl_options)) {
            fprintf(stderr, "Failed to set SSL context options (%ld): %s\n",
              ssl_options, ssl_error());
            presetup_okay = 0;
        } else {
            presetup_okay = 1;
        }

        if (VAL_NO_ERROR != (err = val_enable_dane_ssl(context, sslctx, node,
                                        danestatus, &ssl_dane_data))) {
            fprintf(stderr,
                    "Could not set danestatus for SSL connection %s\n",
                    p_val_error(err));
        }

        ai = val_ainfo;
        while(presetup_okay && ai && (ai->ai_protocol == IPPROTO_TCP) && 
             (ai->ai_family == AF_INET || ai->ai_family == AF_INET6)) {

            int sock;
            char buf[INET6_ADDRSTRLEN];
            size_t buflen = sizeof(buf);
            const char *addr = NULL;

            if (ai->ai_family == AF_INET) {
                sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = htons(port);
            } else {
                sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
                ((struct sockaddr_in6 *)(ai)->ai_addr)->sin6_port = htons(port);
            }

            INET_NTOP(ai->ai_family, ai->ai_addr, sizeof(ai->ai_addr), buf, buflen, addr);
            fprintf(stderr, "Connecting to %s\n", addr);

            if (0 == connect(sock, ai->ai_addr, ai->ai_addrlen)) {
                SSL *ssl = SSL_new(sslctx);
                BIO * sbio = BIO_new_socket(sock,BIO_NOCLOSE);


#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
                SSL_set_tlsext_host_name(ssl, node);
#endif

                SSL_set_bio(ssl,sbio,sbio);

                if ((err = SSL_connect(ssl)) != 1) {
                    fprintf(stderr, "SSL Connect to %s failed: %d\n", node, err);
                } 
                SSL_shutdown(ssl);
                SSL_free(ssl);
            } else {
                fprintf(stderr, "TCP Connect to %s failed\n", node);
            }

            ai = (struct addrinfo *) (ai->ai_next);
        }

    } else if (dane_retval == VAL_DANE_IGNORE_TLSA) {
        fprintf(stderr, "TLSA is either provably non-existant or provably insecure. It will be ignored.\n");
    } else {
        fprintf(stderr, "TLSA record could not be validated.\n");
        ret = 1;
    }

    if (danestatus != NULL)
        val_free_dane(danestatus);

    if (val_ainfo != NULL)
        val_freeaddrinfo(val_ainfo);    

    val_free_dane_ssl(ssl_dane_data);/* MUST happen before we free the context*/
    val_free_context(context);
    val_free_validator_state();

    return ret;
}