Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/server_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,20 @@ int nc_server_config_add_ssh_user_authkey(const struct ly_ctx *ctx, const char *
*/
int nc_server_config_del_ssh_user_authkey(const char *endpt_name, const char *user_name, struct lyd_node **config);

/**
* @brief Hashes a clear-text 'iana-crypt-hash' password the way the server stores it in its configuration.
*
* Only "$0$<clear-text>" is a clear-text password, which is hashed into a crypt(3) SHA-512 digest
* under a freshly generated random salt ("$6$<salt>$<digest>"). Any other @p crypt_hash is already
* hashed, so nothing is done and NULL is returned in @p hashed_password.
*
* @param[in] crypt_hash 'iana-crypt-hash:crypt-hash' value, "$0$<clear-text>" for a clear-text password.
* @param[out] hashed_password Hashed password or NULL if @p crypt_hash was not clear text.
* Memory is allocated and has to be freed by the caller.
* @return 0 on success, non-zero otherwise.
*/
int nc_server_config_hash_password(const char *crypt_hash, char **hashed_password);

/**
* @brief Creates new YANG configuration data nodes for an SSH user's password authentication method.
*
Expand Down
51 changes: 45 additions & 6 deletions src/server_config_util_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,9 +490,15 @@ nc_server_config_ch_del_ssh_user_authkey(const char *client_name, const char *en
"public-keys/libnetconf2-netconf-server:use-system-keys", client_name, endpt_name, user_name);
}

/**
* @brief Hash a clear-text password into a crypt(3) SHA-512 digest.
*
* @param[in] password Clear-text password to hash.
* @param[out] hashed_password Generated "$6$<salt>$<digest>" value.
* @return 0 on success, non-zero otherwise.
*/
static int
_nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tree_path,
const char *password, struct lyd_node **config)
nc_server_config_crypt_password(const char *password, char **hashed_password)
{
int ret = 0;
size_t i;
Expand All @@ -502,6 +508,8 @@ _nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tr
unsigned char rnd[16];
static const char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

*hashed_password = NULL;

cdata = calloc(1, sizeof *cdata);
NC_CHECK_ERRMEM_GOTO(!cdata, ret = 1, cleanup);

Expand All @@ -527,16 +535,47 @@ _nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tr
goto cleanup;
}

ret = nc_server_config_append(ctx, tree_path, "hashed-password", hashed_pw, config);
if (ret) {
goto cleanup;
}
/* crypt_r() returns a pointer into cdata, which is freed below */
*hashed_password = strdup(hashed_pw);
NC_CHECK_ERRMEM_GOTO(!*hashed_password, ret = 1, cleanup);

cleanup:
free(cdata);
return ret;
}

API int
nc_server_config_hash_password(const char *crypt_hash, char **hashed_password)
{
NC_CHECK_ARG_RET(NULL, crypt_hash, hashed_password, 1);

*hashed_password = NULL;

if (strncmp(crypt_hash, "$0$", 3)) {
/* not a clear-text password, nothing to do */
return 0;
}

return nc_server_config_crypt_password(crypt_hash + 3, hashed_password);
}

static int
_nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tree_path,
const char *password, struct lyd_node **config)
{
int ret = 0;
char *hashed_pw = NULL;

if (nc_server_config_crypt_password(password, &hashed_pw)) {
return 1;
}

ret = nc_server_config_append(ctx, tree_path, "hashed-password", hashed_pw, config);

free(hashed_pw);
return ret;
}

API int
nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *endpt_name,
const char *user_name, const char *password, struct lyd_node **config)
Expand Down