Exemple #1
0
main(int argc, char *argv[]){
	int i;
	struct db_sa *sa1 = NULL;

	progname = argv[0];
	leak_detective = 1;

	tool_init_log();

	for (i = 0; i < elemsof(oakley_sadb); i++) {
		/* make sure that leak reports and EFence reports get
		 * placed in the right order.
		 */
		fflush(stdout);
		fflush(stderr);
		printf("\nmain mode oakley: %u\n", i);
		sa_print(&oakley_sadb[i]);
		sa1 = sa_copy_sa_first(&oakley_sadb[i]);

		sa_print(sa1);

		free_sa(sa1);

		fflush(stdout);
		report_leaks();
	}

	tool_close_log();
	exit(0);
}
Exemple #2
0
main(int argc, char *argv[]){
	int i;
	struct db_sa *gsp = NULL;
	struct db_sa *sa1 = NULL;
	struct db_sa *sa2 = NULL;
	struct alg_info_ike *aii;
	char err_buf[256];	/* ??? big enough? */

	EF_PROTECT_FREE = 1;
	EF_FREE_WIPES  = 1;

	progname = argv[0];
	leak_detective = 1;

	tool_init_log();
	init_crypto();

	aii = alg_info_ike_create_from_str("3des", err_buf, sizeof(err_buf));

	gsp = oakley_alg_makedb(aii,
				&oakley_sadb[POLICY_RSASIG >>
					     POLICY_ISAKMP_SHIFT],
				FALSE);
	sa_print(gsp);

	sa_v2_convert(&gsp);

	sa_v2_print(gsp);

	tool_close_log();

	free_sa(&gsp);
	exit(0);
}
Exemple #3
0
int main(int argc, char *argv[])
{
    int i;
    struct db_sa *sa1 = NULL;
    struct db_sa *sa2 = NULL;

    progname = argv[0];
    leak_detective=1;

    tool_init_log();

    for(i=0; i < elemsof(oakley_sadb); i++) {
	printf("\nmain mode oakley: %u\n", i);
	sa_print(&oakley_sadb[i]);
	sa1 = sa_copy_sa(&oakley_sadb[i], 0);

	if(sa2 != NULL) {
	    free_sa(sa2);
	}
	sa2 = sa_copy_sa(sa1, 0);
	free_sa(sa1);

	printf("copy 2\n");
	sa_print(sa2);
    }

    for(i=0; i < elemsof(oakley_am_sadb); i++) {
	printf("\naggr mode oakley: %u\n", i);
	sa_print(&oakley_am_sadb[i]);
	sa1 = sa_copy_sa(&oakley_am_sadb[i], 0);

	if(sa2 != NULL) {
	    free_sa(sa2);
	}
	sa2 = sa_copy_sa(sa1, 0);
	free_sa(sa1);

	printf("copy 2\n");
	sa_print(sa2);
    }

    if(sa2 != NULL) free_sa(sa2);

    report_leaks();
    tool_close_log();
    exit(0);
}
Exemple #4
0
main(int argc, char *argv[]){
	int i;
	struct db_sa *gsp = NULL;
	struct db_sa *sa1 = NULL;
	struct db_sa *sa2 = NULL;

	progname = argv[0];
	leak_detective = 1;

	tool_init_log();

	for (i = 0; i < elemsof(oakley_sadb); i++) {
		gsp = sa_copy_sa(&oakley_empty, 0);

		printf("\nmain mode oakley: %u\n", i);
		//sa_print(&oakley_sadb[i]);
		sa1 = sa_copy_sa(&oakley_sadb[i], 0);

		sa2 = sa_merge_proposals(gsp, sa1);

		printf("sa1:\n");
		sa_print(sa1);

		printf("gsp:\n");
		sa_print(gsp);

		printf("sa2:\n");
		sa_print(sa2);

		free_sa(sa1);
		free_sa(sa2);
		free_sa(gsp);
		report_leaks();
	}

	tool_close_log();
	exit(0);
}
Exemple #5
0
main(int argc, char *argv[]) {
	int i;
	struct db_sa *gsp = NULL;
	struct db_sa *sa1 = NULL;
	struct db_sa *sa2 = NULL;
	struct alg_info_esp *aii;
	char err_buf[100];

	EF_PROTECT_FREE = 1;
	EF_FREE_WIPES  = 1;
	EF_PROTECT_BELOW = 1;

	progname = argv[0];
	leak_detective = 1;

	tool_init_log();
	init_crypto();

	{
		int algo;
		for (algo = 1; algo <= K_SADB_EALG_MAX; algo++)
			esp_ealg[(algo)].sadb_alg_id = (algo);
	}
	{
		int algo;
		for (algo = 1; algo <= K_SADB_AALG_MAX; algo++)
			esp_aalg[(algo)].sadb_alg_id = (algo);
	}
	esp_ealg_num = 10;
	esp_aalg_num = 10;

	aii = alg_info_esp_create_from_str("aes128-sha1", &err_buf, sizeof(err_buf));

	gsp = kernel_alg_makedb(POLICY_ENCRYPT | POLICY_AUTHENTICATE,
				aii,
				TRUE);
	sa_print(gsp);

	gsp = sa_v2_convert(gsp);

	sa_v2_print(gsp);

	tool_close_log();

	free_sa(gsp);
	exit(0);
}
Exemple #6
0
void _m_free(void *v)
{
	struct alloc_block *ab;

	if (v==NULL) return;

	ab = (struct alloc_block *)((char *)v - (unsigned)&((struct alloc_block*)NULL)->content);
	if (!check_block("Free", ab))
		return;

	free_sa(ab);
	alloc_size-=ab->size;
	--alloc_count;
	memset(ab, 0x33, sizeof *ab + ab->size);
	free(ab);
	//GlobalFree(ab);
}
Exemple #7
0
/* main function for snp */
int main(int argc, char** argv){
	int n, port_p, port_a, ret;
	int fd_chat;
	socklen_t addrlen;
	fd_set rfds;
	int maxfd, counter;
	struct hostent *h;
	struct sockaddr_in addr_chat;
	char opt, input[10];
	char buffer[512];
	char options[128];
	char *cmd;
	char *msg;
	char *surname, *snpip, *snpport;
	char *saip, *saport;
	list *start,*temp;
	start = (list *)malloc(sizeof(list)); 
	
	temp = start;
	temp -> prox = NULL;
	temp -> ant = NULL;
	
	surname = NULL;
	snpip = NULL;
	snpport = NULL;
	saip = NULL;
	saport = NULL;
	
	
	/* usage of getopt function which deals with the input (argv)*/
	strcpy(input, "n:s:q:i:p:");
	while((opt = getopt(argc, argv, input))!=-1){
		if(opt == '?'){
			if(optopt == 'n' || optopt == 's' || optopt == 'q' || optopt == 'i' || optopt == 'p'){
				write(1, "Required arg for option -", strlen("Required arg for option -"));
				printf("%c", optopt);
				write(1, "\n", 1);
			}
			else if(isprint(optopt)) {
				write(1,"Unknown option -", strlen("Unknown option -"));
				printf("%c", optopt);
				write(1, "\n", 1);
			}
			else{
				printf("Unknown option character `\\x%x`.\n",optopt);
			}
			return -1;
		}
		if(opt == 'n'){
			surname = optarg;
		}
		if(opt == 's'){
			snpip = optarg;			
		}
		if(opt == 'q'){
			snpport = optarg;			
		}
		if(opt == 'i'){
			saip = optarg;			
		}
		if(opt == 'p'){
			saport = optarg;
		}		
	}

   	/* check if surname, ip and port were given from argv otherwise close */
	if(surname == NULL || snpip == NULL || snpport == NULL){
		exit(1);
	}
	
	/* since it is not mandatory to give the ip of the sa: */ 
	/* we need to check if it was given or if we should use the default (tejo) */
	if(saip == NULL){
		/* connect to the sa, tejo in this case */
		h = gethostbyname("tejo.tecnico.ulisboa.pt");
		if(h == NULL){
			write(1, "Unable to reach sa (tejo)\n", strlen("Unable to reach sa (tejo)\n"));
			exit(1);
		}
	}else{
		/* connect to the sa, other than tejo in this case */
		inet_pton(AF_INET, saip, &temp);
		h = gethostbyaddr(&temp,sizeof(temp),AF_INET);
		if(h == NULL){
			write(1, "Unable to reach sa\n", strlen("Unable to reach sa\n"));
			exit(1);
		}
	}
	
	/* since it is not mandatory to give the port of the sa: */ 
	/* we need to check if it was given or if we should use the default (58000) */
	if(saport == NULL){
		/* no port given */
		port_a = 58000;
	}else{
		/* get port given by input */
		port_a = atoi(saport);
	}

	/* get port given by input for this snp */
	if(sscanf(snpport, "%d\n", &port_p) != 1) {
		write(1, "Not a valid port\n", strlen("Not a valid port\n"));
		exit(1);
	}
	
	/* initializes the socket used to communicate with schats */	
	fd_chat = socket(AF_INET,SOCK_DGRAM, 0);
	if(fd_chat == -1) exit(1);
	
	sscanf(snpport,"%d\n",&port_p);
	memset((void*)&addr_chat, (int)'\0', sizeof(addr_chat));
	addr_chat.sin_family = AF_INET;
	addr_chat.sin_addr.s_addr = htonl(INADDR_ANY);
	addr_chat.sin_port = htons(port_p);

	ret = bind(fd_chat, (struct sockaddr*)&addr_chat, sizeof(addr_chat));
	if(ret == -1) exit(1);
	
	/* register the snp server in the sa serverc*/
	init_sa(h, port_a, surname, snpip, snpport);


	while(1){
		FD_ZERO(&rfds);
		FD_SET(fd_chat,&rfds);
		FD_SET(fileno(stdin), &rfds);
		maxfd = max(fd_chat,fileno(stdin));
		
		/* returns the number of file descriptors ready */
		counter = select(maxfd+1, &rfds, (fd_set*)NULL, (fd_set*)NULL, (struct timeval *)NULL);
		if(counter <= 0) exit(1);
		
		if(FD_ISSET(fileno(stdin), &rfds)){
			fgets(options, 128, stdin);		
			if(strcmp(options, "list\n") == 0){
				/* The typed command is LIST */
				imprime_lista(start->prox);
			}else{
				if(strcmp(options, "exit\n") == 0){
					/* The typed command is EXIT */
					free_sa( h, 58000, surname);
					break;
				}
				else write(1, "Not an option\nThe options are: \n1)list\n2)exit\n", strlen("Not an option\nThe options are: \n1)list\n2)exit\n"));
			}
		}

		if(FD_ISSET(fd_chat, &rfds)){ /*fd_chat is ready*/
			memset(buffer,0,strlen(buffer));
			addrlen = sizeof(addr_chat);
			n = recvfrom(fd_chat, buffer, 128, 0, (struct sockaddr*)&addr_chat, &addrlen);
			if(n == -1) exit(1);
			/* Received command */
			buffer[n] = '\0';
			cmd = (char*) malloc(sizeof(char)*4);
			strncpy(cmd,buffer, 3);
			cmd[3] = '\0';

			if(choose_command(cmd)==0){
				/* The received command is to register a user (REG) */
				msg = register_new(start, buffer, n, surname);
				n = sendto(fd_chat, msg, strlen(msg), 0, (struct sockaddr*)&addr_chat, addrlen);
				if(n==-1) {
					write(1, "NOK message not sent. Error replying!", strlen("NOK message not sent. Error replying!"));
				}
			}
			if(choose_command(cmd) == 1){
				/* The received command is to delete a registered user (UNR) */
				msg = u_unregister(start, buffer, n, surname);
				n = sendto(fd_chat, msg, strlen(msg), 0, (struct sockaddr*)&addr_chat, addrlen);
				if(n==-1) {
					write(1, "NOK message not sent. Error replying!", strlen("NOK message not sent. Error replying!"));
				}
			}
			/* The received command is to query a user (QRY) */
			if(choose_command(cmd) == 2){
				msg = do_qry(start, buffer, n, h, 58000, surname);
				n = sendto(fd_chat, msg, strlen(msg), 0, (struct sockaddr*)&addr_chat, addrlen);		
				if(n==-1) {
					write(1, "NOK message not sent. Error replying!", strlen("NOK message not sent. Error replying!"));
				}
			}
			free(cmd);

		}
		
	}
	close(fd_chat);
	free(start);
    exit(0);
}
Exemple #8
0
/* here we are just freeing RAM */
void free_state(struct state *st)
{
    delete_event(st);	/* delete any pending timer event */

    {
	struct msgid_list *p = st->st_used_msgids;

	while (p != NULL)
	{
	    struct msgid_list *q = p;
	    p = p->next;
	    pfree(q);
	}
    }

    unreference_key(&st->st_peer_pubkey);

    free_sa(st->st_sadb);
    st->st_sadb=NULL;

    if (st->st_sec_in_use) {
#ifdef HAVE_LIBNSS
	SECKEYPrivateKey *privk;
	SECKEYPublicKey   *pubk;
	memcpy(&pubk,st->pubk.ptr,st->pubk.len);
	SECKEY_DestroyPublicKey(pubk);
	freeanychunk(st->pubk);
	memcpy(&privk,st->st_sec_chunk.ptr,st->st_sec_chunk.len);
	SECKEY_DestroyPrivateKey(privk);
#else
	mpz_clear(&(st->st_sec));
#endif
	pfreeany(st->st_sec_chunk.ptr);
    }

    freeanychunk(st->st_firstpacket_me);
    freeanychunk(st->st_firstpacket_him);
    freeanychunk(st->st_tpacket);
    freeanychunk(st->st_rpacket);
    freeanychunk(st->st_p1isa);
    freeanychunk(st->st_gi);
    freeanychunk(st->st_gr);
    freeanychunk(st->st_shared);
    freeanychunk(st->st_ni);
    freeanychunk(st->st_nr);
#ifdef HAVE_LIBNSS
    free_osw_nss_symkey(st->st_skeyid);
    free_osw_nss_symkey(st->st_skey_d);
    free_osw_nss_symkey(st->st_skey_ai);
    free_osw_nss_symkey(st->st_skey_ar);
    free_osw_nss_symkey(st->st_skey_ei);
    free_osw_nss_symkey(st->st_skey_er);
    free_osw_nss_symkey(st->st_skey_pi);
    free_osw_nss_symkey(st->st_skey_pr);
    free_osw_nss_symkey(st->st_enc_key);

    if(st->st_ah.our_keymat!=NULL)
    memset(st->st_ah.our_keymat, 0, st->st_ah.keymat_len);

    if(st->st_ah.peer_keymat!=NULL)
    memset(st->st_ah.peer_keymat, 0, st->st_ah.keymat_len);

    if(st->st_esp.our_keymat!=NULL)
    memset(st->st_esp.our_keymat, 0, st->st_esp.keymat_len);

    if(st->st_esp.peer_keymat!=NULL)
    memset(st->st_esp.peer_keymat, 0, st->st_esp.keymat_len);
#endif
    freeanychunk(st->st_skeyid);
    freeanychunk(st->st_skey_d);
    freeanychunk(st->st_skey_ai);
    freeanychunk(st->st_skey_ar);
    freeanychunk(st->st_skey_ei);
    freeanychunk(st->st_skey_er);
    freeanychunk(st->st_skey_pi);
    freeanychunk(st->st_skey_pr);
    freeanychunk(st->st_enc_key);
    pfreeany(st->st_ah.our_keymat);
    pfreeany(st->st_ah.peer_keymat);
    pfreeany(st->st_esp.our_keymat);
    pfreeany(st->st_esp.peer_keymat);
    freeanychunk(st->st_xauth_password);
#ifdef HAVE_LABELED_IPSEC
    pfreeany(st->sec_ctx);
#endif
    pfree(st);
}
Exemple #9
0
struct db_sa *oakley_alg_mergedb(struct alg_info_ike *ai,
				 enum ikev1_auth_method auth_method,
				 bool single_dh)
{
	passert(ai != NULL);

	struct db_sa *gsp = NULL;

	/* Next two are for multiple proposals in aggressive mode... */
	unsigned last_modp = 0;
	bool warned_dropped_dhgr = FALSE;

	int transcnt = 0;

	/*
	 * for each group, we will create a new proposal item, and then
	 * append it to the list of transforms in the conjoint point.
	 *
	 * when creating each item, we will use the first transform
	 * from the base item as the template.
	 */
	FOR_EACH_IKE_INFO(ai, ike_info) {
		struct db_sa *emp_sp;

		passert(ike_info->ike_encrypt);
		passert(ike_info->ike_prf);
		passert(ike_info->ike_dh_group);

		unsigned ealg = ike_info->ike_encrypt->common.ikev1_oakley_id;
		unsigned halg = ike_info->ike_prf->common.ikev1_oakley_id;
		unsigned modp = ike_info->ike_dh_group->group;
		unsigned eklen = ike_info->ike_eklen;

		DBG(DBG_CONTROL,
		    DBG_log("oakley_alg_makedb() processing ealg=%s=%u halg=%s=%u modp=%s=%u eklen=%u",
			    ike_info->ike_encrypt->common.name, ealg,
			    ike_info->ike_prf->common.name, halg,
			    ike_info->ike_dh_group->common.name, modp,
			    eklen));

		const struct encrypt_desc *enc_desc = ike_info->ike_encrypt;
		if (eklen != 0 && !encrypt_has_key_bit_length(enc_desc, eklen)) {
			PEXPECT_LOG("IKEv1 proposal with ENCRYPT%s (specified) keylen:%d, not valid, should have been dropped",
				    enc_desc->common.name,
				    eklen);
			continue;
		}

		/*
		 * copy the template
		 */
		emp_sp = sa_copy_sa(&oakley_empty);
		passert(emp_sp->dynamic);
		passert(emp_sp->prop_conj_cnt == 1);
		passert(emp_sp->prop_conjs[0].prop_cnt == 1);
		passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);
		struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0];
		passert(trans->attr_cnt == 5);

		/*
		 * See "struct db_attr otempty" above, and spdb.c, for
		 * where these magic values come from.
		 */
		struct db_attr *enc  = &trans->attrs[0];
		struct db_attr *hash = &trans->attrs[1];
		struct db_attr *auth = &trans->attrs[2];
		struct db_attr *grp  = &trans->attrs[3];

		/*
		 * auth type for IKE must be set.
		 */
		passert(auth->type.oakley == OAKLEY_AUTHENTICATION_METHOD);
		auth->val = auth_method;

		if (eklen > 0) {
			struct db_attr *enc_keylen = &trans->attrs[4];

			passert(trans->attr_cnt == 5);
			passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH);
			enc_keylen->val = eklen;
		} else {
			/* truncate */
			trans->attr_cnt = 4;
		}

		passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM);
		if (ealg > 0)
			enc->val = ealg;

		/*
		 * Either pass a hash algorithm or a PRF.
		 *
		 * Since AEAD algorithms don't need the hash,
		 * but do need a PRF, the hash field can be
		 * re-purposed as a PRF field.
		 *
		 * [cagney] While I suspect that type will
		 * never initially be OAKLEY_PRF (it is
		 * initialized using "struct db_attr otempty")
		 * it doesn't hurt to be safe.
		 */
		passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM ||
			hash->type.oakley == OAKLEY_PRF);
		if (halg > 0) {
			hash->val = halg;
			if (ike_alg_enc_requires_integ(enc_desc)) {
				hash->type.oakley = OAKLEY_HASH_ALGORITHM;
			} else {
				hash->type.oakley = OAKLEY_PRF;
			}
		}

		passert(grp->type.oakley == OAKLEY_GROUP_DESCRIPTION);
		if (modp > 0)
			grp->val = modp;

		/*
		 * Aggressive mode really only works with a single DH group.
		 * If this is for Aggressive Mode, and we've previously seen
		 * a different DH group, we try to deal with this.
		 */
		if (single_dh && transcnt > 0 &&
		    ike_info->ike_dh_group->group != last_modp) {
			if (last_modp == OAKLEY_GROUP_MODP1024 ||
			    last_modp == OAKLEY_GROUP_MODP1536) {
				/*
				 * The previous group will work on old Cisco gear,
				 * so we can discard this one.
				 */

				if (!warned_dropped_dhgr) {
					/* complain only once */
					loglog(RC_LOG_SERIOUS,
						"multiple DH groups were set in aggressive mode. Only first one used.");
				}

				loglog(RC_LOG_SERIOUS,
				       "transform (%s,%s,%s keylen %ld) ignored.",
				       enum_name(&oakley_enc_names,
						 ike_info->ike_encrypt->common.ikev1_oakley_id),
				       enum_name(&oakley_hash_names,
						 ike_info->ike_prf->common.ikev1_oakley_id),
				       ike_info->ike_dh_group->common.name,
				       (long)ike_info->ike_eklen);
				free_sa(&emp_sp);
			} else {
				/*
				 * The previous group won't work on old Cisco gear,
				 * so we discard the previous ones.
				 * Of course this modp might be just as bad;
				 * we won't look until the next one comes along.
				 *
				 * Lemma: there will be only a single previous
				 * one in gsp (any others were discarded).
				 */
				loglog(RC_LOG_SERIOUS,
				       "multiple DH groups in aggressive mode can cause interop failure");
				loglog(RC_LOG_SERIOUS,
					"Deleting previous proposal in the hopes of selecting DH 2 or DH 5");

				free_sa(&gsp);
			}

			warned_dropped_dhgr = TRUE;
		}

		 if (emp_sp != NULL) {

			 /*
			  * Exclude 3des et.al. which do not include
			  * default key lengths in the proposal.
			  */
			 if (ike_info->ike_eklen == 0
			     && !ike_info->ike_encrypt->keylen_omitted) {

				const struct encrypt_desc *enc_desc = ike_info->ike_encrypt;
				int def_ks = enc_desc->keydeflen;
				passert(def_ks); /* ike=null not supported */
				int max_ks = encrypt_max_key_bit_length(enc_desc);
				int ks;

				passert(emp_sp->dynamic);
				passert(emp_sp->prop_conj_cnt == 1);
				passert(emp_sp->prop_conjs[0].prop_cnt == 1);
				passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

				if (emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 4) {
					/* add a key length attribute of 0 */
					struct db_trans *tr = &emp_sp->prop_conjs[0].props[0].trans[0];
					const int n = tr->attr_cnt;	/* 4, actually */
					struct db_attr *old_attrs = tr->attrs;
					struct db_attr *new_attrs = alloc_bytes(
						(n + 1) * sizeof(old_attrs[0]),
						"extended trans");

					passert(emp_sp->dynamic);
					passert(old_attrs[0].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[1].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[2].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[3].type.oakley != OAKLEY_KEY_LENGTH);
					memcpy(new_attrs, old_attrs, n * sizeof(old_attrs[0]));
					new_attrs[n].type.oakley = OAKLEY_KEY_LENGTH;
					new_attrs[n].val = 0;

					pfree(old_attrs);
					tr->attrs = new_attrs;
					tr->attr_cnt++;
				}
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 5);
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].type.oakley == OAKLEY_KEY_LENGTH);

				/*
				 * This odd FOR loop executes its body for
				 * exactly two values of ks (max_ks and def_ks)
				 * unless def_ks == max_ks, in which case it is
				 * executed once.
				 */
				for (ks = max_ks; ; ks = def_ks) {
					emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].val = ks;

					if (gsp == NULL) {
						gsp = sa_copy_sa(emp_sp);
					} else {
						struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

						free_sa(&gsp);
						gsp = new;
					}
					if (ks == def_ks)
						break;
				}
				free_sa(&emp_sp);
			} else {
				if (gsp != NULL) {
					/* now merge emp_sa and gsp */
					struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

					free_sa(&gsp);
					free_sa(&emp_sp);
					gsp = new;
				} else {
					gsp = emp_sp;
					emp_sp = NULL;
				}
			}
			last_modp = ike_info->ike_dh_group->group;
		}
Exemple #10
0
/*
 * Create an OAKLEY proposal based on alg_info and policy
 *
 * single_dh is for Aggressive Mode where we must have exactly
 * one DH group.
 */
struct db_sa *oakley_alg_makedb(struct alg_info_ike *ai,
				struct db_sa *base,
				bool single_dh)
{
	struct db_sa *gsp = NULL;
	struct ike_info *ike_info;

	/* Next two are for multiple proposals in agressive mode... */
	unsigned last_modp = 0;
	bool warned_dropped_dhgr = FALSE;

	int transcnt = 0;
	int i;

	/*
	 * start by copying the proposal that would have been picked by
	 * standard defaults.
	 */

	if (ai == NULL) {
		DBG(DBG_CONTROL, DBG_log(
			    "no specific IKE algorithms specified - using defaults"));
		return NULL;
	}

	/*
	 * for each group, we will create a new proposal item, and then
	 * append it to the list of transforms in the conjoint point.
	 *
	 * when creating each item, we will use the first transform
	 * from the base item as the template.
	 */
	ALG_INFO_IKE_FOREACH(ai, ike_info, i) {
		struct db_sa *emp_sp;

		unsigned ealg = ike_info->ike_ealg;
		unsigned halg = ike_info->ike_halg;
		unsigned modp = ike_info->ike_modp;
		unsigned eklen = ike_info->ike_eklen;

		DBG(DBG_CONTROL,
		    DBG_log("oakley_alg_makedb() "
			    "processing ealg=%u halg=%u modp=%u eklen=%u",
			    ealg, halg, modp, eklen));

		const struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ealg);

		if (enc_desc == NULL) {
			DBG_log("oakley_alg_makedb() "
				"ike enc ealg=%d not present",
				ealg);
			continue;
		}
		passert(enc_desc != NULL);

		if (ike_alg_enc_requires_integ(enc_desc)) {
			if (!ike_alg_hash_present(halg)) {
				DBG_log("oakley_alg_makedb() "
					"ike hash halg=%d not present but required for integrity",
					halg);
				continue;
			}
		} else {
			if (!ike_alg_hash_present(halg)) {
				DBG_log("oakley_alg_makedb() "
					"ike PRF=%d not present but needed for AEAD",
					halg);
				continue;
			}
		}

		if (eklen != 0 &&
		    (eklen < enc_desc->keyminlen ||
		     eklen > enc_desc->keymaxlen)) {
			DBG_log("ike_alg_db_new() ealg=%d (specified) keylen:%d, not valid min=%d, max=%d",
				ealg,
				eklen,
				enc_desc->keyminlen,
				enc_desc->keymaxlen);
			continue;
		}

		/*
		 * copy the basic item, and modify it.
		 *
		 * ??? what are these two cases and why does
		 * eklen select between them?
		 *
		 * [cagney] I suspect that this is to
		 * compensate for logic further down that,
		 * when eklen==0, truncates the attrs array to
		 * 4 elements and sa_copy_sa_first() when
		 * applied to that structure won't allocate
		 * space for the 5th (eklen) element - oops.
		 * To be honest, the attrs should be a list OR
		 * the eklen>0 path should always be taken OR
		 * ...
		 *
		 * The convoluted assignment is copying the
		 * auth field (see "struct db_attr otempty"
		 * above), from base to the new proposal.
		 */
		if (eklen > 0) {
			/* duplicate, but change auth to match template */
			emp_sp = sa_copy_sa(&oakley_empty);
			emp_sp->prop_conjs[0].props[0].trans[0].attrs[2] =
				base->prop_conjs[0].props[0].trans[0].attrs[2];
		} else {
			emp_sp = sa_copy_sa_first(base);
		}

		passert(emp_sp->dynamic);
		passert(emp_sp->prop_conj_cnt == 1);
		passert(emp_sp->prop_conjs[0].prop_cnt == 1);
		passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

		struct db_trans *trans = &emp_sp->prop_conjs[0].props[0].trans[0];

		/*
		 * See "struct db_attr otempty" above for
		 * where these magic values come from.
		 */
		passert(trans->attr_cnt == 4 || trans->attr_cnt == 5);
		struct db_attr *enc  = &trans->attrs[0];
		struct db_attr *hash = &trans->attrs[1];
		struct db_attr *auth = &trans->attrs[2];
		struct db_attr *grp  = &trans->attrs[3];

		if (eklen > 0) {
			struct db_attr *enc_keylen = &trans->attrs[4];

			passert(trans->attr_cnt == 5);
			passert(enc_keylen->type.oakley == OAKLEY_KEY_LENGTH);
			enc_keylen->val = eklen;
		} else {
			/* truncate */
			trans->attr_cnt = 4;
		}

		passert(enc->type.oakley == OAKLEY_ENCRYPTION_ALGORITHM);
		if (ealg > 0)
			enc->val = ealg;

		/*
		 * Either pass a hash algorithm or a PRF.
		 *
		 * Since AEAD algorithms don't need the hash,
		 * but do need a PRF, the hash field can be
		 * re-purposed as a PRF field.
		 *
		 * [cagney] While I suspect that type will
		 * never initially be OAKLEY_PRF (it is
		 * initialized using "struct db_attr otempty")
		 * it doesn't hurt to be safe.
		 */
		passert(hash->type.oakley == OAKLEY_HASH_ALGORITHM ||
			hash->type.oakley == OAKLEY_PRF);
		if (halg > 0) {
			hash->val = halg;
			if (ike_alg_enc_requires_integ(enc_desc)) {
				hash->type.oakley = OAKLEY_HASH_ALGORITHM;
			} else {
				hash->type.oakley = OAKLEY_PRF;
			}
		}

		/*
		 * auth type for IKE must be set.
		 *
		 * Logic above uses sa_copy_sa or brute force
		 * to copy the field from BASE.
		 *
		 * ??? until we support AES-GCM in IKE
		 *
		 * [cagney] aes-gcm doesn't require HASH, just
		 * the PRF, so auth is unrelated?
		 */
		passert(auth->type.oakley ==
			OAKLEY_AUTHENTICATION_METHOD);

		passert(grp->type.oakley == OAKLEY_GROUP_DESCRIPTION);
		if (modp > 0)
			grp->val = modp;

		/*
		 * Aggressive mode really only works with a single DH group.
		 * If this is for Aggressive Mode, and we've previously seen
		 * a different DH group, we try to deal with this.
		 */
		if (single_dh && transcnt > 0 &&
		    ike_info->ike_modp != last_modp) {
			if (last_modp == OAKLEY_GROUP_MODP1024 ||
			    last_modp == OAKLEY_GROUP_MODP1536) {
				/*
				 * The previous group will work on old Cisco gear,
				 * so we can discard this one.
				 */

				if (!warned_dropped_dhgr) {
					/* complain only once */
					loglog(RC_LOG_SERIOUS,
						"multiple DH groups were set in aggressive mode. Only first one used.");
				}

				loglog(RC_LOG_SERIOUS,
					"transform (%s,%s,%s keylen %ld) ignored.",
					enum_name(&oakley_enc_names, ike_info->ike_ealg),
					enum_name(&oakley_hash_names, ike_info->ike_halg),
					enum_name(&oakley_group_names, ike_info->ike_modp),
					(long)ike_info->ike_eklen);
				free_sa(&emp_sp);
			} else {
				/*
				 * The previous group won't work on old Cisco gear,
				 * so we discard the previous ones.
				 * Of course this modp might be just as bad;
				 * we won't look until the next one comes along.
				 *
				 * Lemma: there will be only a single previous
				 * one in gsp (any others were discarded).
				 */
				loglog(RC_LOG_SERIOUS,
				       "multiple DH groups in aggressive mode can cause interop failure");
				loglog(RC_LOG_SERIOUS,
					"Deleting previous proposal in the hopes of selecting DH 2 or DH 5");

				free_sa(&gsp);
			}

			warned_dropped_dhgr = TRUE;
		}

		 if (emp_sp != NULL) {
			int def_ks = 0;

			if (ike_info->ike_eklen == 0)
				def_ks = crypto_req_keysize(CRK_IKEv1, ike_info->ike_ealg);

			if (def_ks != 0) {
				const struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg);
				int max_ks = enc_desc->keymaxlen;
				int ks;

				passert(emp_sp->dynamic);
				passert(emp_sp->prop_conj_cnt == 1);
				passert(emp_sp->prop_conjs[0].prop_cnt == 1);
				passert(emp_sp->prop_conjs[0].props[0].trans_cnt == 1);

				if (emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 4) {
					/* add a key length attribute of 0 */
					struct db_trans *tr = &emp_sp->prop_conjs[0].props[0].trans[0];
					const int n = tr->attr_cnt;	/* 4, actually */
					struct db_attr *old_attrs = tr->attrs;
					struct db_attr *new_attrs = alloc_bytes(
						(n + 1) * sizeof(old_attrs[0]),
						"extended trans");

					passert(emp_sp->dynamic);
					passert(old_attrs[0].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[1].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[2].type.oakley != OAKLEY_KEY_LENGTH &&
						old_attrs[3].type.oakley != OAKLEY_KEY_LENGTH);
					memcpy(new_attrs, old_attrs, n * sizeof(old_attrs[0]));
					new_attrs[n].type.oakley = OAKLEY_KEY_LENGTH;
					new_attrs[n].val = 0;

					pfree(old_attrs);
					tr->attrs = new_attrs;
					tr->attr_cnt++;
				}
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attr_cnt == 5);
				passert(emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].type.oakley == OAKLEY_KEY_LENGTH);

				/*
				 * This odd FOR loop executes its body for
				 * exactly two values of ks (def_ks and max_ks)
				 * unless def_ks == max_ks, in which case it is
				 * executed once.
				 */
				for (ks = def_ks; ; ks = max_ks) {
					emp_sp->prop_conjs[0].props[0].trans[0].attrs[4].val = ks;

					if (gsp == NULL) {
						gsp = sa_copy_sa(emp_sp);
					} else {
						struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

						free_sa(&gsp);
						gsp = new;
					}
					if (ks == max_ks)
						break;
				}
				free_sa(&emp_sp);
			} else {
				if (gsp != NULL) {
					/* now merge emp_sa and gsp */
					struct db_sa *new = sa_merge_proposals(gsp, emp_sp);

					free_sa(&gsp);
					free_sa(&emp_sp);
					gsp = new;
				} else {
					gsp = emp_sp;
					emp_sp = NULL;
				}
			}
Exemple #11
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;
}