mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Move Device.SSH. code from bbfdm to sshmngr
This commit is contained in:
parent
970ae77bde
commit
efe19940cb
4 changed files with 8 additions and 941 deletions
|
|
@ -33,7 +33,6 @@
|
|||
#include "routeradvertisement.h"
|
||||
#include "gatewayinfo.h"
|
||||
#include "mqtt.h"
|
||||
#include "ssh.h"
|
||||
#include "userinterface.h"
|
||||
#include "packetcapture.h"
|
||||
#include "selftest.h"
|
||||
|
|
@ -107,7 +106,6 @@ DMOBJ tDeviceObj[] = {
|
|||
{"Services", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, BBFDM_BOTH, NULL},
|
||||
{"GatewayInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tGatewayInfoParams, NULL, BBFDM_CWMP, NULL},
|
||||
{"MQTT", &DMREAD, NULL, NULL, "file:/etc/config/mosquitto", NULL, NULL, NULL, tMQTTObj, tMQTTParams, NULL, BBFDM_BOTH, NULL},
|
||||
{"SSH", &DMREAD, NULL, NULL, "file:/etc/config/dropbear", NULL, NULL, NULL, tSSHObj, tSSHParams, NULL, BBFDM_BOTH, NULL},
|
||||
{"UserInterface", &DMREAD, NULL, NULL, "file:/etc/config/userinterface", NULL, NULL, NULL, tUIHTTPAccessObj, tUIParams, NULL, BBFDM_BOTH, NULL},
|
||||
{"PacketCaptureDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tPacketCaptureObj, tPacketCaptureParams, NULL, BBFDM_CWMP, NULL},
|
||||
{"SelfTestDiagnostics", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tSelfTestParams, NULL, BBFDM_CWMP, NULL},
|
||||
|
|
|
|||
|
|
@ -1,915 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 iopsys Software Solutions AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* Author Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
#define DROPBEAR_KEY_FILE "/etc/dropbear/authorized_keys"
|
||||
|
||||
struct ssh_session_args {
|
||||
struct list_head list;
|
||||
char ip[45];
|
||||
char port[6];
|
||||
char pid[15];
|
||||
};
|
||||
|
||||
static void add_pubkey(const char *cur, const char *new)
|
||||
{
|
||||
if (DM_STRLEN(cur) == 0) {
|
||||
if (DM_STRLEN(new) == 0)
|
||||
return;
|
||||
|
||||
FILE *fp = fopen(DROPBEAR_KEY_FILE, "a");
|
||||
if (fp != NULL) {
|
||||
fputs(new, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
} else {
|
||||
char line[5120] = {0};
|
||||
FILE *fp = fopen(DROPBEAR_KEY_FILE, "r");
|
||||
FILE *tmp = fopen("replace.tmp", "w");
|
||||
|
||||
if (fp == NULL || tmp == NULL)
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRCMP(line, cur) == 0 && DM_STRLEN(new) != 0)
|
||||
fputs(new, tmp);
|
||||
else
|
||||
fputs(line, tmp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(tmp);
|
||||
|
||||
remove(DROPBEAR_KEY_FILE);
|
||||
rename("replace.tmp", DROPBEAR_KEY_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_pubkey(const char *key)
|
||||
{
|
||||
if (DM_STRLEN(key) == 0)
|
||||
return;
|
||||
|
||||
char line[5120] = {0};
|
||||
FILE *fp = fopen(DROPBEAR_KEY_FILE, "r");
|
||||
FILE *tmp = fopen("replace.tmp", "w");
|
||||
|
||||
if (fp == NULL || tmp == NULL)
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRCMP(line, key) != 0)
|
||||
fputs(line, tmp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(tmp);
|
||||
|
||||
remove(DROPBEAR_KEY_FILE);
|
||||
rename("replace.tmp", DROPBEAR_KEY_FILE);
|
||||
}
|
||||
|
||||
static bool key_exist_in_keyfile(const char *key)
|
||||
{
|
||||
if (DM_STRLEN(key) == 0)
|
||||
return true;
|
||||
|
||||
char line[5120] = {0};
|
||||
FILE *fp = fopen(DROPBEAR_KEY_FILE, "r");
|
||||
if (fp == NULL)
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRCMP(line, key) == 0) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool key_exists(const char *key)
|
||||
{
|
||||
struct uci_section *s = NULL, *stmp = NULL;
|
||||
bool exists = false;
|
||||
|
||||
uci_path_foreach_sections_safe(bbfdm, "dmmap_dropbear", "authkey", stmp, s) {
|
||||
char *val = NULL;
|
||||
dmuci_get_value_by_section_string(s, "pubkey", &val);
|
||||
if (DM_STRCMP(val, key) == 0) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
static void ssh_server_session_init(struct list_head *sess_list)
|
||||
{
|
||||
char cmd[512] = {0};
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "netstat -ntp | grep dropbear | awk \'{print $5,$7}\' | cut -d\'/\' -f 1");
|
||||
FILE *pp = popen(cmd, "r");
|
||||
if (pp == NULL)
|
||||
return;
|
||||
|
||||
char line[256] = {0};
|
||||
while (fgets(line, sizeof(line), pp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRLEN(line) == 0)
|
||||
continue;
|
||||
|
||||
char *port = NULL;
|
||||
char *pid = NULL;
|
||||
|
||||
char *chr = strchr(line, ':');
|
||||
if (chr) {
|
||||
*chr = 0;
|
||||
port = chr + 1;
|
||||
}
|
||||
|
||||
if (DM_STRLEN(port) != 0) {
|
||||
char *sp = strchr(port, ' ');
|
||||
if (sp) {
|
||||
*sp = 0;
|
||||
pid = sp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct ssh_session_args *session = dmcalloc(1, sizeof(struct ssh_session_args));
|
||||
if (session == NULL)
|
||||
break;
|
||||
|
||||
strncpy(session->ip, line, sizeof(session->ip));
|
||||
if (DM_STRLEN(port) != 0) {
|
||||
snprintf(session->port, sizeof(session->port), "%s", port);
|
||||
}
|
||||
|
||||
if (DM_STRLEN(pid) != 0) {
|
||||
snprintf(session->pid, sizeof(session->pid), "%s", pid);
|
||||
}
|
||||
|
||||
|
||||
list_add_tail(&session->list, sess_list);
|
||||
}
|
||||
|
||||
pclose(pp);
|
||||
}
|
||||
|
||||
static void free_ssh_session_list(struct list_head *sess_list)
|
||||
{
|
||||
struct ssh_session_args *session = NULL, *tmp = NULL;
|
||||
list_for_each_entry_safe(session, tmp, sess_list, list) {
|
||||
list_del(&session->list);
|
||||
dmfree(session);
|
||||
}
|
||||
}
|
||||
|
||||
static void close_active_sessions(struct uci_section *s)
|
||||
{
|
||||
bool b;
|
||||
char *value = dmuci_get_value_by_section_fallback_def(s, "enable", "1");
|
||||
string_to_bool(value, &b);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
char pid_file[125] = {0};
|
||||
char *sec_name = section_name(s);
|
||||
if (DM_STRLEN(sec_name) == 0)
|
||||
return;
|
||||
|
||||
snprintf(pid_file, sizeof(pid_file), "/var/run/dropbear.%s.pid", sec_name);
|
||||
if (DM_STRLEN(pid_file) == 0)
|
||||
return;
|
||||
|
||||
FILE *fp = fopen(pid_file, "r");
|
||||
if (fp == NULL)
|
||||
return;
|
||||
|
||||
unsigned int pid;
|
||||
if (fscanf(fp, "%u", &pid) != 1) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
char cmd[512] = {0};
|
||||
snprintf(cmd, sizeof(cmd), "ps -w | grep %s | grep -v grep | awk \'{print $1}\'", pid_file);
|
||||
FILE *pp = popen(cmd, "r");
|
||||
if (pp == NULL)
|
||||
return;
|
||||
|
||||
char line[15] = {0};
|
||||
while (fgets(line, sizeof(line), pp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRLEN(line) == 0)
|
||||
continue;
|
||||
|
||||
if (strtoul(line, NULL, 10) == pid)
|
||||
continue;
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "kill -15 %s", line);
|
||||
if (system(cmd) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pclose(pp);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* ADD & DEL OBJ
|
||||
*************************************************************/
|
||||
static int addObjSSHServer(char *refparam, struct dmctx *ctx, void *data, char **instance)
|
||||
{
|
||||
struct uci_section *s = NULL, *dmmap_s = NULL;
|
||||
char s_name[16];
|
||||
|
||||
snprintf(s_name, sizeof(s_name), "server_%s", *instance);
|
||||
|
||||
dmuci_add_section("dropbear", "dropbear", &s);
|
||||
dmuci_rename_section_by_section(s, s_name);
|
||||
dmuci_set_value_by_section(s, "enable", "0");
|
||||
dmuci_set_value_by_section(s, "Port", "22");
|
||||
dmuci_set_value_by_section(s, "IdleTimeout", "180");
|
||||
dmuci_set_value_by_section(s, "SSHKeepAlive", "300");
|
||||
dmuci_set_value_by_section(s, "RootLogin", "0");
|
||||
dmuci_set_value_by_section(s, "PasswordAuth", "0");
|
||||
dmuci_set_value_by_section(s, "RootPasswordAuth", "0");
|
||||
dmuci_set_value_by_section(s, "MaxAuthTries", "3");
|
||||
|
||||
dmuci_add_section_bbfdm("dmmap_dropbear", "dropbear", &dmmap_s);
|
||||
dmuci_set_value_by_section(dmmap_s, "section_name", s_name);
|
||||
dmuci_set_value_by_section(dmmap_s, "server_instance", *instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int delObjSSHServer(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
|
||||
{
|
||||
struct uci_section *s = NULL, *stmp = NULL;
|
||||
|
||||
switch (del_action) {
|
||||
case DEL_INST:
|
||||
close_active_sessions(((struct dm_data *)data)->config_section);
|
||||
dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
|
||||
dmuci_delete_by_section(((struct dm_data *)data)->dmmap_section, NULL, NULL);
|
||||
break;
|
||||
case DEL_ALL:
|
||||
uci_foreach_sections_safe("dropbear", "dropbear", stmp, s) {
|
||||
struct uci_section *dmmap_section = NULL;
|
||||
|
||||
get_dmmap_section_of_config_section("dmmap_dropbear", "dropbear", section_name(s), &dmmap_section);
|
||||
dmuci_delete_by_section(dmmap_section, NULL, NULL);
|
||||
|
||||
close_active_sessions(s);
|
||||
dmuci_delete_by_section(s, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int addObjSSHKey(char *refparam, struct dmctx *ctx, void *data, char **instance)
|
||||
{
|
||||
struct uci_section *s = NULL;
|
||||
|
||||
dmuci_add_section_bbfdm("dmmap_dropbear", "authkey", &s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int delObjSSHKey(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
|
||||
{
|
||||
struct uci_section *s = NULL, *stmp = NULL;
|
||||
char *value = NULL;
|
||||
|
||||
switch (del_action) {
|
||||
case DEL_INST:
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "pubkey", &value);
|
||||
remove_pubkey(value);
|
||||
dmuci_delete_by_section((struct uci_section *)data, NULL, NULL);
|
||||
break;
|
||||
case DEL_ALL:
|
||||
uci_path_foreach_sections_safe(bbfdm, "dmmap_dropbear", "authkey", stmp, s) {
|
||||
dmuci_get_value_by_section_string(s, "pubkey", &value);
|
||||
remove_pubkey(value);
|
||||
dmuci_delete_by_section(s, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* ENTRY METHODS
|
||||
*************************************************************/
|
||||
static int browseSSHServerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
struct dm_data *curr_data = NULL;
|
||||
LIST_HEAD(dup_list);
|
||||
LIST_HEAD(session_list);
|
||||
char *inst = NULL;
|
||||
|
||||
ssh_server_session_init(&session_list);
|
||||
synchronize_specific_config_sections_with_dmmap("dropbear", "dropbear", "dmmap_dropbear", &dup_list);
|
||||
list_for_each_entry(curr_data, &dup_list, list) {
|
||||
bool b;
|
||||
char *enable = dmuci_get_value_by_section_fallback_def(curr_data->config_section, "enable", "1");
|
||||
char *act_date = dmuci_get_value_by_section_fallback_def(curr_data->dmmap_section, "activationdate", "");
|
||||
|
||||
string_to_bool(enable, &b);
|
||||
if (b && DM_STRLEN(act_date) == 0) {
|
||||
char *tm = NULL;
|
||||
dm_time_format(time(NULL), &tm);
|
||||
dmuci_set_value_by_section(curr_data->dmmap_section, "activationdate", tm);
|
||||
}
|
||||
|
||||
curr_data->additional_data = (void *)&session_list;
|
||||
|
||||
inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "server_instance", "server_alias");
|
||||
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)curr_data, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
free_ssh_session_list(&session_list);
|
||||
free_dmmap_config_dup_list(&dup_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int browseSSHKeyInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
struct uci_section *s = NULL, *stmp = NULL;
|
||||
char *inst = NULL;
|
||||
char line[5120] = {0};
|
||||
|
||||
/* create entries for the keys available in DROPBEAR_KEY_FILE but not in dmmap */
|
||||
FILE *fp = fopen(DROPBEAR_KEY_FILE, "r");
|
||||
if (fp != NULL) {
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
struct uci_section *dmmap_sect = NULL;
|
||||
remove_new_line(line);
|
||||
bool exists = false;
|
||||
|
||||
uci_path_foreach_sections_safe(bbfdm, "dmmap_dropbear", "authkey", stmp, s) {
|
||||
char *val = NULL;
|
||||
dmuci_get_value_by_section_string(s, "pubkey", &val);
|
||||
if (DM_STRCMP(val, line) == 0) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
dmmap_sect = NULL;
|
||||
dmuci_add_section_bbfdm("dmmap_dropbear", "authkey", &dmmap_sect);
|
||||
dmuci_set_value_by_section(dmmap_sect, "pubkey", line);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/* delete keys from dmmap which are not available in DROPBEAR_KEY_FILE */
|
||||
stmp = NULL;
|
||||
s = NULL;
|
||||
uci_path_foreach_sections_safe(bbfdm, "dmmap_dropbear", "authkey", stmp, s) {
|
||||
char *val = NULL;
|
||||
dmuci_get_value_by_section_string(s, "pubkey", &val);
|
||||
if (!key_exist_in_keyfile(val)) {
|
||||
dmuci_delete_by_section(s, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* enlist objects */
|
||||
stmp = NULL;
|
||||
s = NULL;
|
||||
uci_path_foreach_sections_safe(bbfdm, "dmmap_dropbear", "authkey", stmp, s) {
|
||||
inst = handle_instance(dmctx, parent_node, s, "instance", "alias");
|
||||
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int browseSSHServerSessionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
|
||||
{
|
||||
bool b;
|
||||
char *inst = NULL;
|
||||
int id = 0;
|
||||
|
||||
struct uci_section *s = ((struct dm_data *)prev_data)->config_section;
|
||||
char *value = dmuci_get_value_by_section_fallback_def(s, "enable", "1");
|
||||
string_to_bool(value, &b);
|
||||
if (!b)
|
||||
return 0;
|
||||
|
||||
char pid_file[125] = {0};
|
||||
char *sec_name = section_name(s);
|
||||
if (DM_STRLEN(sec_name) == 0)
|
||||
return 0;
|
||||
|
||||
snprintf(pid_file, sizeof(pid_file), "/var/run/dropbear.%s.pid", sec_name);
|
||||
if (DM_STRLEN(pid_file) == 0)
|
||||
return 0;
|
||||
|
||||
FILE *fp = fopen(pid_file, "r");
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
|
||||
unsigned int pid;
|
||||
if (fscanf(fp, "%u", &pid) != 1) {
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
char cmd[512] = {0};
|
||||
snprintf(cmd, sizeof(cmd), "ps -w | grep %s | grep -v grep | awk \'{print $1}\'", pid_file);
|
||||
FILE *pp = popen(cmd, "r");
|
||||
if (pp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char line[15] = {0};
|
||||
while (fgets(line, sizeof(line), pp) != NULL) {
|
||||
remove_new_line(line);
|
||||
if (DM_STRLEN(line) == 0)
|
||||
continue;
|
||||
|
||||
if (strtoul(line, NULL, 10) == pid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct ssh_session_args *session = NULL;
|
||||
struct list_head *sess_list = (struct list_head *)((struct dm_data *)prev_data)->additional_data;
|
||||
bool found = false;
|
||||
list_for_each_entry(session, sess_list, list) {
|
||||
if (DM_STRCMP(session->pid, line) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
inst = handle_instance_without_section(dmctx, parent_node, ++id);
|
||||
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)session, inst) == DM_STOP)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pclose(pp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* GET & SET PARAM
|
||||
**************************************************************/
|
||||
static int get_ssh_server_num(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
int cnt = get_number_of_entries(ctx, data, instance, browseSSHServerInst);
|
||||
dmasprintf(value, "%d", cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_key_num(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
int cnt = get_number_of_entries(ctx, data, instance, browseSSHKeyInst);
|
||||
dmasprintf(value, "%d", cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = "Enabled";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_session_num(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
int cnt = get_number_of_entries(ctx, data, instance, browseSSHServerSessionInst);
|
||||
dmasprintf(value, "%d", cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
bool b;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_boolean(ctx, value))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
string_to_bool(value, &b);
|
||||
char *cur = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "1");
|
||||
bool cur_val;
|
||||
string_to_bool(cur, &cur_val);
|
||||
|
||||
if (b == cur_val)
|
||||
break;
|
||||
|
||||
if (b) {
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enable", "1");
|
||||
char *tm = NULL;
|
||||
dm_time_format(time(NULL), &tm);
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "activationdate", tm);
|
||||
} else {
|
||||
close_active_sessions(((struct dm_data *)data)->config_section);
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enable", "0");
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "activationdate", "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "server_alias", instance, value);
|
||||
}
|
||||
|
||||
static int set_ssh_server_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "server_alias", instance, value);
|
||||
}
|
||||
|
||||
static int get_ssh_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
char *linker = NULL;
|
||||
|
||||
dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "Interface", &linker);
|
||||
adm_entry_get_reference_param(ctx, "Device.IP.Interface.*.Name", linker, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *allowed_objects[] = {"Device.IP.Interface.", NULL};
|
||||
struct dm_reference reference = {0};
|
||||
|
||||
bbf_get_reference_args(value, &reference);
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
|
||||
return FAULT_9007;
|
||||
|
||||
if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
|
||||
return FAULT_9007;
|
||||
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "Interface", reference.value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "Port", "22");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}},1))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "Port", value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_idle(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "IdleTimeout", "0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_idle(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}},1))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "IdleTimeout", value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_keepalive(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "SSHKeepAlive", "300");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_keepalive(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}},1))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "SSHKeepAlive", value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_rootlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "RootLogin", "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_rootlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
bool b;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_boolean(ctx, value))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
string_to_bool(value, &b);
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "RootLogin", b ? "1" : "0");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_passwordlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "PasswordAuth", "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_passwordlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
bool b;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_boolean(ctx, value))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
string_to_bool(value, &b);
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "PasswordAuth", b ? "1" : "0");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_rootpasswordlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "RootPasswordAuth", "1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_rootpasswordlogin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
bool b;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_boolean(ctx, value))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
string_to_bool(value, &b);
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "RootPasswordAuth", b ? "1" : "0");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_maxauthtries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "MaxAuthTries", "3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_server_maxauthtries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}},1))
|
||||
return FAULT_9007;
|
||||
break;
|
||||
case VALUESET:
|
||||
dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "MaxAuthTries", value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_activationdate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string(((struct dm_data *)data)->dmmap_section, "activationdate", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_pid(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
bool b;
|
||||
struct uci_section *s = ((struct dm_data *)data)->config_section;
|
||||
char *en = dmuci_get_value_by_section_fallback_def(s, "enable", "1");
|
||||
|
||||
*value = "0";
|
||||
string_to_bool(en, &b);
|
||||
if (!b)
|
||||
return 0;
|
||||
|
||||
char *sec_name = section_name(s);
|
||||
if (DM_STRLEN(sec_name) == 0)
|
||||
return 0;
|
||||
|
||||
char pid_file[256] = {0};
|
||||
snprintf(pid_file, sizeof(pid_file), "/var/run/dropbear.%s.pid", sec_name);
|
||||
if (DM_STRLEN(pid_file) == 0)
|
||||
return 0;
|
||||
|
||||
FILE *fp = fopen(pid_file, "r");
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
|
||||
unsigned int pid;
|
||||
if (fscanf(fp, "%u", &pid) != 1) {
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
dmasprintf(value, "%u", pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_session_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
struct ssh_session_args *args = (struct ssh_session_args *)data;
|
||||
*value = DM_STRLEN(args->ip) ? dmstrdup(args->ip) : "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_server_session_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
struct ssh_session_args *args = (struct ssh_session_args *)data;
|
||||
*value = DM_STRLEN(args->port) ? dmstrdup(args->port) : "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ssh_key_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
return bbf_get_alias(ctx, (struct uci_section *)data, "alias", instance, value);
|
||||
}
|
||||
|
||||
static int set_ssh_key_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
return bbf_set_alias(ctx, (struct uci_section *)data, "alias", instance, value);
|
||||
}
|
||||
|
||||
static int get_ssh_key_pubkey(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "pubkey", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_ssh_key_pubkey(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *cur_val = NULL;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
|
||||
return FAULT_9007;
|
||||
|
||||
/* check if same as current key value */
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "pubkey", &cur_val);
|
||||
if (DM_STRCMP(cur_val, value) == 0)
|
||||
break;
|
||||
|
||||
if (key_exists(value))
|
||||
return FAULT_9001;
|
||||
|
||||
break;
|
||||
case VALUESET:
|
||||
/* check if same as current key value then nothing to do */
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "pubkey", &cur_val);
|
||||
if (DM_STRCMP(cur_val, value) == 0)
|
||||
break;
|
||||
|
||||
add_pubkey(cur_val, value);
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "pubkey", value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int operate_session_delete(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
struct ssh_session_args *args = (struct ssh_session_args *)data;
|
||||
if (DM_STRLEN(args->pid) != 0) {
|
||||
char cmd[128] = {0};
|
||||
snprintf(cmd, sizeof(cmd), "kill -15 %s", args->pid);
|
||||
ret = system(cmd);
|
||||
}
|
||||
|
||||
return (ret != -1) ? 0 : USP_FAULT_COMMAND_FAILURE;
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************
|
||||
* OBJ & LEAF DEFINITION
|
||||
***********************************************************************************************************************************/
|
||||
/* *** Device.SSH. *** */
|
||||
DMOBJ tSSHObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
|
||||
{"Server", &DMWRITE, addObjSSHServer, delObjSSHServer, NULL, browseSSHServerInst, NULL, NULL, tSSHServerObj, tSSHServerParams, NULL, BBFDM_BOTH, NULL},
|
||||
{"AuthorizedKey", &DMWRITE, addObjSSHKey, delObjSSHKey, NULL, browseSSHKeyInst, NULL, NULL, NULL, tSSHKeyParams, NULL, BBFDM_BOTH, NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMOBJ tSSHServerObj[] = {
|
||||
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
|
||||
{"Session", &DMREAD, NULL, NULL, NULL, browseSSHServerSessionInst, NULL, NULL, NULL, tSSHServerSessionParams, NULL, BBFDM_BOTH, NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* *** Device.SSH. *** */
|
||||
DMLEAF tSSHParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
|
||||
{"ServerNumberOfEntries", &DMREAD, DMT_UNINT, get_ssh_server_num, NULL, BBFDM_BOTH},
|
||||
{"AuthorizedKeyNumberOfEntries", &DMREAD, DMT_UNINT, get_ssh_key_num, NULL, BBFDM_BOTH},
|
||||
{"Status", &DMREAD, DMT_STRING, get_ssh_status, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* *** Device.SSH.Server. *** */
|
||||
DMLEAF tSSHServerParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
|
||||
{"Enable", &DMWRITE, DMT_BOOL, get_ssh_server_enable, set_ssh_server_enable, BBFDM_BOTH},
|
||||
{"Alias", &DMWRITE, DMT_STRING, get_ssh_server_alias, set_ssh_server_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
||||
{"Interface", &DMWRITE, DMT_STRING, get_ssh_server_interface, set_ssh_server_interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
|
||||
{"Port", &DMWRITE, DMT_UNINT, get_ssh_server_port, set_ssh_server_port, BBFDM_BOTH},
|
||||
{"IdleTimeout", &DMWRITE, DMT_UNINT, get_ssh_server_idle, set_ssh_server_idle, BBFDM_BOTH},
|
||||
{"KeepAlive", &DMWRITE, DMT_UNINT, get_ssh_server_keepalive, set_ssh_server_keepalive, BBFDM_BOTH},
|
||||
{"AllowRootLogin", &DMWRITE, DMT_BOOL, get_ssh_server_rootlogin, set_ssh_server_rootlogin, BBFDM_BOTH},
|
||||
{"AllowPasswordLogin", &DMWRITE, DMT_BOOL, get_ssh_server_passwordlogin, set_ssh_server_passwordlogin, BBFDM_BOTH},
|
||||
{"AllowRootPasswordLogin", &DMWRITE, DMT_BOOL, get_ssh_server_rootpasswordlogin, set_ssh_server_rootpasswordlogin, BBFDM_BOTH},
|
||||
{"MaxAuthTries", &DMWRITE, DMT_UNINT, get_ssh_server_maxauthtries, set_ssh_server_maxauthtries, BBFDM_BOTH},
|
||||
{"ActivationDate", &DMREAD, DMT_TIME, get_ssh_server_activationdate, NULL, BBFDM_BOTH},
|
||||
{"PID", &DMREAD, DMT_UNINT, get_ssh_server_pid, NULL, BBFDM_BOTH},
|
||||
{"SessionNumberOfEntries", &DMREAD, DMT_UNINT, get_ssh_server_session_num, NULL, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMLEAF tSSHServerSessionParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
|
||||
{"IPAddress", &DMREAD, DMT_STRING, get_ssh_server_session_ip, NULL, BBFDM_BOTH},
|
||||
{"Port", &DMREAD, DMT_UNINT, get_ssh_server_session_port, NULL, BBFDM_BOTH},
|
||||
{"Delete()", &DMSYNC, DMT_COMMAND, NULL, operate_session_delete, BBFDM_USP},
|
||||
{0}
|
||||
};
|
||||
|
||||
DMLEAF tSSHKeyParams[] = {
|
||||
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
|
||||
{"Alias", &DMWRITE, DMT_STRING, get_ssh_key_alias, set_ssh_key_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
|
||||
{"Key", &DMWRITE, DMT_STRING, get_ssh_key_pubkey, set_ssh_key_pubkey, BBFDM_BOTH},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 iopsys Software Solutions AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* Author Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SSH_H
|
||||
#define __SSH_H
|
||||
|
||||
#include "libbbfdm-api/dmcommon.h"
|
||||
|
||||
extern DMOBJ tSSHObj[];
|
||||
extern DMOBJ tSSHServerObj[];
|
||||
extern DMLEAF tSSHParams[];
|
||||
extern DMLEAF tSSHServerParams[];
|
||||
extern DMLEAF tSSHServerSessionParams[];
|
||||
extern DMLEAF tSSHKeyParams[];
|
||||
|
||||
#endif
|
||||
|
|
@ -139,6 +139,14 @@
|
|||
"src/dnsmngr.c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"repo": "https://dev.iopsys.eu/network/sshmngr.git",
|
||||
"proto": "git",
|
||||
"version": "devel",
|
||||
"dm_files": [
|
||||
"src/sshmngr.c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"repo": "https://dev.iopsys.eu/voice/tr104.git",
|
||||
"proto": "git",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue