diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/include/libssh/libssh.h libssh-wfs/include/libssh/libssh.h
--- libssh-trunk/include/libssh/libssh.h	2009-07-18 11:02:19.000000000 -0400
+++ libssh-wfs/include/libssh/libssh.h	2009-07-07 22:35:57.000000000 -0400
@@ -41,6 +41,8 @@
 
 
 #define LIBSSH_VERSION "libssh-0.3-svn"
+// Until our additions get into the upstream repository
+#define WFS_MODIFIED_LIBSSH
 
 #ifdef __cplusplus
 extern "C" {
@@ -161,6 +163,8 @@
 /* log.c */
 void ssh_log(SSH_SESSION *session, int prioriry, char *format, ...);
 
+void ssh_cleanup_lock(void *arg);
+
 /* session.c */
 SSH_SESSION *ssh_new();
 void ssh_set_options(SSH_SESSION *session, SSH_OPTIONS *options);
@@ -173,7 +177,11 @@
 
 
 /* client.c */
-int ssh_connect(SSH_SESSION *session);
+typedef struct ssh_cleanup_frame {
+  void (*handler)(void *);
+  void *arg;
+} ssh_cleanup_frame;
+int ssh_connect(SSH_SESSION *session, struct ssh_cleanup_frame **frames);
 void ssh_disconnect(SSH_SESSION *session);
 int ssh_service_request(SSH_SESSION *session,char *service);
 char *ssh_get_issue_banner(SSH_SESSION *session);
@@ -207,6 +215,8 @@
 /* this one can be called by the client to see the hash of the public key before accepting it */
 int ssh_get_pubkey_hash(SSH_SESSION *session,unsigned char hash[MD5_DIGEST_LEN]);
 STRING *ssh_get_pubkey(SSH_SESSION *session);
+/* You should free the result */
+char *ssh_get_pubkey_base64(SSH_SESSION *session);
 
 /* in connect.c */
 int ssh_fd_poll(SSH_SESSION *session,int *write, int *except);
@@ -230,7 +240,7 @@
 
 CHANNEL *channel_new(SSH_SESSION *session);
 int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char *sourcehost, int localport);
-int channel_open_session(CHANNEL *channel);
+  int channel_open_session(CHANNEL *channel, ssh_cleanup_frame **frames);
 void channel_free(CHANNEL *channel);
 int channel_request_pty(CHANNEL *channel);
 int channel_request_pty_size(CHANNEL *channel, char *term,int cols, int rows);
@@ -243,7 +253,9 @@
 int channel_write(CHANNEL *channel,void *data,int len);
 int channel_send_eof(CHANNEL *channel);
 int channel_is_eof(CHANNEL *channel);
-int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr);
+int channel_read_nf(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr);
+int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr,
+		 ssh_cleanup_frame **frames);
 int channel_poll(CHANNEL *channel, int is_stderr);
 int channel_close(CHANNEL *channel);
 int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stderr);
@@ -288,6 +300,7 @@
 void ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow);
 void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, const char *dsakey);
 void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, const char *rsakey);
+void ssh_options_set_banner(SSH_OPTIONS *opt, const char *banner);
 void ssh_options_set_log_function(SSH_OPTIONS *opt,
     void (*callback)(const char *message, SSH_SESSION *session, int verbosity ));
 void ssh_options_set_log_verbosity(SSH_OPTIONS *opt, int verbosity);
@@ -325,8 +338,9 @@
 int ssh_userauth_none(SSH_SESSION *session, const char *username);
 int ssh_userauth_password(SSH_SESSION *session, const char *username, const char *password);
 int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username, int type, STRING *publickey);
-int ssh_userauth_pubkey(SSH_SESSION *session, const char *username, STRING *publickey, PRIVATE_KEY *privatekey);
-int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase);
+  int ssh_userauth_pubkey(SSH_SESSION *session, const char *username, STRING *publickey, PRIVATE_KEY *privatekey);
+int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase, 
+			    ssh_cleanup_frame **frames);
 int ssh_userauth_kbdint(SSH_SESSION *session, const char *user, const char *submethods);
 int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
 char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/include/libssh/priv.h libssh-wfs/include/libssh/priv.h
--- libssh-trunk/include/libssh/priv.h	2009-07-18 11:02:19.000000000 -0400
+++ libssh-wfs/include/libssh/priv.h	2009-07-07 22:35:57.000000000 -0400
@@ -25,9 +25,12 @@
 
 #ifndef _LIBSSH_PRIV_H
 #define _LIBSSH_PRIV_H
+#include <pthread.h>
 #include "config.h"
 #include "libssh/libssh.h"
 
+#include <assert.h>
+
 /* Debugging constants */
 
 /* Define this if you want to debug crypto systems */
@@ -35,16 +38,25 @@
 /*#define DEBUG_CRYPTO */
 
 /* some constants */
-#define MAX_PACKET_LEN 262144
+// xavid: hack because we send packets that are too big?
+//        there should be an option to allow larger packets
+//        that WheelFS should use
+#define MAX_PACKET_LEN 10*1024*1024
+//#define MAX_PACKET_LEN INT_MAX
+//#define MAX_PACKET_LEN 262144
 #define ERROR_BUFFERLEN 1024
 #define CLIENTBANNER1 "SSH-1.5-" LIBSSH_VERSION
 #define CLIENTBANNER2 "SSH-2.0-" LIBSSH_VERSION
 #define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */
 /* some types for public keys */
+#define TYPE_UNKNOWN 0
 #define TYPE_DSS 1
 #define TYPE_RSA 2
 #define TYPE_RSA1 3
 
+#define PHASE_PUBLICKEY_START 0
+#define PHASE_PUBLICKEY_SIGNATURE 1
+
 /* profiling constants. Don't touch them unless you know what you do */
 #ifdef HAVE_LIBCRYPTO
 #define OPENSSL_BIGNUMS
@@ -350,6 +362,12 @@
     struct ssh_message *ssh_message; /* ssh message */
     int log_verbosity; /*cached copy of the option structure */
     int log_indent; /* indentation level in enter_function logs */
+
+  pthread_mutex_t packet_mutex;
+  pthread_mutex_t crypt_mutex;
+  pthread_mutex_t write_mutex;
+  pthread_mutex_t signal_mutex;
+  pthread_cond_t signal_cond;
 };
 
 struct ssh_kbdint {
@@ -375,6 +393,11 @@
     char *username;
     int method;
     char *password;
+    STRING *publickey;
+    int type; // Algorithm for public key authentication
+    int phase; // Phase of authentication
+    int validated; // 1 if validated, 0 otherwise
+    char *signature;
 };
 
 struct ssh_channel_request_open {
@@ -637,6 +660,45 @@
 #define enter_function() _enter_function(session)
 #define leave_function() _leave_function(session)
 
+// horrible hacks to allow the app to specify cancellation handlers, since
+// things often get canceled in connect
+#define ssh_add_frame(l)			  \
+  if(frames[i] == NULL) goto l; \
+  pthread_cleanup_push( frames[i]->handler, frames[i]->arg ); \
+  i++;
+
+#define ssh_del_frame(l)			  \
+  if(frames[i] == NULL) goto l; \
+  pthread_cleanup_pop(0); \
+  i++;
+
+  // can't loop because cleanup must be in same scope as code
+#define ssh_add_all_frames(l)					\
+  int i = 0;							\
+  ssh_add_frame(l);						\
+  ssh_add_frame(l);						\
+  ssh_add_frame(l);						\
+  ssh_add_frame(l);						\
+  ssh_add_frame(l);						\
+  ssh_add_frame(l);
+
+  // can't loop because cleanup must be in same scope as code
+#define ssh_del_all_frames(l)					\
+  i = 0;							\
+  ssh_del_frame(l);						\
+  ssh_del_frame(l);						\
+  ssh_del_frame(l);						\
+  ssh_del_frame(l);						\
+  ssh_del_frame(l);						\
+  ssh_del_frame(l);
+
+typedef struct _ssh_mem_list {
+  void *ptr;
+  struct _ssh_mem_list *next;
+} ssh_mem_list;
+ssh_mem_list *new_ssh_mem_list();
+void ssh_cleanup_mem(void *);
+
 /** Zero a structure */
 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/include/libssh/server.h libssh-wfs/include/libssh/server.h
--- libssh-trunk/include/libssh/server.h	2009-07-18 11:02:19.000000000 -0400
+++ libssh-wfs/include/libssh/server.h	2009-03-29 15:05:12.000000000 -0400
@@ -72,7 +72,12 @@
 
 char *ssh_message_auth_user(SSH_MESSAGE *msg);
 char *ssh_message_auth_password(SSH_MESSAGE *msg);
+char *ssh_message_auth_publickey(SSH_MESSAGE *msg);
+int ssh_message_auth_phase(SSH_MESSAGE *msg);
+int ssh_message_auth_validated(SSH_MESSAGE *msg);
+
 int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial);
+int ssh_message_auth_reply_request_signature(SSH_MESSAGE *msg);
 void ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods);
 
 CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg);
@@ -83,4 +88,6 @@
 char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg);
 int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg);
 
+void ssh_send_issue_banner(SSH_SESSION *session, const char *banner);
+
 #endif
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/auth1.c libssh-wfs/libssh/auth1.c
--- libssh-trunk/libssh/auth1.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/auth1.c	2009-07-07 22:35:57.000000000 -0400
@@ -33,30 +33,50 @@
 #ifdef HAVE_SSH1
 static int wait_auth1_status(SSH_SESSION *session){
     /* wait for a packet */
+  int ret = SSH_AUTH_ERROR;
+  int failed = pthread_mutex_lock(&session->packet_mutex);
+  assert(!failed);
+  pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+
     if(packet_read(session))
-        return SSH_AUTH_ERROR;
-    if(packet_translate(session))
-        return SSH_AUTH_ERROR;
-    switch(session->in_packet.type){
+        ret = SSH_AUTH_ERROR;
+    else if(packet_translate(session))
+        ret = SSH_AUTH_ERROR;
+    else switch(session->in_packet.type){
         case SSH_SMSG_SUCCESS:
-            return SSH_AUTH_SUCCESS;
+            ret = SSH_AUTH_SUCCESS;
+	    break;
         case SSH_SMSG_FAILURE:
-            return SSH_AUTH_DENIED;
+            ret = SSH_AUTH_DENIED;
     }
-    ssh_set_error(session,SSH_FATAL,"Was waiting for a SUCCESS or "
-    "FAILURE, got %d",session->in_packet.type);
-    return SSH_AUTH_ERROR;
+
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+
+    if(ret == SSH_AUTH_ERROR) {
+      ssh_set_error(session,SSH_FATAL,"Was waiting for a SUCCESS or "
+		    "FAILURE, got %d",session->in_packet.type);
+    }
+    return ret;
 }
 static int send_username(SSH_SESSION *session, char *username){
     STRING *user;
     /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */
     if(session->auth_service_asked)
         return session->auth_service_asked;
+    int ret = SSH_AUTH_ERROR;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_USER);
+    bool x = false;
     if(!username)
         if(!(username=session->options->username)){
             if(ssh_options_default_username(session->options))
-                return session->auth_service_asked=SSH_AUTH_ERROR;
+	      x = true;
+	      goto cleanup;
             else
                 username=session->options->username;
         }
@@ -64,8 +84,17 @@
     buffer_add_ssh_string(session->out_buffer,user);
     free(user);
     packet_send(session);
+
+ cleanup:
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(x) goto exit;
+
     session->auth_service_asked=wait_auth1_status(session);
-    return session->auth_service_asked;
+    ret=session->auth_service_asked;
+ exit:
+    return ret;
 }
 
 /* use the "none" authentication question */
@@ -194,11 +223,18 @@
         strcpy((char *)password_s->string,password);
     }
 
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_AUTH_PASSWORD);
     buffer_add_ssh_string(session->out_buffer,password_s);
     string_burn(password_s);
     free(password_s);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     return wait_auth1_status(session);
 }
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/auth.c libssh-wfs/libssh/auth.c
--- libssh-trunk/libssh/auth.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/auth.c	2009-07-18 10:58:14.000000000 -0400
@@ -57,6 +57,10 @@
     int todo = 0;
     char *auth_methods = NULL;
     enter_function();
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+
     while(cont){
         if(packet_read(session))
             break;
@@ -68,8 +72,8 @@
                 if(!auth || buffer_get_u8(session->in_buffer,&partial)!=1 ){
                     ssh_set_error(session,SSH_FATAL,
                             "invalid SSH_MSG_USERAUTH_FAILURE message");
-                    leave_function();
-                    return SSH_AUTH_ERROR;
+                    err = SSH_AUTH_ERROR;
+		    goto exit;
                 }
                 auth_methods = string_to_char(auth);
                 if(partial) {
@@ -132,6 +136,13 @@
                 break;
         }
     }
+
+ exit:
+    ;
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+
     leave_function();
     return err;
 }
@@ -189,6 +200,10 @@
     user=string_from_char(username);
     method=string_from_char("none");
     service=string_from_char("ssh-connection");
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
     buffer_add_ssh_string(session->out_buffer,user);
     buffer_add_ssh_string(session->out_buffer,service);
@@ -197,6 +212,9 @@
     free(method);
     free(user);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     ret = wait_auth_status(session,0);
     leave_function();
     return ret;
@@ -247,7 +265,10 @@
     service=string_from_char("ssh-connection");
     method=string_from_char("publickey");
     algo=string_from_char(ssh_type_to_char(type));
-
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
     buffer_add_ssh_string(session->out_buffer,user);
     buffer_add_ssh_string(session->out_buffer,service);
@@ -255,12 +276,18 @@
     buffer_add_u8(session->out_buffer,0);
     buffer_add_ssh_string(session->out_buffer,algo);
     buffer_add_ssh_string(session->out_buffer,publickey);
-    packet_send(session);
-    err=wait_auth_status(session,0);
+
     free(user);
     free(method);
     free(service);
     free(algo);
+    packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+
+    err=wait_auth_status(session,0);
+
     leave_function();
     return err;
 }
@@ -300,6 +327,7 @@
             } else
                 username=session->options->username;
         }
+
     if(ask_userauth(session)){
         leave_function();
     	return err;
@@ -309,8 +337,11 @@
     method=string_from_char("publickey");
     algo=string_from_char(ssh_type_to_char(privatekey->type));
 
-
     /* we said previously the public key was accepted */
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
     buffer_add_ssh_string(session->out_buffer,user);
     buffer_add_ssh_string(session->out_buffer,service);
@@ -319,16 +350,23 @@
     buffer_add_ssh_string(session->out_buffer,algo);
     buffer_add_ssh_string(session->out_buffer,publickey);
     sign=ssh_do_sign(session,session->out_buffer,privatekey);
-    if(sign){
-        buffer_add_ssh_string(session->out_buffer,sign);
-        free(sign);
-        packet_send(session);
-        err=wait_auth_status(session,0);
-    }
+
     free(user);
     free(service);
     free(method);
     free(algo);
+
+    if(sign){
+        buffer_add_ssh_string(session->out_buffer,sign);
+        free(sign); 
+
+	packet_send(session);
+        err=wait_auth_status(session,0);
+    }
+
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     leave_function();
     return err;
 }
@@ -378,6 +416,10 @@
     method=string_from_char("password");
     password_s=string_from_char(password);
 
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
     buffer_add_ssh_string(session->out_buffer,user);
     buffer_add_ssh_string(session->out_buffer,service);
@@ -390,6 +432,9 @@
     memset(password_s,0,strlen(password)+4);
     free(password_s);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     err=wait_auth_status(session,0);
     leave_function();
     return err;
@@ -417,7 +462,12 @@
  * \see ssh_options_set_identity()
  */
 
-int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase) {
+void ssh_private_key_cleanup(void *arg) {
+  private_key_free( (PRIVATE_KEY *) arg );
+}
+
+int ssh_userauth_autopubkey(SSH_SESSION *session, const char *passphrase, 
+			    ssh_cleanup_frame **frames) {
     int count=1; /* bypass identity */
     int type=0;
     int err;
@@ -426,23 +476,42 @@
     PRIVATE_KEY *privkey;
     char *id=NULL;
     enter_function();
+
+    int ret = SSH_AUTH_DENIED;
+    // can't loop because cleanup must be in same scope as code
+    ssh_add_all_frames(add1);
+ add1:
+
+    ;// why?
+    ssh_mem_list *id_node = new_ssh_mem_list();
+    ssh_mem_list *pubkey_node = new_ssh_mem_list();
+    id_node->next = pubkey_node;
+    ssh_mem_list *pkf_node = new_ssh_mem_list();
+    pubkey_node->next = pkf_node;
+    pthread_cleanup_push( &ssh_cleanup_mem, id_node );
+
     // always testing none
     err=ssh_userauth_none(session,NULL);
     if(err==SSH_AUTH_ERROR || err==SSH_AUTH_SUCCESS){
-    	leave_function();
-        return err;
+      ret=err;
+      goto exit;
     }
     if(session->options->identity){
         ssh_say(2,"Trying identity file %s\n",session->options->identity);
         keys_path[0]=session->options->identity;
         /* let's hope alloca exists */
         id=malloc(strlen(session->options->identity)+1 + 4);
+	id_node->ptr = id;
         sprintf(id,"%s.pub",session->options->identity);
         pub_keys_path[0]=id;
         count =0;
     }
     while((pubkey=publickey_from_next_file(session,pub_keys_path,keys_path, &privkeyfile,&type,&count))){
+
+        pkf_node->ptr = privkeyfile;
+	pubkey_node->ptr = pubkey;
         err=ssh_userauth_offer_pubkey(session,NULL,type,pubkey);
+
         if(err==SSH_AUTH_ERROR){
             if(id){
                 pub_keys_path[0]=NULL;
@@ -451,8 +520,8 @@
             }
             free(pubkey);
             free(privkeyfile);
-            leave_function();
-            return err;
+	    ret = err;
+	    goto exit;
         } else
         if(err != SSH_AUTH_SUCCESS){
             ssh_say(2,"Public key refused by server\n");
@@ -460,8 +529,11 @@
             pubkey=NULL;
             free(privkeyfile);
             privkeyfile=NULL;
+	    pubkey_node->ptr=NULL;
+	    pkf_node->ptr=NULL;
             continue;
         }
+	ssh_say(2,"Public key accepted by server!\n");
         /* pubkey accepted by server ! */
         privkey=privatekey_from_file(session,privkeyfile,type,passphrase);
         if(!privkey){
@@ -470,42 +542,52 @@
             pubkey=NULL;
             free(privkeyfile);
             privkeyfile=NULL;
+	    pubkey_node->ptr=NULL;
+	    pkf_node->ptr=NULL;
             continue; /* continue the loop with other pubkey */
         }
+	pthread_cleanup_push( &ssh_private_key_cleanup, privkey );
         err=ssh_userauth_pubkey(session,NULL,pubkey,privkey);
+	ssh_say(2,"Got %d when authing Public key...\n",err);
         if(err==SSH_AUTH_ERROR){
             if(id){
                 pub_keys_path[0]=NULL;
                 keys_path[0]=NULL;
                 free(id);
             }
-            free(pubkey);
-            free(privkeyfile);
-            private_key_free(privkey);
-            leave_function();
-            return err;
+	    ret = err;
+	    goto inner_exit;
         } else
         if(err != SSH_AUTH_SUCCESS){
             ssh_say(0,"Weird : server accepted our public key but refused the signature\nit might be a bug of libssh\n");
-            free(pubkey);
-            pubkey=NULL;
-            free(privkeyfile);
-            privkeyfile=NULL;
-            private_key_free(privkey);
-            continue;
+	    goto inner_exit;
         }
         /* auth success */
         ssh_say(1,"Authentication using %s success\n",privkeyfile);
+    inner_exit:
+	;
+	pthread_cleanup_pop(0);
         free(pubkey);
+	pubkey=NULL;
         private_key_free(privkey);
         free(privkeyfile);
+	privkeyfile=NULL;
+	pubkey_node->ptr=NULL;
+	pkf_node->ptr=NULL;
+	if(err==SSH_AUTH_ERROR){
+	  goto exit;
+        } else
+        if(err != SSH_AUTH_SUCCESS){
+	  continue;
+	}
+
         if(id){
             pub_keys_path[0]=NULL;
             keys_path[0]=NULL;
             free(id);
         }
-        leave_function();
-        return SSH_AUTH_SUCCESS;
+        ret = SSH_AUTH_SUCCESS;
+	goto exit;
     }
     /* at this point, pubkey is NULL and so is privkeyfile */
     ssh_say(1,"Tried every public key, none matched\n");
@@ -515,8 +597,20 @@
         keys_path[0]=NULL;
         free(id);
     }
+
+ exit:
+
+    ; // why?
+    pthread_cleanup_pop(0);
+    free(id_node);
+    free(pubkey_node);
+    free(pkf_node);
+
+    ssh_del_all_frames(del1);
+ del1:
+
     leave_function();
-    return SSH_AUTH_DENIED;
+    return ret;
 }
 
 static struct ssh_kbdint *kbdint_new(){
@@ -594,7 +688,12 @@
     STRING *service=string_from_char("ssh-connection");
     STRING *method=string_from_char("keyboard-interactive");
     int err;
+    int r;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
     buffer_add_ssh_string(session->out_buffer,user_s);
     buffer_add_ssh_string(session->out_buffer,service);
@@ -605,7 +704,11 @@
     free(service);
     free(method);
     free(submethods_s);
-    if(packet_send(session)){
+    r = packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r){
         leave_function();
     	return SSH_AUTH_ERROR;
     }
@@ -676,7 +779,12 @@
     STRING *answer;
     u32 i;
     int err;
+    int r;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_INFO_RESPONSE);
     buffer_add_u32(session->out_buffer,htonl(session->kbdint->nprompts));
     for(i=0;i<session->kbdint->nprompts;++i){
@@ -688,7 +796,11 @@
         string_burn(answer);
         free(answer);
     }
-    if(packet_send(session)){
+    r = packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r){
         leave_function();
     	return SSH_AUTH_ERROR;
     }
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/channels1.c libssh-wfs/libssh/channels1.c
--- libssh-trunk/libssh/channels1.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/channels1.c	2009-07-07 22:35:57.000000000 -0400
@@ -65,7 +65,12 @@
 int channel_request_pty_size1(CHANNEL *channel, char *terminal, int col,
         int row){
     STRING *str;
+    int ret;
     SSH_SESSION *session=channel->session;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     str=string_from_char(terminal);
     buffer_add_u8(session->out_buffer,SSH_CMSG_REQUEST_PTY);
     buffer_add_ssh_string(session->out_buffer,str);
@@ -76,16 +81,26 @@
     buffer_add_u32(session->out_buffer,0); /* y */
     buffer_add_u8(session->out_buffer,0); /* tty things */
     ssh_say(2,"Opening a ssh1 pty\n");
-    if(packet_send(session))
-        return -1;
+    ret=packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(ret)
+      return -1;
+
+    ret = -1;
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+
     if(packet_read(session))
-        return -1;
+      goto exit;
     if(packet_translate(session))
-        return -1;
+      goto exit;
     switch (session->in_packet.type){
         case SSH_SMSG_SUCCESS:
             ssh_say(2,"pty : Success\n");
-            return 0;
+	    ret = 0;
             break;
         case SSH_SMSG_FAILURE:
             ssh_set_error(session,SSH_REQUEST_DENIED,
@@ -97,22 +112,40 @@
             ssh_set_error(session,SSH_FATAL,
                     "Received unexpected packet type %d",
                     session->in_packet.type);
-            return -1;
     }
-    return -1;
+ exit:
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    return ret;
 }
 
 int channel_change_pty_size1(CHANNEL *channel, int cols, int rows){
     SSH_SESSION *session=channel->session;
+    int r;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_WINDOW_SIZE);
     buffer_add_u32(session->out_buffer,ntohl(rows));
     buffer_add_u32(session->out_buffer,ntohl(cols));
     buffer_add_u32(session->out_buffer,0);
     buffer_add_u32(session->out_buffer,0);
-    if(packet_send(session))
+    r = packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r)
         return -1;
+
     ssh_say(2,"Change pty size send\n");
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert (!failed);
     packet_wait(session,SSH_SMSG_SUCCESS,1);
+    pthread_cleanup_pop(0);
+    pthread_mutex_unlock(&session->packet_mutex);
     switch (session->in_packet.type){
         case SSH_SMSG_SUCCESS:
             ssh_say(2,"pty size changed\n");
@@ -130,9 +163,20 @@
 
 int channel_request_shell1(CHANNEL *channel){
     SSH_SESSION *session=channel->session;
+    int r;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL);
-    if(packet_send(session))
-        return -1;
+    r=packet_send(session);
+
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r)
+      return -1;
+
     ssh_say(2,"Launched a shell\n");
     return 0;
 }
@@ -140,11 +184,20 @@
 int channel_request_exec1(CHANNEL *channel, char *cmd){
     SSH_SESSION *session=channel->session;
     STRING *command=string_from_char(cmd);
+    int r;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_CMD);
     buffer_add_ssh_string(session->out_buffer,command);
     free(command);
-    if(packet_send(session))
-        return -1;
+    r=packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r)
+      return -1;
     ssh_say(2,"executing %s...\n",cmd);
     return 0;
 }
@@ -175,8 +228,15 @@
     /* actually status is lost somewhere */
     channel->open=0;
     channel->remote_eof=1;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_EXIT_CONFIRMATION);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
 }
 
 void channel_handle1(SSH_SESSION *session, int type){
@@ -196,8 +256,13 @@
 
 int channel_write1(CHANNEL *channel, void *data, int len){
     SSH_SESSION *session=channel->session;
+    int ret;
     int origlen=len;
     int effectivelen;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     while(len>0){
         buffer_add_u8(session->out_buffer,SSH_CMSG_STDIN_DATA);
         if(len > 32000)
@@ -208,10 +273,18 @@
         buffer_add_data(session->out_buffer,data,effectivelen);
         data+=effectivelen;
         len-=effectivelen;
-        if(packet_send(session))
-            return -1;
+        if(packet_send(session)) {
+	  ret=-1;
+	  goto exit;
+	}
     }
-    return origlen;
+    ret=origlen;
+ exit:
+    ;
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    return ret;
 }
 
 #endif /* HAVE_SSH1 */
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/channels.c libssh-wfs/libssh/channels.c
--- libssh-trunk/libssh/channels.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/channels.c	2009-07-09 21:09:39.000000000 -0400
@@ -73,22 +73,34 @@
     u32 foo;
     int err;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_OPEN);
     channel->local_channel=ssh_channel_new_id(session);
     channel->local_maxpacket=maxpacket;
     channel->local_window=window;
+    buffer_add_ssh_string(session->out_buffer,type);
+    free(type);
     ssh_say(2,"creating a channel %d with %d window and %d max packet\n",
             channel->local_channel, window,maxpacket);
-    buffer_add_ssh_string(session->out_buffer,type);
     buffer_add_u32(session->out_buffer,htonl(channel->local_channel));
     buffer_add_u32(session->out_buffer,htonl(channel->local_window));
     buffer_add_u32(session->out_buffer,htonl(channel->local_maxpacket));
-    free(type);
     if(payload)
         buffer_add_buffer(session->out_buffer,payload);
     packet_send(session);
     ssh_say(2,"Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d\n",type_c,channel->local_channel);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    failed = pthread_mutex_lock(&session->packet_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
     err=packet_wait(session,SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,1);
+    pthread_cleanup_pop(0);
+    pthread_mutex_unlock(&session->packet_mutex);
     switch(session->in_packet.type){
         case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
             buffer_get_u32(session->in_buffer,&foo);
@@ -152,6 +164,10 @@
 static void grow_window(SSH_SESSION *session, CHANNEL *channel, int minimumsize){
     u32 new_window=minimumsize>WINDOWBASE ? minimumsize : WINDOWBASE;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_WINDOW_ADJUST);
     buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
     buffer_add_u32(session->out_buffer,htonl(new_window));
@@ -160,6 +176,9 @@
         channel->local_channel,channel->remote_channel,
         channel->local_window + new_window);
     channel->local_window+=new_window;
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     leave_function();
 }
 
@@ -392,15 +411,25 @@
  * \see channel_request_exec()
  * \warning API changed from 0.11
  */
-int channel_open_session(CHANNEL *channel){
+int channel_open_session(CHANNEL *channel, ssh_cleanup_frame **frames){
+  
+  int ret = 0;
+  ssh_add_all_frames(add1);
+ add1:
+
 #ifdef HAVE_SSH1
     if(channel->session->version==2)
 #endif
-        return channel_open(channel,"session",64000,32000,NULL);
+        ret = channel_open(channel,"session",64000,32000,NULL);
 #ifdef HAVE_SSH1
     else
-        return channel_open_session1(channel);
+        ret = channel_open_session1(channel);
 #endif
+
+    ssh_del_all_frames(exit);
+ exit:
+
+    return ret;
 }
 
 /** \brief open a TCP/IP forwarding channel.
@@ -473,11 +502,18 @@
     SSH_SESSION *session=channel->session;
     int ret;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_EOF);
     buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
     ret=packet_send(session);
     ssh_say(1,"Sent a EOF on client channel (%d:%d)\n",channel->local_channel,
         channel->remote_channel);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     channel->local_eof=1;
     leave_function();
     return ret;
@@ -502,9 +538,17 @@
         leave_function();
     	return ret;
     }
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
+    buffer_reinit(session->out_buffer);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_CLOSE);
     buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
     ret=packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     ssh_say(1,"Sent a close on client channel (%d:%d)\n",channel->local_channel,
         channel->remote_channel);
     if(!ret)
@@ -549,15 +593,64 @@
         if(channel->remote_window<len){
 	    ssh_say(2,"Remote window is %d bytes. going to write %d bytes\n",
 	    channel->remote_window,len);
-	    ssh_say(2,"Waiting for a growing window message...\n");
+	    ssh_say(2,"Waiting for a growing window message (local window is %d)...\n",channel->local_window);
             // wonder what happens when the channel window is zero
-            while(channel->remote_window==0){
-                // parse every incoming packet
-                packet_wait(channel->session,0,0);
-            }
+            //while(channel->remote_window==0){
+            //    // parse every incoming packet
+            //    packet_wait(channel->session,0,0);
+            //}
+	    int failed;
+	    int do_fail = 0;
+	    while (channel->remote_window == 0 && 
+		   session->error.error_code < SSH_FATAL) {
+	      failed = pthread_mutex_lock(&channel->session->signal_mutex);
+	      pthread_cleanup_push(&ssh_cleanup_lock, 
+				   (void *) &channel->session->signal_mutex);
+	      assert(!failed);
+	      failed = pthread_mutex_trylock(&channel->session->packet_mutex);
+	      if (!failed) {
+		pthread_cleanup_push(&ssh_cleanup_lock, 
+				     (void *) &session->packet_mutex);
+		if (channel->remote_window == 0) {
+		  packet_wait(channel->session,0,0);
+		}
+		pthread_cleanup_pop(0);
+		pthread_mutex_unlock(&channel->session->packet_mutex);
+	      } else {
+		struct timespec deadline;
+		clock_gettime(CLOCK_REALTIME, &deadline);
+		// arbitrary 5 second timeout to wait for window growth
+		deadline.tv_sec += 5;
+		int r = pthread_cond_timedwait(&channel->session->signal_cond,
+					       &channel->session->signal_mutex,
+					       &deadline);
+		if(r == ETIMEDOUT) {
+		  do_fail = 1;
+		}
+	      }
+	      pthread_cleanup_pop(0);
+	      failed = pthread_mutex_unlock(&channel->session->signal_mutex);
+	      assert(!failed);
+	      if(do_fail) {
+		ssh_say(2,"Waited 5 seconds for a growing window and never got it.\n");
+		leave_function();
+		return -1;
+	      }
+	    }
+	    if(session->error.error_code >= SSH_FATAL) {
+	      ssh_say(2,"Saw error code %d while waiting for growing window (%s).\n",
+		      session->error.error_code, session->error.error_buffer);
+	      leave_function();
+	      return -1;
+	    }
+	    ssh_say(2,"Got a growing window message for %d.\n",len);
             effectivelen=len>channel->remote_window?channel->remote_window:len;
         } else
             effectivelen=len;
+	int failed = pthread_mutex_lock(&channel->session->write_mutex);
+	assert(!failed);
+	pthread_cleanup_push(&ssh_cleanup_lock,
+			     (void *) &channel->session->write_mutex);	
         buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_DATA);
         buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
         buffer_add_u32(session->out_buffer,htonl(effectivelen));
@@ -565,6 +658,9 @@
         packet_send(session);
         ssh_say(2,"channel_write wrote %d bytes\n",effectivelen);
         channel->remote_window-=effectivelen;
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&channel->session->write_mutex);
+	assert(!failed);
         len -= effectivelen;
         data+=effectivelen;
     }
@@ -618,6 +714,10 @@
     SSH_SESSION *session=channel->session;
     int err;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_REQUEST);
     buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
     buffer_add_ssh_string(session->out_buffer,request_s);
@@ -626,12 +726,22 @@
         buffer_add_data(session->out_buffer,buffer_get(buffer),buffer_get_len(buffer));
     packet_send(session);
     ssh_say(3,"Sent a SSH_MSG_CHANNEL_REQUEST %s\n",request);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     free(request_s);
     if(!reply){
     	leave_function();
     	return 0;
     }
+    failed = pthread_mutex_lock(&session->packet_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
     err=packet_wait(session,SSH2_MSG_CHANNEL_SUCCESS,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    free(request_s);
     if(err)
         if(session->in_packet.type==SSH2_MSG_CHANNEL_FAILURE){
             ssh_say(2,"%s channel request failed\n",request);
@@ -823,10 +933,21 @@
  * 0 on end of file\n
  * SSH_ERROR on error
  */
-int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
+int channel_read_nf(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
+  ssh_cleanup_frame *frames[1];
+  frames[0] = NULL;
+  return channel_read(channel, buffer, bytes, is_stderr, frames);
+}
+int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr,
+		 ssh_cleanup_frame **frames){
     BUFFER *stdbuf=NULL;
     SSH_SESSION *session=channel->session;
     int len;
+    int ret = -1;
+
+    ssh_add_all_frames(add1);
+ add1:
+
     buffer_reinit(buffer);
     int maxread=bytes;
     enter_function();
@@ -845,18 +966,39 @@
     /* block reading if asked bytes=0 */
     while((buffer_get_rest_len(stdbuf)==0) || (buffer_get_rest_len(stdbuf) < bytes)){
         if(channel->remote_eof && buffer_get_rest_len(stdbuf)==0){
-            leave_function();
-        	return 0;
+	  ret = 0;
+	  goto exit;
         }
         if(channel->remote_eof)
             break; /* return the resting bytes in buffer */
         if(buffer_get_rest_len(stdbuf)>=maxread) // stop reading when buffer is full enough
             break;
-        if(packet_read(session)||packet_translate(session)){
-            leave_function();
-        	return -1;
-        }
-        packet_parse(session);
+	int failed = pthread_mutex_lock(&session->packet_mutex);
+	assert(!failed);
+	int exit_err = 0;
+	pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+	// Check again in the mutex
+	if ((buffer_get_rest_len(stdbuf)==0) 
+	    || (buffer_get_rest_len(stdbuf) < bytes)) {
+	  if(packet_read(session)||packet_translate(session)){
+	    exit_err = 1;
+	  } else {
+	    packet_parse(session);
+	  }
+	}
+	if(!exit_err) {
+	  pthread_mutex_lock(&session->signal_mutex);
+	  pthread_cond_broadcast(&session->signal_cond);
+	  pthread_mutex_unlock(&session->signal_mutex);
+	}
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&session->packet_mutex);
+	assert(!failed);
+	if(exit_err) {
+	  ret = -1;
+	  goto exit;
+	}
+
     }
     if(channel->local_window < WINDOWLIMIT)
     	grow_window(session,channel,0);
@@ -870,8 +1012,16 @@
         buffer_add_data(buffer,buffer_get_rest(stdbuf),len);
         buffer_pass_bytes(stdbuf,len);
     }
+
+    ret = buffer_get_len(buffer);
+
+ exit:
+
+    ssh_del_all_frames(del1);
+ del1:
+
     leave_function();
-    return buffer_get_len(buffer);
+    return ret;
 }
 
 /** \brief polls the channel for data to read
@@ -935,7 +1085,7 @@
     }
     if(to_read>len)
         to_read=len;
-    lu=channel_read(channel,buffer,to_read,is_stderr);
+    lu=channel_read_nf(channel,buffer,to_read,is_stderr);
     memcpy(dest,buffer_get(buffer),lu>=0?lu:0);
     buffer_free(buffer);
     leave_function();
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/client.c libssh-wfs/libssh/client.c
--- libssh-trunk/libssh/client.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/client.c	2009-07-18 10:58:14.000000000 -0400
@@ -37,7 +37,15 @@
     char *ret;
     enter_function();
     while (i < 127) {
-        if(ssh_socket_read(session->socket, &buffer[i], 1)!= SSH_OK){
+      int r;
+      int failed = pthread_mutex_lock(&session->packet_mutex);
+      pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+      assert(!failed);
+      r=ssh_socket_read(session->socket, &buffer[i], 1);
+      pthread_cleanup_pop(0);
+      failed = pthread_mutex_unlock(&session->packet_mutex);
+      assert(!failed);      
+      if(r != SSH_OK){
             ssh_set_error(session,SSH_FATAL,"Remote host closed connection");
             leave_function();
             return NULL;
@@ -103,12 +111,21 @@
     else
         session->clientbanner=strdup(banner);
     snprintf(buffer,128,"%s\r\n",banner);
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex)
     ssh_socket_write(session->socket,buffer,strlen(buffer));
     ssh_socket_blocking_flush(session->socket);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     leave_function();
     return 0;
 }
 
+
+
 #define DH_STATE_INIT 0
 #define DH_STATE_INIT_TO_SEND 1
 #define DH_STATE_INIT_SENT 2
@@ -118,6 +135,7 @@
 static int dh_handshake(SSH_SESSION *session){
     STRING *e,*f,*pubkey,*signature;
     int ret;
+    int failed;
     enter_function();
     switch(session->dh_handshake_state){
         case DH_STATE_INIT:
@@ -125,8 +143,15 @@
             dh_generate_x(session);
             dh_generate_e(session);
             e=dh_get_e(session);
+	    int failed = pthread_mutex_lock(&session->write_mutex);
+	    assert(!failed);
+	    pthread_cleanup_push(&ssh_cleanup_lock,
+				 (void *) &session->write_mutex);
             buffer_add_ssh_string(session->out_buffer,e);
             ret=packet_send(session);
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->write_mutex);
+	    assert(!failed);
             free(e);
             session->dh_handshake_state=DH_STATE_INIT_TO_SEND;
             if(ret==SSH_ERROR){
@@ -134,46 +159,83 @@
                 return ret;
             }
         case DH_STATE_INIT_TO_SEND:
+	    failed = pthread_mutex_lock(&session->write_mutex);
+	    assert(!failed);
+	    pthread_cleanup_push(&ssh_cleanup_lock,
+				 (void *) &session->write_mutex);
             ret=packet_flush(session,0);
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->write_mutex);
+	    assert(!failed);
             if(ret!=SSH_OK){
                 leave_function();
             	return ret; // SSH_ERROR or SSH_AGAIN
             }
             session->dh_handshake_state=DH_STATE_INIT_SENT;
         case DH_STATE_INIT_SENT:
+	  failed = pthread_mutex_lock(&session->packet_mutex);
+	  pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+	  assert(!failed);
+
             ret=packet_wait(session,SSH2_MSG_KEXDH_REPLY,1);
+
             if(ret != SSH_OK){
-                leave_function();
-            	return ret;
+	      goto init_exit;
             }
             pubkey=buffer_get_ssh_string(session->in_buffer);
             if(!pubkey){
                 ssh_set_error(session,SSH_FATAL,"No public key in packet");
-                leave_function();
-                return SSH_ERROR;
+		ret=SSH_ERROR;
+		goto init_exit;
             }
             dh_import_pubkey(session,pubkey);
             f=buffer_get_ssh_string(session->in_buffer);
             if(!f){
                 ssh_set_error(session,SSH_FATAL,"No F number in packet");
-                leave_function();
-                return SSH_ERROR;
+		ret=SSH_ERROR;
+		goto init_exit;
             }
             dh_import_f(session,f);
             free(f);
             if(!(signature=buffer_get_ssh_string(session->in_buffer))){
                 ssh_set_error(session,SSH_FATAL,"No signature in packet");
-                leave_function();
-                return SSH_ERROR;
+		ret=SSH_ERROR;
+		goto init_exit;
             }
+
+    init_exit:
+	    ;
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->packet_mutex);
+	    assert(!failed);
+
+            if(ret != SSH_OK){
+	      leave_function();
+	      return ret;
+	    }
+
             session->dh_server_signature=signature;
             dh_build_k(session);
             // send the MSG_NEWKEYS
+	    failed = pthread_mutex_lock(&session->write_mutex);
+	    assert(!failed);
+	    pthread_cleanup_push(&ssh_cleanup_lock,
+				 (void *) &session->write_mutex);
             buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
             packet_send(session);
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->write_mutex);
+	    assert(!failed);
             session->dh_handshake_state=DH_STATE_NEWKEYS_TO_SEND;
         case DH_STATE_NEWKEYS_TO_SEND:
+	    failed = pthread_mutex_lock(&session->write_mutex);
+	    assert(!failed);
+	    pthread_cleanup_push(&ssh_cleanup_lock,
+				 (void *) &session->write_mutex);
             ret=packet_flush(session,0);
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->write_mutex);
+	    assert(!failed);
             if(ret != SSH_OK){
                 leave_function();
             	return ret;
@@ -181,7 +243,13 @@
             ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
             session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
         case DH_STATE_NEWKEYS_SENT:
+	  failed = pthread_mutex_lock(&session->packet_mutex);
+	  pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+	  assert(!failed);
             ret=packet_wait(session,SSH2_MSG_NEWKEYS,1);
+	    pthread_cleanup_pop(0);
+	    failed = pthread_mutex_unlock(&session->packet_mutex);
+	  assert(!failed);
             if(ret != SSH_OK){
                 leave_function();
             	return ret;
@@ -226,13 +294,28 @@
 int ssh_service_request(SSH_SESSION *session,char *service){
     STRING *service_s;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_REQUEST);
     service_s=string_from_char(service);
     buffer_add_ssh_string(session->out_buffer,service_s);
     free(service_s);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     ssh_say(3,"Sent SSH_MSG_SERVICE_REQUEST (service %s)\n",service);
-    if(packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1)){
+    failed = pthread_mutex_lock(&session->packet_mutex);
+    int res;
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert(!failed);
+    res = packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    if(res){
         ssh_set_error(session,SSH_FATAL,"did not receive SERVICE_ACCEPT");
         leave_function();
         return -1;
@@ -251,32 +334,40 @@
  * \see ssh_new()
  * \see ssh_disconnect()
  */
-int ssh_connect(SSH_SESSION *session){
+int ssh_connect(SSH_SESSION *session, ssh_cleanup_frame **frames){
   int fd;
   int ssh1, ssh2;
+  int err = 0;
   SSH_OPTIONS *options=session->options;
   if(!session->options){
       ssh_set_error(session,SSH_FATAL,"Must set options before connect");
       return SSH_ERROR;
   }
   enter_function();
+
+  ssh_add_all_frames(add1);
+ add1:
+
+  ssh_say(2,"(%x) Entering ssh_connect\n",(unsigned) pthread_self());
+
   session->alive=0;
   session->client=1;
   ssh_crypto_init();
   ssh_socket_init();
   if(options->fd==-1 && !options->host){
       ssh_set_error(session,SSH_FATAL,"Hostname required");
-      leave_function();
-      return SSH_ERROR;
+      err = SSH_ERROR;
+      goto exit;
   }
   if(options->fd != -1)
       fd=options->fd;
-  else
+  else {
       fd=ssh_connect_host(session,options->host,options->bindaddr,options->port,
           options->timeout,options->timeout_usec);
+  }
   if(fd<0){
-	  leave_function();
-	  return -1;
+      err = -1;
+      goto exit;
   }
   set_status(options,0.2);
   ssh_socket_set_fd(session->socket,fd);
@@ -284,8 +375,8 @@
   if(!(session->serverbanner=ssh_get_banner(session))){
       ssh_socket_close(session->socket);
       session->alive=0;
-      leave_function();
-      return -1;
+      err = -1;
+      goto exit;
   }
   set_status(options,0.4);
   ssh_say(2,"banner : %s\n",session->serverbanner);
@@ -293,8 +384,8 @@
   if(ssh_analyze_banner(session,&ssh1,&ssh2)){
       ssh_socket_close(session->socket);
       session->alive=0;
-      leave_function();
-      return -1;
+      err = -1;
+      goto exit;
   }
   /* here we decide which version of the protocol to use */
   if(ssh2 && options->ssh2allowed)
@@ -307,8 +398,8 @@
         session->serverbanner);
         ssh_socket_close(session->socket);
         session->alive=0;
-        leave_function();
-        return -1;
+	err = -1;
+	goto exit;
   }
   ssh_send_banner(session,0);
   set_status(options,0.5);
@@ -317,24 +408,24 @@
         if(ssh_get_kex(session,0)){
             ssh_socket_close(session->socket);
             session->alive=0;
-            leave_function();
-            return -1;
+            err = -1;
+	    goto exit;
         }
         set_status(options,0.6);
         ssh_list_kex(&session->server_kex);
         if(set_kex(session)){
             ssh_socket_close(session->socket);
             session->alive=0;
-            leave_function();
-            return -1;
+            err = -1;
+	    goto exit;
         }
         ssh_send_kex(session,0);
         set_status(options,0.8);
-        if(dh_handshake(session)){
+	if(dh_handshake(session)){
             ssh_socket_close(session->socket);
             session->alive=0;
-            leave_function();
-            return -1;
+            err = -1;
+	    goto exit;
         }
         set_status(options,1.0);
         session->connected=1;
@@ -343,15 +434,21 @@
         if(ssh_get_kex1(session)){
             ssh_socket_close(session->socket);
             session->alive=0;
-            leave_function();
-            return -1;
+            err = -1;
+	    goto exit;
         }
         set_status(options,0.6);
         session->connected=1;
         break;
   }
+
+ exit:
+
+  ssh_del_all_frames(del1);
+ del1:
+
   leave_function();
-  return 0;
+  return err;
 }
 
 /** this is the banner showing a disclaimer to users who log in,
@@ -373,12 +470,20 @@
     STRING *str;
     enter_function();
     if(ssh_socket_is_open(session->socket)) {
+      int failed = pthread_mutex_lock(&session->write_mutex);
+      assert(!failed);
+      pthread_cleanup_push(&ssh_cleanup_lock,
+			   (void *) &session->write_mutex);
+      buffer_reinit(session->out_buffer);
         buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT);
         buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION));
         str=string_from_char("Bye Bye");
         buffer_add_ssh_string(session->out_buffer,str);
         free(str);
         packet_send(session);
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&session->write_mutex);
+	assert(!failed);
         ssh_socket_close(session->socket);
     }
     session->alive=0;
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/crypt.c libssh-wfs/libssh/crypt.c
--- libssh-trunk/libssh/crypt.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/crypt.c	2009-07-29 15:04:18.000000000 -0400
@@ -37,7 +37,7 @@
 u32 packet_decrypt_len(SSH_SESSION *session, char *crypted){
     u32 decrypted;
     if(session->current_crypto)
-        packet_decrypt(session,crypted,session->current_crypto->in_cipher->blocksize);
+        packet_decrypt(session,crypted,session->current_crypto->in_cipher->blocksize); 
     memcpy(&decrypted,crypted,sizeof(decrypted));
     ssh_log(session,SSH_LOG_PACKET,"packet size decrypted : %d (0x%lx)",ntohl(decrypted),ntohl(decrypted));
     return ntohl(decrypted);
@@ -47,6 +47,8 @@
     struct crypto_struct *crypto=session->current_crypto->in_cipher;
     char *out=malloc(len);
     ssh_log(session,SSH_LOG_PACKET,"Decrypting %d bytes",len);
+    assert(pthread_mutex_lock(&session->crypt_mutex) == 0);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->crypt_mutex);
 #ifdef HAVE_LIBGCRYPT
     crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey,session->current_crypto->decryptIV);
     crypto->cbc_decrypt(crypto,data,out,len);
@@ -54,6 +56,8 @@
     crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey);
     crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV);
 #endif
+    pthread_cleanup_pop(0);
+    assert(pthread_mutex_unlock(&session->crypt_mutex) == 0);
     memcpy(data,out,len);
     memset(out,0,len);
     free(out);
@@ -70,6 +74,8 @@
         return NULL; /* nothing to do here */
     crypto= session->current_crypto->out_cipher;
     ssh_log(session,SSH_LOG_PACKET,"encrypting packet with seq num: %d, len: %d",session->send_seq,len);
+    assert(pthread_mutex_lock(&session->crypt_mutex) == 0);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->crypt_mutex);
 #ifdef HAVE_LIBGCRYPT
     crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey,session->current_crypto->encryptIV);
 #elif defined HAVE_LIBCRYPTO
@@ -93,6 +99,8 @@
 #elif defined HAVE_LIBCRYPTO
     crypto->cbc_encrypt(crypto,data,out,len,session->current_crypto->encryptIV);
 #endif
+    pthread_cleanup_pop(0);
+    assert(pthread_mutex_unlock(&session->crypt_mutex) == 0);
     memcpy(data,out,len);
     memset(out,0,len);
     free(out);
@@ -107,6 +115,8 @@
     unsigned char hmacbuf[EVP_MAX_MD_SIZE];
     unsigned int len;
     u32 seq=htonl(session->recv_seq);
+    assert(pthread_mutex_lock(&session->crypt_mutex) == 0);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->crypt_mutex);
     ctx=hmac_init(session->current_crypto->decryptMAC,20,HMAC_SHA1);
     hmac_update(ctx,(unsigned char *)&seq,sizeof(u32));
     hmac_update(ctx,buffer_get(buffer),buffer_get_len(buffer));
@@ -116,5 +126,7 @@
     ssh_print_hexa("Computed mac",hmacbuf,len);
     ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(u32));
 #endif
+    pthread_cleanup_pop(0);
+    assert(pthread_mutex_unlock(&session->crypt_mutex) == 0);
     return memcmp(mac,hmacbuf,len);
 }
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/dh.c libssh-wfs/libssh/dh.c
--- libssh-trunk/libssh/dh.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/dh.c	2009-07-07 22:35:57.000000000 -0400
@@ -46,6 +46,7 @@
 #include <openssl/rand.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
+#include <openssl/buffer.h>
 #endif
 
 static unsigned char p_value[] = {
@@ -381,6 +382,8 @@
 }
 
 void hashbufout_add_cookie(SSH_SESSION *session){
+    if(session->out_hashbuf)
+        buffer_free(session->out_hashbuf);
     session->out_hashbuf=buffer_new();
     buffer_add_u8(session->out_hashbuf,20);
     if(session->server)
@@ -391,6 +394,8 @@
 
 
 void hashbufin_add_cookie(SSH_SESSION *session,unsigned char *cookie){
+    if(session->in_hashbuf)
+        buffer_free(session->in_hashbuf);
     session->in_hashbuf=buffer_new();
     buffer_add_u8(session->in_hashbuf,20);
     buffer_add_data(session->in_hashbuf,cookie,16);
@@ -484,6 +489,30 @@
     return MD5_DIGEST_LEN;
 }
 
+// You should free() the return value
+char *ssh_get_pubkey_base64(SSH_SESSION *session) {
+  // Convert to base64
+  BIO *bmem, *b64;
+  BUF_MEM *bptr;
+  
+  b64 = BIO_new(BIO_f_base64());
+  BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
+  bmem = BIO_new(BIO_s_mem());
+  b64 = BIO_push(b64, bmem);
+  BIO_write(b64, string_data(session->current_crypto->server_pubkey), 
+	    string_len(session->current_crypto->server_pubkey));
+  BIO_flush(b64);
+  BIO_get_mem_ptr(b64, &bptr);
+  
+  char *str64 = (char *)malloc(bptr->length+1);
+  memcpy(str64, bptr->data, bptr->length);
+  str64[bptr->length] = 0;
+  
+  BIO_free_all(b64);
+  
+  return str64;
+}
+
 /** \deprecated same as ssh_get_pubkey_hash()
  */
 int pubkey_get_hash(SSH_SESSION *session, unsigned char hash[MD5_DIGEST_LEN]){
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/error.c libssh-wfs/libssh/error.c
--- libssh-trunk/libssh/error.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/error.c	2009-07-07 22:35:57.000000000 -0400
@@ -70,6 +70,8 @@
     if(priority <= verbosity)
         vfprintf(stderr,format,va);
     va_end(va);
+    fflush(stderr);
+    __fpurge(stderr);
 }
 
 void ssh_set_verbosity(int num){
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/kex.c libssh-wfs/libssh/kex.c
--- libssh-trunk/libssh/kex.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/kex.c	2009-07-07 22:35:57.000000000 -0400
@@ -168,7 +168,15 @@
     char *strings[10];
     int i;
     enter_function();
-    if(packet_wait(session,SSH2_MSG_KEXINIT,1)){
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    int res;
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert(!failed);
+    res = packet_wait(session,SSH2_MSG_KEXINIT,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    if(res){
     	leave_function();
     	return -1;
     }
@@ -256,6 +264,10 @@
     int i=0;
     KEX *kex=(server_kex ? &session->server_kex : &session->client_kex);
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_KEXINIT);
     buffer_add_data(session->out_buffer,kex->cookie,16);
     hashbufout_add_cookie(session);
@@ -270,6 +282,9 @@
     buffer_add_u8(session->out_buffer,0);
     buffer_add_u32(session->out_buffer,0);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     leave_function();
 }
 
@@ -414,7 +429,15 @@
     u16 bits;
     enter_function();
     ssh_log(session,SSH_LOG_PROTOCOL,"Waiting for a SSH_SMSG_PUBLIC_KEY");
-    if(packet_wait(session,SSH_SMSG_PUBLIC_KEY,1)){
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    int res;
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert(!failed);
+    res = packet_wait(session,SSH_SMSG_PUBLIC_KEY,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    if(res){
     	leave_function();
         return -1;
     }
@@ -476,6 +499,10 @@
         return -1;
     }
     ssh_log(session,SSH_LOG_PROTOCOL,"sending SSH_CMSG_SESSION_KEY");
+    failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH_CMSG_SESSION_KEY);
     buffer_add_u8(session->out_buffer,SSH_CIPHER_3DES);
     buffer_add_data(session->out_buffer,session->server_kex.cookie,8);
@@ -492,6 +519,9 @@
     buffer_add_u32(session->out_buffer,0);
 
     packet_send(session); 
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     /* we can set encryption */
     if(crypt_set_algorithms(session)){
     	leave_function();
@@ -500,7 +530,14 @@
     session->current_crypto=session->next_crypto;
     session->next_crypto=NULL;
     ssh_log(session,SSH_LOG_PROTOCOL,"Waiting for a SSH_SMSG_SUCCESS");
-    if(packet_wait(session,SSH_SMSG_SUCCESS,1)){
+    failed = pthread_mutex_lock(&session->packet_mutex);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert(!failed);
+    res = packet_wait(session,SSH_SMSG_SUCCESS,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    if(res){
         char buffer[1024];
         snprintf(buffer,sizeof(buffer),"Key exchange failed : %s",ssh_get_error(session));
         ssh_set_error(session,SSH_FATAL,"%s",buffer);
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/log.c libssh-wfs/libssh/log.c
--- libssh-trunk/libssh/log.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/log.c	2009-07-07 22:35:57.000000000 -0400
@@ -55,6 +55,8 @@
 		} else {
 			fprintf(stderr,"[%d] %s\n",verbosity,buffer);
 		}
+		fflush(stderr);
+		__fpurge(stderr);
 	}
 }
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/messages.c libssh-wfs/libssh/messages.c
--- libssh-trunk/libssh/messages.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/messages.c	2009-07-07 22:35:57.000000000 -0400
@@ -36,6 +36,11 @@
 #include "libssh/server.h"
 #include "libssh/ssh2.h"
 
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#endif
 
 static SSH_MESSAGE *message_new(SSH_SESSION *session){
     SSH_MESSAGE *msg=session->ssh_message;
@@ -61,17 +66,31 @@
     service_c=string_to_char(service);
     ssh_say(2,"Sending a SERVICE_ACCEPT for service %s\n",service_c);
     free(service_c);
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_ACCEPT);
     buffer_add_ssh_string(session->out_buffer,service);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     free(service);
     leave_function();
     return 0;
 }
 
 static void handle_unimplemented(SSH_SESSION *session){
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u32(session->out_buffer,htonl(session->recv_seq-1));
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
 }
 
 static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){
@@ -83,34 +102,218 @@
     enter_function();
     msg=message_new(session);
     msg->type=SSH_AUTH_REQUEST;
+    msg->auth_request.validated = 0;
     msg->auth_request.username=string_to_char(user);
-    free(user);
     service_c=string_to_char(service);
     method_c=string_to_char(method);
-    free(service);
-    free(method);
     ssh_say(2,"auth request for service %s, method %s for user '%s'\n",service_c,method_c,
             msg->auth_request.username);
     free(service_c);
     if(!strcmp(method_c,"none")){
         msg->auth_request.method=SSH_AUTH_NONE;
-        free(method_c);
-        leave_function();
-        return msg;
-    }
-    if(!strcmp(method_c,"password")){
+    } else if(!strcmp(method_c,"password")){
         STRING *pass;
         u8 tmp;
         msg->auth_request.method=SSH_AUTH_PASSWORD;
-        free(method_c);
         buffer_get_u8(session->in_buffer,&tmp);
         pass=buffer_get_ssh_string(session->in_buffer);
         msg->auth_request.password=string_to_char(pass);
         free(pass);
-        leave_function();
-        return msg;
+    } else if(!strcmp(method_c,"publickey")){
+        STRING *algo, *blob;
+        u8 has_sig;
+	char *algo_c;
+
+        msg->auth_request.method=SSH_AUTH_PUBLICKEY;
+        buffer_get_u8(session->in_buffer,&has_sig);
+        algo=buffer_get_ssh_string(session->in_buffer);
+	algo_c = string_to_char(algo);
+
+	if (!strcmp(algo_c,"ssh-dss")) {
+	  msg->auth_request.type = TYPE_DSS;
+	} else if (!strcmp(algo_c,"ssh-rsa")) {
+	  msg->auth_request.type = TYPE_RSA;
+	} else {
+	  msg->auth_request.type = TYPE_UNKNOWN;
+	}
+        blob=buffer_get_ssh_string(session->in_buffer);
+	// Convert to base64
+	BIO *bmem, *b64;
+	BUF_MEM *bptr;
+
+	b64 = BIO_new(BIO_f_base64());
+	BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
+	bmem = BIO_new(BIO_s_mem());
+	b64 = BIO_push(b64, bmem);
+	BIO_write(b64, string_data(blob), string_len(blob));
+	BIO_flush(b64);
+	BIO_get_mem_ptr(b64, &bptr);
+
+	char *str64 = (char *)malloc(bptr->length+1);
+	memcpy(str64, bptr->data, bptr->length);
+	str64[bptr->length] = 0;
+
+	BIO_free_all(b64);
+	
+        msg->auth_request.password=str64;
+	if (has_sig) {
+	  STRING *sigbufstr = buffer_get_ssh_string(session->in_buffer);
+	  BUFFER *sigbuf = buffer_new();
+	  buffer_add_data(sigbuf, string_data(sigbufstr),
+			  string_len(sigbufstr));
+	  STRING *sigtag = buffer_get_ssh_string(sigbuf);
+	  STRING *sig = buffer_get_ssh_string(sigbuf);
+	  buffer_free(sigbuf);
+	  free(sigbufstr);
+	  char *sigtag_c = string_to_char(sigtag);
+	  if (strcmp(algo_c,sigtag_c)) {
+	    ssh_say(0,"WARNING: Signature tag doesn't match algo: '%s' != '%s'\n",
+		    sigtag_c,algo_c);
+	  }
+	  free(sigtag_c);
+	  free(sigtag);
+	  msg->auth_request.signature = string_to_char(sig);
+	  msg->auth_request.phase = PHASE_PUBLICKEY_SIGNATURE;
+
+	  // Validate signature here
+
+	  // Glue data to validate the signature against
+	  BUFFER *sigdatabuf = buffer_new();
+	  STRING *session_identifier = string_new(SHA_DIGEST_LEN);
+	  string_fill(session_identifier,session->current_crypto->session_id,
+		      SHA_DIGEST_LEN);
+	  buffer_add_ssh_string(sigdatabuf,session_identifier);
+	  free(session_identifier);
+	  buffer_add_u8(sigdatabuf,SSH2_MSG_USERAUTH_REQUEST);
+	  buffer_add_ssh_string(sigdatabuf,user);
+	  buffer_add_ssh_string(sigdatabuf,service);
+	  STRING *tmp = string_from_char("publickey");
+	  buffer_add_ssh_string(sigdatabuf,tmp);
+	  free(tmp);
+	  buffer_add_u8(sigdatabuf,1);
+	  buffer_add_ssh_string(sigdatabuf,algo);
+	  buffer_add_ssh_string(sigdatabuf,blob);
+
+	  unsigned char hash[SHA_DIGEST_LEN+1];
+	  sha1(buffer_get(sigdatabuf),buffer_get_len(sigdatabuf),hash+1);
+	  hash[0] = 0;
+	  buffer_free(sigdatabuf);
+
+#ifdef HAVE_LIBGCRYPT
+#error INCOMPLETE!
+	  gcry_sexp_t s_sig, s_data, s_pubkey;
+	  size_t dummy;
+
+	  gcry_sexp_build(&s_data,&dummy,
+			  "(data (flags pkcs1) (hash sha1 %s))",
+			  data);
+
+	  switch (msg->auth_request.type) {
+	  case TYPE_DSS:
+
+	    gcry_sexp_build(&s_sig,&dummy,
+			    "(sig-val (dsa (r %d) (s %d)))");
+	    gcry_sexp_build(&s_pubkey,&dummy,
+			    "(public-key (dsa (p %d) (q %d) (g %d) (y %d)))");
+	    break;
+	  case TYPE_RSA:
+	  case TYPE_RSA1:
+	    gcry_sexp_build(&s_sig,&dummy,
+			    "(sig-val (rsa (s %d)))");
+	    gcry_sexp_build(&s_pubkey,&dummy,
+			    "(public-key (rsa (n %d) (e %d)))");
+	    break;
+	  default:
+	    goto end_gcrypt; // Leave at default of false
+	  }
+	  msg->auth_request.validated = (gcry_pk_verify(s_sig,
+							s_data,
+							s_pubkey) == 0);
+	end_gcrypt:
+	  gcry_sexp_release(s_sig);
+	  gcry_sexp_release(s_data);
+	  gcry_sexp_release(s_pubkey);
+#elif defined(HAVE_LIBCRYPTO)
+	  unsigned char *pubkeystr = (unsigned char *)string_data(blob);
+	  switch (msg->auth_request.type) {
+	  case TYPE_RSA:
+	  case TYPE_RSA1:
+	    {
+	      BUFFER *rsapkbuf = buffer_new();
+	      buffer_add_data(rsapkbuf, string_data(blob),string_len(blob));
+	      STRING *ssh_rsa = buffer_get_ssh_string(rsapkbuf);
+	      STRING *e = buffer_get_ssh_string(rsapkbuf);
+	      STRING *n = buffer_get_ssh_string(rsapkbuf);
+	      ERR_clear_error();
+	      RSA *pubkey = RSA_new();
+	      if (pubkey != NULL) {
+		pubkey->e = BN_mpi2bn((unsigned char *)e,4+string_len(e),NULL);
+		pubkey->n = BN_mpi2bn((unsigned char *)n,4+string_len(n),NULL);
+	      }
+	      unsigned long err = ERR_get_error();
+	      if (pubkey == NULL || pubkey->e == NULL || pubkey->n == NULL) {
+		ERR_load_crypto_strings();
+		ssh_say(1,"Got a libcrypto error %lu parsing the sent publickey: %s\n",
+			err, ERR_error_string(err,NULL));
+		ERR_clear_error();
+		break;
+	      }
+	      msg->auth_request.validated = 
+		(RSA_verify(NID_sha1, 
+			    hash+1, SHA_DIGEST_LEN,
+			    (unsigned char *)string_data(sig), 
+			    string_len(sig),
+			    pubkey) == 1);
+	      err = ERR_get_error();
+	      if (err != 0) {
+		ERR_load_crypto_strings();
+		ssh_say(1,"Got a libcrypto error %lu validating sig: %s\n",
+			err, ERR_error_string(err,NULL));
+		ERR_clear_error();
+		break;
+	      }
+	      free(ssh_rsa);
+	      free(e);
+	      free(n);
+	      RSA_free(pubkey);
+	      buffer_free(rsapkbuf);
+	    }
+	    break;
+	  case TYPE_DSS:
+	    {
+	      /* This code doesn't work... base it on the RSA code above. */
+	      DSA *pubkey = d2i_DSA_PUBKEY(NULL,
+					   &pubkeystr,
+					   string_len(blob));
+	      if (pubkey == NULL) {
+		break;
+	      }
+	      msg->auth_request.validated = 
+		(DSA_verify(0, buffer_get(sigdatabuf), buffer_get_len(sigdatabuf),
+			    (unsigned char *)msg->auth_request.signature, 
+			    strlen(msg->auth_request.signature),
+			    pubkey) == 1);
+	      DSA_free(pubkey);
+	    }
+	    break;
+	  default:
+	    ;// msg->auth_request.validated = 0; -- default
+	  }
+#endif
+	  free(sig);
+	} else {
+	  msg->auth_request.phase = PHASE_PUBLICKEY_START;
+	}
+	free(algo_c);
+	free(algo);
+        free(blob);
+    } else {
+      msg->auth_request.method=SSH_AUTH_UNKNOWN;
     }
-    msg->auth_request.method=SSH_AUTH_UNKNOWN;
+    // Don't free these until here, because we need them for checking sigs
+    free(user);
+    free(service);
+    free(method);
     free(method_c);
     leave_function();
     return msg;
@@ -124,6 +327,14 @@
     return msg->auth_request.password;
 }
 
+char *ssh_message_auth_publickey(SSH_MESSAGE *msg){
+    return msg->auth_request.password;
+}
+
+int ssh_message_auth_phase(SSH_MESSAGE *msg){
+    return msg->auth_request.phase;
+}
+
 void ssh_message_auth_set_methods(SSH_MESSAGE *msg,int methods){
     msg->session->auth_methods=methods;
 }
@@ -134,6 +345,10 @@
     SSH_SESSION *session=msg->session;
     int ret;
     enter_function();
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_FAILURE);
     if(session->auth_methods==0){
         session->auth_methods=SSH_AUTH_PUBLICKEY|SSH_AUTH_PASSWORD;
@@ -157,6 +372,9 @@
     else
         buffer_add_u8(session->out_buffer,0); // no partial success
     ret = packet_send(msg->session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     leave_function();
     return ret;
 }
@@ -164,8 +382,55 @@
 int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial){
     if(partial)
         return ssh_message_auth_reply_default(msg,partial);
+    int r;
+    int failed = pthread_mutex_lock(&msg->session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &msg->session->write_mutex);
     buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS);
-    return packet_send(msg->session);
+    r=packet_send(msg->session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&msg->session->write_mutex);
+    assert(!failed);
+    return r;
+}
+
+int ssh_message_auth_reply_request_signature(SSH_MESSAGE *msg) {
+  const char *type_c;
+  SSH_SESSION *session = msg->session;
+  if (msg->auth_request.type == TYPE_DSS) {
+    type_c = "ssh-dss";
+  } else if (msg->auth_request.type == TYPE_RSA
+	     || msg->auth_request.type == TYPE_RSA1) {
+    type_c = "ssh-rsa";
+  } else {
+    // Fail!
+    return ssh_message_auth_reply_default(msg,0);
+  }
+  enter_function();
+
+  ssh_say(2,"Sending a request for a signature\n");
+
+  int ret;
+  int failed = pthread_mutex_lock(&session->write_mutex);
+  assert(!failed);
+  pthread_cleanup_push(&ssh_cleanup_lock,
+		       (void *) &session->write_mutex);
+  buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_PK_OK);
+  
+  STRING *type = string_from_char(type_c);
+  buffer_add_ssh_string(session->out_buffer, type);
+  free(type);
+  STRING *publickey = string_from_char(msg->auth_request.password);
+  buffer_add_ssh_string(session->out_buffer, publickey);
+  free(publickey);
+  
+  ret = packet_send(session);
+  pthread_cleanup_pop(0);
+  failed = pthread_mutex_unlock(&session->write_mutex);
+  assert(!failed);
+  leave_function();
+  return ret;
 }
 
 static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session){
@@ -197,6 +462,15 @@
     return msg;
 }
 
+/**
+   Returns 1 if the signature validates, 0 if the signature is invalid,
+   the algorithm is unknown, or msg is not phase PHASE_PUBLICKEY_SIGNATURE,
+   type SSH_AUTH_PUBLICKEY, subtype SSH_AUTH_PUBLICKEY.
+ */
+int ssh_message_auth_validated(SSH_MESSAGE *msg) {
+  return msg->auth_request.validated;
+}
+
 CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg){
 	SSH_SESSION *session=msg->session;
 	enter_function();
@@ -208,13 +482,22 @@
     chan->remote_maxpacket=msg->channel_request_open.packet_size;
     chan->remote_window=msg->channel_request_open.window;
     chan->open=1;
+    int r;
+    int failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
     buffer_add_u32(session->out_buffer,htonl(chan->remote_channel));
     buffer_add_u32(session->out_buffer,htonl(chan->local_channel));
     buffer_add_u32(session->out_buffer,htonl(chan->local_window));
     buffer_add_u32(session->out_buffer,htonl(chan->local_maxpacket));
     ssh_say(2,"Accepting a channel request_open for chan %d\n",chan->remote_channel);
-    if(packet_send(session)){
+    r=packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
+    if(r){
         channel_free(chan);
         leave_function();
         return NULL;
@@ -225,12 +508,20 @@
 
 static int ssh_message_channel_request_open_reply_default(SSH_MESSAGE *msg){
     ssh_say(2,"Refusing a channel\n");
+    int r;
+    int failed = pthread_mutex_lock(&msg->session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &msg->session->write_mutex);
     buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_OPEN_FAILURE);
     buffer_add_u32(msg->session->out_buffer,htonl(msg->channel_request_open.sender));
     buffer_add_u32(msg->session->out_buffer,htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED));
     buffer_add_u32(msg->session->out_buffer,0); // reason is an empty string
     buffer_add_u32(msg->session->out_buffer,0); // language too
-    return packet_send(msg->session);
+    r=packet_send(msg->session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&msg->session->write_mutex);
+    assert(!failed);
 }
 
 static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){
@@ -315,9 +606,18 @@
     if(msg->channel_request.want_reply){
         channel=msg->channel_request.channel->remote_channel;
         ssh_say(2,"Sending a channel_request success to channel %d\n",channel);
+	int r;
+	int failed = pthread_mutex_lock(&msg->session->write_mutex);
+	assert(!failed);
+	pthread_cleanup_push(&ssh_cleanup_lock,
+			     (void *) &msg->session->write_mutex);
         buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_SUCCESS);
         buffer_add_u32(msg->session->out_buffer,htonl(channel));
-        return packet_send(msg->session);
+        r=packet_send(msg->session);
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&msg->session->write_mutex);
+	assert(!failed);
+	return r;
     } else {
         ssh_say(2,"The client doesn't want to know the request successed\n");
         return 0;
@@ -329,9 +629,18 @@
     if(msg->channel_request.want_reply){
         channel=msg->channel_request.channel->remote_channel;
         ssh_say(2,"Sending a default channel_request denied to channel %d\n",channel);
+	int r;
+	int failed = pthread_mutex_lock(&msg->session->write_mutex);
+	assert(!failed);
+	pthread_cleanup_push(&ssh_cleanup_lock,
+			     (void *) &msg->session->write_mutex);
         buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_FAILURE);
         buffer_add_u32(msg->session->out_buffer,htonl(channel));
-        return packet_send(msg->session);
+        r=packet_send(msg->session);
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&msg->session->write_mutex);
+	assert(!failed);
+	return r;
     } else {
         ssh_say(2,"The client doesn't want to know the request failed ! \n");
         return 0;
@@ -341,16 +650,21 @@
 SSH_MESSAGE *ssh_message_get(SSH_SESSION *session){
 	SSH_MESSAGE *ret;
 	enter_function();
+	
+	int failed = pthread_mutex_lock(&session->packet_mutex);
+	assert(!failed);
+	pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
     while(1){
-        if(packet_read(session) || packet_translate(session)){
-        	leave_function();
-        	return NULL;
+      if(packet_read(session) || packet_translate(session)){
+        	ret = NULL;
+		goto exit;
         }
+
         switch(session->in_packet.type){
             case SSH2_MSG_SERVICE_REQUEST:
                 if(handle_service_request(session)){
-                	leave_function();
-                	return NULL;
+                	ret = NULL;
+			goto exit;
                 }
                 break;
             case SSH2_MSG_IGNORE:
@@ -358,25 +672,30 @@
                 break;
             case SSH2_MSG_USERAUTH_REQUEST:
                 ret = handle_userauth_request(session);
-                leave_function();
-                return ret;
+		goto exit;
             case SSH2_MSG_CHANNEL_OPEN:
                 ret = handle_channel_request_open(session);
-                leave_function();
-                return ret;
+		goto exit;
             case SSH2_MSG_CHANNEL_REQUEST:
                 ret = handle_channel_request(session);
-                leave_function();
-                return ret;
+		goto exit;
             default:
                 handle_unimplemented(session);
                 ssh_set_error(session,SSH_FATAL,"Unhandled message %d\n",session->in_packet.type);
-                leave_function();
-                return NULL;
+		ret = NULL;
+		goto exit;
         }
     }
+
+ exit:
+
+    ;
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+
     leave_function();
-    return NULL;
+    return ret;
 }
 
 int ssh_message_type(SSH_MESSAGE *msg){
@@ -419,8 +738,11 @@
         case SSH_AUTH_REQUEST:
             if(msg->auth_request.username)
                 free(msg->auth_request.username);
+            if(msg->auth_request.signature)
+                free(msg->auth_request.signature);
             if(msg->auth_request.password){
-                memset(msg->auth_request.password,0,strlen(msg->auth_request.password));
+                memset(msg->auth_request.password,0,
+		       strlen(msg->auth_request.password));
                 free(msg->auth_request.password);
             }
             break;
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/misc.c libssh-wfs/libssh/misc.c
--- libssh-trunk/libssh/misc.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/misc.c	2009-07-07 22:35:57.000000000 -0400
@@ -37,18 +37,24 @@
 #endif
 
 #include "libssh/libssh.h"
+#include "libssh/priv.h"
 
 #ifndef _WIN32
 char *ssh_get_user_home_dir(){
     static char szPath[PATH_MAX] = {0};
-    struct passwd *pwd = NULL;
+    struct passwd pwd;
+    struct passwd *res = NULL;
+    int err;
+    int buflen = (long) sysconf(_SC_GETPW_R_SIZE_MAX);
+    char buf[buflen];
 
-    pwd = getpwuid(getuid());
-    if (pwd == NULL) {
+
+    err = getpwuid_r(getuid(), &pwd, buf, buflen, &res);
+    if (err != 0 || res == NULL) {
       return NULL;
     }
 
-    snprintf(szPath, PATH_MAX - 1, "%s", pwd->pw_dir);
+    snprintf(szPath, PATH_MAX - 1, "%s", pwd.pw_dir);
 
     return szPath;
 }
@@ -84,3 +90,26 @@
     return (( ((u64)low) << 32) | ( high));
 #endif
 }
+
+void ssh_cleanup_lock(void *arg) {
+  pthread_mutex_t *l = (pthread_mutex_t *) arg;
+  pthread_mutex_unlock(l);
+}
+
+ssh_mem_list *new_ssh_mem_list() {
+  ssh_mem_list *ml = 
+    (ssh_mem_list *) malloc(sizeof(ssh_mem_list));
+  ml->ptr = NULL;
+  ml->next = NULL;
+  return ml;
+}
+
+void ssh_cleanup_mem(void *arg) {
+  ssh_mem_list *ml = (ssh_mem_list *) arg;
+  while( ml != NULL ) {
+    free(ml->ptr);
+    ssh_mem_list *next = ml->next;
+    free(ml);
+    ml = next;
+  }
+}
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/options.c libssh-wfs/libssh/options.c
--- libssh-trunk/libssh/options.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/options.c	2009-07-07 22:35:58.000000000 -0400
@@ -296,16 +296,20 @@
 
 #ifndef _WIN32
 static char *get_username_from_uid(SSH_OPTIONS *opt, uid_t uid){
-    struct passwd *pwd = NULL;
+    struct passwd pwd;
+    struct passwd *res = NULL;
+    int err;
+    int buflen = (long) sysconf(_SC_GETPW_R_SIZE_MAX);
+    char buf[buflen];
 
-    pwd = getpwuid(uid);
+    err = getpwuid_r(uid, &pwd, buf, buflen, &res);
 
-    if (pwd == NULL) {
+    if (err != 0 || res == NULL) {
       ssh_set_error(opt,SSH_FATAL,"uid %d doesn't exist !",uid);
       return NULL;
     }
 
-    return strdup(pwd->pw_name);
+    return strdup(pwd.pw_name);
 }
 #endif
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/packet.c libssh-wfs/libssh/packet.c
--- libssh-trunk/libssh/packet.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/packet.c	2009-07-29 15:04:18.000000000 -0400
@@ -70,7 +70,11 @@
             }
 //    be_read=completeread(session->fd,buffer,blocksize);
             // can't fail since we're sure there is enough data in socket buffer
-            ssh_socket_read(session->socket,buffer,blocksize);
+            ret=ssh_socket_read(session->socket,buffer,blocksize);
+            if(ret != SSH_OK){
+                leave_function();
+            	return ret;
+            }
             len=packet_decrypt_len(session,buffer);
             buffer_add_data(session->in_buffer,buffer,blocksize);
             if(len> MAX_PACKET_LEN){
@@ -96,10 +100,14 @@
                 ret=ssh_socket_wait_for_data(session->socket,session,to_be_read);
                 if(ret!=SSH_OK){
                     leave_function();
-                	return ret;
+		    return ret;
                 }
                 packet=malloc(to_be_read);
-                ssh_socket_read(session->socket,packet,to_be_read-current_macsize);
+                ret=ssh_socket_read(session->socket,packet,to_be_read-current_macsize);
+                if(ret!=SSH_OK){
+                    leave_function();
+		    return ret;
+                }
                 ssh_log(session,SSH_LOG_PACKET,"Read a %d bytes packet",len);
                 buffer_add_data(session->in_buffer,packet,to_be_read-current_macsize);
                 free(packet);
@@ -108,7 +116,11 @@
                 /* decrypt the rest of the packet (blocksize bytes already have been decrypted */
                 packet_decrypt(session,buffer_get(session->in_buffer)+blocksize,
                                buffer_get_len(session->in_buffer)-blocksize);
-                ssh_socket_read(session->socket,mac,macsize);
+                ret=ssh_socket_read(session->socket,mac,macsize);
+                if(ret!=SSH_OK){
+                    leave_function();
+		    return ret;
+                }
                 if(packet_hmac_verify(session,session->in_buffer,mac)){
                     ssh_set_error(session,SSH_FATAL,"HMAC error");
                     leave_function();
@@ -400,12 +412,14 @@
 #endif /* HAVE_SSH1 */
 
 int packet_send(SSH_SESSION *session){
+  int ret;
 #ifdef HAVE_SSH1
     if (session->version==1)
-        return packet_send1(session);
+        ret = packet_send1(session);
     else 
 #endif
-        return packet_send2(session);
+        ret = packet_send2(session);
+    return ret;
 }
 
 void packet_parse(SSH_SESSION *session){
@@ -523,7 +537,7 @@
         ret=packet_read2(session);
         if(ret != SSH_OK){
             leave_function();
-        	return ret;
+	    return ret;
         }
         if(packet_translate(session)){
             leave_function();
@@ -548,15 +562,15 @@
            default:
                if(type && (type != session->in_packet.type)){
                    ssh_set_error(session,SSH_FATAL,"waitpacket(): Received a %d type packet, was waiting for a %d\n",session->in_packet.type,type);
-                   leave_function();
+		   leave_function();
                    return SSH_ERROR;
                }
                leave_function();
-               return SSH_OK;
+	       return SSH_OK;
            }
         if(blocking==0){
             leave_function();
-        	return SSH_OK; //shouldn't it return SSH_AGAIN here ?
+	    return SSH_OK; //shouldn't it return SSH_AGAIN here ?
         }
     }
     leave_function();
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/server.c libssh-wfs/libssh/server.c
--- libssh-trunk/libssh/server.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/server.c	2009-07-14 19:23:51.000000000 -0400
@@ -221,7 +221,15 @@
     PUBLIC_KEY *pub;
     PRIVATE_KEY *prv;
     BUFFER *buf=buffer_new();
-    if(packet_wait(session, SSH2_MSG_KEXDH_INIT ,1))
+    int failed = pthread_mutex_lock(&session->packet_mutex);
+    assert(!failed);
+    int res;
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    res = packet_wait(session, SSH2_MSG_KEXDH_INIT ,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
+    if(res)
         return -1;
     e=buffer_get_ssh_string(session->in_buffer);
     if(!e){
@@ -241,7 +249,7 @@
             prv=session->rsa_key;
             break;
         default:
-            prv=NULL;
+	    prv=NULL;
     }
     pub=publickey_from_privatekey(prv);
     pubkey=publickey_to_string(pub);
@@ -249,7 +257,11 @@
     dh_import_pubkey(session,pubkey);
     dh_build_k(session);
     make_sessionid(session);
-    sign=ssh_sign_session_id(session,prv);
+    if(prv != NULL){
+      sign=ssh_sign_session_id(session,prv);
+    } else {
+      sign=NULL;
+    }
     buffer_free(buf);
     /* free private keys as they should not be readable past this point */
     if(session->rsa_key){
@@ -260,18 +272,34 @@
         private_key_free(session->dsa_key);
         session->dsa_key=NULL;
     }
+    if(sign == NULL) {
+      free(f);
+      return -1;
+    }
+    failed = pthread_mutex_lock(&session->write_mutex);
+    assert(!failed);
+    pthread_cleanup_push(&ssh_cleanup_lock,
+			 (void *) &session->write_mutex);
     buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_REPLY);
     buffer_add_ssh_string(session->out_buffer,pubkey);
     buffer_add_ssh_string(session->out_buffer,f);
     buffer_add_ssh_string(session->out_buffer,sign);
     free(sign);
-    packet_send(session);
+    packet_send(session); 
     free(f);
     buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
     packet_send(session);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->write_mutex);
+    assert(!failed);
     ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
-
+    failed = pthread_mutex_lock(&session->packet_mutex);
+    pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
+    assert(!failed);
     packet_wait(session,SSH2_MSG_NEWKEYS,1);
+    pthread_cleanup_pop(0);
+    failed = pthread_mutex_unlock(&session->packet_mutex);
+    assert(!failed);
     ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
     generate_session_keys(session);
     /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
@@ -301,3 +329,24 @@
 }
 /** @}
  */
+
+void ssh_send_issue_banner(SSH_SESSION *session, const char *banner) {
+  STRING *banner_s, *lang_s;
+  enter_function();
+  int failed = pthread_mutex_lock(&session->write_mutex);
+  assert(!failed);
+  pthread_cleanup_push(&ssh_cleanup_lock,
+		       (void *) &session->write_mutex);
+  buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_BANNER);
+  banner_s = string_from_char(banner);
+  buffer_add_ssh_string(session->out_buffer,banner_s);
+  string_free(banner_s);
+  lang_s = string_from_char("en");
+  buffer_add_ssh_string(session->out_buffer,lang_s);
+  string_free(lang_s);
+  packet_send(session);
+  pthread_cleanup_pop(0);
+  failed = pthread_mutex_unlock(&session->write_mutex);
+  assert(!failed);
+  leave_function();
+}
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/session.c libssh-wfs/libssh/session.c
--- libssh-trunk/libssh/session.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/session.c	2009-07-07 22:35:58.000000000 -0400
@@ -48,6 +48,16 @@
     session->log_indent=0;
     session->out_buffer=buffer_new();
     session->in_buffer=buffer_new();
+    int failed = pthread_mutex_init(&session->packet_mutex,NULL);
+    assert (!failed);
+    failed = pthread_mutex_init(&session->crypt_mutex,NULL);
+    assert (!failed);
+    failed = pthread_mutex_init(&session->write_mutex,NULL);
+    assert (!failed);
+    failed = pthread_mutex_init(&session->signal_mutex,NULL);
+    assert (!failed);
+    failed = pthread_cond_init(&session->signal_cond,NULL);
+    assert (!failed);
     return session;
 }
 
@@ -62,6 +72,10 @@
         buffer_free(session->in_buffer);
     if(session->out_buffer)
         buffer_free(session->out_buffer);
+    if(session->in_hashbuf)
+        buffer_free(session->in_hashbuf);
+    if(session->out_hashbuf)
+        buffer_free(session->out_hashbuf);
     if(session->banner)
         free(session->banner);
     if(session->options)
@@ -72,6 +86,8 @@
         crypto_free(session->next_crypto);
     if(session->socket)
     	ssh_socket_free(session->socket);
+    if(session->dh_server_signature)
+    	free(session->dh_server_signature);
     // delete all channels
     while(session->channels)
         channel_free(session->channels);
@@ -93,6 +109,16 @@
         ssh_message_free(session->ssh_message);
         free(session->ssh_message);
     }
+    int failed = pthread_mutex_destroy(&session->packet_mutex);
+    assert (!failed);
+    failed = pthread_mutex_destroy(&session->signal_mutex);
+    assert (!failed);
+    failed = pthread_mutex_destroy(&session->crypt_mutex);
+    assert (!failed);
+    failed = pthread_mutex_destroy(&session->write_mutex);
+    assert (!failed);
+    failed = pthread_cond_destroy(&session->signal_cond);
+    assert (!failed);
     memset(session,'X',sizeof(SSH_SESSION)); /* burn connection, it could hangs
                                                 sensitive datas */
     free(session);
@@ -177,13 +203,20 @@
             return r; // error or no data available
         }
         /* if an exception happened, it will be trapped by packet_read() */
+	int failed = pthread_mutex_lock(&session->packet_mutex);
+	assert(!failed);
+	pthread_cleanup_push(&ssh_cleanup_lock, (void *) &session->packet_mutex);
         if(packet_read(session)||packet_translate(session)){
-            leave_function();
-        	return -1;
+	  r=-1;
+	  goto exit;
         }
         packet_parse(session);
+	pthread_cleanup_pop(0);
+	failed = pthread_mutex_unlock(&session->packet_mutex);
+	assert(!failed);
         ++i;
     } while(r>0);
+ exit:
     leave_function();
     return r;
 }
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/sftp.c libssh-wfs/libssh/sftp.c
--- libssh-trunk/libssh/sftp.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/sftp.c	2009-07-07 22:35:58.000000000 -0400
@@ -44,7 +44,9 @@
     memset(sftp,0,sizeof(SFTP_SESSION));
     sftp->session=session;
     sftp->channel=channel_new(session);
-    if(channel_open_session(sftp->channel)){
+    ssh_cleanup_frame *frames[4];
+    bzero( frames, 4*sizeof(ssh_cleanup_frame *) );
+    if(channel_open_session(sftp->channel, frames)){
         channel_free(sftp->channel);
         free(sftp);
         leave_function();
@@ -142,7 +144,7 @@
     sftp_enter_function();
     packet->sftp=sftp;
     packet->payload=buffer_new();
-    if(channel_read(sftp->channel,packet->payload,4,0)<=0){
+    if(channel_read_nf(sftp->channel,packet->payload,4,0)<=0){
         buffer_free(packet->payload);
         free(packet);
         sftp_leave_function();
@@ -150,7 +152,7 @@
     }
     buffer_get_u32(packet->payload,&size);
     size=ntohl(size);
-    if(channel_read(sftp->channel,packet->payload,1,0)<=0){
+    if(channel_read_nf(sftp->channel,packet->payload,1,0)<=0){
         buffer_free(packet->payload);
         free(packet);
         sftp_leave_function();
@@ -158,7 +160,7 @@
     }
     buffer_get_u8(packet->payload,&packet->type);
     if(size>1)
-        if(channel_read(sftp->channel,packet->payload,size-1,0)<=0){
+        if(channel_read_nf(sftp->channel,packet->payload,size-1,0)<=0){
             buffer_free(packet->payload);
             free(packet);
             sftp_leave_function();
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/socket.c libssh-wfs/libssh/socket.c
--- libssh-trunk/libssh/socket.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/socket.c	2009-07-29 15:04:18.000000000 -0400
@@ -261,6 +261,7 @@
 		leave_function();
 		return ret;
 	}
+	if( buffer_get_rest(s->in_buffer) ) ;
 	memcpy(buffer,buffer_get_rest(s->in_buffer),len);
 	buffer_pass_bytes(s->in_buffer,len);
 	leave_function();
@@ -310,8 +311,10 @@
     }
     if(session->blocking){
         buf=malloc(to_read);
+	pthread_cleanup_push( &free, buf );
         r=ssh_socket_completeread(session->socket,buf,to_read);
-        if(r==SSH_ERROR || r ==0){
+	pthread_cleanup_pop(0);
+        if(r==SSH_ERROR || r < to_read){
             ssh_set_error(session,SSH_FATAL,
                 (r==0)?"Connection closed by remote host" : "Error reading socket");
             ssh_socket_close(session->socket);
@@ -433,6 +436,7 @@
     }
     fd->fd=s->fd;
     fd->events=0;
+    fd->revents=0;
     if(!s->data_to_read)
         fd->events |= POLLIN;
     if(!s->data_to_write)
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/string.c libssh-wfs/libssh/string.c
--- libssh-trunk/libssh/string.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/string.c	2009-07-09 21:09:40.000000000 -0400
@@ -79,6 +79,9 @@
     char *string=malloc(len);
     memcpy(string,str->string,len-1);
     string[len-1]=0;
+    if (strlen(string) != (len-1)) {
+      ssh_say(1, "warning: string_to_char STRING contains \\0!\n");
+    }
     return string;
 }
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/libssh/wrapper.c libssh-wfs/libssh/wrapper.c
--- libssh-trunk/libssh/wrapper.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/libssh/wrapper.c	2009-07-07 22:35:58.000000000 -0400
@@ -578,6 +578,12 @@
     server=session->server_kex.methods[SSH_HOSTKEYS];
     client=session->client_kex.methods[SSH_HOSTKEYS];
     match=ssh_find_matching(client,server);
+    if(!match) {
+        ssh_set_error(session,SSH_FATAL,"bad match in %s",server);
+        free(match);
+        leave_function();
+        return SSH_ERROR;
+    }
     if(!strcmp(match,"ssh-dss"))
         session->hostkeys=TYPE_DSS;
     else if(!strcmp(match,"ssh-rsa"))
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/Makefile.am libssh-wfs/Makefile.am
--- libssh-trunk/Makefile.am	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/Makefile.am	2009-07-09 21:09:39.000000000 -0400
@@ -2,7 +2,7 @@
 
 AM_CPPFLAGS = -I$(srcdir)/include
 
-LDADD = $(top_builddir)/libssh/libssh.la
+LDADD = $(top_builddir)/libssh/libssh.la -lrt
 
 noinst_PROGRAMS = samplesshd samplessh 
 
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/README.wfs libssh-wfs/README.wfs
--- libssh-trunk/README.wfs	1969-12-31 19:00:00.000000000 -0500
+++ libssh-wfs/README.wfs	2009-07-29 15:50:34.000000000 -0400
@@ -0,0 +1,12 @@
+This is a modified version of libssh, available at
+http://0xbadc0de.be/wiki/libssh:libssh, with some additons related to
+public-key authentication on the server.  Hopefully, those
+modifications will be merged upstream, but for now, you need to compile
+and install this seperately to use WheelFS with secure connections.
+
+This is based on libssh subversion revision number 198.
+
+diff -Naur --exclude "autom4te*" --exclude aclocal.m4 --exclude debian --exclude "config*" --exclude ".*" --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude "Doxyfile*" --exclude Makefile.Windows libssh-trunk libssh-wfs > /tmp/libssh-wfs.patch
+
+~Xavid and Jeremy
+
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/sample.c libssh-wfs/sample.c
--- libssh-trunk/sample.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/sample.c	2009-07-07 22:35:57.000000000 -0400
@@ -174,7 +174,7 @@
         }
         if(channels[0]){
             while(channel && channel_is_open(channel) && channel_poll(channel,0)){
-                lus=channel_read(channel,readbuf,0,0);
+                lus=channel_read_nf(channel,readbuf,0,0);
                 if(lus==-1){
                     ssh_say(0,"error reading channel : %s\n",ssh_get_error(session));
                     return;
@@ -187,7 +187,7 @@
                     write(1,buffer_get(readbuf),lus);
             }
             while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
-                lus=channel_read(channel,readbuf,0,1);
+                lus=channel_read_nf(channel,readbuf,0,1);
                 if(lus==-1){
                     ssh_say(0,"error reading channel : %s\n",ssh_get_error(session));
                     return;
@@ -218,7 +218,9 @@
         tcgetattr(0,&terminal_local);
         memcpy(&terminal,&terminal_local,sizeof(struct termios));
     }
-    if(channel_open_session(channel)){
+    ssh_cleanup_frame *frames[4];
+    bzero( frames, 4*sizeof(ssh_cleanup_frame *) );
+    if(channel_open_session(channel, frames)){
         printf("error opening channel : %s\n",ssh_get_error(session));
         return;
     }
@@ -247,7 +249,9 @@
     for(i=0;i<MAXCMD && cmds[i];++i)
         s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
     channel=channel_new(session);
-    channel_open_session(channel);
+    ssh_cleanup_frame *frames[4];
+    bzero( frames, 4*sizeof(ssh_cleanup_frame *) );
+    channel_open_session(channel, frames);
     if(channel_request_exec(channel,buffer)){
         printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
         return;
@@ -390,7 +394,9 @@
     ssh_options_set_host(options,host);
     session=ssh_new();
     ssh_set_options(session,options);
-    if(ssh_connect(session)){
+    ssh_cleanup_frame *frames[4];
+    bzero( frames, 4*sizeof(ssh_cleanup_frame *) );
+    if(ssh_connect(session, frames)){
         fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
         ssh_disconnect(session);
 	    ssh_finalize();
@@ -454,7 +460,7 @@
     printf("\n");
 
     /* no ? you should :) */
-    auth=ssh_userauth_autopubkey(session, NULL);
+    auth=ssh_userauth_autopubkey(session, NULL, frames);
     if(auth==SSH_AUTH_ERROR){
         fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session));
 	    ssh_finalize();
diff -Naur --exclude 'autom4te*' --exclude aclocal.m4 --exclude debian --exclude 'config*' --exclude '.*' --exclude CVS --exclude stamp-h1 --exclude Makefile --exclude Makefile.in --exclude libtool --exclude lib.bat --exclude 'Doxyfile*' --exclude Makefile.Windows libssh-trunk/samplesshd.c libssh-wfs/samplesshd.c
--- libssh-trunk/samplesshd.c	2009-07-18 11:02:26.000000000 -0400
+++ libssh-wfs/samplesshd.c	2009-07-07 22:35:57.000000000 -0400
@@ -144,7 +144,7 @@
     printf("it works !\n");
     BUFFER *buf=buffer_new();
     do{
-        i=channel_read(chan,buf,0,0);
+        i=channel_read_nf(chan,buf,0,0);
         if(i>0)
             write(1,buffer_get(buf),buffer_get_len(buf));
     } while (i>0);
