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); }
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); }
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); }
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); }
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); }
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); }
/* 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); }
/* 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); }
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; }
/* * 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; } }
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; }