/* compare two struct id values, DNs can contain wildcards */ bool match_id(const struct id *a, const struct id *b, int *wildcards) { bool match; if (b->kind == ID_NONE) { *wildcards = MAX_WILDCARDS; match = TRUE; } else if (a->kind != b->kind) { match = FALSE; } else if (a->kind == ID_DER_ASN1_DN) { match = match_dn(a->name, b->name, wildcards); } else { *wildcards = 0; match = same_id(a, b); } DBG(DBG_CONTROLMORE, { char abuf[IDTOA_BUF]; char bbuf[IDTOA_BUF]; idtoa(a, abuf, IDTOA_BUF); idtoa(b, bbuf, IDTOA_BUF); DBG_log(" match_id a=%s", abuf); DBG_log(" b=%s", bbuf); DBG_log(" results %s", match ? "matched" : "fail"); });
struct secret *pick_key(struct secret *host_secrets , char *idname) { struct id id; struct secret *s; err_t e; e = atoid(idname, &id, FALSE); if(e) { printf("%s: key '%s' is invalid\n", progname, idname); exit(4); } s = osw_find_secret_by_id(host_secrets, PPK_RSA , &id, NULL, TRUE /* asymmetric */); if(s==NULL) { char abuf[IDTOA_BUF]; idtoa(&id, abuf, IDTOA_BUF); printf("%s: can not find key: %s (%s)\n", progname, idname, abuf); exit(5); } return s; }
void show_myid_status(void) { char idstr[IDTOA_BUF]; (void)idtoa(&myids[myid_state], idstr, sizeof(idstr)); whack_log(RC_COMMENT, "myid = %s", idstr); }
static void key_add_ugh(const struct id *keyid, err_t ugh) { char name[IDTOA_BUF]; /* longer IDs will be truncated in message */ (void)idtoa(keyid, name, sizeof(name)); loglog(RC_NOKEY, "failure to fetch key for %s from DNS: %s", name, ugh); }
static void calc_myid_str(enum myid_state s) { /* preformat the ID name */ char buf[IDTOA_BUF]; idtoa(&myids[s], buf, IDTOA_BUF); /* replace() uses pfreeany() */ replace(myid_str[s], clone_str(buf, "myid string")); }
void block_peer_log(const char *msg, block_peer *peer) { char peer_ip_str[IDTOA_BUF]; struct id id; iptoid(&peer->ip, &id); idtoa(&id, peer_ip_str, IDTOA_BUF); loglog(RC_LOG_SERIOUS, msg, peer_ip_str); }
static void print(struct private_key_stuff *pks, int count, struct id *id, bool disclose) { char idb[IDTOA_BUF] = "n/a"; if (id) { idtoa(id, idb, IDTOA_BUF); } char pskbuf[128] = ""; if (pks->kind == PPK_PSK || pks->kind == PPK_XAUTH) { datatot(pks->u.preshared_secret.ptr, pks->u.preshared_secret.len, 'x', pskbuf, sizeof(pskbuf)); } if (count) { /* ipsec.secrets format */ printf("%d(%d): ", pks->line, count); } else { /* NSS format */ printf("<%2d> ", pks->line); } switch (pks->kind) { case PPK_PSK: printf("PSK keyid: %s\n", idb); if (disclose) printf(" psk: \"%s\"\n", pskbuf); break; case PPK_RSA: { printf("RSA"); char *keyid = pks->u.RSA_private_key.pub.keyid; printf(" keyid: %s", keyid[0] ? keyid : "<missing-pubkey>"); if (id) { printf(" id: %s", idb); } char *ckaid = ckaid_as_string(pks->u.RSA_private_key.pub.ckaid); printf(" ckaid: %s\n", ckaid); pfree(ckaid); break; } case PPK_XAUTH: printf("XAUTH keyid: %s\n", idb); if (disclose) printf(" xauth: \"%s\"\n", pskbuf); break; case PPK_NULL: /* can't happen but the compiler does not know that */ printf("NULL authentication -- cannot happen: %s\n", idb); abort(); } }
int print_key(struct secret *secret , struct private_key_stuff *pks , void *uservoid, bool disclose) { int lineno = osw_get_secretlineno(secret); struct id_list *l = osw_get_idlist(secret); char idb[IDTOA_BUF]; int count=1; char pskbuf[128]; if(pks->kind == PPK_PSK || pks->kind==PPK_XAUTH) { datatot(pks->u.preshared_secret.ptr, pks->u.preshared_secret.len, 'x', pskbuf, sizeof(pskbuf)); } while(l) { idtoa(&l->id, idb, IDTOA_BUF); switch(pks->kind) { case PPK_PSK: printf("%d(%d): PSK keyid: %s\n", lineno, count, idb); if(disclose) printf(" psk: \"%s\"\n", pskbuf); break; case PPK_RSA: printf("%d(%d): RSA keyid: %s with id: %s\n", lineno, count, pks->u.RSA_private_key.pub.keyid,idb); break; case PPK_XAUTH: printf("%d(%d): XAUTH keyid: %s\n", lineno, count, idb); if(disclose) printf(" xauth: \"%s\"\n", pskbuf); break; case PPK_PIN: printf("%d:(%d) PIN key-type not yet supported for id: %s\n", lineno, count, idb); break; } l=l->next; count++; } return 1; }
/** Lookup information about the hostpair, and set things like bandwidth * relative crypto strength, compression and credentials. * * @param IPsec Policy Query * @return void */ static void info_lookuphostpair(struct ipsec_policy_cmd_query *ipcq) { struct connection *c; struct state *p1st, *p2st; /* default result: no crypto */ ipcq->strength = IPSEC_PRIVACY_NONE; ipcq->bandwidth = IPSEC_QOS_WIRESPEED; ipcq->credential_count = 0; #ifdef DEBUG { char sstr[ADDRTOT_BUF], dstr[ADDRTOT_BUF]; addrtot(&ipcq->query_local, 0, sstr, sizeof(sstr)); addrtot(&ipcq->query_remote, 0, dstr, sizeof(dstr)); DBG_log("info request for %s -> %s", sstr, dstr); } #endif /* okay, look up what connection handles this ip pair */ c = find_connection_for_clients(NULL, &ipcq->query_local, &ipcq->query_remote, ipcq->proto); if (c == NULL) { /* try reversing it */ c = find_connection_for_clients(NULL, &ipcq->query_remote, &ipcq->query_local, ipcq->proto); if (c != NULL) { ip_address tmp; /* If it is reversed, swap it */ tmp = ipcq->query_local; ipcq->query_local = ipcq->query_remote; ipcq->query_remote = tmp; } } if (c == NULL) { #ifdef DEBUG DBG_log("no connection found"); #endif return; /* no crypto */ } if (c->newest_ipsec_sa == SOS_NOBODY) { ip_subnet us, them; DBG_log("connection %s found, no ipsec state, looking again", c->name); addrtosubnet(&ipcq->query_local, &us); addrtosubnet(&ipcq->query_remote, &them); c = find_client_connection(c, &us, &them, 0, 0, 0, 0); if (c == NULL) return; /* no crypto */ } DBG_log("connection %s[%ld] with state %u" , c->name, c->instance_serial , (unsigned int)c->newest_ipsec_sa); if (c->newest_ipsec_sa == SOS_NOBODY) return; /* no crypto */ /* we found a connection, try to lookup the state */ p2st = state_with_serialno(c->newest_ipsec_sa); p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); if (p1st == NULL || p2st == NULL) { DBG_log("connection %s[%ld] has missing states %s %s" , c->name, c->instance_serial , (p1st ? "phase1" : "") , (p2st ? "phase1" : "")); return; /* no crypto */ } /* if we have AH present, then record minimal info */ if (p2st->st_ah.present) { ipcq->strength = IPSEC_PRIVACY_INTEGRAL; ipcq->auth_detail = p2st->st_esp.attrs.transattrs.integ_hash; } if (p2st->st_esp.present) { /* * XXX-mcr Please do not shout at me about relative strengths * here. I'm not a cryptographer. I just diddle bits. */ switch (p2st->st_esp.attrs.transattrs.encrypt) { case ESP_NULL: /* actually, do not change it if we set it from AH */ break; case ESP_DES: case ESP_DES_IV64: case ESP_DES_IV32: case ESP_RC4: ipcq->strength = IPSEC_PRIVACY_ROT13; break; case ESP_RC5: case ESP_IDEA: case ESP_CAST: case ESP_BLOWFISH: case ESP_3DES: ipcq->strength = IPSEC_PRIVACY_PRIVATE; ipcq->bandwidth = IPSEC_QOS_VOIP; break; case ESP_3IDEA: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_INTERACTIVE; break; case ESP_AES: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_FTP; break; } ipcq->esp_detail = p2st->st_esp.attrs.transattrs.encrypt; } if (p2st->st_ipcomp.present) ipcq->comp_detail = p2st->st_esp.attrs.transattrs.encrypt; /* now! the credentails that were used */ /* for the moment we only have 1 credential, the DNS name, * because the DNS servers do not return the chain of SIGs yet */ if(!c->spd.this.key_from_DNS_on_demand) { /* the key didn't come from the DNS in some way, * so it must have been loaded locally. */ ipcq->credential_count = 1; ipcq->credentials[0].ii_type = c->spd.this.id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; } #if 0 switch (c->spd.id.kind) { case ID_IPV4_ADDR: } if (c->gw_info == NULL) { plog("rcv_info: connection %s had NULL gw_info.", c->name); return } #endif ipcq->credential_count = 1; /* pull credentials out of gw_info */ switch (p1st->st_peer_pubkey->dns_auth_level) { case DAL_UNSIGNED: case DAL_NOTSEC: /* these seem to be the same for this purpose */ ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_type = CERT_NONE; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); break; case DAL_SIGNED: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_DNS_SIGNED_KEY; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); if (p1st->st_peer_pubkey->dns_sig != NULL) { strncat(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig , p1st->st_peer_pubkey->dns_sig , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig) - strlen(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig -1)); } break; case DAL_LOCAL: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name , sizeof(ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name)); break; } }
stf_status ikev2_verify_rsa_sha1(struct state *st , enum phase1_role role , unsigned char *idhash , const struct pubkey_list *keys_from_dns , const struct gw_info *gateways_from_dns , pb_stream *sig_pbs) { struct pubkey_list *p, **pp; struct connection *c = st->st_connection; int pathlen; pp = &pluto_pubkeys; { DBG(DBG_CONTROL, char buf[IDTOA_BUF]; dntoa_or_null(buf, IDTOA_BUF, c->spd.that.ca, "%any"); DBG_log("ikev2 verify required CA is '%s'", buf)); } { time_t n; n = 1438262454; /* Thu Jul 30 09:21:01 EDT 2015 in seconds */ list_certs(n); } for (p = pluto_pubkeys; p != NULL; p = *pp) { char keyname[IDTOA_BUF]; struct pubkey *key = p->key; pp = &p->next; idtoa(&key->id, keyname, IDTOA_BUF); DBG_log("checking alg=%d == %d, keyid=%s same_id=%u\n" , key->alg, PUBKEY_ALG_RSA , keyname , same_id(&st->ikev2.st_peer_id, &key->id)); if (key->alg == PUBKEY_ALG_RSA && same_id(&st->ikev2.st_peer_id, &key->id) && trusted_ca(key->issuer, c->spd.that.ca, &pathlen)) { time_t tnow; DBG(DBG_CONTROL, char buf[IDTOA_BUF]; dntoa_or_null(buf, IDTOA_BUF, key->issuer, "%any"); DBG_log("key issuer CA is '%s'", buf)); /* check if found public key has expired */ time(&tnow); if (key->until_time != UNDEFINED_TIME && key->until_time < tnow) { loglog(RC_LOG_SERIOUS, "cached RSA public key has expired and has been deleted"); *pp = free_public_keyentry(p); continue; /* continue with next public key */ } return STF_OK; } }
static stf_status aggr_inI1_outR1_common(struct msg_digest *md, int authtype) { /* With Aggressive Mode, we get an ID payload in this, the first * message, so we can use it to index the preshared-secrets * when the IP address would not be meaningful (i.e. Road * Warrior). So our first task is to unravel the ID payload. */ struct state *st; struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; struct connection *c = find_host_connection(&md->iface->ip_addr, md->iface->port, &md->sender, md->sender_port, LEMPTY); #if 0 if (c == NULL && md->iface->ike_float) { c = find_host_connection(&md->iface->addr, pluto_nat_port, &md->sender, md->sender_port, LEMPTY); } #endif if (c == NULL) { /* see if a wildcarded connection can be found */ pb_stream pre_sa_pbs = sa_pd->pbs; lset_t policy = preparse_isakmp_sa_body(&pre_sa_pbs) | POLICY_AGGRESSIVE; c = find_host_connection(&md->iface->ip_addr, pluto_port, (ip_address*)NULL, md->sender_port, policy); if (c == NULL || (c->policy & POLICY_AGGRESSIVE) == 0) { ipstr_buf b; loglog(RC_LOG_SERIOUS, "initial Aggressive Mode message from %s" " but no (wildcard) connection has been configured%s%s", ipstr(&md->sender, &b), (policy != LEMPTY) ? " with policy=" : "", (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); /* XXX notification is in order! */ return STF_IGNORE; } /* Create a temporary connection that is a copy of this one. * His ID isn't declared yet. */ c = rw_instantiate(c, &md->sender, NULL, NULL); } /* Set up state */ cur_state = md->st = st = new_state(); /* (caller will reset cur_state) */ st->st_connection = c; st->st_remoteaddr = md->sender; st->st_remoteport = md->sender_port; st->st_localaddr = md->iface->ip_addr; st->st_localport = md->iface->port; st->st_interface = md->iface; change_state(st, STATE_AGGR_R1); /* until we have clue who this is, then be conservative about allocating * them any crypto bandwidth */ st->st_import = pcim_stranger_crypto; st->st_policy |= POLICY_AGGRESSIVE; st->st_oakley.auth = authtype; if (!ikev1_decode_peer_id(md, FALSE, TRUE)) { char buf[IDTOA_BUF]; ipstr_buf b; (void) idtoa(&st->st_connection->spd.that.id, buf, sizeof(buf)); loglog(RC_LOG_SERIOUS, "initial Aggressive Mode packet claiming to be from %s" " on %s but no connection has been authorized", buf, ipstr(&md->sender, &b)); /* XXX notification is in order! */ return STF_FAIL + INVALID_ID_INFORMATION; } c = st->st_connection; extra_debugging(c); st->st_try = 0; /* Not our job to try again from start */ st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */ memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE); get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender); insert_state(st); /* needs cookies, connection, and msgid (0) */ st->st_doi = ISAKMP_DOI_IPSEC; st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */ { ipstr_buf b; libreswan_log("responding to Aggressive Mode, state #%lu, connection \"%s\" from %s", st->st_serialno, st->st_connection->name, ipstr(&c->spd.that.host_addr, &b)); } merge_quirks(st, md); set_nat_traversal(st, md); /* save initiator SA for HASH */ clonereplacechunk(st->st_p1isa, sa_pd->pbs.start, pbs_room(&sa_pd->pbs), "sa in aggr_inI1_outR1()"); /* * parse_isakmp_sa picks the right group, which we need to know * before we do any calculations. We will call it again to have it * emit the winning SA into the output. */ /* SA body in */ { pb_stream sabs = sa_pd->pbs; RETURN_STF_FAILURE(parse_isakmp_sa_body(&sabs, &sa_pd->payload.sa, NULL, FALSE, st)); } /* KE in */ RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, &md->chain[ISAKMP_NEXT_KE]->pbs)); /* Ni in */ RETURN_STF_FAILURE(accept_v1_nonce(md, &st->st_ni, "Ni")); { struct ke_continuation *ke = alloc_thing( struct ke_continuation, "outI2 KE"); ke->ke_md = md; set_suspended(st, md); if (!st->st_sec_in_use) { /* need to calculate KE and Nonce */ pcrc_init(&ke->ke_pcrc, aggr_inI1_outR1_continue1); return build_ke(&ke->ke_pcrc, st, st->st_oakley.group, st->st_import); } else { /* KE and Nonce calculated */ ke->ke_pcrc.pcrc_serialno = st->st_serialno; /* transitional */ return aggr_inI1_outR1_tail(&ke->ke_pcrc, NULL); } } }