mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-12 11:20:10 +01:00
ssh token: Move SSH code to a separate utils file
This commit is contained in:
@@ -6,11 +6,13 @@ TOKENS_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
|
||||
|
||||
if SSHPLUGIN_TOKEN
|
||||
libcryptsetup_token_ssh_la_LDFLAGS = $(TOKENS_LDFLAGS)
|
||||
libcryptsetup_token_ssh_la_SOURCES = tokens/ssh/libcryptsetup-token-ssh.c
|
||||
libcryptsetup_token_ssh_la_SOURCES = tokens/ssh/libcryptsetup-token-ssh.c \
|
||||
tokens/ssh/ssh-utils.c \
|
||||
tokens/ssh/ssh-utils.h
|
||||
libcryptsetup_token_ssh_la_LIBADD = -lssh libcryptsetup.la @JSON_C_LIBS@
|
||||
lib_LTLIBRARIES += libcryptsetup-token-ssh.la
|
||||
|
||||
cryptsetup_ssh_SOURCES = tokens/ssh/cryptsetup-ssh.c
|
||||
cryptsetup_ssh_SOURCES = tokens/ssh/cryptsetup-ssh.c tokens/ssh/ssh-utils.h
|
||||
cryptsetup_ssh_LDADD = libcryptsetup.la @JSON_C_LIBS@
|
||||
|
||||
sbin_PROGRAMS += cryptsetup-ssh
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
#define TOKEN_NAME "ssh"
|
||||
|
||||
#define PASSWORD_LENGTH 8192
|
||||
|
||||
#define l_err(cd, x...) crypt_logf(cd, CRYPT_LOG_ERROR, x)
|
||||
#define l_dbg(cd, x...) crypt_logf(cd, CRYPT_LOG_DEBUG, x)
|
||||
|
||||
|
||||
@@ -29,13 +29,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <json-c/json.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
#define PASSWORD_LENGTH 8192
|
||||
#include "ssh-utils.h"
|
||||
|
||||
#define TOKEN_NAME "ssh"
|
||||
#define TOKEN_VERSION_MAJOR "1"
|
||||
@@ -78,148 +74,6 @@ static json_object *get_token_jobj(struct crypt_device *cd, int token)
|
||||
return json_tokener_parse(json_slot);
|
||||
}
|
||||
|
||||
static int sshplugin_download_password(struct crypt_device *cd, ssh_session ssh,
|
||||
const char *path, char **password, size_t *password_len)
|
||||
{
|
||||
char *pass = NULL;
|
||||
size_t pass_len;
|
||||
int r;
|
||||
sftp_attributes sftp_attr = NULL;
|
||||
sftp_session sftp = NULL;
|
||||
sftp_file file = NULL;
|
||||
|
||||
sftp = sftp_new(ssh);
|
||||
if (!sftp) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot create sftp session: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = sftp_init(sftp);
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot init sftp session: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = sftp_open(sftp, path, O_RDONLY, 0);
|
||||
if (!file) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot create sftp session: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sftp_attr = sftp_fstat(file);
|
||||
if (!sftp_attr) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot stat sftp file: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pass_len = sftp_attr->size > PASSWORD_LENGTH ? PASSWORD_LENGTH : sftp_attr->size;
|
||||
pass = malloc(pass_len);
|
||||
if (!pass) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Not enough memory.\n");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = sftp_read(file, pass, pass_len);
|
||||
if (r < 0 || (size_t)r != pass_len) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot read remote key: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*password = pass;
|
||||
*password_len = pass_len;
|
||||
|
||||
r = SSH_OK;
|
||||
out:
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
free(pass);
|
||||
}
|
||||
|
||||
if (sftp_attr)
|
||||
sftp_attributes_free(sftp_attr);
|
||||
|
||||
if (file)
|
||||
sftp_close(file);
|
||||
if (sftp)
|
||||
sftp_free(sftp);
|
||||
return r == SSH_OK ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static ssh_session sshplugin_session_init(struct crypt_device *cd,
|
||||
const char *host, const char *user)
|
||||
{
|
||||
int r, port = 22;
|
||||
ssh_session ssh = ssh_new();
|
||||
if (!ssh)
|
||||
return NULL;
|
||||
|
||||
ssh_options_set(ssh, SSH_OPTIONS_HOST, host);
|
||||
ssh_options_set(ssh, SSH_OPTIONS_USER, user);
|
||||
ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_NORMAL, "SSH token initiating ssh session.\n");
|
||||
|
||||
r = ssh_connect(ssh);
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Connection failed: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = ssh_session_is_known_server(ssh);
|
||||
if (r != SSH_SERVER_KNOWN_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Server not known: ");
|
||||
r = SSH_AUTH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = SSH_OK;
|
||||
|
||||
/* initialise list of authentication methods. yes, according to official libssh docs... */
|
||||
ssh_userauth_none(ssh, NULL);
|
||||
out:
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
ssh_disconnect(ssh);
|
||||
ssh_free(ssh);
|
||||
ssh = NULL;
|
||||
}
|
||||
|
||||
return ssh;
|
||||
}
|
||||
|
||||
static int sshplugin_public_key_auth(struct crypt_device *cd, ssh_session ssh, const ssh_key pkey)
|
||||
{
|
||||
int r;
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_DEBUG, "Trying public key authentication method.\n");
|
||||
|
||||
if (!(ssh_userauth_list(ssh, NULL) & SSH_AUTH_METHOD_PUBLICKEY)) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Public key auth method not allowed on host.\n");
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
r = ssh_userauth_try_publickey(ssh, NULL, pkey);
|
||||
if (r == SSH_AUTH_SUCCESS) {
|
||||
crypt_log(cd, CRYPT_LOG_DEBUG, "Public key method accepted.\n");
|
||||
r = ssh_userauth_publickey(ssh, NULL, pkey);
|
||||
}
|
||||
|
||||
if (r != SSH_AUTH_SUCCESS) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Public key authentication error: ");
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int cryptsetup_token_open_pin(struct crypt_device *cd, int token, const char *pin,
|
||||
size_t pin_size __attribute__((unused)), char **password, size_t *password_len,
|
||||
void *usrptr __attribute__((unused)))
|
||||
|
||||
171
tokens/ssh/ssh-utils.c
Normal file
171
tokens/ssh/ssh-utils.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* ssh plugin utilities
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz <gmazyland@gmail.com>
|
||||
* Copyright (C) 2020-2021 Vojtech Trefny
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <fcntl.h>
|
||||
#include <libcryptsetup.h>
|
||||
|
||||
#define KEYFILE_LENGTH_MAX 8192
|
||||
|
||||
int sshplugin_download_password(struct crypt_device *cd, ssh_session ssh,
|
||||
const char *path, char **password, size_t *password_len)
|
||||
{
|
||||
char *pass = NULL;
|
||||
size_t pass_len;
|
||||
int r;
|
||||
sftp_attributes sftp_attr = NULL;
|
||||
sftp_session sftp = NULL;
|
||||
sftp_file file = NULL;
|
||||
|
||||
sftp = sftp_new(ssh);
|
||||
if (!sftp) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot create sftp session: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = sftp_init(sftp);
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot init sftp session: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = sftp_open(sftp, path, O_RDONLY, 0);
|
||||
if (!file) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot create sftp session: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sftp_attr = sftp_fstat(file);
|
||||
if (!sftp_attr) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot stat sftp file: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pass_len = sftp_attr->size > KEYFILE_LENGTH_MAX ? KEYFILE_LENGTH_MAX : sftp_attr->size;
|
||||
pass = malloc(pass_len);
|
||||
if (!pass) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Not enough memory.\n");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = sftp_read(file, pass, pass_len);
|
||||
if (r < 0 || (size_t)r != pass_len) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Cannot read remote key: ");
|
||||
r = SSH_FX_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*password = pass;
|
||||
*password_len = pass_len;
|
||||
|
||||
r = SSH_OK;
|
||||
out:
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
free(pass);
|
||||
}
|
||||
|
||||
if (sftp_attr)
|
||||
sftp_attributes_free(sftp_attr);
|
||||
|
||||
if (file)
|
||||
sftp_close(file);
|
||||
if (sftp)
|
||||
sftp_free(sftp);
|
||||
return r == SSH_OK ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
ssh_session sshplugin_session_init(struct crypt_device *cd, const char *host, const char *user)
|
||||
{
|
||||
int r, port = 22;
|
||||
ssh_session ssh = ssh_new();
|
||||
if (!ssh)
|
||||
return NULL;
|
||||
|
||||
ssh_options_set(ssh, SSH_OPTIONS_HOST, host);
|
||||
ssh_options_set(ssh, SSH_OPTIONS_USER, user);
|
||||
ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_NORMAL, "SSH token initiating ssh session.\n");
|
||||
|
||||
r = ssh_connect(ssh);
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Connection failed: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = ssh_session_is_known_server(ssh);
|
||||
if (r != SSH_SERVER_KNOWN_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Server not known: ");
|
||||
r = SSH_AUTH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = SSH_OK;
|
||||
|
||||
/* initialise list of authentication methods. yes, according to official libssh docs... */
|
||||
ssh_userauth_none(ssh, NULL);
|
||||
out:
|
||||
if (r != SSH_OK) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
ssh_disconnect(ssh);
|
||||
ssh_free(ssh);
|
||||
ssh = NULL;
|
||||
}
|
||||
|
||||
return ssh;
|
||||
}
|
||||
|
||||
int sshplugin_public_key_auth(struct crypt_device *cd, ssh_session ssh, const ssh_key pkey)
|
||||
{
|
||||
int r;
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_DEBUG, "Trying public key authentication method.\n");
|
||||
|
||||
if (!(ssh_userauth_list(ssh, NULL) & SSH_AUTH_METHOD_PUBLICKEY)) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Public key auth method not allowed on host.\n");
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
r = ssh_userauth_try_publickey(ssh, NULL, pkey);
|
||||
if (r == SSH_AUTH_SUCCESS) {
|
||||
crypt_log(cd, CRYPT_LOG_DEBUG, "Public key method accepted.\n");
|
||||
r = ssh_userauth_publickey(ssh, NULL, pkey);
|
||||
}
|
||||
|
||||
if (r != SSH_AUTH_SUCCESS) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "Public key authentication error: ");
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, "\n");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
29
tokens/ssh/ssh-utils.h
Normal file
29
tokens/ssh/ssh-utils.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* ssh plugin utilities
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz <gmazyland@gmail.com>
|
||||
* Copyright (C) 2020-2021 Vojtech Trefny
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
#include <libcryptsetup.h>
|
||||
|
||||
int sshplugin_download_password(struct crypt_device *cd, ssh_session ssh,
|
||||
const char *path, char **password, size_t *password_len);
|
||||
ssh_session sshplugin_session_init(struct crypt_device *cd, const char *host, const char *user);
|
||||
int sshplugin_public_key_auth(struct crypt_device *cd, ssh_session ssh, const ssh_key pkey);
|
||||
Reference in New Issue
Block a user