void add_file(SshAgent agent, const char *filename) { SshPrivateKey key = NULL; char *saved_comment, *comment = NULL, *pass; int query_cnt; unsigned char *certs = NULL; size_t certs_len; char privname[500], pubname[500]; unsigned long magic; struct stat st; if (action == ADD_URL) { printf("Adding URL identity: %s\n", filename); snprintf(privname, sizeof(privname), "%s", filename); if (have_attrs) ssh_agent_add_with_attrs(agent, NULL, NULL, 0, privname, path_limit, path_constraint, use_limit, forbid_compat, key_timeout, agent_completion, (void *)agent); else ssh_agent_add(agent, NULL, NULL, 0, privname, agent_completion, (void *)agent); return; } else if (action == DELETE_URL) { printf("Deleting URL identity: %s\n", filename); snprintf(privname, sizeof(privname), "%s", filename); ssh_agent_delete(agent, NULL, 0, privname, agent_completion, (void *)agent); return; } #ifdef WITH_PGP if (pgp_mode == PGP_KEY_NONE) #endif /* WITH_PGP */ { /* Construct the names of the public and private key files. */ if (strlen(filename) > 4 && strcmp(filename + strlen(filename) - 4, ".pub") == 0) { snprintf(pubname, sizeof(pubname), "%s", filename); snprintf(privname, sizeof(privname), "%s", filename); privname[strlen(privname) - 4] = '\0'; } else { snprintf(pubname, sizeof(pubname), "%s.pub", filename); snprintf(privname, sizeof(privname), "%s", filename); } if (action == ADD) printf("Adding identity: %s\n", pubname); else if (action == DELETE) printf("Deleting identity: %s\n", pubname); if (stat(pubname, &st) < 0) { printf("Public key file %s does not exist.\n", pubname); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } if (stat(privname, &st) < 0) { printf("Private key file %s does not exist.\n", privname); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } /* Read the public key blob. */ magic = ssh2_key_blob_read(user, pubname, TRUE, &saved_comment, &certs, &certs_len, NULL); if (magic != SSH_KEY_MAGIC_PUBLIC) { printf("Bad public key file %s\n", pubname); ssh_xfree(certs); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } if (action == ADD) { /* Loop until we manage to load the file, or a maximum number of attempts have been made. First try with an empty passphrase. */ pass = ssh_xstrdup(""); query_cnt = 0; while ((key = ssh_privkey_read(user, privname, pass, &comment, NULL)) == NULL) { char buf[1024]; FILE *f; /* Free the old passphrase. */ memset(pass, 0, strlen(pass)); ssh_xfree(pass); query_cnt++; if (query_cnt > 5) { fprintf(stderr, "You don't seem to know the correct passphrase.\n"); exit(EXIT_STATUS_BADPASS); } /* Ask for a passphrase. */ if (!use_stdin && getenv("DISPLAY") && !isatty(fileno(stdin))) { snprintf(buf, sizeof(buf), "ssh-askpass2 '%sEnter passphrase for %.100s'", ((query_cnt <= 1) ? "" : "You entered wrong passphrase. "), saved_comment); f = popen(buf, "r"); if (!fgets(buf, sizeof(buf), f)) { pclose(f); ssh_xfree(saved_comment); exit(EXIT_STATUS_BADPASS); } pclose(f); if (strchr(buf, '\n')) *strchr(buf, '\n') = 0; pass = ssh_xstrdup(buf); } else { if (query_cnt <= 1) { if ((strcmp(privname, saved_comment) == 0) || (((strlen(privname) + 4) == strlen(saved_comment)) && (strncmp(privname, saved_comment, strlen(privname)) == 0))) { printf("Need passphrase for %s.\n", privname); } else { printf("Need passphrase for %s (%s).\n", privname, saved_comment); } } else { printf("Bad passphrase.\n"); } pass = ssh_read_passphrase("Enter passphrase: ", use_stdin); if (pass == NULL || strcmp(pass, "") == 0) { ssh_xfree(saved_comment); ssh_xfree(pass); exit(EXIT_STATUS_BADPASS); } } } memset(pass, 0, strlen(pass)); ssh_xfree(pass); ssh_xfree(saved_comment); /* Construct a comment for the key by combining file name and comment in the file. */ if ((saved_comment = strrchr(privname, '/')) != NULL) saved_comment++; else saved_comment = privname; saved_comment = ssh_string_concat_3(saved_comment, ": ", comment); } else { /* Construct a comment for the key by combining file name and comment in the file. */ if ((saved_comment = strrchr(privname, '/')) != NULL) saved_comment++; else saved_comment = privname; if (comment) saved_comment = ssh_string_concat_3(saved_comment, ": ", comment); else saved_comment = ssh_xstrdup(saved_comment); } if (action == ADD) { /* Send the key to the authentication agent. */ if (have_attrs) ssh_agent_add_with_attrs(agent, key, certs, certs_len, saved_comment, path_limit, path_constraint, use_limit, forbid_compat, key_timeout, agent_completion, (void *)agent); else ssh_agent_add(agent, key, certs, certs_len, saved_comment, agent_completion, (void *)agent); ssh_private_key_free(key); } else if (action == DELETE) { ssh_agent_delete(agent, certs, certs_len, saved_comment, agent_completion, (void *)agent); } ssh_xfree(saved_comment); } #ifdef WITH_PGP else { unsigned char *blob, *public_blob; size_t blob_len, public_blob_len; Boolean found = FALSE; unsigned long id; char *endptr; SshPgpSecretKey pgp_key; SshPrivateKey key; char buf[1024]; FILE *f; comment = NULL; switch (pgp_mode) { case PGP_KEY_NAME: found = ssh2_find_pgp_secret_key_with_name(user, pgp_keyring, filename, &blob, &blob_len, &comment); break; case PGP_KEY_FINGERPRINT: found = ssh2_find_pgp_secret_key_with_fingerprint(user, pgp_keyring, filename, &blob, &blob_len, &comment); break; case PGP_KEY_ID: id = strtoul(filename, &endptr, 0); if ((*filename != '\0') && (*endptr == '\0')) { found = ssh2_find_pgp_secret_key_with_id(user, pgp_keyring, id, &blob, &blob_len, &comment); } else { fprintf(stderr, "%s: invalid pgp key id \"%s\".\n", av0, filename); found = FALSE; } break; default: ssh_fatal("internal error"); } if (! found) { fprintf(stderr, "%s: pgp key \"%s\" not found.\n", av0, filename); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } if (ssh_pgp_secret_key_decode(blob, blob_len, &pgp_key) == 0) { fprintf(stderr, "%s: unable to decode pgp key \"%s\".\n", av0, filename); memset(blob, 'F', blob_len); ssh_xfree(blob); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } if ((public_blob_len = ssh_encode_pubkeyblob(pgp_key->public_key->key, &public_blob)) == 0) { fprintf(stderr, "%s: unable to encode pgp key \"%s\".\n", av0, filename); ssh_pgp_secret_key_free(pgp_key); memset(blob, 'F', blob_len); ssh_xfree(blob); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } if (action == ADD) { query_cnt = 0; while ((pgp_key->key == NULL) && (pgp_key->decryption_failed == TRUE)) { query_cnt++; if (query_cnt > 5) { fprintf(stderr, "You don't seem to know the correct passphrase.\n"); exit(EXIT_STATUS_BADPASS); } /* Ask for a passphrase. */ if (!use_stdin && getenv("DISPLAY") && !isatty(fileno(stdin))) { snprintf(buf, sizeof(buf), "ssh-askpass2 '%sEnter passphrase for \"%.100s\"'", ((query_cnt <= 1) ? "" : "You entered wrong passphrase. "), comment); f = popen(buf, "r"); if (!fgets(buf, sizeof(buf), f)) { pclose(f); fprintf(stderr, "No passphrase.\n"); exit(EXIT_STATUS_BADPASS); } pclose(f); if (strchr(buf, '\n')) *strchr(buf, '\n') = 0; pass = ssh_xstrdup(buf); } else { if (query_cnt <= 1) printf("Need passphrase for \"%s\".\n", comment); else printf("Bad passphrase.\n"); pass = ssh_read_passphrase("Enter passphrase: ", use_stdin); if (pass == NULL || strcmp(pass, "") == 0) { ssh_xfree(pass); fprintf(stderr, "No passphrase.\n"); exit(EXIT_STATUS_BADPASS); } } ssh_pgp_secret_key_free(pgp_key); if (ssh_pgp_secret_key_decode_with_passphrase(blob, blob_len, pass, &pgp_key) == 0) { memset(pass, 0, strlen(pass)); ssh_xfree(pass); fprintf(stderr, "%s: unable to decode pgp key \"%s\".\n", av0, filename); memset(blob, 'F', blob_len); ssh_xfree(blob); ssh_xfree(public_blob); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } memset(pass, 0, strlen(pass)); ssh_xfree(pass); } if (pgp_key->key == NULL) { fprintf(stderr, "%s: unable to decode pgp key \"%s\".\n", av0, filename); ssh_xfree(public_blob); ssh_pgp_secret_key_free(pgp_key); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } memset(blob, 'F', blob_len); ssh_xfree(blob); if (ssh_private_key_copy(pgp_key->key, &key) != SSH_CRYPTO_OK) { fprintf(stderr, "%s: unable to export pgp key \"%s\".\n", av0, filename); ssh_pgp_secret_key_free(pgp_key); (*agent_completion)(SSH_AGENT_ERROR_OK, (void *)agent); return; } ssh_pgp_secret_key_free(pgp_key); if (have_attrs) ssh_agent_add_with_attrs(agent, key, public_blob, public_blob_len, comment, path_limit, path_constraint, use_limit, forbid_compat, key_timeout, agent_completion, (void *)agent); else ssh_agent_add(agent, key, public_blob, public_blob_len, comment, agent_completion, (void *)agent); ssh_xfree(comment); ssh_xfree(public_blob); ssh_private_key_free(key); return; } else if (action == DELETE) { ssh_agent_delete(agent, public_blob, public_blob_len, filename, agent_completion, (void *)agent); ssh_pgp_secret_key_free(pgp_key); memset(blob, 'F', blob_len); ssh_xfree(blob); ssh_xfree(public_blob); return; } } #endif /* WITH_PGP */ }
SshEapToken ssh_eap_dup_token(SshEapToken src) { SshEapToken dst; dst = ssh_calloc(1, sizeof(*dst)); if (dst == NULL) return NULL; dst->type = src->type; switch (src->type) { case SSH_EAP_TOKEN_PRIVATE_KEY: if (src->token.prvkey.private_key != NULL) { if (ssh_private_key_copy(src->token.prvkey.private_key, &dst->token.prvkey.private_key) != SSH_CRYPTO_OK) { ssh_free(dst); return NULL; } if (src->token.prvkey.id_data != NULL) { dst->token.prvkey.id_data = ssh_memdup(src->token.prvkey.id_data, src->token.prvkey.id_data_size); if (dst->token.prvkey.id_data == NULL) { ssh_private_key_free(dst->token.prvkey.private_key); ssh_free(dst); return NULL; } dst->token.prvkey.id_data_size = src->token.prvkey.id_data_size; } } break; case SSH_EAP_TOKEN_CERTIFICATE_AUTHORITY: { int cnt; int i; /* Count the ca count. */ for (cnt = 0; src->token.cas && src->token.cas[cnt]; cnt++) ; if (cnt == 0) { SSH_DEBUG(SSH_D_ERROR, ("Cannot duplicate token, no" " CA's to duplicate.")); ssh_free(dst); return NULL; } dst->token.cas = ssh_calloc(cnt + 1, sizeof(unsigned char *)); if (dst->token.cas == NULL) { ssh_free(dst); return NULL; } for (i = 0; i < cnt; i++) dst->token.cas[i] = src->token.cas[i]; break; } #ifdef SSHDIST_EAP_SIM case SSH_EAP_TOKEN_SIM_CHALLENGE: #endif /* SSHDIST_EAP_SIM */ #ifdef SSHDIST_EAP_AKA case SSH_EAP_TOKEN_AKA_CHALLENGE: case SSH_EAP_TOKEN_AKA_SYNCH_REQ: #endif /* SSHDIST_EAP_AKA */ case SSH_EAP_TOKEN_USERNAME: case SSH_EAP_TOKEN_SHARED_SECRET: case SSH_EAP_TOKEN_SALT: if (src->token.buffer.dptr != NULL) { dst->token.buffer.dptr = ssh_malloc(src->token.buffer.len); if (dst->token.buffer.dptr == NULL) { ssh_free(dst); return NULL; } dst->token.buffer.len = src->token.buffer.len; memcpy(dst->token.buffer.dptr, src->token.buffer.dptr, src->token.buffer.len); } else { dst->token.buffer.dptr = NULL; dst->token.buffer.len = 0; } break; case SSH_EAP_TOKEN_COUNTER32: dst->token.counter32 = src->token.counter32; break; #ifdef SSHDIST_EAP_AKA_DASH case SSH_EAP_TOKEN_AKA_DASH_KDF_INPUT: dst->token.success = src->token.success; break; #endif /* SSHDIST_EAP_AKA_DASH */ #ifdef SSHDIST_EAP_AKA case SSH_EAP_TOKEN_AKA_AUTH_REJECT: #endif /* SSHDIST_EAP_AKA */ case SSH_EAP_TOKEN_NONE: break; default: SSH_NOTREACHED; } SSH_DEBUG(SSH_D_MY, ("duplicated token at %p", dst)); return dst; }
void ikev2_fb_request_certificates_cb(SshIkev2Error error_code, SshPrivateKey private_key_out, int number_of_certificates, SshIkev2CertEncoding *cert_encs, const unsigned char **certs, size_t *cert_lengths, void *context) { SshIkev2FbNegotiation neg = (SshIkev2FbNegotiation) context; SshIkeCertificateEncodingType *ikev1_cert_encodings = NULL; SshPrivateKey private_key_copy = NULL; unsigned char **ikev1_certs = NULL; size_t *ikev1_cert_lengths = NULL; int i; SSH_IKEV2_FB_V2_COMPLETE_CALL(neg); if (error_code != SSH_IKEV2_ERROR_OK) { SSH_DEBUG(SSH_D_FAIL, ("Private key/Certificate lookup failed, " "error '%s'", ssh_ikev2_error_to_string(error_code))); goto error; } if (number_of_certificates == 0) { SSH_DEBUG(SSH_D_FAIL, ("No certificates found")); goto error; } SSH_ASSERT(private_key_out != NULL); if (ssh_private_key_copy(private_key_out, &private_key_copy) != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_FAIL, ("Private key copy failed")); goto error; } /* Copy the returned certificates */ ikev1_cert_encodings = ssh_calloc(number_of_certificates, sizeof(SshIkeCertificateEncodingType)); ikev1_certs = ssh_calloc(number_of_certificates, sizeof(unsigned char *)); ikev1_cert_lengths = ssh_calloc(number_of_certificates, sizeof(size_t)); if (ikev1_cert_encodings == NULL || ikev1_certs == NULL || ikev1_cert_lengths == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Memory allocation failure")); goto error; } for (i = 0; i < number_of_certificates; i++) { ikev1_cert_encodings[i] = ikev2_fb_v2_cert_encoding_to_v1(cert_encs[i]); ikev1_cert_lengths[i] = cert_lengths[i]; if (!(ikev1_certs[i] = ssh_memdup(certs[i], cert_lengths[i]))) { SSH_DEBUG(SSH_D_FAIL, ("Certificate copy failed")); goto error; } } /* Save the certificates and private key. */ neg->number_of_certificates = number_of_certificates; neg->cert_encodings = ikev1_cert_encodings; neg->certs = ikev1_certs; neg->cert_lengths = ikev1_cert_lengths; neg->private_key = private_key_copy; SSH_DEBUG(SSH_D_LOWOK, ("Found %d certificates", number_of_certificates)); SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); return; error: if (private_key_copy) ssh_private_key_free(private_key_copy); if (ikev1_certs) for (i = 0; i < number_of_certificates; i++) ssh_free(ikev1_certs[i]); ssh_free(ikev1_certs); ssh_free(ikev1_cert_encodings); ssh_free(ikev1_cert_lengths); SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); }