From 2daf3dc4a8d83dd74d98ce8cea2b2e457fedbc5a Mon Sep 17 00:00:00 2001 From: Debanga Sarma Date: Tue, 9 Apr 2024 22:04:35 +0530 Subject: [PATCH] feat: add option to read user-supplied key string in ssh_bind_options_set() Signed-off-by: Debanga Sarma Reviewed-by: Jakub Jelen --- include/libssh/server.h | 1 + src/options.c | 115 ++++++++++++++++------------------------ 2 files changed, 47 insertions(+), 69 deletions(-) diff --git a/include/libssh/server.h b/include/libssh/server.h index 9ce79277..e437f292 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -58,6 +58,7 @@ enum ssh_bind_options_e { SSH_BIND_OPTIONS_PROCESS_CONFIG, SSH_BIND_OPTIONS_MODULI, SSH_BIND_OPTIONS_RSA_MIN_SIZE, + SSH_BIND_OPTIONS_IMPORT_KEY_STR, }; typedef struct ssh_bind_struct* ssh_bind; diff --git a/src/options.c b/src/options.c index 81be625d..61a7e4a7 100644 --- a/src/options.c +++ b/src/options.c @@ -2048,6 +2048,10 @@ static int ssh_bind_set_algo(ssh_bind sshbind, * Set the Private Key for the server directly * (ssh_key). It will be free'd by ssh_bind_free(). * + * - SSH_BIND_OPTIONS_IMPORT_KEY_STR: + * Set the Private key for the server from a + * base64 encoded buffer (const char *). + * * - SSH_BIND_OPTIONS_CIPHERS_C_S: * Set the symmetric cipher client to server * (const char *, comma-separated list). @@ -2137,18 +2141,37 @@ ssh_bind_options_set(ssh_bind sshbind, case SSH_BIND_OPTIONS_ECDSAKEY: /* deprecated */ case SSH_BIND_OPTIONS_HOSTKEY: + case SSH_BIND_OPTIONS_IMPORT_KEY: + case SSH_BIND_OPTIONS_IMPORT_KEY_STR: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { int key_type; - ssh_key key; ssh_key *bind_key_loc = NULL; - char **bind_key_path_loc; + ssh_key key = NULL; + char **bind_key_path_loc = NULL; - rc = ssh_pki_import_privkey_file(value, NULL, NULL, NULL, &key); - if (rc != SSH_OK) { - return -1; + if (type == SSH_BIND_OPTIONS_IMPORT_KEY_STR) { + const char *key_str = (const char *)value; + rc = ssh_pki_import_privkey_base64(key_str, + NULL, + NULL, + NULL, + &key); + if (rc == SSH_ERROR) { + ssh_set_error(sshbind, + SSH_FATAL, + "Failed to import key from buffer"); + return -1; + } + } else if (type == SSH_BIND_OPTIONS_IMPORT_KEY) { + key = (ssh_key)value; + } else { + rc = ssh_pki_import_privkey_file(value, NULL, NULL, NULL, &key); + if (rc != SSH_OK) { + return -1; + } } allowed = ssh_bind_key_size_allowed(sshbind, key); if (!allowed) { @@ -2156,10 +2179,8 @@ ssh_bind_options_set(ssh_bind sshbind, SSH_FATAL, "The host key size %d is too small.", ssh_key_size(key)); - ssh_key_free(key); return -1; } - key_type = ssh_key_type(key); switch (key_type) { case SSH_KEYTYPE_ECDSA_P256: @@ -2189,69 +2210,25 @@ ssh_bind_options_set(ssh_bind sshbind, "Unsupported key type %d", key_type); } - - if (bind_key_loc == NULL) { - ssh_key_free(key); - return -1; + if (type == SSH_BIND_OPTIONS_RSAKEY || + type == SSH_BIND_OPTIONS_ECDSAKEY || + type == SSH_BIND_OPTIONS_HOSTKEY) { + if (bind_key_loc == NULL) { + ssh_key_free(key); + return -1; + } + /* Set the location of the key on disk even though we don't + need it in case some other function wants it */ + rc = ssh_bind_set_key(sshbind, bind_key_path_loc, value); + if (rc < 0) { + ssh_key_free(key); + return -1; + } + } else { + if (bind_key_loc == NULL) { + return -1; + } } - - /* Set the location of the key on disk even though we don't - need it in case some other function wants it */ - rc = ssh_bind_set_key(sshbind, bind_key_path_loc, value); - if (rc < 0) { - ssh_key_free(key); - return -1; - } - ssh_key_free(*bind_key_loc); - *bind_key_loc = key; - } - break; - case SSH_BIND_OPTIONS_IMPORT_KEY: - if (value == NULL) { - ssh_set_error_invalid(sshbind); - return -1; - } else { - int key_type; - ssh_key *bind_key_loc = NULL; - ssh_key key = (ssh_key)value; - - allowed = ssh_bind_key_size_allowed(sshbind, key); - if (!allowed) { - ssh_set_error(sshbind, - SSH_FATAL, - "The host key size %d is too small.", - ssh_key_size(key)); - return -1; - } - - key_type = ssh_key_type(key); - switch (key_type) { - case SSH_KEYTYPE_ECDSA_P256: - case SSH_KEYTYPE_ECDSA_P384: - case SSH_KEYTYPE_ECDSA_P521: -#ifdef HAVE_ECC - bind_key_loc = &sshbind->ecdsa; -#else - ssh_set_error(sshbind, - SSH_FATAL, - "ECDSA key used and libssh compiled " - "without ECDSA support"); -#endif - break; - case SSH_KEYTYPE_RSA: - bind_key_loc = &sshbind->rsa; - break; - case SSH_KEYTYPE_ED25519: - bind_key_loc = &sshbind->ed25519; - break; - default: - ssh_set_error(sshbind, - SSH_FATAL, - "Unsupported key type %d", - key_type); - } - if (bind_key_loc == NULL) - return -1; ssh_key_free(*bind_key_loc); *bind_key_loc = key; }