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; } }
/* Handle a kernel request. Supposedly, there's a message in * the kernelsock socket. */ void whack_handle(int whackctlfd) { struct whack_message msg; struct sockaddr_un whackaddr; int whackaddrlen = sizeof(whackaddr); int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen); ssize_t n; if (whackfd < 0) { log_errno((e, "accept() failed in whack_handle()")); return; } n = read(whackfd, &msg, sizeof(msg)); if (n == -1) { log_errno((e, "read() failed in whack_handle()")); close(whackfd); return; } whack_log_fd = whackfd; /* sanity check message */ { err_t ugh = NULL; next_str = msg.string; str_roof = (char *)&msg + n; if (next_str > str_roof) { ugh = builddiag("truncated message from whack: got %d bytes; expected %d. Message ignored." , n, (int) sizeof(msg)); } else if (msg.magic != WHACK_MAGIC) { ugh = builddiag("message from whack has bad magic %d; should be %d; probably wrong version. Message ignored" , msg.magic, WHACK_MAGIC); } else if (!unpack_str(&msg.name) /* string 1 */ || !unpack_str(&msg.left.id) /* string 2 */ || !unpack_str(&msg.left.cert) /* string 3 */ || !unpack_str(&msg.left.updown) /* string 4 */ #ifdef VIRTUAL_IP || !unpack_str(&msg.left.virt) #endif || !unpack_str(&msg.right.id) /* string 5 */ || !unpack_str(&msg.right.cert) /* string 6 */ || !unpack_str(&msg.right.updown) /* string 7 */ #ifdef VIRTUAL_IP || !unpack_str(&msg.right.virt) #endif || !unpack_str(&msg.keyid) /* string 8 */ || !unpack_str(&msg.ike) /* string 9 */ || !unpack_str(&msg.esp) /* string 10 */ || !unpack_str(&msg.dnshostname) /* string 11 */ || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */ { ugh = "message from whack contains bad string"; } else { msg.keyval.ptr = next_str; /* grab chunk */ } if (ugh != NULL) { loglog(RC_BADWHACKMESSAGE, "%s", ugh); whack_log_fd = NULL_FD; close(whackfd); return; } } if (msg.whack_options) { #ifdef DEBUG if (msg.name == NULL) { /* we do a two-step so that if either old or new would * cause the message to print, it will be printed. */ cur_debugging |= msg.debugging; DBG(DBG_CONTROL , DBG_log("base debugging = %s" , bitnamesof(debug_bit_names, msg.debugging))); cur_debugging = base_debugging = msg.debugging; } else if (!msg.whack_connection) { struct connection *c = con_by_name(msg.name, TRUE); if (c != NULL) { c->extra_debugging = msg.debugging; DBG(DBG_CONTROL , DBG_log("\"%s\" extra_debugging = %s" , c->name , bitnamesof(debug_bit_names, c->extra_debugging))); } } #endif } /* Deleting combined with adding a connection works as replace. * To make this more useful, in only this combination, * delete will silently ignore the lack of the connection. */ if (msg.whack_delete) { struct connection *c = con_by_name(msg.name, !msg.whack_connection); /* note: this is a "while" because road warrior * leads to multiple connections with the same name. */ for (; c != NULL; c = con_by_name(msg.name, FALSE)) delete_connection(c); } if (msg.whack_deletestate) { struct state *st = state_with_serialno(msg.whack_deletestateno); if (st == NULL) { loglog(RC_UNKNOWN_NAME, "no state #%lu to delete" , msg.whack_deletestateno); } else { delete_state(st); } } if (msg.whack_connection) add_connection(&msg); /* process "listen" before any operation that could require it */ if (msg.whack_listen) { log("listening for IKE messages"); listening = TRUE; find_ifaces(); load_preshared_secrets(); } if (msg.whack_unlisten) { log("no longer listening for IKE messages"); listening = FALSE; } if (msg.whack_reread & REREAD_SECRETS) { load_preshared_secrets(); } if (msg.whack_reread & REREAD_MYCERT) { load_mycert(); } if (msg.whack_reread & REREAD_CACERTS) { load_cacerts(); } if (msg.whack_reread & REREAD_CRLS) { load_crls(); } if (msg.whack_list & LIST_PUBKEYS) { list_public_keys(msg.whack_utc); } if (msg.whack_list & LIST_CERTS) { list_certs(msg.whack_utc); } if (msg.whack_list & LIST_CACERTS) { list_cacerts(msg.whack_utc); } if (msg.whack_list & LIST_CRLS) { list_crls(msg.whack_utc); } if (msg.whack_key) { /* add a public key */ struct id keyid; err_t ugh = atoid(msg.keyid, &keyid); if (ugh != NULL) { loglog(RC_BADID, "bad --keyid \"%s\": %s", msg.keyid, ugh); } else { if (!msg.whack_addkey) delete_public_keys(&keyid, msg.pubkey_alg); if (msg.keyval.len == 0) { struct key_add_continuation *kc = alloc_thing(struct key_add_continuation , "key add continuation"); int wfd = dup_any(whackfd); kc->whack_fd = wfd; ugh = start_adns_query(&keyid , NULL , T_KEY , key_add_continue , &kc->ac); if (ugh != NULL) { key_add_ugh(&keyid, ugh); close_any(wfd); } } else { ugh = add_public_key(&keyid, DAL_LOCAL, msg.pubkey_alg , &msg.keyval, &pubkeys); if (ugh != NULL) loglog(RC_LOG_SERIOUS, "%s", ugh); } } }