Exemplo n.º 1
0
Arquivo: spdb.c Projeto: mkj/libreswan
/*
 * this routine takes two proposals and conjoins them (or)
 */
struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b)
{
	struct db_sa *n;
	unsigned int i, j, k;

	if (a == NULL || a->prop_conj_cnt == 0)
		return sa_copy_sa(b, 0);

	if (b == NULL || b->prop_conj_cnt == 0)
		return sa_copy_sa(a, 0);

	n = clone_thing(*a, "conjoin sa");

	passert(a->prop_conj_cnt == b->prop_conj_cnt);
	passert(a->prop_conj_cnt == 1);

	n->prop_conjs =
		clone_bytes(n->prop_conjs,
			    n->prop_conj_cnt * sizeof(n->prop_conjs[0]),
			    "sa copy prop conj array");

	for (i = 0; i < n->prop_conj_cnt; i++) {
		struct db_prop_conj *pca = &n->prop_conjs[i];
		struct db_prop_conj *pcb = &b->prop_conjs[i];

		passert(pca->prop_cnt == pcb->prop_cnt);
		passert(pca->prop_cnt == 1);

		pca->props = clone_bytes(pca->props,
					 pca->prop_cnt * sizeof(pca->props[0]),
					 "sa copy prop array");

		for (j = 0; j < pca->prop_cnt; j++) {
			struct db_prop *pa = &pca->props[j];
			struct db_prop *pb = &pcb->props[j];
			struct db_trans *t;
			int t_cnt = (pa->trans_cnt + pb->trans_cnt);

			t = alloc_bytes(t_cnt * sizeof(pa->trans[0]),
					"sa copy trans array");

			memcpy(t, pa->trans, (pa->trans_cnt) *
			       sizeof(pa->trans[0]));
			memcpy(t + (pa->trans_cnt),
			       pb->trans,
			       (pb->trans_cnt) * sizeof(pa->trans[0]));

			pa->trans = t;
			pa->trans_cnt = t_cnt;
			for (k = 0; k < pa->trans_cnt; k++)
				clone_trans(&pa->trans[k], 0);
		}
	}

	n->parentSA = a->parentSA;
	return n;
}
Exemplo n.º 2
0
Arquivo: spdb.c Projeto: mkj/libreswan
void clone_trans(struct db_trans *tr, int extra)
{
	tr->attrs = clone_bytes(tr->attrs,
				(tr->attr_cnt + extra) * sizeof(tr->attrs[0]),
				"sa copy attrs array");
	if (extra)
		tr->attr_cnt = tr->attr_cnt + extra;
}
Exemplo n.º 3
0
void clone_propconj(struct db_prop_conj *pc, int extra)
{
    unsigned int i;

    pc->props = clone_bytes(pc->props
			   , (pc->prop_cnt+extra)*sizeof(pc->props[0])
			   , "sa copy prop array");
    for(i=0; i<pc->prop_cnt; i++) {
	clone_prop(&pc->props[i], 0);
    }
}
Exemplo n.º 4
0
void clone_prop(struct db_prop *p, int extra)
{
    unsigned int i;

    p->trans = clone_bytes(p->trans
			  , (p->trans_cnt+extra)*sizeof(p->trans[0])
			  , "sa copy trans array");
    for(i=0; i<p->trans_cnt; i++) {
	clone_trans(&p->trans[i]);
    }
}
Exemplo n.º 5
0
Arquivo: spdb.c Projeto: mkj/libreswan
static void clone_prop(struct db_prop *p, int extra)
{
	unsigned int i;

	p->trans = clone_bytes(p->trans,
			       (p->trans_cnt + extra) * sizeof(p->trans[0]),
			       "sa copy trans array");
	/* p->trans_cnt is unchanged */
	for (i = 0; i < p->trans_cnt; i++)
		clone_trans(&p->trans[i], 0);
}
Exemplo n.º 6
0
Arquivo: spdb.c Projeto: mkj/libreswan
/*
 * clone the sa, but keep only the first transform (if any) of the first proposal (if any)
 * ??? does this make sense?
 */
struct db_sa *sa_copy_sa_first(struct db_sa *sa)
{
	struct db_sa *nsa;
	struct db_prop_conj *pc;
	struct db_prop *p;

	nsa = clone_thing(*sa, "sa copy prop_conj");
	nsa->dynamic = TRUE;
	if (nsa->prop_conj_cnt == 0)
		return nsa;

	nsa->prop_conj_cnt = 1;
	nsa->prop_conjs = clone_bytes(nsa->prop_conjs,
				      sizeof(nsa->prop_conjs[0]),
				      "sa copy 1 prop conj array");

	pc = &nsa->prop_conjs[0];
	if (pc->prop_cnt == 0)
		return nsa;

	pc->prop_cnt = 1;
	pc->props = clone_bytes(pc->props,
				sizeof(pc->props[0]),
				"sa copy 1 prop array");

	p = &pc->props[0];
	if (p->trans_cnt == 0)
		return nsa;

	p->trans_cnt = 1;
	p->trans = clone_bytes(p->trans,
			       sizeof(p->trans[0]),
			       "sa copy 1 trans array");

	clone_trans(&p->trans[0], 0);
	return nsa;
}
Exemplo n.º 7
0
struct db_sa *sa_copy_sa(struct db_sa *sa, int extra)
{
    unsigned int i;
    struct db_sa *nsa;

    nsa = clone_thing(*sa, "sa copy prop_conj");
    nsa->dynamic = TRUE;
    nsa->parentSA= sa->parentSA;

    nsa->prop_conjs =
	clone_bytes(nsa->prop_conjs
		    , (nsa->prop_conj_cnt+extra)*sizeof(nsa->prop_conjs[0])
		    , "sa copy prop conj array");

    for(i=0; i<nsa->prop_conj_cnt; i++) {
	clone_propconj(&nsa->prop_conjs[i], 0);
    }

    return nsa;
}
Exemplo n.º 8
0
/*
 * Make private copy of string in struct id.
 * This is needed if the result of atoid is to be kept.
 */
void unshare_id_content(struct id *id)
{
	switch (id->kind) {
	case ID_FQDN:
	case ID_USER_FQDN:
	case ID_DER_ASN1_DN:
	case ID_KEY_ID:
		id->name.ptr = clone_bytes(id->name.ptr, id->name.len,
					"keep id name");
		/* Somehow assert we have a valid id here? */
		break;
	case ID_MYID:
	case ID_FROMCERT:
	case ID_NONE:
	case ID_IPV4_ADDR:
	case ID_IPV6_ADDR:
		break;
	default:
		bad_case(id->kind);
	}
}
Exemplo n.º 9
0
/*
 *  add an ietfAttribute to the chained list
 */
static ietfAttr_t*
add_ietfAttr(ietfAttr_t *attr)
{
    ietfAttrList_t **listp = &ietfAttributes;
    ietfAttrList_t *list = *listp;
    int cmp = -1;
    
    while (list != NULL)
    {
      cmp = cmp_ietfAttr(attr, list->attr);
      if (cmp <= 0)
          break;
      listp = &list->next;
      list = *listp;
    }
    
    if (cmp == 0)
    {
      /* attribute already exists, increase count */
      pfree(attr);
      list->attr->count++;
      return list->attr;
    }
    else
    {
      ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList");
    
      /* new attribute, unshare value */
      attr->value.ptr = clone_bytes(attr->value.ptr, attr->value.len
          , "attr value");
      attr->count = 1;
      time(&attr->installed);
     
      el->attr = attr;
      el->next = list;
      *listp = el;
    
      return attr;
    }
}
Exemplo n.º 10
0
void recv_pcap_packet_gen(u_char *user,
			  const struct pcap_pkthdr *h,
			  const u_char *bytes)
{
	struct msg_digest *md;
	u_int32_t *dlt;
	struct iphdr  *ip;
	struct udphdr *udp;
	u_char    *ike;
	const struct iface_port *ifp = &if1;
	int packet_len;
	err_t from_ugh;

	union {
		struct sockaddr sa;
		struct sockaddr_in sa_in4;
		struct sockaddr_in6 sa_in6;
	} from;

	md = alloc_md();
	dlt = (u_int32_t *)bytes;
	if (*dlt != PF_INET)
		return;

	ip  = (struct iphdr *)(dlt + 1);
	udp = (struct udphdr *)(dlt + ip->ihl + 1);
	ike = (u_char *)(udp + 1);

	from.sa_in4.sin_addr.s_addr = ip->saddr;
	from.sa_in4.sin_port        = udp->source;

	md->iface = ifp;
	packet_len = h->len - (ike - bytes);

	happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender));

	from_ugh = initaddr((void *) &from.sa_in4.sin_addr,
			    sizeof(from.sa_in4.sin_addr),
			    AF_INET, &md->sender);
	setportof(from.sa_in4.sin_port, &md->sender);
	md->sender_port = ntohs(from.sa_in4.sin_port);

	cur_from      = &md->sender;
	cur_from_port = md->sender_port;

	/* Clone actual message contents
	 * and set up md->packet_pbs to describe it.
	 */
	init_pbs(&md->packet_pbs,
		 clone_bytes(ike, packet_len,
			     "message buffer in comm_handle()"),
		 packet_len, "packet");

	DBG_log("*received %d bytes from %s:%u on %s (port=%d)",
		(int) pbs_room(&md->packet_pbs),
		ip_str(&md->sender), (unsigned) md->sender_port,
		ifp->ip_dev->id_rname,
		ifp->port);

	DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs));

	process_packet(&md);

	if (md != NULL)
		release_md(md);

	cur_state = NULL;
	reset_cur_connection();
	cur_from = NULL;
}
Exemplo n.º 11
0
stf_status send_crypto_helper_request(struct pluto_crypto_req *r,
				 struct pluto_crypto_req_cont *cn)
{
	static int pc_worker_num = 0;	/* index of last worker assigned work */
	struct pluto_crypto_worker *w;	/* best worker for task */
	struct pluto_crypto_worker *c;	/* candidate worker */
	struct state *st = cur_state;	/* TRANSITIONAL */

	/*
	 * transitional: caller must have set pcrc_serialno.
	 * It ought to match cur_state->st_serialno.
	 */
	passert(cn->pcrc_serialno == st->st_serialno);

	passert(st->st_serialno != SOS_NOBODY);
	cn->pcrc_serialno = st->st_serialno;

	passert(cn->pcrc_func != NULL);

	/* do it all ourselves? */
	if (pc_workers == NULL) {
		reset_cur_state();

		pluto_do_crypto_op(r, -1);

		/* call the continuation */
		(*cn->pcrc_func)(cn, r);

		pfree(cn);	/* ownership transferred from caller */

		/* indicate that we completed the work */
		return STF_INLINE;
	}

	/* attempt to send to a worker thread */

	/* set up the id */
	r->pcr_id = pcw_id++;
	cn->pcrc_id = r->pcr_id;
	cn->pcrc_pcr = r;

	/* Find the first of the least-busy workers (if any) */

	w = NULL;
	for (c = pc_workers; c != &pc_workers[pc_workers_cnt]; c++) {
		DBG(DBG_CONTROL,
		    DBG_log("crypto helper %d%s: pcw_work: %d",
			    pc_worker_num,
			    c->pcw_dead? " DEAD" : "",
			    c->pcw_work));

		if (!c->pcw_dead && (w == NULL || c->pcw_work < w->pcw_work)) {
			w = c;	/* c is the best so far */
			if (c->pcw_work == 0)
				break;	/* early out: cannot do better */
		}
	}

	if (w != NULL &&
	    (w->pcw_work < w->pcw_maxbasicwork ||
	      (w->pcw_work < w->pcw_maxcritwork && r->pcr_pcim > pcim_ongoing_crypto)))
	{
		/* allocate task to worker w */

		/* link it to the worker's active list
		 * cn transferred from caller
		 */
		TAILQ_INSERT_TAIL(&w->pcw_active, cn, pcrc_list);

		passert(w->pcw_master_fd != -1);

		cn->pcrc_reply_stream = reply_stream;
		if (pbs_offset(&reply_stream) != 0) {
			/* copy partially built reply stream to heap
			 * IMPORTANT: don't leak this.
			 */
			cn->pcrc_reply_buffer =
				clone_bytes(reply_stream.start,
					    pbs_offset(&reply_stream),
						       "saved reply buffer");
		}

		if (!crypto_write_request(w, r)) {
			/* free the heap space */
			if (pbs_offset(&cn->pcrc_reply_stream) != 0)
				pfree(cn->pcrc_reply_buffer);
			cn->pcrc_reply_buffer = NULL;
			loglog(RC_LOG_SERIOUS, "cannot start crypto helper %d: failed to write",
				w->pcw_helpernum);
			return STF_FAIL;
		}

		w->pcw_work++;
	} else if (r->pcr_pcim >= pcim_demand_crypto) {
		/* Task is important: put it all on the backlog queue for later */

		/* cn transferred from caller */
		TAILQ_INSERT_TAIL(&backlog, cn, pcrc_list);

		/* copy the request */
		r = clone_bytes(r, r->pcr_len, "saved crypto request");
		cn->pcrc_pcr = r;

		cn->pcrc_reply_stream = reply_stream;
		if (pbs_offset(&reply_stream) != 0) {
			/* copy partially built reply stream to heap
			 * IMPORTANT: don't leak this.
			 */
			cn->pcrc_reply_buffer =
				clone_bytes(reply_stream.start,
					    pbs_offset(&reply_stream),
					    "saved reply buffer");
		}

		backlog_queue_len++;
		DBG(DBG_CONTROL,
		    DBG_log("critical demand crypto operation queued on backlog as %dth item; request ID %u",
			    backlog_queue_len, r->pcr_id));
	} else {
		/* didn't find any available workers */
		DBG(DBG_CONTROL,
		    DBG_log("failed to find any available crypto worker (import=%s)",
			    enum_name(&pluto_cryptoimportance_names,
				      r->pcr_pcim)));

		loglog(RC_LOG_SERIOUS, "cannot start crypto helper: failed to find any available worker");

		pfree(cn);	/* ownership transferred from caller */
		return STF_TOOMUCHCRYPTO;
	}

	/* cn ownership transferred on to backlog */

	DBG(DBG_CONTROLMORE, DBG_log("#%lu %s:%u st->st_calculating = TRUE;", st->st_serialno, __FUNCTION__, __LINE__));
	st->st_calculating = TRUE;
	delete_event(st);
	event_schedule(EVENT_CRYPTO_FAILED, EVENT_CRYPTO_FAILED_DELAY, st);

	return STF_SUSPEND;
}
Exemplo n.º 12
0
/*
 * this function is called with a request to do some cryptographic operations
 * along with a continuation structure, which will be used to deal with
 * the response.
 *
 * This may fail if there are no helpers that can take any data, in which
 * case an error is returned.
 *
 */
err_t send_crypto_helper_request(struct pluto_crypto_req *r
				 , struct pluto_crypto_req_cont *cn
				 , bool *toomuch)
{
    struct pluto_crypto_worker *w;
    int cnt;

    /* do it all ourselves? */
    if(pc_workers == NULL) {
	reset_cur_state();

#ifdef HAVE_LIBNSS
	pluto_do_crypto_op(r,pc_helper_num);
#else
	pluto_do_crypto_op(r);
#endif
	/* call the continuation */
	(*cn->pcrc_func)(cn, r, NULL);

	/* indicate that we did everything ourselves */
	*toomuch = TRUE;

	pfree(cn);
	return NULL;
    }

    /* set up the id */
    r->pcr_id = pcw_id++;
    cn->pcrc_id = r->pcr_id;
    cn->pcrc_pcr = r;

    /* find an available worker */
    cnt = pc_workers_cnt;
    do {
	pc_worker_num++;
 	if(pc_worker_num >= pc_workers_cnt) {
 	    pc_worker_num = 0;
 	}
	w = &pc_workers[pc_worker_num];

 	DBG(DBG_CONTROL
 	    , DBG_log("%d: w->pcw_dead: %d w->pcw_work: %d cnt: %d",
 		      pc_worker_num, w->pcw_dead, w->pcw_work, cnt));

	/* see if there is something to clean up after */
	if(w->pcw_dead      == TRUE
	   && w->pcw_reaped == TRUE) {
	    cleanup_crypto_helper(w, 0);
 	    DBG(DBG_CONTROL
 		, DBG_log("clnup %d: w->pcw_dead: %d w->pcw_work: %d cnt: %d",
 			  pc_worker_num, w->pcw_dead, w->pcw_work, cnt));
	}
    } while(((w->pcw_work >= w->pcw_maxbasicwork))
 	    && --cnt > 0);

    if(cnt == 0 && r->pcr_pcim > pcim_ongoing_crypto) {
	cnt = pc_workers_cnt;
 	while((w->pcw_work >= w->pcw_maxcritwork)
	      && --cnt > 0) {

 	    /* find an available worker */
	    pc_worker_num++;
 	    if(pc_worker_num >= pc_workers_cnt) {
 		pc_worker_num = 0;
  	    }

	    w = &pc_workers[pc_worker_num];
	    /* see if there is something to clean up after */
	    if(w->pcw_dead      == TRUE
	       && w->pcw_reaped == TRUE) {
		cleanup_crypto_helper(w, 0);
	    }
	}
	DBG(DBG_CONTROL
	    , DBG_log("crit %d: w->pcw_dead: %d w->pcw_work: %d cnt: %d",
		      pc_worker_num, w->pcw_dead, w->pcw_work, cnt));
    }

    if(cnt == 0 && r->pcr_pcim >= pcim_demand_crypto) {
	/* it is very important. Put it all on a queue for later */

	TAILQ_INSERT_TAIL(&backlog, cn, pcrc_list);

	/* copy the request */
	r = clone_bytes(r, r->pcr_len, "saved cryptorequest");
	cn->pcrc_pcr = r;

	cn->pcrc_reply_stream = reply_stream;
	if (pbs_offset(&reply_stream)) {
	    cn->pcrc_reply_buffer = clone_bytes(reply_stream.start
		    , pbs_offset(&reply_stream), "saved reply buffer");
	}

	backlogqueue_len++;
	DBG(DBG_CONTROL
	    , DBG_log("critical demand crypto operation queued on backlog as %d'th item, id: q#%u"
		      , backlogqueue_len, r->pcr_id));
	*toomuch = FALSE;
	return NULL;
    }

    if(cnt == 0) {
	/* didn't find any workers */
	DBG(DBG_CONTROL
	    , DBG_log("failed to find any available worker (import=%s)"
		      , enum_name(&pluto_cryptoimportance_names,r->pcr_pcim)));

	*toomuch = TRUE;
	return "failed to find any available worker";
    }

    /* w points to a work. Make sure it is live */
    if(w->pcw_pid == -1) {
	init_crypto_helper(w, pc_worker_num);
	if(w->pcw_pid == -1) {
	    DBG(DBG_CONTROL
		, DBG_log("found only a dead helper, and failed to restart it"));
	    *toomuch = TRUE;
	    return "failed to start a new helper";
	}
    }

    /* link it to the active worker list */
    TAILQ_INSERT_TAIL(&w->pcw_active, cn, pcrc_list);

    passert(w->pcw_pid != -1);
    passert(w->pcw_pipe != -1);
    passert(w->pcw_work < w->pcw_maxcritwork);

    cn->pcrc_reply_stream = reply_stream;
    if (pbs_offset(&reply_stream))
	cn->pcrc_reply_buffer = clone_bytes(reply_stream.start
		, pbs_offset(&reply_stream), "saved reply buffer");

    if(!crypto_write_request(w, r)) {
	openswan_log("failed to write crypto request: %s\n",
		     strerror(errno));
	if (pbs_offset(&cn->pcrc_reply_stream))
	    pfree(cn->pcrc_reply_buffer);
	cn->pcrc_reply_buffer = NULL;
	return "failed to write";
    }

    w->pcw_work++;
    *toomuch = FALSE;
    return NULL;
}
Exemplo n.º 13
0
void clone_trans(struct db_trans *tr)
{
    tr->attrs = clone_bytes(tr->attrs
			    , tr->attr_cnt*sizeof(tr->attrs[0])
			    , "sa copy attrs array");
}