Пример #1
1
static ssh_session create_ssh_connection(const char* hostname, const unsigned int port, const char* username,
	const char* password, const char* sshkey_path, const char* sshkey_passphrase)
{
	ssh_session sshs;

	/* Open session and set options */
	sshs = ssh_new();
	if (sshs == NULL) {
		errmsg_print("Can't create ssh session");
		return NULL;
	}

	if (!hostname)
		return NULL;

	if (ssh_options_set(sshs, SSH_OPTIONS_HOST, hostname)) {
		errmsg_print("Can't set the hostname: %s\n", hostname);
		goto failure;
	}

	if (port != 0) {
		if (ssh_options_set(sshs, SSH_OPTIONS_PORT, &port)) {
			errmsg_print("Can't set the port: %d\n", port);
			goto failure;
		}
	}

	if (!username)
		username = g_get_user_name();

	if (ssh_options_set(sshs, SSH_OPTIONS_USER, username)) {
		errmsg_print("Can't set the username: %s\n", username);
		goto failure;
	}

	verbose_print("Opening ssh connection to %s@%s:%u\n", username, hostname, port);

	/* Connect to server */
	if (ssh_connect(sshs) != SSH_OK) {
		errmsg_print("Error connecting to %s@%s:%u (%s)\n", username, hostname, port,
			ssh_get_error(sshs));
		goto failure;
	}

#ifdef HAVE_LIBSSH_USERAUTH_AGENT
	verbose_print("Connecting using ssh-agent...");
	/* Try to authenticate using ssh agent */
	if (ssh_userauth_agent(sshs, NULL) == SSH_AUTH_SUCCESS) {
		verbose_print("done\n");
		return sshs;
	}
	verbose_print("failed\n");
#endif

	/* If a public key path has been provided, try to authenticate using it */
	if (sshkey_path) {
		ssh_key pkey = ssh_key_new();
		int ret;

		verbose_print("Connecting using public key in %s...", sshkey_path);
		ret = ssh_pki_import_privkey_file(sshkey_path, sshkey_passphrase, NULL, NULL, &pkey);

		if (ret == SSH_OK) {
			if (ssh_userauth_publickey(sshs, NULL, pkey) == SSH_AUTH_SUCCESS) {
				verbose_print("done\n");
				ssh_key_free(pkey);
				return sshs;
			}
		}
		ssh_key_free(pkey);
		verbose_print("failed (%s)\n", ssh_get_error(sshs));
	}

	/* Try to authenticate using standard public key */
	verbose_print("Connecting using standard public key...");
	if (ssh_userauth_publickey_auto(sshs, NULL, NULL) == SSH_AUTH_SUCCESS) {
		verbose_print("done\n");
		return sshs;
	}
	verbose_print("failed\n");

	/* If a password has been provided and all previous attempts failed, try to use it */
	if (password) {
		verbose_print("Connecting using password...");
		if (ssh_userauth_password(sshs, username, password) == SSH_AUTH_SUCCESS) {
			verbose_print("done\n");
			return sshs;
		}
		verbose_print("failed\n");
	}

	errmsg_print("Can't find a valid authentication. Disconnecting.\n");

	/* All authentication failed. Disconnect and return */
	ssh_disconnect(sshs);

failure:
	ssh_free(sshs);
	return NULL;
}
Пример #2
0
ssh_key pki_publickey_from_privatekey(ssh_key privkey) {
    ssh_key pubkey = NULL;

    if (privkey == NULL || !ssh_key_is_private(privkey)) {
        return NULL;
    }

    pubkey = ssh_key_new();
    if (pubkey == NULL) {
        return NULL;
    }
    pubkey->type = privkey->type;

    switch (pubkey->type) {
        case SSH_KEYTYPE_DSS:
            pubkey->dsa = DSA_new();
            if (pubkey->dsa == NULL) {
                goto fail;
            }
            pubkey->dsa->p = BN_dup(privkey->dsa->p);
            pubkey->dsa->q = BN_dup(privkey->dsa->q);
            pubkey->dsa->g = BN_dup(privkey->dsa->g);
            pubkey->dsa->pub_key = BN_dup(privkey->dsa->pub_key);
            if (pubkey->dsa->p == NULL ||
                    pubkey->dsa->q == NULL ||
                    pubkey->dsa->g == NULL ||
                    pubkey->dsa->pub_key == NULL) {
                goto fail;
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            pubkey->rsa = RSA_new();
            if (pubkey->rsa == NULL) {
                goto fail;
            }
            pubkey->rsa->e = BN_dup(privkey->rsa->e);
            pubkey->rsa->n = BN_dup(privkey->rsa->n);
            if (pubkey->rsa->e == NULL ||
                    pubkey->rsa->n == NULL) {
                goto fail;
            }
            break;
        case SSH_KEYTYPE_ECDSA:
        case SSH_KEYTYPE_UNKNOWN:
            ssh_key_free(pubkey);
            return NULL;
    }
    pubkey->type_c = ssh_key_type_to_char(privkey->type);

    return pubkey;
fail:
    ssh_key_free(pubkey);

    return NULL;
}
Пример #3
0
/**
 * @brief Generates a keypair.
 *
 * @param[in] type      Type of key to create
 *
 * @param[in] parameter Parameter to the creation of key:
 *                      rsa : length of the key in bits (e.g. 1024, 2048, 4096)
 *                      dsa : length of the key in bits (e.g. 1024, 2048, 3072)
 *                      ecdsa : bits of the key (e.g. 256, 384, 512)
 * @param[out] pkey     A pointer to store the allocated private key. You need
 *                      to free the memory.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @warning             Generating a key pair may take some time.
 */
int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
        ssh_key *pkey){
    int rc;
    ssh_key key = ssh_key_new();

    if (key == NULL) {
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;

    switch(type){
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            rc = pki_key_generate_rsa(key, parameter);
            if(rc == SSH_ERROR)
                goto error;
            break;
        case SSH_KEYTYPE_DSS:
            rc = pki_key_generate_dss(key, parameter);
            if(rc == SSH_ERROR)
                goto error;
            break;
        case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
            rc = pki_key_generate_ecdsa(key, parameter);
            if (rc == SSH_ERROR) {
                goto error;
            }

            /* Update key type */
            key->type_c = ssh_pki_key_ecdsa_name(key);
            break;
#endif
        case SSH_KEYTYPE_ED25519:
            rc = pki_key_generate_ed25519(key);
            if (rc == SSH_ERROR) {
                goto error;
            }
            break;
        case SSH_KEYTYPE_DSS_CERT01:
        case SSH_KEYTYPE_RSA_CERT01:
        case SSH_KEYTYPE_UNKNOWN:
            goto error;
    }

    *pkey = key;
    return SSH_OK;
error:
    ssh_key_free(key);
    return SSH_ERROR;
}
Пример #4
0
static int check_authorized_keys(struct ssh_key_struct *client_pubkey) {
	#define MAX_PUBKEY_SIZE 0x4000

	const char *authorized_keys_path = tmate_settings->authorized_keys_path;
	const char *token_delim = " ";

	FILE *file;
	char key_buf[MAX_PUBKEY_SIZE], *key_type, *key_content;
	enum ssh_keytypes_e type;
	ssh_key pkey;

	if (authorized_keys_path == NULL)
		return SSH_AUTH_SUCCESS;

	file = fopen(authorized_keys_path, "rb");
	if (file == NULL) {
		tmate_fatal("Could not open authorized_keys file: \"%s\"", authorized_keys_path);
		return SSH_AUTH_DENIED;
	}

	while (fgets(key_buf, MAX_PUBKEY_SIZE, file)) {
		if (key_buf[0] == '#' || key_buf[0] == '\0')
			continue;

		key_type = strtok(key_buf, token_delim);
		if (key_type == NULL)
			continue;

		type = ssh_key_type_from_name(key_type);
		if (type == SSH_KEYTYPE_UNKNOWN)
			continue;

		key_content = strtok(NULL, token_delim);
		if (key_content == NULL)
			continue;

		pkey = ssh_key_new();
		if (ssh_pki_import_pubkey_base64(key_content, type, &pkey) != SSH_OK) {
			ssh_key_free(pkey);
			continue;
		}

		if (!ssh_key_cmp(pkey, client_pubkey, SSH_KEY_CMP_PUBLIC)) {
			ssh_key_free(pkey);
			fclose(file);
			return SSH_AUTH_SUCCESS;
		}

		ssh_key_free(pkey);
	}

	fclose(file);
	return SSH_AUTH_DENIED;
}
Пример #5
0
static int pki_import_cert_buffer(ssh_buffer buffer,
                                  enum ssh_keytypes_e type,
                                  ssh_key *pkey) {
    ssh_buffer cert;
    ssh_string type_s;
    ssh_key key;
    int rc;

    key = ssh_key_new();
    if (key == NULL) {
        return SSH_ERROR;
    }
    cert = ssh_buffer_new();
    if (cert == NULL) {
        ssh_key_free(key);
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PUBLIC;

    /*
     * The cert blob starts with the key type as an ssh_string, but this
     * string has been read out of the buffer to identify the key type.
     * Simply add it again as first element before copying the rest.
     */
    type_s = ssh_string_from_char(key->type_c);
    if (type_s == NULL) {
        goto fail;
    }
    rc = ssh_buffer_add_ssh_string(cert, type_s);
    ssh_string_free(type_s);
    if (rc != 0) {
        goto fail;
    }

    rc = ssh_buffer_add_buffer(cert, buffer);
    if (rc != 0) {
        goto fail;
    }
    key->cert = (void*) cert;

    *pkey = key;
    return SSH_OK;

fail:
    ssh_key_free(key);
    ssh_buffer_free(cert);
    return SSH_ERROR;
}
Пример #6
0
static void torture_pki_import_privkey_base64_NULL_key(void **state) {
    int rc;
    char *key_str;
    ssh_key key;
    const char *passphrase = LIBSSH_PASSPHRASE;

    (void) state; /* unused */

    key_str = read_file(LIBSSH_RSA_TESTKEY);
    assert_true(key_str != NULL);

    key = ssh_key_new();
    assert_true(key != NULL);

    /* test if it returns -1 if key is NULL */
    rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, NULL);
    assert_true(rc == -1);

    free(key_str);
    ssh_key_free(key);
}
Пример #7
0
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
        ssh_auth_callback auth_fn, void *auth_data)
{
    ssh_key key = NULL;
    mbedtls_pk_context *rsa = NULL;
    mbedtls_pk_context *ecdsa = NULL;
    ed25519_privkey *ed25519 = NULL;
    enum ssh_keytypes_e type;
    int valid;
    /* mbedtls pk_parse_key expects strlen to count the 0 byte */
    size_t b64len = strlen(b64_key) + 1;
    unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0};

    type = pki_privatekey_type_from_string(b64_key);
    if (type == SSH_KEYTYPE_UNKNOWN) {
        SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
        return NULL;
    }

    switch (type) {
        case SSH_KEYTYPE_RSA:
            rsa = malloc(sizeof(mbedtls_pk_context));
            if (rsa == NULL) {
                return NULL;
            }

            mbedtls_pk_init(rsa);

            if (passphrase == NULL) {
                if (auth_fn) {
                    valid = auth_fn("Passphrase for private key:", (char *) tmp,
                            MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
                    if (valid < 0) {
                        return NULL;
                    }
                    /* TODO fix signedness and strlen */
                    valid = mbedtls_pk_parse_key(rsa,
                            (const unsigned char *) b64_key,
                            b64len, tmp,
                            strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
                } else {
                    valid = mbedtls_pk_parse_key(rsa,
                            (const unsigned char *) b64_key,
                            b64len, NULL,
                            0);
                }
            } else {
                valid = mbedtls_pk_parse_key(rsa,
                        (const unsigned char *) b64_key, b64len,
                        (const unsigned char *) passphrase,
                        strnlen(passphrase, MAX_PASSPHRASE_SIZE));
            }

            if (valid != 0) {
                char error_buf[100];
                mbedtls_strerror(valid, error_buf, 100);
                SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
                goto fail;
            }
            break;
        case SSH_KEYTYPE_ECDSA:
            ecdsa = malloc(sizeof(mbedtls_pk_context));
            if (ecdsa == NULL) {
                return NULL;
            }

            mbedtls_pk_init(ecdsa);

            if (passphrase == NULL) {
                if (auth_fn) {
                    valid = auth_fn("Passphrase for private key:", (char *) tmp,
                            MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
                    if (valid < 0) {
                        return NULL;
                    }
                    valid = mbedtls_pk_parse_key(ecdsa,
                            (const unsigned char *) b64_key,
                            b64len, tmp,
                            strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
                } else {
                    valid = mbedtls_pk_parse_key(ecdsa,
                            (const unsigned char *) b64_key,
                            b64len, NULL,
                            0);
                }
            } else {
                valid = mbedtls_pk_parse_key(ecdsa,
                        (const unsigned char *) b64_key, b64len,
                        (const unsigned char *) passphrase,
                        strnlen(passphrase, MAX_PASSPHRASE_SIZE));
            }

            if (valid != 0) {
                char error_buf[100];
                mbedtls_strerror(valid, error_buf, 100);
                SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
                goto fail;
            }
            break;
        case SSH_KEYTYPE_ED25519:
            /* Cannot open ed25519 keys with libmbedcrypto */
        default:
            SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
                    type);
            return NULL;
    }

    key = ssh_key_new();
    if (key == NULL) {
        goto fail;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
    key->rsa = rsa;
    if (ecdsa != NULL) {
        mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa);

        key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
        if (key->ecdsa == NULL) {
            goto fail;
        }

        mbedtls_ecdsa_init(key->ecdsa);
        mbedtls_ecdsa_from_keypair(key->ecdsa, keypair);
        mbedtls_pk_free(ecdsa);
        SAFE_FREE(ecdsa);
    } else {
        key->ecdsa = NULL;
    }
    key->ed25519_privkey = ed25519;
    rsa = NULL;
    ecdsa = NULL;
    if (key->type == SSH_KEYTYPE_ECDSA) {
        key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
        key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
    }

    return key;
fail:
    ssh_key_free(key);
    if (rsa != NULL) {
        mbedtls_pk_free(rsa);
        SAFE_FREE(rsa);
    }
    if (ecdsa != NULL) {
        mbedtls_pk_free(ecdsa);
        SAFE_FREE(ecdsa);
    }
    return NULL;
}
Пример #8
0
static int pki_import_pubkey_buffer(ssh_buffer buffer,
                                    enum ssh_keytypes_e type,
                                    ssh_key *pkey) {
    ssh_key key;
    int rc;

    key = ssh_key_new();
    if (key == NULL) {
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PUBLIC;

    switch (type) {
        case SSH_KEYTYPE_DSS:
            {
                ssh_string p;
                ssh_string q;
                ssh_string g;
                ssh_string pubkey;

                p = ssh_buffer_get_ssh_string(buffer);
                if (p == NULL) {
                    goto fail;
                }
                q = ssh_buffer_get_ssh_string(buffer);
                if (q == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);

                    goto fail;
                }
                g = ssh_buffer_get_ssh_string(buffer);
                if (g == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);

                    goto fail;
                }
                pubkey = ssh_buffer_get_ssh_string(buffer);
                if (pubkey == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);
                    ssh_string_burn(g);
                    ssh_string_free(g);

                    goto fail;
                }

                rc = pki_pubkey_build_dss(key, p, q, g, pubkey);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
                ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
                ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
#endif
                ssh_string_burn(p);
                ssh_string_free(p);
                ssh_string_burn(q);
                ssh_string_free(q);
                ssh_string_burn(g);
                ssh_string_free(g);
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            {
                ssh_string e;
                ssh_string n;

                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }
                n = ssh_buffer_get_ssh_string(buffer);
                if (n == NULL) {
                    ssh_string_burn(e);
                    ssh_string_free(e);

                    goto fail;
                }

                rc = pki_pubkey_build_rsa(key, e, n);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
                ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
#endif
                ssh_string_burn(e);
                ssh_string_free(e);
                ssh_string_burn(n);
                ssh_string_free(n);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
            {
                ssh_string e;
                ssh_string i;
                int nid;

                i = ssh_buffer_get_ssh_string(buffer);
                if (i == NULL) {
                    goto fail;
                }
                nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
                ssh_string_free(i);
                if (nid == -1) {
                    goto fail;
                }


                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }

                rc = pki_pubkey_build_ecdsa(key, nid, e);
                ssh_string_burn(e);
                ssh_string_free(e);
                if (rc < 0) {
                    goto fail;
                }

                /* Update key type */
                key->type_c = ssh_pki_key_ecdsa_name(key);
            }
            break;
#endif
        case SSH_KEYTYPE_ED25519:
        {
            ssh_string pubkey = ssh_buffer_get_ssh_string(buffer);
            if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
                SSH_LOG(SSH_LOG_WARN, "Invalid public key length");
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            key->ed25519_pubkey = malloc(ED25519_PK_LEN);
            if (key->ed25519_pubkey == NULL) {
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
            ssh_string_burn(pubkey);
            ssh_string_free(pubkey);
        }
        break;
        case SSH_KEYTYPE_DSS_CERT01:
        case SSH_KEYTYPE_RSA_CERT01:
        case SSH_KEYTYPE_UNKNOWN:
        default:
            SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type);
            goto fail;
    }

    *pkey = key;
    return SSH_OK;
fail:
    ssh_key_free(key);

    return SSH_ERROR;
}
Пример #9
0
ssh_key pki_private_key_from_base64(const char *b64_key,
                                    const char *passphrase,
                                    ssh_auth_callback auth_fn,
                                    void *auth_data)
{
    gcry_sexp_t dsa = NULL;
    gcry_sexp_t rsa = NULL;
    ssh_key key = NULL;
    enum ssh_keytypes_e type;
    int valid;

    /* needed for gcrypt initialization */
    if (ssh_init() < 0) {
        return NULL;
    }

    type = pki_privatekey_type_from_string(b64_key);
    if (type == SSH_KEYTYPE_UNKNOWN) {
        SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
        return NULL;
    }

    switch (type) {
    case SSH_KEYTYPE_DSS:
        if (passphrase == NULL) {
            if (auth_fn) {
                valid = b64decode_dsa_privatekey(b64_key, &dsa, auth_fn,
                                                 auth_data, "Passphrase for private key:");
            } else {
                valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, NULL,
                                                 NULL);
            }
        } else {
            valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, (void *)
                                             passphrase, NULL);
        }

        if (!valid) {
            SSH_LOG(SSH_LOG_WARN, "Parsing private key");
            goto fail;
        }
        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
        if (passphrase == NULL) {
            if (auth_fn) {
                valid = b64decode_rsa_privatekey(b64_key, &rsa, auth_fn,
                                                 auth_data, "Passphrase for private key:");
            } else {
                valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, NULL,
                                                 NULL);
            }
        } else {
            valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL,
                                             (void *)passphrase, NULL);
        }

        if (!valid) {
            SSH_LOG(SSH_LOG_WARN, "Parsing private key");
            goto fail;
        }
        break;
    case SSH_KEYTYPE_ED25519:
    /* Cannot open ed25519 keys with libgcrypt */
    case SSH_KEYTYPE_ECDSA:
    case SSH_KEYTYPE_UNKNOWN:
    default:
        SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", type);
        return NULL;
    }

    key = ssh_key_new();
    if (key == NULL) {
        goto fail;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
    key->dsa = dsa;
    key->rsa = rsa;

    return key;
fail:
    ssh_key_free(key);
    gcry_sexp_release(dsa);
    gcry_sexp_release(rsa);

    return NULL;
}
Пример #10
0
ssh_key pki_private_key_from_base64(ssh_session session,
                                    const char *b64_key,
                                    const char *passphrase) {
    BIO *mem = NULL;
    DSA *dsa = NULL;
    RSA *rsa = NULL;
    ssh_key key;
    enum ssh_keytypes_e type;

    /* needed for openssl initialization */
    if (ssh_init() < 0) {
        return NULL;
    }

    type = pki_privatekey_type_from_string(b64_key);
    if (type == SSH_KEYTYPE_UNKNOWN) {
        ssh_set_error(session, SSH_FATAL, "Unknown or invalid private key.");
        return NULL;
    }

    mem = BIO_new_mem_buf((void*)b64_key, -1);

    switch (type) {
        case SSH_KEYTYPE_DSS:
            if (passphrase == NULL) {
                if (session->common.callbacks && session->common.callbacks->auth_function) {
                    dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, session);
                } else {
                    /* openssl uses its own callback to get the passphrase here */
                    dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, NULL);
                }
            } else {
                dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, (void *) passphrase);
            }

            BIO_free(mem);

            if (dsa == NULL) {
                ssh_set_error(session, SSH_FATAL,
                              "Parsing private key: %s",
                              ERR_error_string(ERR_get_error(), NULL));
                return NULL;
            }

            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            if (passphrase == NULL) {
                if (session->common.callbacks && session->common.callbacks->auth_function) {
                    rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, session);
                } else {
                    /* openssl uses its own callback to get the passphrase here */
                    rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL);
                }
            } else {
                rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, (void *) passphrase);
            }

            BIO_free(mem);

            if (rsa == NULL) {
                ssh_set_error(session, SSH_FATAL,
                              "Parsing private key: %s",
                              ERR_error_string(ERR_get_error(),NULL));
                return NULL;
            }

            break;
        case SSH_KEYTYPE_ECDSA:
        case SSH_KEYTYPE_UNKNOWN:
            BIO_free(mem);
            ssh_set_error(session, SSH_FATAL,
                          "Unkown or invalid private key type %d", type);
            return NULL;
    }

    key = ssh_key_new();
    if (key == NULL) {
        goto fail;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
    key->dsa = dsa;
    key->rsa = rsa;

    return key;
fail:
    ssh_key_free(key);
    DSA_free(dsa);
    RSA_free(rsa);

    return NULL;
}
Пример #11
0
int ssh_pki_import_pubkey_base64(ssh_session session,
                                 const char *b64_key,
                                 enum ssh_keytypes_e type,
                                 ssh_key *pkey) {
    ssh_buffer buffer;
    ssh_key key;
    int rc;

    key = ssh_key_new();
    if (key == NULL) {
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PUBLIC;

    buffer = base64_to_bin(b64_key);

    switch (type) {
        case SSH_KEYTYPE_DSS:
            {
                ssh_string p;
                ssh_string q;
                ssh_string g;
                ssh_string pubkey;

                p = buffer_get_ssh_string(buffer);
                if (p == NULL) {
                    goto fail;
                }
                q = buffer_get_ssh_string(buffer);
                if (q == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);

                    goto fail;
                }
                g = buffer_get_ssh_string(buffer);
                if (g == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);

                    goto fail;
                }
                pubkey = buffer_get_ssh_string(buffer);
                if (g == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);
                    ssh_string_burn(g);
                    ssh_string_free(g);

                    goto fail;
                }

                rc = pki_pubkey_build_dss(key, p, q, g, pubkey);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
                ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
                ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
#endif
                ssh_string_burn(p);
                ssh_string_free(p);
                ssh_string_burn(q);
                ssh_string_free(q);
                ssh_string_burn(g);
                ssh_string_free(g);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            {
                ssh_string e;
                ssh_string n;

                e = buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }
                n = buffer_get_ssh_string(buffer);
                if (n == NULL) {
                    ssh_string_burn(e);
                    ssh_string_free(e);

                    goto fail;
                }

                rc = pki_pubkey_build_rsa(key, e, n);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
                ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
#endif
                ssh_string_burn(e);
                ssh_string_free(e);
                ssh_string_burn(n);
                ssh_string_free(n);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_ECDSA:
        case SSH_KEYTYPE_UNKNOWN:
            ssh_set_error(session, SSH_FATAL,
                    "Unknown public key protocol %d",
                    type);
            goto fail;
    }

    ssh_buffer_free(buffer);

    *pkey = key;
    return SSH_OK;
fail:
    ssh_buffer_free(buffer);
    ssh_key_free(key);

    return SSH_ERROR;
}
Пример #12
0
/**
 * @internal
 *
 * @brief Import a private key from a ssh buffer.
 *
 * @param[in] key_blob_buffer The key blob to import as specified in
 *                            key.c:key_private_serialize in OpenSSH source
 *                            code.
 *
 * @param[out] pkey     A pointer where the allocated key can be stored. You
 *                      need to free the memory.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_key_free()
 */
static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer,
                                           ssh_key *pkey)
{
    enum ssh_keytypes_e type;
    char *type_s = NULL;
    ssh_key key = NULL;
    ssh_string pubkey = NULL, privkey = NULL;
    int rc;

    if (pkey == NULL) {
        return SSH_ERROR;
    }

    rc = ssh_buffer_unpack(key_blob_buffer, "s", &type_s);
    if (rc == SSH_ERROR){
        ssh_pki_log("Unpack error");
        return SSH_ERROR;
    }

    type = ssh_key_type_from_name(type_s);
    if (type == SSH_KEYTYPE_UNKNOWN) {
        ssh_pki_log("Unknown key type found!");
        return SSH_ERROR;
    }
    SAFE_FREE(type_s);

    key = ssh_key_new();
    if (key == NULL) {
        ssh_pki_log("Out of memory");
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;

    switch (type) {
    case SSH_KEYTYPE_ED25519:
        rc = ssh_buffer_unpack(key_blob_buffer, "SS", &pubkey, &privkey);
        if (rc != SSH_OK){
            ssh_pki_log("Unpack error");
            goto fail;
        }
        if(ssh_string_len(pubkey) != ED25519_PK_LEN ||
                ssh_string_len(privkey) != ED25519_SK_LEN){
            ssh_pki_log("Invalid ed25519 key len");
            goto fail;
        }
        key->ed25519_privkey = malloc(ED25519_SK_LEN);
        key->ed25519_pubkey = malloc(ED25519_PK_LEN);
        if(key->ed25519_privkey == NULL || key->ed25519_pubkey == NULL){
            goto fail;
        }
        memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_SK_LEN);
        memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
        memset(ssh_string_data(privkey), 0, ED25519_SK_LEN);
        SAFE_FREE(privkey);
        SAFE_FREE(pubkey);
        break;
    case SSH_KEYTYPE_DSS:
        /* p,q,g,pub_key,priv_key */
    case SSH_KEYTYPE_RSA:
        /* n,e,d,iqmp,p,q */
    case SSH_KEYTYPE_RSA1:
    case SSH_KEYTYPE_ECDSA:
        /* curve_name, group, privkey */
        ssh_pki_log("Unsupported private key method %s", key->type_c);
        goto fail;
    case SSH_KEYTYPE_UNKNOWN:
        ssh_pki_log("Unknown private key protocol %s", key->type_c);
        goto fail;
    }

    *pkey = key;
    return SSH_OK;
fail:
    ssh_key_free(key);
    if(privkey != NULL){
        memset(ssh_string_data(privkey), 0, ssh_string_len(privkey));
    }
    SAFE_FREE(pubkey);
    SAFE_FREE(privkey);

    return SSH_ERROR;
}