Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add knownhosts mode option to netopeer2-cli #1631

Merged
merged 1 commit into from
Sep 2, 2024
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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ set(LIBYANG_DEP_SOVERSION 3.0.0)
set(LIBYANG_DEP_SOVERSION_MAJOR 3)

# libnetconf2 required version
set(LIBNETCONF2_DEP_VERSION 3.4.0)
set(LIBNETCONF2_DEP_SOVERSION 4.3.6)
set(LIBNETCONF2_DEP_VERSION 3.5.0)
set(LIBNETCONF2_DEP_SOVERSION 4.4.0)
set(LIBNETCONF2_DEP_SOVERSION_MAJOR 4)

# sysrepo required version
Expand Down
100 changes: 63 additions & 37 deletions cli/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ cmd_auth_help(void)
static void
cmd_knownhosts_help(void)
{
printf("knownhosts [--help] [--del <key_index>]\n");
printf("knownhosts (--help | --del <key_index> | --mode <accept|accept-new|ask|skip|strict>)\n");
}

static void
Expand Down Expand Up @@ -1420,18 +1420,20 @@ cmd_auth(const char *arg, char **UNUSED(tmp_config_file))
static int
cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
{
char *ptr, *kh_file, *line = NULL, **pkeys = NULL, *text;
int del_idx = -1, i, j, pkey_len = 0, written, text_len;
char *ptr, *kh_file = NULL, *line = NULL, **pkeys = NULL, *text = NULL, *mode = NULL;
int del_idx = -1, i, j, pkey_len = 0, written, text_len, ret = EXIT_SUCCESS;
size_t line_len;
FILE *file;
FILE *file = NULL;
struct passwd *pwd;
struct arglist cmd;
struct option long_options[] = {
{"help", 0, 0, 'h'},
{"del", 1, 0, 'd'},
{"mode", 1, 0, 'm'},
{0, 0, 0, 0}
};
int option_index = 0, c;
NC_SSH_KNOWNHOSTS_MODE knownhosts_mode;

optind = 0;

Expand All @@ -1440,30 +1442,52 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
return EXIT_FAILURE;
}

while ((c = getopt_long(cmd.count, cmd.list, "hd:", long_options, &option_index)) != -1) {
while ((c = getopt_long(cmd.count, cmd.list, "hd:m:", long_options, &option_index)) != -1) {
switch (c) {
case 'h':
cmd_knownhosts_help();
clear_arglist(&cmd);
return EXIT_SUCCESS;
break;
ret = EXIT_SUCCESS;
goto cleanup;
case 'd':
del_idx = strtol(optarg, &ptr, 10);
if ((*ptr != '\0') || (del_idx < 0)) {
ERROR("knownhosts", "Wrong index");
clear_arglist(&cmd);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
break;
case 'm':
mode = optarg;
break;
default:
ERROR("knownhosts", "Unknown option -%c", c);
cmd_knownhosts_help();
clear_arglist(&cmd);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
}

clear_arglist(&cmd);
if (mode) {
if (!strcmp(mode, "accept")) {
knownhosts_mode = NC_SSH_KNOWNHOSTS_ACCEPT;
} else if (!strcmp(mode, "accept-new")) {
knownhosts_mode = NC_SSH_KNOWNHOSTS_ACCEPT_NEW;
} else if (!strcmp(mode, "ask")) {
knownhosts_mode = NC_SSH_KNOWNHOSTS_ASK;
} else if (!strcmp(mode, "skip")) {
knownhosts_mode = NC_SSH_KNOWNHOSTS_SKIP;
} else if (!strcmp(mode, "strict")) {
knownhosts_mode = NC_SSH_KNOWNHOSTS_STRICT;
} else {
ERROR("knownhosts", "Unknown mode \"%s\"", mode);
ret = EXIT_FAILURE;
goto cleanup;
}

nc_client_ssh_set_knownhosts_mode(knownhosts_mode);
nc_client_ssh_ch_set_knownhosts_mode(knownhosts_mode);
goto cleanup;
}

errno = 0;
pwd = getpwuid(getuid());
Expand All @@ -1473,19 +1497,20 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
} else {
ERROR("knownhosts", "Failed to get a pwd entry (%s)", strerror(errno));
}
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}

if (asprintf(&kh_file, "%s/.ssh/known_hosts", pwd->pw_dir) == -1) {
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}

if ((file = fopen(kh_file, "r+")) == NULL) {
ERROR("knownhosts", "Cannot open \"%s\" (%s)", kh_file, strerror(errno));
free(kh_file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
free(kh_file);

/* list */
if (del_idx == -1) {
Expand Down Expand Up @@ -1558,17 +1583,16 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
text_len = ftell(file);
if (text_len < 0) {
ERROR("knownhosts", "ftell on the known hosts file failed (%s)", strerror(errno));
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
fseek(file, 0, SEEK_SET);

text = malloc(text_len + 1);
if (fread(text, 1, text_len, file) < (unsigned)text_len) {
ERROR("knownhosts", "Cannot read known hosts file (%s)", strerror(ferror(file)));
free(text);
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
text[text_len] = '\0';
fseek(file, 0, SEEK_SET);
Expand All @@ -1577,9 +1601,8 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))

if (!ptr || (strlen(ptr) < 2)) {
ERROR("knownhosts", "Key index %d does not exist", del_idx);
free(text);
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}

if (ptr[0] == '\n') {
Expand All @@ -1590,9 +1613,8 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
written = fwrite(text, 1, ptr - text, file);
if (written < ptr - text) {
ERROR("knownhosts", "Failed to write to known hosts file (%s)", strerror(ferror(file)));
free(text);
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}

ptr = strchr(ptr, '\n');
Expand All @@ -1602,23 +1624,27 @@ cmd_knownhosts(const char *arg, char **UNUSED(tmp_config_file))
/* write the rest */
if (fwrite(ptr, 1, strlen(ptr), file) < strlen(ptr)) {
ERROR("knownhosts", "Failed to write to known hosts file (%s)", strerror(ferror(file)));
free(text);
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
written += strlen(ptr);
}
free(text);

if (ftruncate(fileno(file), written) < 0) {
ERROR("knownhosts", "ftruncate() on known hosts file failed (%s)", strerror(ferror(file)));
fclose(file);
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto cleanup;
}
}

fclose(file);
return EXIT_SUCCESS;
cleanup:
clear_arglist(&cmd);
free(kh_file);
free(text);
if (file) {
fclose(file);
}
return ret;
}

static int
Expand Down
19 changes: 18 additions & 1 deletion cli/doc/netopeer2-cli.1
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ Manage the user knownhosts file where all the known SSH server host keys are sto
.PP

.B knownhosts
[\-\-help] [\-\-del <key_index>]
(\-\-help | \-\-del <key_index> | \-\-mode <accept|accept-new|ask|skip|strict>)
.PP
.RS 4

Expand All @@ -948,6 +948,23 @@ a modified host key.
.RE
.PP

.B \-\-(m)ode
\fIaccept|accept-new|ask|skip|strict\fR
.RS 4
Set the host key checking mode used when connecting over SSH.
.IP accept
Add the host key to the knownhosts file without prompting and allow connections to servers that changed their host key.
.IP accept-new
Add the host key to the knownhosts file without prompting, but only if it is not already there.
.IP \fIask\fR
Prompt the user to accept the host key. This is the default mode.
.IP skip
Skip the host key and do not add it to the knownhosts file.
.IP strict
Do not add the host key to the knownhosts file and refuse to connect to hosts whose host key is not known or has changed.
.RE
.PP


.SS listen
Listen for a NETCONF Call Home connection.
Expand Down