Skip to content

Commit

Permalink
Generate any (SSH) key without content
Browse files Browse the repository at this point in the history
This also makes it possible to remove the key 'genkey' if the
user wants.
  • Loading branch information
mattiaswal committed Nov 28, 2024
1 parent eabf79c commit efe2c50
Showing 1 changed file with 73 additions and 65 deletions.
138 changes: 73 additions & 65 deletions src/confd/src/ietf-keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "core.h"

#define XPATH_KEYSTORE_ "/ietf-keystore:keystore/asymmetric-keys"
#define SSH_PRIVATE_KEY "/tmp/ssh.key"
#define SSH_PUBLIC_KEY "/tmp/ssh.pub"

/* return file size */
static size_t filesz(const char *fn)
Expand All @@ -21,19 +23,6 @@ static size_t filesz(const char *fn)
return st.st_size;
}

/* sanity check, must exist and be of non-zero size */
static bool fileok(const char *fn)
{
if (!fexist(fn))
return false;

/* Minimum size of BEGIN + END markers */
if (filesz(fn) < 60)
return false;

return true;
}

/* read file of max len bytes, return as malloc()'ed buffer */
static char *filerd(const char *fn, size_t len)
{
Expand Down Expand Up @@ -65,74 +54,93 @@ static char *filerd(const char *fn, size_t len)
static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name,
const char *xpath, sr_event_t event, uint32_t request_id, void *_)
{
const char *priv_keyfile = "/cfg/ssl/private/netconf.key";
const char *pub_keyfile = "/cfg/ssl/public/netconf.pub";
char *pub_key = NULL, *priv_key = NULL;
int rc = SR_ERR_INTERNAL;
sr_val_t *list = NULL;
size_t count = 0;

switch (event) {
case SR_EV_UPDATE:
/* Check NETCONF default hostkey pair */
/* Check SSH (and NETCONF) default hostkey pair */
break;
default:
return SR_ERR_OK;
}

if (srx_isset(session, XPATH_KEYSTORE_"/asymmetric-key[name='genkey']/cleartext-private-key") &&
srx_isset(session, XPATH_KEYSTORE_"/asymmetric-key[name='genkey']/public-key")) {
return SR_ERR_OK; /* already set */
}
WARN("NETCONF private and public host keys missing in confiugration.");

if (!fileok(priv_keyfile) || !fileok(pub_keyfile)) {
NOTE("Generating NETCONF SSH host keys ...");
if (systemf("/usr/libexec/infix/mkkeys %s %s", priv_keyfile, pub_keyfile))
goto err;
} else {
NOTE("Using existing SSH host keys for NETCONF.");
rc = sr_get_items(session, xpath, 0, 0, &list, &count);
if (rc != SR_ERR_OK) {
ERROR("Cannot find any asymmetric keys in configuration");
return 0;
}


for (size_t i = 0; i < count; ++i) {
sr_val_t *entry = &list[i];

ERROR("xpath: %s", entry->xpath);
if (!srx_isset(session, "%s/cleartext-private-key", entry->xpath) && !srx_isset(session, "%s/public-key", entry->xpath)) {
char *private_key_format, *public_key_format;
public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath);
if (!public_key_format)
continue;
private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath);
if (!private_key_format) {
free(public_key_format);
continue;
}

if (!strcmp(private_key_format, "ietf-crypto-types:rsa-private-key-format") &&
!strcmp(public_key_format, "ietf-crypto-types:ssh-public-key-format"))
{
char *pub_key = NULL, *priv_key = NULL, *name;
name = srx_get_str(session, "%s/name", entry->xpath);
NOTE("SSH key (%s) does not exist, generating...", name);
if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) {
ERROR("Failed to generate SSH keys for %s", name);
goto next;
}

priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY));
if (!priv_key)
goto next;

pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY));
if (!pub_key)
goto next;

rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath);
if (rc) {
ERROR("Failed setting private key for %s... rc: %d", name, rc);
goto next;
}
rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath);
if (rc != SR_ERR_OK) {
ERROR("Failed setting public key for %s... rc: %d", name, rc);
goto next;
}
ERROR("Freeing...");
next:
unlink(SSH_PRIVATE_KEY);
unlink(SSH_PUBLIC_KEY);
if(priv_key)
free(priv_key);
if(pub_key)
free(pub_key);
free(name);
}
free(public_key_format);
free(private_key_format);
}
}

priv_key = filerd(priv_keyfile, filesz(priv_keyfile));
if (!priv_key)
goto err;

pub_key = filerd(pub_keyfile, filesz(pub_keyfile));
if (!pub_key)
goto err;

xpath = XPATH_KEYSTORE_"/asymmetric-key[name='genkey']/cleartext-private-key";
rc = sr_set_item_str(session, xpath, priv_key, NULL, SR_EDIT_NON_RECURSIVE);
if (rc) {
ERROR("Failed setting private key ... rc: %d", rc);
goto err;
}

xpath = XPATH_KEYSTORE_"/asymmetric-key[name='genkey']/public-key";
rc = sr_set_item_str(session, xpath, pub_key, NULL, SR_EDIT_NON_RECURSIVE);
if (rc != SR_ERR_OK) {
ERROR("Failed setting public key ... rc: %d", rc);
goto err;
}

err:
if (pub_key)
free(pub_key);
if (priv_key)
free(priv_key);

if (rc != SR_ERR_OK)
return rc;

return SR_ERR_OK;
}

int ietf_keystore_init(struct confd *confd)
{
int rc;

rc = sr_module_change_subscribe(confd->session, "ietf-keystore", "/ietf-keystore:keystore//.",
change_cb, confd, 0, SR_SUBSCR_UPDATE, &confd->sub);
if (rc)
ERROR("%s failed: %s", __func__, sr_strerror(rc));
REGISTER_CHANGE(confd->session, "ietf-keystore", "/ietf-keystore:keystore//.",
SR_SUBSCR_UPDATE, change_cb, confd, &confd->sub);
fail:
ERROR("%s failed: %s", __func__, sr_strerror(rc));
return rc;
}

0 comments on commit efe2c50

Please sign in to comment.