コード例 #1
0
ファイル: ipsec_doi.c プロジェクト: fatenever/libreswan
/* accept_KE
 *
 * Check and accept DH public value (Gi or Gr) from peer's message.
 * According to RFC2409 "The Internet key exchange (IKE)" 5:
 *  The Diffie-Hellman public value passed in a KE payload, in either
 *  a phase 1 or phase 2 exchange, MUST be the length of the negotiated
 *  Diffie-Hellman group enforced, if necessary, by pre-pending the
 *  value with zeros.
 */
notification_t accept_KE(chunk_t *dest, const char *val_name,
			 const struct oakley_group_desc *gr,
			 pb_stream *pbs)
{
	if (pbs_left(pbs) != gr->bytes) {
		loglog(RC_LOG_SERIOUS,
		       "KE has %u byte DH public value; %u required",
		       (unsigned) pbs_left(pbs), (unsigned) gr->bytes);
		/* XXX Could send notification back */
		return INVALID_KEY_INFORMATION;
	}
	clonereplacechunk(*dest, pbs->cur, pbs_left(pbs), val_name);
	DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest);
	return NOTHING_WRONG;
}
コード例 #2
0
ファイル: ikev2_nss.c プロジェクト: 1309578252/Openswan
/*
 * replaces try_RSA_signature_v2()
 */
err_t
try_RSA_signature_v2(const u_char hash_val[MAX_DIGEST_LEN]
		     , size_t hash_len
		     , const pb_stream *sig_pbs, struct pubkey *kr
		     , struct state *st)
{
    const u_char *sig_val = sig_pbs->cur;
    size_t sig_len = pbs_left(sig_pbs);
    const struct RSA_public_key *k = &kr->u.rsa;

    if (k == NULL)
	return "1""no key available";	/* failure: no key to use */

    /* decrypt the signature -- reversing RSA_sign_hash */
    if (sig_len != k->k)
    {
	return "1""SIG length does not match public key length";
    }

    err_t ugh = RSA_signature_verify_nss (k,hash_val,hash_len,sig_val,sig_len);
    if(ugh!=NULL) {
	return ugh;
    }

    unreference_key(&st->st_peer_pubkey);
    st->st_peer_pubkey = reference_key(kr);

    return NULL;
}
コード例 #3
0
ファイル: x509keys.c プロジェクト: st3fan/libreswan
void
ikev2_decode_cert(struct msg_digest *md)
{
    struct payload_digest *p;

    for (p = md->chain[ISAKMP_NEXT_v2CERT]; p != NULL; p = p->next)
    {
	struct ikev2_cert *const v2cert = &p->payload.v2cert;
	chunk_t blob;
	time_t valid_until;
	blob.ptr = p->pbs.cur;
	blob.len = pbs_left(&p->pbs);
	if (v2cert->isac_enc == CERT_X509_SIGNATURE)
	{
	    x509cert_t cert2 = empty_x509cert;
	    if (parse_x509cert(blob, 0, &cert2))
	    {
		if (verify_x509cert(&cert2, strict_crl_policy, &valid_until))
		{
		    DBG(DBG_X509 | DBG_PARSING,
			DBG_log("Public key validated")
		    )
			add_x509_public_key(NULL, &cert2, valid_until, DAL_SIGNED);
		}
		else
		{
		    plog("X.509 certificate rejected");
		}
		free_generalNames(cert2.subjectAltName, FALSE);
		free_generalNames(cert2.crlDistributionPoints, FALSE);
	    }
	    else
		plog("Syntax error in X.509 certificate");
	}
	else if (v2cert->isac_enc == CERT_PKCS7_WRAPPED_X509)
	{
	    x509cert_t *cert2 = NULL;

	    if (parse_pkcs7_cert(blob, &cert2))
		store_x509certs(&cert2, strict_crl_policy);
	    else
		plog("Syntax error in PKCS#7 wrapped X.509 certificates");
	}
	else
	{
	    loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload",
		   enum_show(&ikev2_cert_type_names, v2cert->isac_enc));
	    DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob);
	}
    }
}
コード例 #4
0
ファイル: ipsec_doi.c プロジェクト: 1309578252/Openswan
notification_t
accept_nonce(struct msg_digest *md, chunk_t *dest
	     , const char *name, enum next_payload_types paynum)
{
    pb_stream *nonce_pbs = &md->chain[paynum]->pbs;
    size_t len = pbs_left(nonce_pbs);

    if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)
    {
	loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
	    , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
	return PAYLOAD_MALFORMED;	/* ??? */
    }
    clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce");
    return NOTHING_WRONG;
}
コード例 #5
0
ファイル: x509keys.c プロジェクト: st3fan/libreswan
/*
 * Decode the CR payload of Phase 1.
 */
void
decode_cr(struct msg_digest *md, generalName_t **requested_ca)
{
    struct payload_digest *p;

    for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next)
    {
	struct isakmp_cr *const cr = &p->payload.cr;
	chunk_t ca_name;
	
	ca_name.len = pbs_left(&p->pbs);
	ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL;

	DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name);

	if (cr->isacr_type == CERT_X509_SIGNATURE)
	{

	    if (ca_name.len > 0)
	    {
		generalName_t *gn;
		
		if (!is_asn1(ca_name))
		    continue;

		gn = alloc_thing(generalName_t, "generalName");
		clonetochunk(ca_name, ca_name.ptr,ca_name.len, "ca name");
		gn->kind = GN_DIRECTORY_NAME;
		gn->name = ca_name;
		gn->next = *requested_ca;
		*requested_ca = gn;
	    }

	    DBG(DBG_PARSING | DBG_CONTROL,
		char buf[IDTOA_BUF];
		dntoa_or_null(buf, IDTOA_BUF, ca_name, "%any");
		DBG_log("requested CA: '%s'", buf);
	    )
	}
	else
	    loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload",
		   enum_show(&cert_type_names, cr->isacr_type));
    }
コード例 #6
0
ファイル: packet.c プロジェクト: Biamp-Systems/mb-linux
bool
in_raw(void *bytes, size_t len, pb_stream *ins, const char *name)
{
    if (pbs_left(ins) < len)
    {
	loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name);
	return FALSE;
    }
    else
    {
	if (bytes == NULL)
	{
	    DBG(DBG_PARSING
		, DBG_log("skipping %u raw bytes of %s (%s)"
		    , (unsigned) len, ins->name, name);
		  DBG_dump(name, ins->cur, len));
	}
	else
	{
コード例 #7
0
ファイル: ikev2_ppk.c プロジェクト: libreswan/libreswan
/*
 * used by responder, for extracting PPK_ID from IKEv2 Notify
 * PPK_ID Payload, we store PPK_ID and its type in payl
 */
bool extract_ppk_id(pb_stream *pbs, struct ppk_id_payload *payl)
{
	size_t len = pbs_left(pbs);
	u_char dst[PPK_ID_MAXLEN];
	int idtype;

	if (len > PPK_ID_MAXLEN) {
		loglog(RC_LOG_SERIOUS, "PPK ID length is too big");
		return FALSE;
	}
	if (len <= 1) {
		loglog(RC_LOG_SERIOUS, "PPK ID data must be at least 1 byte (received %zd bytes including ppk type byte)",
			len);
		return FALSE;
	}

	if (!in_raw(dst, len, pbs, "Unified PPK_ID Payload")) {
		loglog(RC_LOG_SERIOUS, "PPK ID data could not be read");
		return FALSE;
	}

	DBG(DBG_CONTROL, DBG_log("received PPK_ID type: %s",
		enum_name(&ikev2_ppk_id_type_names, dst[0])));

	idtype = (int)dst[0];
	switch (idtype) {
	case PPK_ID_FIXED:
		DBG(DBG_CONTROL, DBG_log("PPK_ID of type PPK_ID_FIXED."));
		break;

	case PPK_ID_OPAQUE:
	default:
		loglog(RC_LOG_SERIOUS, "PPK_ID type %d (%s) not supported",
			idtype, enum_name(&ikev2_ppk_id_type_names, idtype));
		return FALSE;
	}

	/* clone ppk id data without ppk id type byte */
	clonetochunk(payl->ppk_id, dst + 1, len - 1, "PPK_ID data");
	DBG(DBG_CONTROL, DBG_dump_chunk("Extracted PPK_ID", payl->ppk_id));

	return TRUE;
}
コード例 #8
0
ファイル: ikev2_psk.c プロジェクト: fatenever/libreswan
stf_status ikev2_verify_psk_auth(struct state *st,
				 enum original_role role,
				 unsigned char *idhash,
				 pb_stream *sig_pbs)
{
	unsigned int hash_len =  st->st_oakley.prf_hasher->hash_digest_len;
	unsigned char calc_hash[hash_len];
	size_t sig_len = pbs_left(sig_pbs);

	enum original_role invertrole;

	invertrole = (role == ORIGINAL_INITIATOR ? ORIGINAL_RESPONDER : ORIGINAL_INITIATOR);

	if (sig_len != hash_len) {
		libreswan_log("negotiated prf: %s ",
			      st->st_oakley.prf_hasher->common.name);
		libreswan_log(
			"I2 hash length:%lu does not match with PRF hash len %lu",
			(long unsigned) sig_len,
			(long unsigned) hash_len);
		return STF_FAIL;
	}

	if (!ikev2_calculate_psk_sighash(st, invertrole, idhash,
					 st->st_firstpacket_him, calc_hash))
		return STF_FAIL;

	DBG(DBG_PRIVATE,
	    DBG_dump("Received PSK auth octets", sig_pbs->cur, sig_len);
	    DBG_dump("Calculated PSK auth octets", calc_hash, hash_len));

	if (memeq(sig_pbs->cur, calc_hash, hash_len) ) {
		return STF_OK;
	} else {
		libreswan_log("AUTH mismatch: Received AUTH != computed AUTH");
		return STF_FAIL;
	}
}
コード例 #9
0
ファイル: ikev2_crypto.c プロジェクト: 1309578252/Openswan
err_t
try_RSA_signature_v2(const u_char hash_val[MAX_DIGEST_LEN]
		     , size_t hash_len
		     , const pb_stream *sig_pbs, struct pubkey *kr
		     , struct state *st)
{
    const u_char *sig_val = sig_pbs->cur;
    size_t sig_len = pbs_left(sig_pbs);
    u_char s[RSA_MAX_OCTETS];	/* for decrypted sig_val */
    u_char *sig;
    unsigned int padlen;
    const struct RSA_public_key *k = &kr->u.rsa;

    if (k == NULL)
	return "1""no key available";	/* failure: no key to use */

    /* decrypt the signature -- reversing RSA_sign_hash */
    if (sig_len != k->k)
    {
        DBG_log("sig_len: %u != k->k: %u"
                , (unsigned int)sig_len, (unsigned int)k->k);
	return "1""SIG length does not match public key length";
    }

    /* actual exponentiation; see PKCS#1 v2.0 5.1 */
    {
	chunk_t temp_s;
	MP_INT c;

	n_to_mpz(&c, sig_val, sig_len);
	oswcrypto.mod_exp(&c, &c, &k->e, &k->n);

	temp_s = mpz_to_n(&c, sig_len);	/* back to octets */
	memcpy(s, temp_s.ptr, sig_len);
	pfree(temp_s.ptr);
	mpz_clear(&c);
    }

    /* check signature contents */
    /* verify padding */
    padlen = sig_len - 3 - (hash_len+der_digestinfo_len);
    /* now check padding */
    sig = s;

    DBG(DBG_CRYPT,
	DBG_dump("v2rsa decrypted SIG1:", sig, sig_len));

    if(sig[0]    != 0x00
       || sig[1] != 0x01
       || sig[padlen+2] != 0x00) {
	return "2""SIG padding does not check out";
    }

    /* skip padding */
    sig += padlen+3;

    /* 2 verify that the has was done with SHA1 */
    if(memcmp(der_digestinfo, sig, der_digestinfo_len)!=0) {
	return "SIG not performed with SHA1";
    }

    sig += der_digestinfo_len;

    DBG(DBG_CRYPT,
	DBG_dump("v2rsa decrypted SIG:", hash_val, hash_len);
	DBG_dump("v2rsa computed hash:", sig, hash_len);
    );
コード例 #10
0
ファイル: dpd.c プロジェクト: qianguozheng/Openswan
/**
 * DPD out Responder
 *
 * @param st A state structure (phase 1)
 * @param n A notification (isakmp_notification)
 * @param pbs A PB Stream
 * @return stf_status 
 */
stf_status
dpd_inR(struct state *p1st
	, struct isakmp_notification *const n
	, pb_stream *pbs)
{
    time_t tm = now();
    u_int32_t seqno;
     
    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
    {
        loglog(RC_LOG_SERIOUS, "recevied R_U_THERE_ACK for unestablished ISKAMP SA");
        return STF_FAIL;
    }

   if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
    {
        loglog(RC_LOG_SERIOUS, "R_U_THERE_ACK has invalid SPI length (%d)", n->isan_spisize);
        return STF_FAIL + PAYLOAD_MALFORMED;
    }
     
    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
    {
        /* RFC states we *SHOULD* check cookies, not MUST.  So invalid
           cookies are technically valid, as per Geoffrey Huang */
        loglog(RC_LOG_SERIOUS, "R_U_THERE_ACK has invalid icookie");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
    {
        /* RFC states we *SHOULD* check cookies, not MUST.  So invalid
           cookies are technically valid, as per Geoffrey Huang */
        loglog(RC_LOG_SERIOUS, "R_U_THERE_ACK has invalid rcookie (tolerated)");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (pbs_left(pbs) != sizeof(seqno))
    {
        loglog(RC_LOG_SERIOUS, "R_U_THERE_ACK has invalid data length (%d)", (int) pbs_left(pbs));
        return STF_FAIL + PAYLOAD_MALFORMED;
    }
        
    seqno = ntohl(*(u_int32_t *)pbs->cur);
    DBG(DBG_DPD, DBG_log("R_U_THERE_ACK, seqno received: %u expected: %u (state=#%lu)",
			 seqno, p1st->st_dpd_expectseqno, p1st->st_serialno));

    if (!p1st->st_dpd_expectseqno && seqno != p1st->st_dpd_expectseqno) {
        loglog(RC_LOG_SERIOUS, "R_U_THERE_ACK has unexpected sequence number (expected: %u got: %u", seqno, p1st->st_dpd_expectseqno);
	p1st->st_dpd_expectseqno = 0;
	/* do not update time stamp, so we'll send a new one sooner */
    } else {
	/* update the time stamp */
	p1st->st_last_dpd = tm;
    }

    p1st->st_dpd_expectseqno = 0;

    /*
     * since there was activity, kill any EVENT_DPD_TIMEOUT that might
     * be waiting.
     */
    if(p1st->st_dpd_event != NULL
       && p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT) {
	delete_dpd_event(p1st);
    }

    return STF_IGNORE;
}       
コード例 #11
0
ファイル: dpd.c プロジェクト: qianguozheng/Openswan
/**
 * DPD in Initiator, out Responder
 *
 * @param st A state structure (the phase 1 state)
 * @param n A notification (isakmp_notification)
 * @param pbs A PB Stream
 * @return stf_status 
 */
stf_status
dpd_inI_outR(struct state *p1st
	     , struct isakmp_notification *const n
	     , pb_stream *pbs)
{
    time_t tm = now();
    u_int32_t seqno;
        
    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
    {   
        loglog(RC_LOG_SERIOUS, "DPD Error: received R_U_THERE for unestablished ISKAMP SA");
        return STF_IGNORE;
    }
    if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
    {
        loglog(RC_LOG_SERIOUS, "DPD Error: R_U_THERE has invalid SPI length (%d)", n->isan_spisize);
        return STF_FAIL + PAYLOAD_MALFORMED;
    }
        
    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
    {
        /* RFC states we *SHOULD* check cookies, not MUST.  So invalid
           cookies are technically valid, as per Geoffrey Huang */
        loglog(RC_LOG_SERIOUS, "DPD Warning: R_U_THERE has invalid icookie (broken Cisco?)");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
    {
        loglog(RC_LOG_SERIOUS, "DPD Warning: R_U_THERE has invalid rcookie (broken Cisco?)");      
    }
    pbs->cur += COOKIE_SIZE;

    if (pbs_left(pbs) != sizeof(seqno))
    {
        loglog(RC_LOG_SERIOUS, "DPD Error: R_U_THERE has invalid data length (%d)", (int) pbs_left(pbs));
        return STF_FAIL + PAYLOAD_MALFORMED;
    }

    seqno = ntohl(*(u_int32_t *)pbs->cur);
    if (p1st->st_dpd_peerseqno && seqno <= p1st->st_dpd_peerseqno) {
        loglog(RC_LOG_SERIOUS, "DPD Info: received old or duplicate R_U_THERE");
        return STF_IGNORE;
    }
     
    DBG(DBG_DPD, DBG_log("received R_U_THERE seq:%u time:%lu (state=#%lu name=\"%s\")"
			 , seqno
			 , (unsigned long)tm
			 , p1st->st_serialno, p1st->st_connection->name));

    p1st->st_dpd_peerseqno = seqno;

    if (send_isakmp_notification(p1st, R_U_THERE_ACK
				 , pbs->cur, pbs_left(pbs)) != STF_IGNORE)
    {
        loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK"); 
        return STF_IGNORE;
    }

    /* update the time stamp */
    p1st->st_last_dpd = tm;

    /*
     * since there was activity, kill any EVENT_DPD_TIMEOUT that might
     * be waiting.
     */
    if(p1st->st_dpd_event != NULL
       && p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT) {
	delete_dpd_event(p1st);
    }

    return STF_IGNORE;
}
コード例 #12
0
ファイル: dpd.c プロジェクト: millken/zhuxianB30
/*****************************************************************************************   
 函数名称: dpd_inR
 功能描述: 处理R_U_THERE_ACK 报文,判断报文长度是否正确以及通过序列号判断
 		   报文是否是自己想要的
 输入参数: p1st,n,pbs
 输出参数: 无
 返 回 值: stf_status
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云    
 修改目的: ACk处理   
 修改日期: 2012年3月20日
********************************************************************************************/ 
stf_status dpd_inR(struct state *p1st, struct isakmp_notification *const n, pb_stream *pbs)
{

    EV_ADD ev_arg;     
    
    
	if(!p1st->hidden_variables.st_is_dp_dev)
	{
	    time_t tm = now();
	    u_int32_t seqno;
        

	    char buf_remoteip[20] = {0};
		addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip));

	    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "recevied R_U_THERE_ACK for unestablished ISKAMP SA");
	        return STF_FAIL;
	    }

	   if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
	    {
	       IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
		   	            "<%s> < %s > R_U_THERE_ACK has invalid SPI length (%d)",
		   	            p1st->st_connection->name, buf_remoteip, n->isan_spisize);
	        return STF_FAIL + PAYLOAD_MALFORMED;
	    }
	     
	    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid icookie");
	    }
		
	    pbs->cur += COOKIE_SIZE;
	    
	    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid rcookie (tolerated)");
	    }
		
	    pbs->cur += COOKIE_SIZE;
	    
	    if (pbs_left(pbs) != sizeof(seqno))
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
				"<%s> < %s > R_U_THERE_ACK has invalid data length (%d)",
				p1st->st_connection->name, buf_remoteip, (int) pbs_left(pbs));
	        return STF_FAIL + PAYLOAD_MALFORMED;
	    }
	        
	    seqno = ntohl(*(u_int32_t *)pbs->cur);
		
	    DBG(DBG_DPD, DBG_log("R_U_THERE_ACK, seqno received: %u expected: %u (state=#%lu)",
				 seqno, p1st->st_dpd_expectseqno, p1st->st_serialno));

	    if (seqno != p1st->st_dpd_expectseqno) 
		{
		    IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has unexpected sequence number (expected: %u got: %u", seqno, p1st->st_dpd_expectseqno);
			return STF_IGNORE;
		}
		else 
	    {
	        p1st->st_last_dpd = tm;
	    }

	}
	
    if(p1st->st_dpd_timeout_event != NULL)
	{
	    ev_arg.u.st = p1st;  
		disable_event(EVENT_DPD_TIMEOUT, &ev_arg);
    }
	
    return STF_IGNORE;
}       
コード例 #13
0
ファイル: dpd.c プロジェクト: millken/zhuxianB30
 /*****************************************************************************************   
 函数名称: dpd_inI_outR
 功能描述: 处理R_U_THERE报文,判断R_U_THERE报文长度是否正确以及
 			通过序列号判断自己想要的报文
 输入参数: p1st,n,pbs
 输出参数: stf_status
 返 回 值: 无
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云    
 修改目的: dpd_outI处理  
 修改日期: 2012年3月20日
********************************************************************************************/  	 
stf_status dpd_inI_outR(struct state *p1st, 
                        struct isakmp_notification *const n, pb_stream *pbs)
{
    time_t tm = now();
    u_int32_t seqno;
    char buf_remoteip[20] = {0};
    EV_ADD ev_arg;


    
	addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip));
	
    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
    {   
        return STF_IGNORE;
    }
    if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
    {
        IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
			"<%s> < %s > DPD Error: R_U_THERE has invalid SPI length (%d)", 
			p1st->st_connection->name, buf_remoteip, n->isan_spisize);
        return STF_FAIL + PAYLOAD_MALFORMED;
    }
        
    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Warning: R_U_THERE has invalid icookie (broken Cisco?)");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Warning: R_U_THERE has invalid rcookie (broken Cisco?)");      
    }
    pbs->cur += COOKIE_SIZE;

    if (pbs_left(pbs) != sizeof(seqno))
    {
       IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
	   	            "<%s> < %s > DPD Error: R_U_THERE has invalid data length (%d)", 
	   	            p1st->st_connection->name, buf_remoteip, (int) pbs_left(pbs));
        return STF_FAIL + PAYLOAD_MALFORMED;
    }

    seqno = ntohl(*(u_int32_t *)pbs->cur);
    if (p1st->st_dpd_peerseqno && seqno <= p1st->st_dpd_peerseqno) 
	{
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Info: received old or duplicate R_U_THERE");
        return STF_IGNORE;
    }
     
    DBG(DBG_DPD, DBG_log("received R_U_THERE seq:%u time:%lu (state=#%lu name=\"%s\")"
			 , seqno
			 , (unsigned long)tm
			 , p1st->st_serialno, p1st->st_connection->name));

    p1st->st_dpd_peerseqno = seqno;

    if (send_isakmp_notification(p1st, R_U_THERE_ACK
				 , pbs->cur, pbs_left(pbs)) != STF_IGNORE)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Info: could not send R_U_THERE_ACK"); 
        return STF_IGNORE;
    }

    p1st->st_last_dpd = tm;

    if(p1st->st_dpd_timeout_event != NULL) 
	{
	    ev_arg.u.st = p1st;
		disable_event(EVENT_DPD_TIMEOUT, &ev_arg);
    }

    return STF_IGNORE;
}
コード例 #14
0
ファイル: ikev2_redirect.c プロジェクト: libreswan/libreswan
err_t parse_redirect_payload(pb_stream *input_pbs,
			     const char *allowed_targets_list,
			     const chunk_t *nonce,
			     ip_address *redirect_ip /* result */)
{
	struct ikev2_redirect_part gw_info;

	if (!in_struct(&gw_info, &ikev2_redirect_desc, input_pbs, NULL))
		return "received deformed REDIRECT payload";

	int af;

	switch (gw_info.gw_identity_type) {
	case GW_IPV4:
		af = AF_INET;
		break;
	case GW_IPV6:
		af = AF_INET6;
		break;
	case GW_FQDN:
		af  = AF_UNSPEC;
		break;
	default:
		return "bad GW Ident Type";
	}

	/* in_raw() actual GW Identity */
	switch (af) {
	case AF_UNSPEC:
	{
		/*
		 * The FQDN string isn't NUL-terminated.
		 *
		 * The length is stored in a byte so it cannot be
		 * larger than 0xFF.
		 * Some helpful compilers moan about this test being always true
		 * so I eliminated it:
		 *	passert(gw_info.gw_identity_len <= 0xFF);
		 */
		unsigned char gw_str[0xFF];

		if (!in_raw(&gw_str, gw_info.gw_identity_len, input_pbs, "GW Identity"))
			return "error while extracting GW Identity from variable part of IKEv2_REDIRECT Notify payload";

		err_t ugh = ttoaddr((char *) gw_str, gw_info.gw_identity_len,
					AF_UNSPEC, redirect_ip);
		if (ugh != NULL)
			return ugh;
		break;
	}
	case AF_INET:
	case AF_INET6:
	{
		if (pbs_left(input_pbs) < gw_info.gw_identity_len)
			return "variable part of payload is smaller than transfered GW Identity Length";

		/* parse address directly to redirect_ip */
		err_t ugh = initaddr(input_pbs->cur, gw_info.gw_identity_len, af, redirect_ip);
		if (ugh != NULL)
			return ugh;

		DBG(DBG_PARSING, {
			ip_address_buf b;
			DBG_log("   GW Identity IP: %s", ipstr(redirect_ip, &b));
		});
		input_pbs->cur += gw_info.gw_identity_len;
		break;
	}
	}
コード例 #15
0
ファイル: packet.c プロジェクト: Biamp-Systems/mb-linux
bool
in_struct(void *struct_ptr, struct_desc *sd
, pb_stream *ins, pb_stream *obj_pbs)
{
    err_t ugh = NULL;
    u_int8_t *cur = ins->cur;

    if (ins->roof - cur < (ptrdiff_t)sd->size) {
	ugh = builddiag("not enough room in input packet for %s", sd->name);
    } else {
	u_int8_t *roof = cur + sd->size;    /* may be changed by a length field */
	u_int8_t *outp = struct_ptr;
	bool immediate = FALSE;
	field_desc *fp;

	for (fp = sd->fields; ugh == NULL; fp++) {
	    size_t i = fp->size;

	    passert(ins->roof - cur >= (ptrdiff_t)i);
	    passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
	    passert(outp - (cur - ins->cur) == struct_ptr);

#if 0
	    DBG(DBG_PARSING, DBG_log("%d %s"
		, (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
#endif
	    switch (fp->field_type) {
	    case ft_mbz:	/* must be zero */
		for (; i != 0; i--) {
		    if (*cur++ != 0) {
			ugh = builddiag("byte %d of %s must be zero, but is not"
			    , (int) (cur - ins->cur), sd->name);
			break;
		    }
		    *outp++ = '\0';	/* probably redundant */
		}
		break;

	    case ft_nat:	/* natural number (may be 0) */
	    case ft_len:	/* length of this struct and any following crud */
	    case ft_lv:		/* length/value field of attribute */
	    case ft_enum:	/* value from an enumeration */
	    case ft_loose_enum:	/* value from an enumeration with only some names known */
	    case ft_af_enum:	/* Attribute Format + value from an enumeration */
	    case ft_set:	/* bits representing set */
	    {
		u_int32_t n = 0;

		for (; i != 0; i--)
		    n = (n << BITS_PER_BYTE) | *cur++;

		switch (fp->field_type) {
		case ft_len:	/* length of this struct and any following crud */
		case ft_lv:	/* length/value field of attribute */
		{
		    u_int32_t len = fp->field_type == ft_len? n
			: immediate? sd->size : n + sd->size;

		    if (len < sd->size) {
			ugh = builddiag("%s of %s is smaller than minimum"
			    , fp->name, sd->name);
		    } else if (pbs_left(ins) < len) {
			ugh = builddiag("%s of %s is larger than can fit"
			    , fp->name, sd->name);
		    } else {
			roof = ins->cur + len;
		    }
		    break;
		}
		case ft_af_enum:	/* Attribute Format + value from an enumeration */
		    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
			immediate = TRUE;
		    /* FALL THROUGH */
		case ft_enum:	/* value from an enumeration */
		    if (enum_name(fp->desc, n) == NULL) {
			ugh = builddiag("%s of %s has an unknown value: %lu"
			    , fp->name, sd->name, (unsigned long)n);
		    }
		    /* FALL THROUGH */
		case ft_loose_enum:	/* value from an enumeration with only some names known */
		    break;
		case ft_set:	/* bits representing set */
		    if (!testset(fp->desc, n)) {
			ugh = builddiag("bitset %s of %s has unknown member(s): %s"
			    , fp->name, sd->name, bitnamesof(fp->desc, n));
		    }
		    break;
		default:
			break;
		}
		i = fp->size;
		switch (i) {
		case 8/BITS_PER_BYTE:
		    *(u_int8_t *)outp = n;
		    break;
		case 16/BITS_PER_BYTE:
		    *(u_int16_t *)outp = n;
		    break;
		case 32/BITS_PER_BYTE:
		    *(u_int32_t *)outp = n;
		    break;
		default:
		    impossible();
		}
		outp += i;
		break;
	    }

	    case ft_raw:	/* bytes to be left in network-order */
		for (; i != 0; i--) {
		    *outp++ = *cur++;
		}
		break;

	    case ft_end:	/* end of field list */
		passert(cur == ins->cur + sd->size);
		if (obj_pbs != NULL) {
		    init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
		    obj_pbs->container = ins;
		    obj_pbs->desc = sd;
		    obj_pbs->cur = cur;
		}
		ins->cur = roof;
		DBG(DBG_PARSING
		    , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
		return TRUE;

	    default:
		impossible();
	    }
	}
    }

    /* some failure got us here: report it */
    loglog(RC_LOG_SERIOUS, ugh);
    return FALSE;
}
コード例 #16
0
ファイル: pbs.c プロジェクト: 1309578252/Openswan
int pbs_left_get(pb_stream *pbs) {
    return pbs_left(pbs);
}
コード例 #17
0
ファイル: nat_traversal.c プロジェクト: a1phageek/kyocera-kr1
void nat_traversal_natd_lookup(struct msg_digest *md)
{
	char hash[MAX_DIGEST_LEN];
	struct payload_digest *p;
	struct state *st = md->st;
	int i;

	if (!st || !md->iface || !st->st_oakley.hasher) {
		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
			__FILE__, __LINE__);
		return;
	}

	/** Count NAT-D **/
	for (p = md->chain[ISAKMP_NEXT_NATD_R], i=0; p != NULL; p = p->next, i++);

	/**
	 * We need at least 2 NAT-D (1 for us, many for peer)
	 */
	if (i < 2) {
		loglog(RC_LOG_SERIOUS,
		"NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negotiation", i);
		st->nat_traversal = 0;
		return;
	} 
#ifdef NAT_D_DEBUG
	else
		loglog(RC_LOG_SERIOUS,
		"NAT-Traversal: %d NAT-D - Continuing NAT-Traversal negotiation", i);
#endif


	/**
	 * First one with my IP & port
	 */
	p = md->chain[ISAKMP_NEXT_NATD_R];
	_natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
		&(md->iface->addr), ntohs(st->st_connection->this.host_port));
	if (!( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len) &&
		(memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)==0)
		)) {
#ifdef NAT_D_DEBUG
		DBG_log("NAT_TRAVERSAL_NAT_BHND_ME");
		DBG_dump("expected NAT-D:", hash, st->st_oakley.hasher->hash_digest_len);
		DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
#endif
		st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
	}

	/**
	 * The others with sender IP & port
	 */
	_natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie,
		&(md->sender), ntohs(md->sender_port));
	for (p = p->next, i=0 ; p != NULL; p = p->next) {
		if ( (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len) &&
			(memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)==0)
			) {
			i++;
		}
	}
	if (!i) {
#ifdef NAT_D_DEBUG
		DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER");
		DBG_dump("expected NAT-D:", hash, st->st_oakley.hasher->hash_digest_len);
		p = md->chain[ISAKMP_NEXT_NATD_R];
		for (p = p->next, i=0 ; p != NULL; p = p->next) {
			DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs));
		}
#endif
		st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
	}
#ifdef FORCE_NAT_TRAVERSAL
	st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER);
	st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME);
#endif
}