mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-12 19:30:04 +01:00
Add example SSH token handler.
Provides example of loadable token handler for activation json validation and metadata dump. For creating new ssh example token use special cryptsetup-ssh binary.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
EXTRA_DIST = COPYING.LGPL FAQ docs misc
|
EXTRA_DIST = COPYING.LGPL FAQ docs misc tokens
|
||||||
SUBDIRS = po tests
|
SUBDIRS = po tests
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
DISTCLEAN_TARGETS =
|
DISTCLEAN_TARGETS =
|
||||||
@@ -38,6 +38,7 @@ include lib/crypto_backend/Makemodule.am
|
|||||||
include lib/Makemodule.am
|
include lib/Makemodule.am
|
||||||
|
|
||||||
include src/Makemodule.am
|
include src/Makemodule.am
|
||||||
|
include tokens/Makemodule.am
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
|||||||
@@ -347,6 +347,10 @@ AC_ARG_ENABLE([udev],
|
|||||||
AS_HELP_STRING([--disable-udev], [disable udev support]),
|
AS_HELP_STRING([--disable-udev], [disable udev support]),
|
||||||
[], [enable_udev=yes])
|
[], [enable_udev=yes])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([ssh-token],
|
||||||
|
AS_HELP_STRING([--enable-ssh-token], [enable build of ssh-token]))
|
||||||
|
AM_CONDITIONAL(SSHPLUGIN_TOKEN, test "x$enable_ssh_token" = "xyes")
|
||||||
|
|
||||||
dnl Try to use pkg-config for devmapper, but fallback to old detection
|
dnl Try to use pkg-config for devmapper, but fallback to old detection
|
||||||
PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [
|
PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [
|
||||||
AC_CHECK_LIB(devmapper, dm_task_set_name,,
|
AC_CHECK_LIB(devmapper, dm_task_set_name,,
|
||||||
@@ -380,6 +384,11 @@ PKG_CHECK_MODULES([JSON_C], [json-c])
|
|||||||
AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include <json-c/json.h>])
|
AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include <json-c/json.h>])
|
||||||
AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include <json-c/json.h>])
|
AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include <json-c/json.h>])
|
||||||
|
|
||||||
|
dnl Check for libssh for SSH plugin
|
||||||
|
if test "x$enable_ssh_token" = "xyes"; then
|
||||||
|
PKG_CHECK_MODULES([LIBSSH], [libssh])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Crypto backend configuration.
|
dnl Crypto backend configuration.
|
||||||
AC_ARG_WITH([crypto_backend],
|
AC_ARG_WITH([crypto_backend],
|
||||||
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
|
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ static int _password_auth(struct crypt_device *cd, ssh_session ssh, password_cb_
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SSHTEST_token_open(struct crypt_device *cd,
|
static int SSHPLUGIN_token_open(struct crypt_device *cd,
|
||||||
int token,
|
int token,
|
||||||
char **password,
|
char **password,
|
||||||
size_t *password_len,
|
size_t *password_len,
|
||||||
@@ -280,9 +280,9 @@ static int SSHTEST_token_open(struct crypt_device *cd,
|
|||||||
return r ? -EINVAL : r;
|
return r ? -EINVAL : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
const crypt_token_handler SSHTEST_token = {
|
const crypt_token_handler SSHPLUGIN_token = {
|
||||||
.name = "sshkeytest",
|
.name = "sshkeytest",
|
||||||
.open = SSHTEST_token_open,
|
.open = SSHPLUGIN_token_open,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int token_add(const char *device, const char *server,
|
static int token_add(const char *device, const char *server,
|
||||||
@@ -292,7 +292,7 @@ static int token_add(const char *device, const char *server,
|
|||||||
json_object *jobj = NULL, *jobj_keyslots;
|
json_object *jobj = NULL, *jobj_keyslots;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = crypt_token_register(&SSHTEST_token);
|
r = crypt_token_register(&SSHPLUGIN_token);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ static int token_add(const char *device, const char *server,
|
|||||||
}
|
}
|
||||||
|
|
||||||
jobj = json_object_new_object();
|
jobj = json_object_new_object();
|
||||||
json_object_object_add(jobj, "type", json_object_new_string(SSHTEST_token.name)); /* mandatory */
|
json_object_object_add(jobj, "type", json_object_new_string(SSHPLUGIN_token.name)); /* mandatory */
|
||||||
|
|
||||||
jobj_keyslots = json_object_new_array();
|
jobj_keyslots = json_object_new_array();
|
||||||
json_object_array_add(jobj_keyslots, json_object_new_string("0")); /* assign to first keyslot only */
|
json_object_array_add(jobj_keyslots, json_object_new_string("0")); /* assign to first keyslot only */
|
||||||
@@ -361,7 +361,7 @@ static int open_by_token(const char *device, const char *name)
|
|||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = crypt_token_register(&SSHTEST_token);
|
r = crypt_token_register(&SSHPLUGIN_token);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
|||||||
17
tokens/Makemodule.am
Normal file
17
tokens/Makemodule.am
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
EXTRA_DIST += tokens/libcryptsetup-token.sym
|
||||||
|
|
||||||
|
TOKENS_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
|
||||||
|
-Wl,--version-script=$(top_srcdir)/tokens/libcryptsetup-token.sym \
|
||||||
|
-version-info 0:0:0
|
||||||
|
|
||||||
|
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_LIBADD = -lssh libcryptsetup.la @JSON_C_LIBS@
|
||||||
|
lib_LTLIBRARIES += libcryptsetup-token-ssh.la
|
||||||
|
|
||||||
|
cryptsetup_ssh_SOURCES = tokens/ssh/cryptsetup-ssh.c
|
||||||
|
cryptsetup_ssh_LDADD = libcryptsetup.la @JSON_C_LIBS@
|
||||||
|
|
||||||
|
sbin_PROGRAMS += cryptsetup-ssh
|
||||||
|
endif
|
||||||
9
tokens/libcryptsetup-token.sym
Normal file
9
tokens/libcryptsetup-token.sym
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
CRYPTSETUP_TOKEN_1.0 {
|
||||||
|
global: cryptsetup_token_open;
|
||||||
|
cryptsetup_token_open_pin;
|
||||||
|
cryptsetup_token_buffer_free;
|
||||||
|
cryptsetup_token_validate;
|
||||||
|
cryptsetup_token_dump;
|
||||||
|
cryptsetup_token_version;
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
122
tokens/ssh/cryptsetup-ssh.c
Normal file
122
tokens/ssh/cryptsetup-ssh.c
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Example of LUKS2 token storing third party metadata (EXAMPLE)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-2020 Milan Broz <gmazyland@gmail.com>
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* - generate ssh example token
|
||||||
|
*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include "libcryptsetup.h"
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
static int token_add(
|
||||||
|
const char *device,
|
||||||
|
const char *server,
|
||||||
|
const char *user,
|
||||||
|
const char *path,
|
||||||
|
const char *keypath)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct crypt_device *cd;
|
||||||
|
json_object *jobj = NULL;
|
||||||
|
json_object *jobj_keyslots = NULL;
|
||||||
|
const char *string_token;
|
||||||
|
int r, token;
|
||||||
|
|
||||||
|
r = crypt_init(&cd, device);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = crypt_load(cd, CRYPT_LUKS2, NULL);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
r = -EINVAL;
|
||||||
|
jobj = json_object_new_object();
|
||||||
|
if (!jobj)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* type is mandatory field in all tokens and must match handler name member */
|
||||||
|
json_object_object_add(jobj, "type", json_object_new_string(TOKEN_NAME));
|
||||||
|
|
||||||
|
jobj_keyslots = json_object_new_array();
|
||||||
|
|
||||||
|
/* mandatory array field (may be empty and assigned later */
|
||||||
|
json_object_object_add(jobj, "keyslots", jobj_keyslots);
|
||||||
|
|
||||||
|
/* custom metadata */
|
||||||
|
json_object_object_add(jobj, "ssh_server", json_object_new_string(server));
|
||||||
|
json_object_object_add(jobj, "ssh_user", json_object_new_string(user));
|
||||||
|
json_object_object_add(jobj, "ssh_path", json_object_new_string(path));
|
||||||
|
json_object_object_add(jobj, "ssh_keypath", json_object_new_string(keypath));
|
||||||
|
|
||||||
|
string_token = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
|
||||||
|
if (!string_token) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
l_dbg(cd, "Token JSON: %s", string_token);
|
||||||
|
|
||||||
|
r = crypt_token_json_set(cd, CRYPT_ANY_TOKEN, string_token);
|
||||||
|
if (r < 0) {
|
||||||
|
l_err(cd, "Failed to write ssh token json.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = r;
|
||||||
|
r = crypt_token_assign_keyslot(cd, token, CRYPT_ANY_SLOT);
|
||||||
|
if (r != token) {
|
||||||
|
crypt_token_json_set(cd, token, NULL);
|
||||||
|
r = -EINVAL;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
json_object_put(jobj);
|
||||||
|
crypt_free(cd);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void token_help(void)
|
||||||
|
{
|
||||||
|
printf("Use parameters:\n add device server user path keypath\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// crypt_set_debug_level(CRYPT_LOG_DEBUG);
|
||||||
|
|
||||||
|
/* Adding slot to device */
|
||||||
|
if (argc > 6 && !strcmp("add", argv[1]))
|
||||||
|
return token_add(argv[2], argv[3], argv[4], argv[5], argv[6]);
|
||||||
|
|
||||||
|
token_help();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
336
tokens/ssh/libcryptsetup-token-ssh.c
Normal file
336
tokens/ssh/libcryptsetup-token-ssh.c
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
* Example of LUKS2 ssh token handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-2020 Milan Broz <gmazyland@gmail.com>
|
||||||
|
* Copyright (C) 2020 Vojtech Trefny
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* - generate LUKS device
|
||||||
|
* - store passphrase used in previous step remotely (single line w/o \r\n)
|
||||||
|
* - add new token using this example
|
||||||
|
* - activate device by token
|
||||||
|
*
|
||||||
|
* 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 <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
|
||||||
|
|
||||||
|
#define TOKEN_NAME "ssh"
|
||||||
|
#define TOKEN_VERSION_MAJOR "1"
|
||||||
|
#define TOKEN_VERSION_MINOR "0"
|
||||||
|
|
||||||
|
#define SERVER_ARG "plugin-ssh-server"
|
||||||
|
#define USER_ARG "plugin-ssh-user"
|
||||||
|
#define PATH_ARG "plugin-ssh-path"
|
||||||
|
#define KEYPATH_ARG "plugin-ssh-keypath"
|
||||||
|
|
||||||
|
#define l_dbg(cd, x...) crypt_logf(cd, CRYPT_LOG_DEBUG, x)
|
||||||
|
|
||||||
|
struct sshplugin_context {
|
||||||
|
const char *server;
|
||||||
|
const char *user;
|
||||||
|
const char *path;
|
||||||
|
const char *sshkey_path;
|
||||||
|
|
||||||
|
int token;
|
||||||
|
int keyslot;
|
||||||
|
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
struct crypt_cli *cli;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *cryptsetup_token_version(void)
|
||||||
|
{
|
||||||
|
return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_object *get_token_jobj(struct crypt_device *cd, int token)
|
||||||
|
{
|
||||||
|
const char *json_slot;
|
||||||
|
|
||||||
|
/* libcryptsetup API call */
|
||||||
|
if (crypt_token_json_get(cd, token, &json_slot))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
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,
|
||||||
|
char **password, size_t *password_len, void *usrptr)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
json_object *jobj_server, *jobj_user, *jobj_path, *jobj_token, *jobj_keypath;
|
||||||
|
ssh_key pkey;
|
||||||
|
ssh_session ssh;
|
||||||
|
|
||||||
|
jobj_token = get_token_jobj(cd, token);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
|
||||||
|
|
||||||
|
r = ssh_pki_import_privkey_file(json_object_get_string(jobj_keypath), pin, NULL, NULL, &pkey);
|
||||||
|
if (r != SSH_OK) {
|
||||||
|
if (r == SSH_EOF) {
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR, "Failed to open and import private key.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
crypt_log(cd, CRYPT_LOG_ERROR, "Failed to import private key (password protected?).\n");
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh = sshplugin_session_init(cd, json_object_get_string(jobj_server),
|
||||||
|
json_object_get_string(jobj_user));
|
||||||
|
if (!ssh) {
|
||||||
|
ssh_key_free(pkey);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sshplugin_public_key_auth(cd, ssh, pkey);
|
||||||
|
ssh_key_free(pkey);
|
||||||
|
|
||||||
|
if (r == SSH_AUTH_SUCCESS)
|
||||||
|
r = sshplugin_download_password(cd, ssh, json_object_get_string(jobj_path),
|
||||||
|
password, password_len);
|
||||||
|
|
||||||
|
ssh_disconnect(ssh);
|
||||||
|
ssh_free(ssh);
|
||||||
|
|
||||||
|
return r ? -EINVAL : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cryptsetup_token_open(struct crypt_device *cd, int token,
|
||||||
|
char **password, size_t *password_len, void *usrptr)
|
||||||
|
{
|
||||||
|
return cryptsetup_token_open_pin(cd, token, NULL, password, password_len, usrptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptsetup_token_dump(struct crypt_device *cd, const char *json)
|
||||||
|
{
|
||||||
|
json_object *jobj_token, *jobj_server, *jobj_user, *jobj_path, *jobj_keypath;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
|
jobj_token = json_tokener_parse(json);
|
||||||
|
if (!jobj_token)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
|
||||||
|
json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf) - 1, "\tssh_server: %s\n\tssh_user: %s\n"
|
||||||
|
"\tssh_path: %s\n\tssh_key_path: %s\n",
|
||||||
|
json_object_get_string(jobj_server),
|
||||||
|
json_object_get_string(jobj_user),
|
||||||
|
json_object_get_string(jobj_path),
|
||||||
|
json_object_get_string(jobj_keypath));
|
||||||
|
|
||||||
|
crypt_log(cd, CRYPT_LOG_NORMAL, buf);
|
||||||
|
json_object_put(jobj_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cryptsetup_token_validate(struct crypt_device *cd, const char *json)
|
||||||
|
{
|
||||||
|
enum json_tokener_error jerr;
|
||||||
|
json_object *jobj_token, *jobj;
|
||||||
|
int r = -EINVAL;
|
||||||
|
|
||||||
|
jobj_token = json_tokener_parse_verbose(json, &jerr);
|
||||||
|
if (!jobj_token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(jobj_token, "ssh_server", &jobj) ||
|
||||||
|
!json_object_is_type(jobj, json_type_string)) {
|
||||||
|
l_dbg(cd, "ssh_server element is missing or not string.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(jobj_token, "ssh_user", &jobj) ||
|
||||||
|
!json_object_is_type(jobj, json_type_string)) {
|
||||||
|
l_dbg(cd, "ssh_user element is missing or not string.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(jobj_token, "ssh_path", &jobj) ||
|
||||||
|
!json_object_is_type(jobj, json_type_string)) {
|
||||||
|
l_dbg(cd, "ssh_path element is missing or not string.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(jobj_token, "ssh_keypath", &jobj) ||
|
||||||
|
!json_object_is_type(jobj, json_type_string)) {
|
||||||
|
l_dbg(cd, "ssh_keypath element is missing or not string.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
json_object_put(jobj_token);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user