Merge "Refactor leafValueFromValue"
diff --git a/src/netconf-client.cpp b/src/netconf-client.cpp
index 73d8433..f1cdfe2 100644
--- a/src/netconf-client.cpp
+++ b/src/netconf-client.cpp
@@ -6,6 +6,7 @@
*
*/
+#include <cstring>
#include <libyang/Tree_Data.hpp>
#include <mutex>
extern "C" {
@@ -13,6 +14,7 @@
}
#include <sstream>
#include "netconf-client.h"
+#include "UniqueResource.h"
namespace libnetconf {
@@ -58,6 +60,13 @@
nc_reply_free(reinterpret_cast<nc_reply*>(reply));
}
+char *ssh_auth_interactive_cb(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
+{
+ const auto cb = static_cast<const client::KbdInteractiveCb*>(priv);
+ auto res = (*cb)(auth_name, instruction, prompt, echo);
+ return ::strdup(res.c_str());
+}
+
template <auto fn>
using deleter_from_fn = std::integral_constant<decltype(fn), fn>;
@@ -222,6 +231,27 @@
return session;
}
+std::unique_ptr<Session> Session::connectKbdInteractive(const std::string& host, const uint16_t port, const std::string& user, const KbdInteractiveCb& callback)
+{
+ impl::ClientInit::instance();
+
+ std::lock_guard lk(impl::clientOptions);
+ auto cb_guard = make_unique_resource([user, &callback]() {
+ nc_client_ssh_set_username(user.c_str());
+ nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 5);
+ nc_client_ssh_set_auth_interactive_clb(impl::ssh_auth_interactive_cb, static_cast<void *>(&const_cast<KbdInteractiveCb&>(callback)));
+ }, []() {
+ nc_client_ssh_set_auth_interactive_clb(nullptr, nullptr);
+ nc_client_ssh_set_username(nullptr);
+ });
+
+ auto session = std::make_unique<Session>(nc_connect_ssh(host.c_str(), port, nullptr));
+ if (!session->m_session) {
+ throw std::runtime_error{"nc_connect_ssh failed"};
+ }
+ return session;
+}
+
std::unique_ptr<Session> Session::connectSocket(const std::string& path)
{
impl::ClientInit::instance();
diff --git a/src/netconf-client.h b/src/netconf-client.h
index bd89e6b..1923e71 100644
--- a/src/netconf-client.h
+++ b/src/netconf-client.h
@@ -1,5 +1,6 @@
#pragma once
+#include <functional>
#include <libnetconf2/messages_client.h>
#include <memory>
#include <optional>
@@ -22,11 +23,14 @@
~ReportedError() override;
};
+using KbdInteractiveCb = std::function<std::string(const std::string&, const std::string&, const std::string&, bool)>;
+
class Session {
public:
Session(struct nc_session* session);
~Session();
static std::unique_ptr<Session> connectPubkey(const std::string& host, const uint16_t port, const std::string& user, const std::string& pubPath, const std::string& privPath);
+ static std::unique_ptr<Session> connectKbdInteractive(const std::string& host, const uint16_t port, const std::string& user, const KbdInteractiveCb& callback);
static std::unique_ptr<Session> connectSocket(const std::string& path);
std::vector<std::string_view> capabilities() const;
std::shared_ptr<libyang::Data_Node> getConfig(const NC_DATASTORE datastore,
diff --git a/src/netconf_access.cpp b/src/netconf_access.cpp
index bf01ca0..5b1ad78 100644
--- a/src/netconf_access.cpp
+++ b/src/netconf_access.cpp
@@ -68,6 +68,13 @@
datastoreInit();
}
+NetconfAccess::NetconfAccess(std::unique_ptr<libnetconf::client::Session>&& session)
+ : m_session(std::move(session))
+ , m_schema(new YangSchema())
+{
+ datastoreInit();
+}
+
NetconfAccess::NetconfAccess(const std::string& socketPath)
: m_schema(new YangSchema())
{
diff --git a/src/netconf_access.hpp b/src/netconf_access.hpp
index ccfffcc..29101ed 100644
--- a/src/netconf_access.hpp
+++ b/src/netconf_access.hpp
@@ -31,6 +31,7 @@
public:
NetconfAccess(const std::string& hostname, uint16_t port, const std::string& user, const std::string& pubKey, const std::string& privKey);
NetconfAccess(const std::string& socketPath);
+ NetconfAccess(std::unique_ptr<libnetconf::client::Session>&& session);
~NetconfAccess() override;
std::map<std::string, leaf_data_> getItems(const std::string& path) override;
void setLeaf(const std::string& path, leaf_data_ value) override;
diff --git a/src/python_netconf.cpp b/src/python_netconf.cpp
index 83964d6..eaa4349 100644
--- a/src/python_netconf.cpp
+++ b/src/python_netconf.cpp
@@ -5,9 +5,11 @@
*
*/
+#include <pybind11/functional.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "netconf_access.hpp"
+#include "netconf-client.h"
using namespace std::literals;
using namespace pybind11::literals;
@@ -58,6 +60,12 @@
pybind11::class_<NetconfAccess>(m, "NetconfAccess")
.def(pybind11::init<const std::string&>(), "socketPath"_a)
+ .def(pybind11::init(
+ [](const std::string& host, const uint16_t port, const std::string& user, const libnetconf::client::KbdInteractiveCb interactiveAuth) {
+ auto session = libnetconf::client::Session::connectKbdInteractive(host, port, user, interactiveAuth);
+ return std::make_unique<NetconfAccess>(std::move(session));
+ }),
+ "server"_a, "port"_a=830, "username"_a, "interactive_auth"_a)
.def("getItems", &NetconfAccess::getItems, "xpath"_a)
.def("setLeaf", &NetconfAccess::setLeaf, "xpath"_a, "value"_a)
.def("commitChanges", &NetconfAccess::commitChanges)