int sc_pkcs15emu_initialize_public_keys(sc_pkcs15_card_t *p15card, p15data_items *items) { const pubdata *keys = items->public_keys; int i, r; if(!keys) return SC_SUCCESS; /* set public keys */ for (i = 0; keys[i].label; i++) { r = add_public_key(p15card, &keys[i], 0, 0); if (r < 0) SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r); } return SC_SUCCESS; }
int initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, char wanttoexit, char ignorePublicKeys) { int n, nlen, elen, len, tmp; unsigned int olen; X509* server_cert; const EVP_MD *md; EVP_PKEY* pkey; EVP_MD_CTX md_ctx; unsigned char *encoded = NULL; char b64_encoded[100]; unsigned char *key_buf = NULL; assert((ClientRealm_get_tunnelType(cr) == 0) || (ClientRealm_get_tunnelType(cr) == 1)); switch (ClientRealm_get_tunnelType(cr)) { case 0: { if (ip_connect(&tmp, ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), ClientRealm_get_ipFamily(cr), ClientRealm_get_localName(cr), ClientRealm_get_localPort(cr))) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect_%s error for %s, %s", (ClientRealm_get_ipFamily(cr) & 0x02) ? "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); #else aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect error for %s, %s", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); #endif if (wanttoexit) { exit(1); } else { return 1; } } SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); break; } #ifdef HAVE_LIBPTHREAD case 1: { if (initialize_http_proxy_client(&tmp, cr, ctx)) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "http_proxy_connect_%s error for %s, %s (proxy: %s, %s)", (ClientRealm_get_ipFamily(cr) & 0x02) ? "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); #else aflog(LOG_T_INIT, LOG_I_CRIT, "http_proxy_connect error for %s, %s (proxy: %s, %s)", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); #endif if (wanttoexit) { exit(1); } else { return 1; } } SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); break; } #endif default: { aflog(LOG_T_INIT, LOG_I_CRIT, "Unknown tunnel type"); if (wanttoexit) { exit(1); } else { return 1; } break; } } SslFd_set_ssl(ClientRealm_get_masterSslFd(cr), SSL_new(ctx)); if (SSL_set_fd(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), SslFd_get_fd(ClientRealm_get_masterSslFd(cr))) != 1) { aflog(LOG_T_INIT, LOG_I_CRIT, "Problem with initializing ssl... exiting"); if (wanttoexit) { exit(1); } else { close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); return 2; } } alarm(60); aflog(LOG_T_INIT, LOG_I_INFO, "Trying SSL_connect"); if ((n = SSL_connect(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == 1) { if ((server_cert = SSL_get_peer_certificate(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Server did not present a certificate... exiting"); exit(1); } /* FIXME: change almost everything here */ pkey = X509_get_pubkey(server_cert); if (pkey == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Server's public key is invalid... exiting"); exit(1); } nlen = BN_num_bytes(pkey->pkey.rsa->n); elen = BN_num_bytes(pkey->pkey.rsa->e); len = nlen + elen; key_buf = malloc(len); if (key_buf == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Cannot allocate memory for server's public key checking... exiting"); exit(1); } BN_bn2bin(pkey->pkey.rsa->n, key_buf); BN_bn2bin(pkey->pkey.rsa->e, key_buf + nlen); md = EVP_md5(); EVP_DigestInit(&md_ctx, md); EVP_DigestUpdate(&md_ctx, key_buf, len); encoded = calloc(1, EVP_MAX_MD_SIZE+1); if (encoded == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Cannot allocate memory for server's public key checking... exiting"); exit(1); } EVP_DigestFinal(&md_ctx, encoded, &olen); if (b64_ntop(encoded, olen, b64_encoded, 100) == -1) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Problem with base64 encoding... exiting"); exit(1); } switch (check_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded)) { case SSL_PUBLIC_KEY_VALID: /* public key is ok - do nothing */ break; case SSL_PUBLIC_KEY_NOT_KNOWN: aflog(LOG_T_MAIN, LOG_I_WARNING, "WARNING: implicitly added new server's public key to the list of known hosts"); add_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded); break; default: if (ignorePublicKeys) { aflog(LOG_T_MAIN, LOG_I_WARNING, "WARNING: Invalid server's public key... ignoring"); } else { aflog(LOG_T_MAIN, LOG_I_CRIT, "Invalid server's public key... exiting"); aflog(LOG_T_MAIN, LOG_I_CRIT, "Please delete conflicting entry in %s or use '--ignorepkeys' option", get_store_filename()); exit(1); } } memset(key_buf, 0, len); free(key_buf); free(encoded); aflog(LOG_T_INIT, LOG_I_INFO, "SSL_connect successful"); } else { alarm(0); aflog(LOG_T_INIT, LOG_I_CRIT, "SSL_connect has failed (%d | %d)... exiting", n, SSL_get_error(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), n)); if (wanttoexit) { exit(1); } else { close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); return 3; } } alarm(0); buff[0] = AF_S_LOGIN; buff[1] = ClientRealm_get_password(cr)[0]; buff[2] = ClientRealm_get_password(cr)[1]; buff[3] = ClientRealm_get_password(cr)[2]; buff[4] = ClientRealm_get_password(cr)[3]; return 0; }
static void key_add_request(const struct whack_message *msg) { struct id keyid; err_t ugh = atoid(msg->keyid, &keyid, FALSE, FALSE); if (ugh != NULL) { loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh); } else { if (!msg->whack_addkey) delete_public_keys(&pluto_pubkeys, &keyid, msg->pubkey_alg); if (msg->keyval.len == 0) { struct key_add_common *oc = alloc_thing(struct key_add_common, "key add common things"); enum key_add_attempt kaa; /* initialize state shared by queries */ oc->refCount = 0; oc->whack_fd = dup_any(whack_log_fd); oc->success = FALSE; for (kaa = ka_TXT; kaa != ka_roof; kaa++) { struct key_add_continuation *kc = alloc_thing( struct key_add_continuation, "key add continuation"); oc->diag[kaa] = NULL; oc->refCount++; kc->common = oc; kc->lookingfor = kaa; switch (kaa) { case ka_TXT: ugh = start_adns_query(&keyid, &keyid, /* same */ ns_t_txt, key_add_continue, &kc->ac); break; #ifdef USE_KEYRR case ka_KEY: ugh = start_adns_query(&keyid, NULL, ns_t_key, key_add_continue, &kc->ac); break; #endif /* USE_KEYRR */ default: bad_case(kaa); /* suppress gcc warning */ } if (ugh != NULL) { oc->diag[kaa] = clone_str(ugh, "early key add failure"); oc->refCount--; } } /* Done launching queries. * Handle total failure case. */ key_add_merge(oc, &keyid); } else { ugh = add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg, &msg->keyval, &pluto_pubkeys); if (ugh != NULL) loglog(RC_LOG_SERIOUS, "%s", ugh); } }
/* 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); } } }