server session CHANGE support for ecdsa keys data
diff --git a/src/netconf.h b/src/netconf.h
index ce1642d..4022617 100644
--- a/src/netconf.h
+++ b/src/netconf.h
@@ -126,6 +126,15 @@
 } NC_PARAMTYPE;
 
 /**
+ * @brief Enumeration of SSH key types.
+ */
+typedef enum NC_SSH_KEY {
+    NC_SSH_DSA,               /**< DSA SSH key */
+    NC_SSH_RSA,               /**< RSA SSH key */
+    NC_SSH_ECDSA              /**< ECDSA SSH key */
+} NC_SSH_KEY;
+
+/**
  * @brief Transform given time_t (seconds since the epoch) into the RFC 3339 format
  * accepted by NETCONF functions.
  *
diff --git a/src/session.c b/src/session.c
index d88871c..25fc410 100644
--- a/src/session.c
+++ b/src/session.c
@@ -116,6 +116,23 @@
     assert((ts->tv_nsec >= 0) && (ts->tv_nsec < 1000000000L));
 }
 
+const char *
+nc_keytype2str(NC_SSH_KEY type)
+{
+    switch (type) {
+    case NC_SSH_DSA:
+        return "DSA";
+    case NC_SSH_RSA:
+        return "RSA";
+    case NC_SSH_ECDSA:
+        return "EC";
+    default:
+        break;
+    }
+
+    return NULL;
+}
+
 int
 nc_sock_enable_keepalive(int sock)
 {
diff --git a/src/session_p.h b/src/session_p.h
index 367cd29..92daa59 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -189,7 +189,7 @@
     int (*user_verify_clb)(const struct nc_session *session);
 
     int (*server_cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,char **privkey_path,
-                           char **privkey_data, int *privkey_data_rsa);
+                           char **privkey_data, NC_SSH_KEY *privkey_type);
     void *server_cert_data;
     void (*server_cert_data_free)(void *data);
 
@@ -215,7 +215,7 @@
     uint16_t authkey_count;
     pthread_mutex_t authkey_lock;
 
-    int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path, char **privkey_data, int *privkey_data_rsa);
+    int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type);
     void *hostkey_data;
     void (*hostkey_data_free)(void *data);
 #endif
@@ -505,6 +505,8 @@
 
 void nc_addtimespec(struct timespec *ts, uint32_t msec);
 
+const char *nc_keytype2str(NC_SSH_KEY type);
+
 int nc_sock_enable_keepalive(int sock);
 
 struct nc_session *nc_new_session(NC_SIDE side, int shared_ti);
diff --git a/src/session_server.c b/src/session_server.c
index 636b1a2..9f0ac4b 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -51,6 +51,11 @@
     uint16_t i;
     struct nc_endpt *endpt = NULL;
 
+    if (!name) {
+        ERRARG("endpt_name");
+        return NULL;
+    }
+
     /* WRITE LOCK */
     pthread_rwlock_wrlock(&server_opts.endpt_lock);
 
@@ -81,6 +86,11 @@
     uint16_t i;
     struct nc_ch_client *client = NULL;
 
+    if (!name) {
+        ERRARG("client_name");
+        return NULL;
+    }
+
     /* READ LOCK */
     pthread_rwlock_rdlock(&server_opts.ch_client_lock);
 
@@ -468,6 +478,7 @@
             format = ((struct lyd_node_leaf_list *)child)->value_str;
         }
     }
+    VRB("Schema \"%s\" was requested.", identifier);
 
     /* check version */
     if (version && (strlen(version) != 10) && strcmp(version, "1.0")) {
diff --git a/src/session_server.h b/src/session_server.h
index c3e584c..9e20fd2 100644
--- a/src/session_server.h
+++ b/src/session_server.h
@@ -509,17 +509,6 @@
                               const char *username);
 
 /**
- * @brief Add endpoint SSH host keys the server will identify itself with. Only the name is set, the key itself
- *        wil be retrieved using a callback.
- *
- * @param[in] endpt_name Existing endpoint name.
- * @param[in] name Arbitrary name of the host key.
- * @param[in] idx Optional index where to add the key. -1 adds at the end.
- * @return 0 on success, -1 on error.
- */
-int nc_server_ssh_endpt_add_hostkey(const char *endpt_name, const char *name, int16_t idx);
-
-/**
  * @brief Set the callback for SSH password authentication. If none is set, local system users are used.
  *
  * @param[in] passwd_auth_clb Callback that should authenticate the user. Username can be directly obtained from \p session.
@@ -564,15 +553,26 @@
  *                        to be set. The one set will be freed.
  *                        - \p privkey_path expects a PEM file,
  *                        - \p privkey_data expects a base-64 encoded ANS.1 DER data,
- *                        - \p privkey_data_rsa flag whether \p privkey_data are the data of an RSA (1) or a DSA (0) key.
+ *                        - \p privkey_type type of the key in \p privkey_data.
  * @param[in] user_data Optional arbitrary user data that will be passed to \p hostkey_clb.
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_ssh_set_hostkey_clb(int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path,
-                                                      char **privkey_data, int *privkey_data_rsa),
+                                                      char **privkey_data, NC_SSH_KEY *privkey_type),
                                    void *user_data, void (*free_user_data)(void *user_data));
 
 /**
+ * @brief Add endpoint SSH host keys the server will identify itself with. Only the name is set, the key itself
+ *        wil be retrieved using a callback.
+ *
+ * @param[in] endpt_name Existing endpoint name.
+ * @param[in] name Arbitrary name of the host key.
+ * @param[in] idx Optional index where to add the key. -1 adds at the end.
+ * @return 0 on success, -1 on error.
+ */
+int nc_server_ssh_endpt_add_hostkey(const char *endpt_name, const char *name, int16_t idx);
+
+/**
  * @brief Delete endpoint SSH host key. Their order is preserved.
  *
  * @param[in] endpt_name Existing endpoint name.
@@ -613,6 +613,14 @@
 int nc_server_ssh_endpt_set_auth_methods(const char *endpt_name, int auth_methods);
 
 /**
+ * @brief Get endpoint accepted SSH authentication methods.
+ *
+ * @param[in] endpt_name Existing endpoint name.
+ * @return Accepted authentication methods bit field of NC_SSH_AUTH_TYPE.
+ */
+int nc_server_ssh_endpt_get_auth_methods(const char *endpt_name);
+
+/**
  * @brief Set endpoint SSH authentication attempts of every client. 3 by default.
  *
  * @param[in] endpt_name Existing endpoint name.
@@ -664,12 +672,12 @@
  *                     - \p cert_data expects a base-64 encoded ASN.1 DER data,
  *                     - \p privkey_path expects a PEM file,
  *                     - \p privkey_data expects a base-64 encoded ANS.1 DER data,
- *                     - \p privkey_data_rsa flag whether \p privkey_data are the data of an RSA (1) or a DSA (0) key.
+ *                     - \p privkey_type type of the key in \p privkey_data.
  * @param[in] user_data Optional arbitrary user data that will be passed to \p cert_clb.
  * @param[in] free_user_data Optional callback that will be called during cleanup to free any \p user_data.
  */
 void nc_server_tls_set_server_cert_clb(int (*cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,
-                                                       char **privkey_path, char **privkey_data, int *privkey_data_rsa),
+                                                       char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type),
                                        void *user_data, void (*free_user_data)(void *user_data));
 
 /**
diff --git a/src/session_server_ch.h b/src/session_server_ch.h
index c069108..17b4b90 100644
--- a/src/session_server_ch.h
+++ b/src/session_server_ch.h
@@ -246,6 +246,14 @@
 int nc_server_ssh_ch_client_set_auth_methods(const char *client_name, int auth_methods);
 
 /**
+ * @brief Get accepted Call Home SSH authentication methods.
+ *
+ * @param[in] client_name Existing Call Home client name.
+ * @return Accepted authentication methods bit field of NC_SSH_AUTH_TYPE.
+ */
+int nc_server_ssh_ch_client_get_auth_methods(const char *client_name);
+
+/**
  * @brief Set Call Home SSH authentication attempts of every client. 3 by default.
  *
  * @param[in] client_name Existing Call Home client name.
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index 892c436..73a2ded 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -35,7 +35,7 @@
 extern struct nc_server_opts server_opts;
 
 static char *
-base64der_key_to_tmp_file(const char *in, int rsa)
+base64der_key_to_tmp_file(const char *in, const char *key_str)
 {
     char path[12] = "/tmp/XXXXXX";
     int fd, written;
@@ -61,11 +61,11 @@
 
     /* write the key into the file */
     written = fwrite("-----BEGIN ", 1, 11, file);
-    written += fwrite((rsa ? "RSA" : "DSA"), 1, 3, file);
+    written += fwrite(key_str, 1, strlen(key_str), file);
     written += fwrite(" PRIVATE KEY-----\n", 1, 18, file);
     written += fwrite(in, 1, strlen(in), file);
     written += fwrite("\n-----END ", 1, 10, file);
-    written += fwrite((rsa ? "RSA" : "DSA"), 1, 3, file);
+    written += fwrite(key_str, 1, strlen(key_str), file);
     written += fwrite(" PRIVATE KEY-----", 1, 17, file);
 
     fclose(file);
@@ -181,7 +181,7 @@
 
 API void
 nc_server_ssh_set_hostkey_clb(int (*hostkey_clb)(const char *name, void *user_data, char **privkey_path,
-                                                 char **privkey_data, int *privkey_data_rsa),
+                                                 char **privkey_data, NC_SSH_KEY *privkey_type),
                               void *user_data, void (*free_user_data)(void *user_data))
 {
     if (!hostkey_clb) {
@@ -427,12 +427,6 @@
 static int
 nc_server_ssh_set_auth_methods(int auth_methods, struct nc_server_ssh_opts *opts)
 {
-    if (!(auth_methods & NC_SSH_AUTH_PUBLICKEY) && !(auth_methods & NC_SSH_AUTH_PASSWORD)
-            && !(auth_methods & NC_SSH_AUTH_INTERACTIVE)) {
-        ERRARG("auth_methods");
-        return -1;
-    }
-
     opts->auth_methods = auth_methods;
     return 0;
 }
@@ -473,6 +467,42 @@
     return ret;
 }
 
+API int
+nc_server_ssh_endpt_get_auth_methods(const char *endpt_name)
+{
+    int ret;
+    struct nc_endpt *endpt;
+
+    /* LOCK */
+    endpt = nc_server_endpt_lock_get(endpt_name, NC_TI_LIBSSH, NULL);
+    if (!endpt) {
+        return -1;
+    }
+    ret = endpt->opts.ssh->auth_methods;
+    /* UNLOCK */
+    pthread_rwlock_unlock(&server_opts.endpt_lock);
+
+    return ret;
+}
+
+API int
+nc_server_ssh_ch_client_get_auth_methods(const char *client_name)
+{
+    int ret;
+    struct nc_ch_client *client;
+
+    /* LOCK */
+    client = nc_server_ch_client_lock(client_name, NC_TI_LIBSSH, NULL);
+    if (!client) {
+        return -1;
+    }
+    ret = client->opts.ssh->auth_methods;
+    /* UNLOCK */
+    nc_server_ch_client_unlock(client);
+
+    return ret;
+}
+
 static int
 nc_server_ssh_set_auth_attempts(uint16_t auth_attempts, struct nc_server_ssh_opts *opts)
 {
@@ -1280,7 +1310,8 @@
 {
     uint8_t i;
     char *privkey_path, *privkey_data;
-    int privkey_data_rsa, ret;
+    int ret;
+    NC_SSH_KEY privkey_type;
 
     if (!server_opts.hostkey_clb) {
         ERR("Callback for retrieving SSH host keys not set.");
@@ -1289,13 +1320,13 @@
 
     for (i = 0; i < hostkey_count; ++i) {
         privkey_path = privkey_data = NULL;
-        if (server_opts.hostkey_clb(hostkeys[i], server_opts.hostkey_data, &privkey_path, &privkey_data, &privkey_data_rsa)) {
+        if (server_opts.hostkey_clb(hostkeys[i], server_opts.hostkey_data, &privkey_path, &privkey_data, &privkey_type)) {
             ERR("Host key callback failed.");
             return -1;
         }
 
         if (privkey_data) {
-            privkey_path = base64der_key_to_tmp_file(privkey_data, privkey_data_rsa);
+            privkey_path = base64der_key_to_tmp_file(privkey_data, nc_keytype2str(privkey_type));
             if (!privkey_path) {
                 ERR("Temporarily storing a host key into a file failed (%s).", strerror(errno));
                 free(privkey_data);
diff --git a/src/session_server_tls.c b/src/session_server_tls.c
index bac0357..9e2db74 100644
--- a/src/session_server_tls.c
+++ b/src/session_server_tls.c
@@ -135,7 +135,7 @@
 }
 
 static EVP_PKEY *
-base64der_to_privatekey(const char *in, int rsa)
+base64der_to_privatekey(const char *in, const char *key_str)
 {
     EVP_PKEY *out;
     char *buf;
@@ -145,7 +145,8 @@
         return NULL;
     }
 
-    if (asprintf(&buf, "%s%s%s%s%s%s%s", "-----BEGIN ", (rsa ? "RSA" : "DSA"), " PRIVATE KEY-----\n", in, "\n-----END ", (rsa ? "RSA" : "DSA"), " PRIVATE KEY-----") == -1) {
+    if (asprintf(&buf, "%s%s%s%s%s%s%s", "-----BEGIN ", key_str, " PRIVATE KEY-----\n", in, "\n-----END ",
+                key_str, " PRIVATE KEY-----") == -1) {
         return NULL;
     }
     bio = BIO_new_mem_buf(buf, strlen(buf));
@@ -973,7 +974,7 @@
 
 API void
 nc_server_tls_set_server_cert_clb(int (*cert_clb)(const char *name, void *user_data, char **cert_path, char **cert_data,
-                                                  char **privkey_path, char **privkey_data, int *privkey_data_rsa),
+                                                  char **privkey_path, char **privkey_data, NC_SSH_KEY *privkey_type),
                                   void *user_data, void (*free_user_data)(void *user_data))
 {
     if (!cert_clb) {
@@ -1796,7 +1797,8 @@
 nc_tls_ctx_set_server_cert_key(SSL_CTX *tls_ctx, const char *cert_name)
 {
     char *cert_path = NULL, *cert_data = NULL, *privkey_path = NULL, *privkey_data = NULL;
-    int privkey_data_rsa = 1, ret = 0;
+    int ret = 0;
+    NC_SSH_KEY privkey_type;
     X509 *cert = NULL;
     EVP_PKEY *pkey = NULL;
 
@@ -1809,7 +1811,7 @@
     }
 
     if (server_opts.server_cert_clb(cert_name, server_opts.server_cert_data, &cert_path, &cert_data, &privkey_path,
-                                    &privkey_data, &privkey_data_rsa)) {
+                                    &privkey_data, &privkey_type)) {
         ERR("Server certificate callback failed.");
         return -1;
     }
@@ -1838,7 +1840,7 @@
             goto cleanup;
         }
     } else {
-        pkey = base64der_to_privatekey(privkey_data, privkey_data_rsa);
+        pkey = base64der_to_privatekey(privkey_data, nc_keytype2str(privkey_type));
         if (!pkey || (SSL_CTX_use_PrivateKey(tls_ctx, pkey) != 1)) {
             ERR("Loading the server private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
             ret = -1;