From c124b00204eef876cccce13f69c9a50b43cb0528 Mon Sep 17 00:00:00 2001
From: drbob <drbob@lunamutt.com>
Date: Mon, 9 Sep 2013 23:53:53 +1000
Subject: [PATCH]  - changes to allow password protected server keys.

Used the existing sshbind->common.callbacks data structure
to store auth callback functions. These are used when
loading keys in ssh_bind_listen.

Added addition API call: ssh_bind_set_auth_callbacks
to set the bind->common.callbacks parameter.
---
 include/libssh/server.h |   28 +++++++++++++++++++++++++---
 src/bind.c              |   40 ++++++++++++++++++++++++++++++++++------
 2 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/include/libssh/server.h b/include/libssh/server.h
index dbffecd..2c7b395 100644
--- a/include/libssh/server.h
+++ b/include/libssh/server.h
@@ -29,6 +29,8 @@
 #define SERVER_H
 
 #include "libssh/libssh.h"
+#include "libssh/callbacks.h"
+
 #define SERVERBANNER CLIENTBANNER
 
 #ifdef __cplusplus
@@ -167,16 +169,36 @@ LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o);
  * @return              SSH_OK on success, SSH_ERROR if an error occured.
  *
  * @code
+ *     struct ssh_bind_callbacks_struct cb = {
+ *         .incoming_connect = my_connect_cb_function
+ *     };
+ *     // ssh_bind_callbacks_init(&cb); NOTE THIS DOESNT EXIST YET.
+ *     ssh_bind_set_callbacks(session, &cb);
+ * @endcode
+ */
+LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
+    void *userdata);
+
+/**
+ * @brief Set the callback for this bind.
+ *
+ * @param[in] sshbind   The bind to set the callback on.
+ *
+ * @param[in] cb        An already set up ssh_callbacks instance.
+ *
+ * @return              SSH_OK on success, SSH_ERROR if an error occured.
+ *
+ * @code
  *     struct ssh_callbacks_struct cb = {
  *         .userdata = data,
  *         .auth_function = my_auth_function
  *     };
  *     ssh_callbacks_init(&cb);
- *     ssh_bind_set_callbacks(session, &cb);
+ *     ssh_bind_set_auth_callbacks(bind, &cb);
  * @endcode
  */
-LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
-    void *userdata);
+LIBSSH_API int ssh_bind_set_auth_callbacks(ssh_bind sshbind, ssh_callbacks cb);
+
 
 /**
  * @brief  Set the session to blocking/nonblocking mode.
diff --git a/src/bind.c b/src/bind.c
index e4c9327..4f722b1 100644
--- a/src/bind.c
+++ b/src/bind.c
@@ -148,6 +148,8 @@ int ssh_bind_listen(ssh_bind sshbind) {
   const char *host;
   socket_t fd;
   int rc;
+  ssh_auth_callback auth_fn = NULL;
+  void *auth_data = NULL;
 
   if (ssh_init() < 0) {
     ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
@@ -162,12 +164,22 @@ int ssh_bind_listen(ssh_bind sshbind) {
       return SSH_ERROR;
   }
 
+  if (sshbind->common.callbacks) {
+      auth_fn = sshbind->common.callbacks->auth_function;
+      auth_data = sshbind->common.callbacks->userdata;
+  }
+  else {
+      auth_fn = NULL;
+      auth_data = NULL;
+  }
+   
+
 #ifdef HAVE_ECC
   if (sshbind->ecdsakey) {
       rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
                                        NULL,
-                                       NULL,
-                                       NULL,
+                                       auth_fn,
+                                       auth_data,
                                        &sshbind->ecdsa);
       if (rc == SSH_ERROR || rc == SSH_EOF) {
           ssh_set_error(sshbind, SSH_FATAL,
@@ -187,8 +199,8 @@ int ssh_bind_listen(ssh_bind sshbind) {
   if (sshbind->dsakey) {
       rc = ssh_pki_import_privkey_file(sshbind->dsakey,
                                        NULL,
-                                       NULL,
-                                       NULL,
+                                       auth_fn,
+                                       auth_data,
                                        &sshbind->dsa);
       if (rc == SSH_ERROR || rc == SSH_EOF) {
           ssh_set_error(sshbind, SSH_FATAL,
@@ -208,8 +220,8 @@ int ssh_bind_listen(ssh_bind sshbind) {
   if (sshbind->rsakey) {
       rc = ssh_pki_import_privkey_file(sshbind->rsakey,
                                        NULL,
-                                       NULL,
-                                       NULL,
+                                       auth_fn,
+                                       auth_data,
                                        &sshbind->rsa);
       if (rc == SSH_ERROR || rc == SSH_EOF) {
           ssh_set_error(sshbind, SSH_FATAL,
@@ -274,6 +286,22 @@ int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
   return 0;
 }
 
+int ssh_bind_set_auth_callbacks(ssh_bind sshbind, ssh_callbacks cb) {
+  if (sshbind == NULL || cb == NULL) {
+    return SSH_ERROR;
+  }
+
+  if(cb->size <= 0 || cb->size > 1024 * sizeof(void *)){
+        ssh_set_error(sshbind,SSH_FATAL,
+                        "Invalid callback passed in (badly initialized)");
+
+        return SSH_ERROR;
+  }
+  sshbind->common.callbacks = cb;
+  return 0;
+}
+
+
 /** @internal
  * @brief callback being called by poll when an event happens
  *
-- 
1.7.3.5

