Ejemplo n.º 1
0
void pluto_do_crypto_op(struct pluto_crypto_req *r, int helpernum)
{
    DBG(DBG_CONTROL
	, DBG_log("helper %d doing %s op id: %u"
		  , helpernum
		  , enum_show(&pluto_cryptoop_names, r->pcr_type)
		  , r->pcr_id));
#else
void pluto_do_crypto_op(struct pluto_crypto_req *r)
{
    DBG(DBG_CONTROL
	, DBG_log("helper %d doing %s op id: %u"
		  , pc_helper_num
		  , enum_show(&pluto_cryptoop_names, r->pcr_type)
		  , r->pcr_id));
#endif
#ifdef DEBUG
    {
	char *d = getenv("PLUTO_CRYPTO_HELPER_DELAY");
	if(d != NULL) {
	    int delay=atoi(d);

	    DBG_log("helper is pausing for %d seconds", delay);
	    sleep(delay);
	}
    }
#endif

    /* now we have the entire request in the buffer, process it */
    switch(r->pcr_type) {
    case pcr_build_kenonce:
	calc_ke(r);
	calc_nonce(r);
	break;

    case pcr_build_nonce:
	calc_nonce(r);
	break;

    case pcr_compute_dh_iv:
	calc_dh_iv(r);
	break;

    case pcr_compute_dh:
	calc_dh(r);
	break;

    case pcr_compute_dh_v2:
	calc_dh_v2(r);
	break;

    case pcr_rsa_sign:
    case pcr_rsa_check:
    case pcr_x509cert_fetch:
    case pcr_x509crl_fetch:
	break;
    }
}
Ejemplo n.º 2
0
static void pluto_do_crypto_op(struct pluto_crypto_req *r, int helpernum)
{
	struct timeval tv0;
	gettimeofday(&tv0, NULL);
	const char *story = NULL;

	DBG(DBG_CONTROL,
	    DBG_log("crypto helper %d doing %s; request ID %u",
		    helpernum,
		    enum_show(&pluto_cryptoop_names, r->pcr_type),
		    r->pcr_id));
	if (crypto_helper_delay > 0) {
		DBG_log("crypto helper is pausing for %u seconds",
			crypto_helper_delay);
		sleep(crypto_helper_delay);
	}

	/* now we have the entire request in the buffer, process it */
	switch (r->pcr_type) {
	case pcr_build_ke_and_nonce:
		calc_ke(r);
		/* FALL THROUGH */
	case pcr_build_nonce:
		calc_nonce(r);
		break;

	case pcr_compute_dh_iv:
		calc_dh_iv(r);
		break;

	case pcr_compute_dh:
		calc_dh(r);
		break;

	case pcr_compute_dh_v2:
		calc_dh_v2(r, &story);
		break;
	}

	DBG(DBG_CONTROL, {
			struct timeval tv1;
			unsigned long tv_diff;
			gettimeofday(&tv1, NULL);
			tv_diff = (tv1.tv_sec  - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec);
			DBG_log("crypto helper %d finished %s%s; request ID %u time elapsed %ld usec",
					helpernum,
					enum_show(&pluto_cryptoop_names, r->pcr_type),
					(story != NULL) ? story : "",
					r->pcr_id, tv_diff));
	}

}
Ejemplo n.º 3
0
/* send the request, make sure it all goes down. */
static bool crypto_write_request(struct pluto_crypto_worker *w
				 ,struct pluto_crypto_req *r)
{
    unsigned char *wdat = (unsigned char *)r;
    int wlen = r->pcr_len;
    int cnt;

    DBG(DBG_CONTROL
	, DBG_log("asking helper %d to do %s op on seq: %u (len=%u, pcw_work=%d)"
		  , w->pcw_helpernum
		  , enum_show(&pluto_cryptoop_names, r->pcr_type)
		  , r->pcr_id, (unsigned int)r->pcr_len, w->pcw_work+1));

    do {
	errno=0;
	cnt = write(w->pcw_pipe, wdat, wlen);

	if(cnt <= 0) {
	    openswan_log("write to helper failed: cnt=%d err=%s\n",
			 cnt, strerror(errno));
	    return FALSE;
	}
	if(DBGP(DBG_CONTROL) || cnt != wlen) {
	    DBG_log("crypto helper write of request: cnt=%d<wlen=%d. \n", cnt, wlen);
	}

	wlen -= cnt;
	wdat += cnt;

    } while(wlen > 0);

    return TRUE;
}
Ejemplo n.º 4
0
/** Compute DH shared secret from our local secret and the peer's public value.
 * We make the leap that the length should be that of the group
 * (see quoted passage at start of ACCEPT_KE).
 */
static void
calc_dh_shared(chunk_t *shared, const chunk_t g
	       , const MP_INT *sec
	       , const struct oakley_group_desc *group)
{
    MP_INT mp_g, mp_shared;
    struct timeval tv0, tv1;
    unsigned long tv_diff;

    gettimeofday(&tv0, NULL);
    n_to_mpz(&mp_g, g.ptr, g.len);
    mpz_init(&mp_shared);
    mpz_powm(&mp_shared, &mp_g, sec, group->modulus);
    mpz_clear(&mp_g);

    *shared = mpz_to_n(&mp_shared, group->bytes);
    mpz_clear(&mp_shared);

    gettimeofday(&tv1, NULL);
    tv_diff=(tv1.tv_sec  - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec);
    DBG(DBG_CRYPT, 
    	DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec"
		, enum_show(&oakley_group_names, group->group)
		, tv_diff);
       );
Ejemplo n.º 5
0
/*
 * This routine places an event in the event list.
 */
void event_schedule(enum event_type type, time_t tm, struct state *st)
{
	struct event *ev = alloc_thing(struct event,
				       "struct event in event_schedule()");

	passert(tm >= 0);
	ev->ev_type = type;
	ev->ev_time = tm + now();
	ev->ev_state = st;

	/* If the event is associated with a state, put a backpointer to the
	 * event in the state object, so we can find and delete the event
	 * if we need to (for example, if we receive a reply).
	 */
	if (st != NULL) {
		if (type == EVENT_DPD || type == EVENT_DPD_TIMEOUT) {
			passert(st->st_dpd_event == NULL);
			st->st_dpd_event = ev;
		} else if (type == EVENT_v2_LIVENESS) {
			passert(st->st_liveness_event == NULL);
			st->st_liveness_event = ev;
		} else {
			passert(st->st_event == NULL);
			st->st_event = ev;
		}
	}

	DBG(DBG_CONTROL, {
		    if (st == NULL) {
			    DBG_log(
				    "inserting event %s, timeout in %lu seconds",
				    enum_show(&timer_event_names,
					      type), (unsigned long)tm);
		    } else {
			    DBG_log(
				    "inserting event %s, timeout in %lu seconds for #%lu",
				    enum_show(&timer_event_names,
					      type), (unsigned long)tm,
				    ev->ev_state->st_serialno);
		    }
	    });
Ejemplo n.º 6
0
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);
	}
    }
}
Ejemplo n.º 7
0
/*
 * 	Show IKE algorithms for 
 * 	- this connection (result from ike= string)
 * 	- newest SA
 */
void
ike_alg_show_connection(struct connection *c, const char *instance)
{
	char buf[256];
	struct state *st;
	if (c->alg_info_ike) {
		alg_info_snprint(buf, sizeof(buf), 
				(struct alg_info *)c->alg_info_ike);
		whack_log(RC_COMMENT
		    , "\"%s\"%s:   IKE algorithms wanted: %s"
		    , c->name
		    , instance
		    , buf);
	}
	if (c->alg_info_ike) {
		alg_info_snprint_ike(buf, sizeof(buf), c->alg_info_ike);
		whack_log(RC_COMMENT
		    , "\"%s\"%s:   IKE algorithms found:  %s"
		    , c->name
		    , instance
		    , buf);
	}
	st = state_with_serialno(c->newest_isakmp_sa);
	if (st)
		whack_log(RC_COMMENT
		, "\"%s\"%s:   IKE algorithm newest: %s_%d-%s-%s"
		, c->name
		, instance
		, enum_show(&oakley_enc_names, st->st_oakley.encrypt)
		+7 /* strlen("OAKLEY_") */
		/* , st->st_oakley.encrypter->keydeflen */
		, st->st_oakley.enckeylen
		, enum_show(&oakley_hash_names, st->st_oakley.hash)
		+7 /* strlen("OAKLEY_") */
		, enum_show(&oakley_group_names, st->st_oakley.group->group)
		+13 /* strlen("OAKLEY_GROUP_") */
	 );
}
Ejemplo n.º 8
0
/*
 * extracts the certificate to be sent to the peer
 */
chunk_t get_mycert(cert_t cert)
{
	switch (cert.type) {
	case CERT_NONE:
		return empty_chunk; /* quietly forget about it */

	case CERT_X509_SIGNATURE:
		return cert.u.x509->certificate;

	default:
		loglog(RC_LOG_SERIOUS,"get_mycert: Unknown certificate type: "
			"%s (%d)", enum_show(&cert_type_names, cert.type),
			cert.type);
		return empty_chunk;
	}
}
Ejemplo n.º 9
0
/* send the request, make sure it all goes down. */
static bool crypto_write_request(struct pluto_crypto_worker *w,
				 const struct pluto_crypto_req *r)
{
	const unsigned char *wdat = (unsigned char *)r;
	size_t wlen = r->pcr_len;

	passert(wlen == sizeof(*r));

	DBG(DBG_CONTROL,
	    DBG_log("asking crypto helper %d to do %s; request ID %u (len=%zu, pcw_work=%d)",
		    w->pcw_helpernum,
		    enum_show(&pluto_cryptoop_names, r->pcr_type),
		    r->pcr_id, r->pcr_len, w->pcw_work));

	while (wlen > 0) {
		ssize_t cnt = write(w->pcw_master_fd, wdat, wlen);

		if (cnt < 0) {
			libreswan_log(
				"write to crypto helper %d failed: cnt=%d err=%s",
				w->pcw_helpernum, (int)cnt, strerror(errno));
			return FALSE;
		}

		if (cnt == 0) {
			/* Not clear why this would happen.  Socket full? */
			libreswan_log(
				"write to crypto helper %d failed to write any bytes",
				w->pcw_helpernum);
			return FALSE;
		}

		if ((size_t)cnt != wlen) {
			libreswan_log("short write to crypto helper %d (%zu of %zu bytes); will continue",
				w->pcw_helpernum, (size_t)cnt, wlen);
		}

		wlen -= cnt;
		wdat += cnt;
	}

	return TRUE;
}
Ejemplo n.º 10
0
/*
 * 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));
    }
Ejemplo n.º 11
0
/* delete a state object */
void
delete_state(struct state *st)
{
    struct connection *const c = st->st_connection;
    struct state *old_cur_state = cur_state == st? NULL : cur_state;

    openswan_log("deleting state #%lu (%s)",
                 st->st_serialno,
                 enum_show(&state_names, st->st_state));

    /*
     * for most IKEv2 things, we may have further things to do after marking the state deleted,
     * so we do not actually free it here at all, but back in the main loop when all the work is done.
     */
    if(st->st_ikev2) {
        /* child sa*/
        if(st->st_clonedfrom != 0) {
            DBG(DBG_CONTROL, DBG_log("received request to delete child state"));
            if(st->st_state == STATE_CHILDSA_DEL) {
		DBG(DBG_CONTROL, DBG_log("now deleting the child state"));

            } else {
                /* Only send request if child sa is established
		 * otherwise continue with deletion
		 */
		if(IS_CHILD_SA_ESTABLISHED(st)) {
                    DBG(DBG_CONTROL, DBG_log("sending Child SA delete equest"));
                    send_delete(st);
                    change_state(st, STATE_CHILDSA_DEL);

                    /* actual deletion when we receive peer response*/
                    return;
		}
            }

        } else {
            DBG(DBG_CONTROL, DBG_log("considering request to delete IKE parent state"));
            /* parent sa */
            if(st->st_state == STATE_IKESA_DEL) {
                DBG(DBG_CONTROL, DBG_log("now deleting the IKE (or parent) state"));

            } else {
		/* Another check to verify if a secured
		 * INFORMATIONAL exchange can be sent or not
		 */
		if(st->st_skey_ei.ptr && st->st_skey_ai.ptr
                   && st->st_skey_er.ptr && st->st_skey_ar.ptr) {
                    DBG(DBG_CONTROL, DBG_log("sending IKE SA delete request"));
                    send_delete(st);
                    change_state(st, STATE_IKESA_DEL);

                    /* actual deletion when we receive peer response*/
                    return;
		}
            }
        }
    }

    /* If DPD is enabled on this state object, clear any pending events */
    if(st->st_dpd_event != NULL)
            delete_dpd_event(st);

    /* if there is a suspended state transition, disconnect us */
    if (st->st_suspended_md != NULL)
    {
	passert(st->st_suspended_md->st == st);
	DBG(DBG_CONTROL, DBG_log("disconnecting state #%lu from md",
	    st->st_serialno));
	st->st_suspended_md->st = NULL;
    }

    /* tell the other side of any IPSEC SAs that are going down */
    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
    || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
	send_delete(st);

    delete_event(st);	/* delete any pending timer event */

    /* Ditch anything pending on ISAKMP SA being established.
     * Note: this must be done before the unhash_state to prevent
     * flush_pending_by_state inadvertently and prematurely
     * deleting our connection.
     */
    flush_pending_by_state(st);

    /* if there is anything in the cryptographic queue, then remove this
     * state from it.
     */
    delete_cryptographic_continuation(st);

    /* effectively, this deletes any ISAKMP SA that this state represents */
    unhash_state(st);

    /* tell kernel to delete any IPSEC SA
     * ??? we ought to tell peer to delete IPSEC SAs
     */
    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
	|| IS_CHILD_SA_ESTABLISHED(st))
	delete_ipsec_sa(st, FALSE);
    else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
	delete_ipsec_sa(st, TRUE);

    if (c->newest_ipsec_sa == st->st_serialno)
	c->newest_ipsec_sa = SOS_NOBODY;

    if (c->newest_isakmp_sa == st->st_serialno)
	c->newest_isakmp_sa = SOS_NOBODY;

    /*
     * fake a state change here while we are still associated with a
     * connection.  Without this the state logging (when enabled) cannot
     * work out what happened.
     */
    fake_state(st, STATE_UNDEFINED);

    st->st_connection = NULL;	/* we might be about to free it */
    cur_state = old_cur_state;	/* without st_connection, st isn't complete */
    connection_discard(c);

    change_state(st, STATE_UNDEFINED);

    release_whack(st);

    change_state(st, STATE_CHILDSA_DEL);
}
Ejemplo n.º 12
0
		    cur_state = old_cur_state;
#ifdef DEBUG
		    set_debugging(old_cur_debugging);
#endif
		}
	    }
	}
    }
}

static void delete_state_function(struct state *this
				  , struct connection *c UNUSED
				  , void *arg UNUSED)
{
    openswan_log("deleting state (%s)"
		 , enum_show(&state_names, this->st_state));

    if(this->st_event != NULL) delete_event(this);
    delete_state(this);
}

/*
 * delete all states that were created for a given connection.
 * if relations == TRUE, then also delete states that share
 * the same phase 1 SA.
 */
static bool same_phase1_sa_relations(struct state *this
				     , struct connection *c, void *arg
				     , int pass UNUSED)
{
    so_serial_t *pparent_sa = (so_serial_t *)arg;
Ejemplo n.º 13
0
/* MUST BE THREAD-SAFE */
static PK11SymKey *calc_dh_shared(const chunk_t g,	/* converted to SECItem */
				  /*const*/ SECKEYPrivateKey *privk,	/* NSS doesn't do const */
				  const struct oakley_group_desc *group,
				  const SECKEYPublicKey *local_pubk)
{
	struct timeval tv0;
	SECKEYPublicKey *remote_pubk;
	SECItem nss_g;
	PK11SymKey *dhshared;
	PRArenaPool *arena;
	SECStatus status;
	unsigned int dhshared_len;

	DBG(DBG_CRYPT,
		DBG_log("Started DH shared-secret computation in NSS:"));

	gettimeofday(&tv0, NULL);

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	passert(arena != NULL);

	remote_pubk = (SECKEYPublicKey *)
		PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));

	remote_pubk->arena = arena;
	remote_pubk->keyType = dhKey;
	remote_pubk->pkcs11Slot = NULL;
	remote_pubk->pkcs11ID = CK_INVALID_HANDLE;

	nss_g.data = g.ptr;
	nss_g.len = (unsigned int)g.len;
	nss_g.type = siBuffer;

	status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.prime,
				  &local_pubk->u.dh.prime);
	passert(status == SECSuccess);

	status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.base,
				  &local_pubk->u.dh.base);
	passert(status == SECSuccess);

	status = SECITEM_CopyItem(remote_pubk->arena,
				  &remote_pubk->u.dh.publicValue, &nss_g);
	passert(status == SECSuccess);

	dhshared = PK11_PubDerive(privk, remote_pubk, PR_FALSE, NULL, NULL,
				  CKM_DH_PKCS_DERIVE,
				  CKM_CONCATENATE_DATA_AND_BASE,
				  CKA_DERIVE, group->bytes,
				  lsw_return_nss_password_file_info());
	passert(dhshared != NULL);

	dhshared_len = PK11_GetKeyLength(dhshared);
	if (group->bytes > dhshared_len) {
		DBG(DBG_CRYPT,
		    DBG_log("Dropped %lu leading zeros",
			    group->bytes - dhshared_len));
		chunk_t zeros;
		PK11SymKey *newdhshared;
		CK_KEY_DERIVATION_STRING_DATA string_params;
		SECItem params;

		zeros = hmac_pads(0x00, group->bytes - dhshared_len);
		params.data = (unsigned char *)&string_params;
		params.len = sizeof(string_params);
		string_params.pData = zeros.ptr;
		string_params.ulLen = zeros.len;

		newdhshared = PK11_Derive(dhshared,
					  CKM_CONCATENATE_DATA_AND_BASE,
					  &params,
					  CKM_CONCATENATE_DATA_AND_BASE,
					  CKA_DERIVE, 0);
		passert(newdhshared != NULL);
		PK11_FreeSymKey(dhshared);
		dhshared = newdhshared;
		freeanychunk(zeros);
	} else {
		DBG(DBG_CRYPT,
		    DBG_log("Dropped no leading zeros %d", dhshared_len));
	}

	/* nss_symkey_log(dhshared, "dhshared"); */

	DBG(DBG_CRYPT, {
		struct timeval tv1;
		unsigned long tv_diff;

		gettimeofday(&tv1, NULL);
		tv_diff = (tv1.tv_sec  - tv0.tv_sec) * 1000000 +
			  (tv1.tv_usec - tv0.tv_usec);
		DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec",
			       enum_show(&oakley_group_names, group->group),
			       tv_diff);
	});
Ejemplo n.º 14
0
static void doi_log_cert_thinking(struct msg_digest *md UNUSED,
				  u_int16_t auth,
				  enum ike_cert_type certtype,
				  enum certpolicy policy,
				  bool gotcertrequest,
				  bool send_cert)
{
	DBG(DBG_CONTROL,
	    DBG_log("thinking about whether to send my certificate:"));

	DBG(DBG_CONTROL, {
		char esb[ENUM_SHOW_BUF_LEN];

		DBG_log("  I have RSA key: %s cert.type: %s ",
		    enum_showb(&oakley_auth_names, auth, esb, sizeof(esb)),
		    enum_show(&ike_cert_type_names, certtype));
	});

	DBG(DBG_CONTROL,
	    DBG_log("  sendcert: %s and I did%s get a certificate request ",
		    enum_show(&certpolicy_type_names, policy),
		    gotcertrequest ? "" : " not"));

	DBG(DBG_CONTROL,
	    DBG_log("  so %ssend cert.", send_cert ? "" : "do not "));

	if (!send_cert) {
		if (auth == OAKLEY_PRESHARED_KEY)
			DBG(DBG_CONTROL,
			    DBG_log("I did not send a certificate because digital signatures are not being used. (PSK)"));
		else if (certtype == CERT_NONE)
Ejemplo n.º 15
0
/* print a host struct
 *
 * This code assumes that the network and host structure
 * members have the same alignment and size!  This requires
 * that all padding be explicit.
 */
void
DBG_print_struct(const char *label, const void *struct_ptr
, struct_desc *sd, bool len_meaningful)
{
    bool immediate = FALSE;
    const u_int8_t *inp = struct_ptr;
    field_desc *fp;

    DBG_log("%s%s:", label, sd->name);

    for (fp = sd->fields; fp->field_type != ft_end; fp++) {
	int i = fp->size;
	u_int32_t n = 0;

	switch (fp->field_type) {
	case ft_mbz:	/* must be zero */
	    inp += i;
	    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 */
	    switch (i) {
	    case 8/BITS_PER_BYTE:
		n = *(const u_int8_t *)inp;
		break;
	    case 16/BITS_PER_BYTE:
		n = *(const u_int16_t *)inp;
		break;
	    case 32/BITS_PER_BYTE:
		n = *(const u_int32_t *)inp;
		break;
	    default:
		impossible();
	    }
	    switch (fp->field_type) {
	    case ft_len:	/* length of this struct and any following crud */
	    case ft_lv:		/* length/value field of attribute */
		if (!immediate && !len_meaningful)
		    break;
		/* FALL THROUGH */
	    case ft_nat:	/* natural number (may be 0) */
		DBG_log("   %s: %lu", fp->name, (unsigned long)n);
		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 */
	    case ft_loose_enum:	/* value from an enumeration with only some names known */
		DBG_log("   %s: %s", fp->name, enum_show(fp->desc, n));
		break;
	    case ft_set:	/* bits representing set */
		DBG_log("   %s: %s", fp->name, bitnamesof(fp->desc, n));
		break;
	    default:
		impossible();
		break;
	    }
	    inp += i;
	    break;

	case ft_raw:	/* bytes to be left in network-order */
	    {
		char m[50];	/* arbitrary limit on name width in log */

		snprintf(m, sizeof(m), "   %s:", fp->name);
		DBG_dump(m, inp, i);
		inp += i;
	    }
	    break;
	default:
	    impossible();
	    break;
	}
    }
}
Ejemplo n.º 16
0
static int
initiate_a_connection(struct connection *c
		      , void *arg)
{
    struct initiate_stuff *is = (struct initiate_stuff *)arg;
    int whackfd = is->whackfd;
    lset_t moredebug = is->moredebug;
    enum crypto_importance importance = is->importance;
    int success = 0;

    set_cur_connection(c);

    /* turn on any extra debugging asked for */
    c->extra_debugging |= moredebug;

    if (!oriented(*c))
    {
	loglog(RC_ORIENT, "We cannot identify ourselves with either end of this connection.");
    }
    else if (NEVER_NEGOTIATE(c->policy))
    {
	loglog(RC_INITSHUNT
	       , "cannot initiate an authby=never connection");
    }
    else if (c->kind != CK_PERMANENT)
    {
	if (isanyaddr(&c->spd.that.host_addr)) {
#ifdef DYNAMICDNS
	    if (c->dnshostname != NULL) {
		loglog(RC_NOPEERIP, "cannot initiate connection without resolved dynamic peer IP address, will keep retrying");
		success = 1;
		c->policy |= POLICY_UP;
	    } else
#endif
		loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address (kind=%s)"
		       , enum_show(&connection_kind_names, c->kind));
	} else
	    loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards (kind=%s)"
		   , enum_show(&connection_kind_names, c->kind));
    }
    else
    {
	/* We will only request an IPsec SA if policy isn't empty
	 * (ignoring Main Mode items).
	 * This is a fudge, but not yet important.
	 * If we are to proceed asynchronously, whackfd will be NULL_FD.
	 */
	c->policy |= POLICY_UP;

	if(c->policy & (POLICY_ENCRYPT|POLICY_AUTHENTICATE)) {
	    struct alg_info_esp *alg = c->alg_info_esp;
	    struct db_sa *phase2_sa = kernel_alg_makedb(c->policy, alg, TRUE);

	    if(alg != NULL && phase2_sa == NULL) {
		whack_log(RC_NOALGO, "can not initiate: no acceptable kernel algorithms loaded");
		reset_cur_connection();
		close_any(is->whackfd);
		return 0;
	    }
	    free_sa(phase2_sa);
	}

	{
	    whackfd = dup(whackfd);
	    ipsecdoi_initiate(whackfd, c, c->policy, 1
			      , SOS_NOBODY, importance
                              , NULL_POLICY
			     );
	    success = 1;
	}
    }
    reset_cur_connection();

    return success;
}