Browse Source

Updating code to PuTTY 344ec3ae

Including part of 2e7ced64 (Give BPPs a Frontend, so they can do their own logging) - as it's useful for our thread-safe implementation of pktin_free_queue_callback

Source commit: f80dbdfd2041e079359ca77b1872e2d39eb47faf
Martin Prikryl 6 years ago
parent
commit
26237b4a04

+ 1 - 1
source/Putty.cbproj

@@ -57,7 +57,7 @@
 		<BCC_wsus>false</BCC_wsus>
 		<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
 		<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;$(DCC_Namespace)</DCC_Namespace>
-		<Defines>SECURITY_WIN32;MPEXT;_WINDOWS;$(Defines)</Defines>
+		<Defines>SECURITY_WIN32;WINSCP;MPEXT;_WINDOWS;$(Defines)</Defines>
 		<FinalOutputDir>$(INTERM_PATH)\$(Platform)\$(Config)</FinalOutputDir>
 		<IncludePath>putty\;putty\windows\;$(BDS)\include;$(IncludePath)</IncludePath>
 		<IntermediateOutputDir>$(INTERM_PATH)\$(Platform)\$(Config)</IntermediateOutputDir>

+ 6 - 1
source/core/PuttyIntf.cpp

@@ -106,6 +106,11 @@ struct callback_set * get_callback_set(Plug plug)
   return SecureShell->GetCallbackSet();
 }
 //---------------------------------------------------------------------------
+struct callback_set * get_frontend_callback_set(Frontend * frontend)
+{
+  return reinterpret_cast<TSecureShell *>(frontend)->GetCallbackSet();
+}
+//---------------------------------------------------------------------------
 extern "C" char * do_select(Plug plug, SOCKET skt, int startup)
 {
   bool pfwd;
@@ -280,7 +285,7 @@ void old_keyfile_warning(void)
   // no reference to TSecureShell instance available
 }
 //---------------------------------------------------------------------------
-void display_banner(void * frontend, const char * banner, int size)
+void display_banner(Frontend * frontend, const char * banner, int size)
 {
   DebugAssert(frontend);
   UnicodeString Banner(UTF8String(banner, size));

+ 4 - 0
source/core/SecureShell.cpp

@@ -63,6 +63,10 @@ __fastcall TSecureShell::~TSecureShell()
   Active = false;
   ResetConnection();
   CloseHandle(FSocketEvent);
+  sfree(FCallbackSet->ic_pktin_free);
+  pktin_free_queue_callback(FCallbackSet.get());
+  DebugAssert(FCallbackSet->pktin_freeq_head->next == FCallbackSet->pktin_freeq_head);
+  sfree(FCallbackSet->pktin_freeq_head);
 }
 //---------------------------------------------------------------------------
 void __fastcall TSecureShell::ResetConnection()

+ 7 - 7
source/putty/callback.c

@@ -4,6 +4,7 @@
  */
 
 #include <stddef.h>
+#include <assert.h> // WINSCP
 
 #include "putty.h"
 
@@ -19,12 +20,10 @@ struct callback {
 // It would call callbacks registered any on thread from the thread that happens to call it.
 // We need to create separate callback queue for every SSH session.
 #define CALLBACK_SET_VAR callback_set_v
-#define CALLBACK_SET_VAR_PARAM CALLBACK_SET_VAR,
 #define cbcurr CALLBACK_SET_VAR->cbcurr
 #define cbhead CALLBACK_SET_VAR->cbhead
 #define cbtail CALLBACK_SET_VAR->cbtail
 #else
-#define CALLBACK_SET_VAR_PARAM
 struct callback *cbcurr = NULL, *cbhead = NULL, *cbtail = NULL;
 #endif
 
@@ -47,16 +46,18 @@ static void run_idempotent_callback(void *ctx)
     ic->fn(ic->ctx);
 }
 
-void queue_idempotent_callback(CALLBACK_SET struct IdempotentCallback *ic)
+void queue_idempotent_callback(struct IdempotentCallback *ic)
 {
     if (ic->queued)
         return;
     ic->queued = TRUE;
-    queue_toplevel_callback(CALLBACK_SET_VAR_PARAM run_idempotent_callback, ic);
+#ifdef MPEXT
+    assert(ic->set != NULL);
+#endif
+    queue_toplevel_callback(ic->set, run_idempotent_callback, ic);
 }
 
-#ifndef MPEXT
-void delete_callbacks_for_context(void *ctx)
+void delete_callbacks_for_context(CALLBACK_SET void *ctx)
 {
     struct callback *newhead, *newtail;
 
@@ -81,7 +82,6 @@ void delete_callbacks_for_context(void *ctx)
     cbhead = newhead;
     cbtail = newtail;
 }
-#endif
 
 void queue_toplevel_callback(CALLBACK_SET toplevel_callback_fn_t fn, void *ctx)
 {

+ 10 - 5
source/putty/putty.h

@@ -1407,7 +1407,7 @@ int askappend(Frontend *frontend, Filename *filename,
 	      void (*callback)(void *ctx, int result), void *ctx);
 
 #ifdef MPEXT
-void display_banner(void *frontend, const char* banner, int size);
+void display_banner(Frontend *frontend, const char* banner, int size);
 #endif
 /*
  * Exports from console frontends (wincons.c, uxcons.c)
@@ -1652,8 +1652,12 @@ unsigned long timing_last_clock(void);
 typedef void (*toplevel_callback_fn_t)(void *ctx);
 #ifdef MPEXT
 typedef struct callback callback;
+struct IdempotentCallback;
+typedef struct PacketQueueNode PacketQueueNode;
 struct callback_set {
     struct callback *cbcurr, *cbhead, *cbtail;
+    IdempotentCallback * ic_pktin_free;
+    PacketQueueNode * pktin_freeq_head;
 };
 #define CALLBACK_SET_ONLY struct callback_set * callback_set_v
 #define CALLBACK_SET CALLBACK_SET_ONLY,
@@ -1665,9 +1669,8 @@ void queue_toplevel_callback(CALLBACK_SET toplevel_callback_fn_t fn, void *ctx);
 int run_toplevel_callbacks(CALLBACK_SET_ONLY);
 int toplevel_callback_pending(CALLBACK_SET_ONLY);
 struct callback_set * get_callback_set(Plug plug);
-#ifndef MPEXT
-void delete_callbacks_for_context(void *ctx);
-#endif
+struct callback_set * get_frontend_callback_set(Frontend * frontend);
+void delete_callbacks_for_context(CALLBACK_SET void *ctx);
 
 /*
  * Another facility in callback.c deals with 'idempotent' callbacks,
@@ -1682,8 +1685,9 @@ struct IdempotentCallback {
     toplevel_callback_fn_t fn;
     void *ctx;
     int queued;
+    struct callback_set * set;
 };
-void queue_idempotent_callback(CALLBACK_SET struct IdempotentCallback *ic);
+void queue_idempotent_callback(struct IdempotentCallback *ic);
 
 #ifndef MPEXT
 typedef void (*toplevel_callback_notify_fn_t)(void *ctx);
@@ -1733,6 +1737,7 @@ void request_callback_notifications(toplevel_callback_notify_fn_t notify,
 extern CRITICAL_SECTION putty_section;
 void putty_initialize();
 void putty_finalize();
+void pktin_free_queue_callback(void *vctx);
 #define MPEXT_PUTTY_SECTION_ENTER EnterCriticalSection(&putty_section);
 #define MPEXT_PUTTY_SECTION_LEAVE LeaveCriticalSection(&putty_section);
 #else

+ 18 - 13
source/putty/ssh.c

@@ -28,10 +28,6 @@
 #define GSS_CTXT_MAYFAIL (1<<3)	/* Context may expire during handshake */
 #endif
 
-#ifdef MPEXT
-#define queue_idempotent_callback(IC) queue_idempotent_callback(get_callback_set(&ssh->plugvt), IC)
-#endif
-
 static const char *const ssh2_disconnect_reasons[] = {
     NULL,
     "host not allowed to connect",
@@ -3283,7 +3279,7 @@ static void ssh1_protocol_setup(Ssh ssh)
 {
     int i;
 
-    ssh->bpp = ssh1_bpp_new();
+    ssh->bpp = ssh1_bpp_new(ssh->frontend);
 
     /*
      * Most messages are handled by the main protocol routine.
@@ -8668,7 +8664,7 @@ static void ssh2_protocol_setup(Ssh ssh)
 {
     int i;
 
-    ssh->bpp = ssh2_bpp_new(&ssh->stats);
+    ssh->bpp = ssh2_bpp_new(ssh->frontend, &ssh->stats);
 
 #ifndef NO_GSSAPI
     /* Load and pick the highest GSS library on the preference list. */
@@ -8732,7 +8728,7 @@ static void ssh2_bare_connection_protocol_setup(Ssh ssh)
 {
     int i;
 
-    ssh->bpp = ssh2_bare_bpp_new();
+    ssh->bpp = ssh2_bare_bpp_new(ssh->frontend);
 
     /*
      * Everything defaults to ssh2_msg_unexpected for the moment;
@@ -9095,37 +9091,46 @@ static const char *ssh_init(Frontend *frontend, Backend **backend_handle,
     ssh->incoming_data_seen_eof = FALSE;
     ssh->incoming_data_eof_message = NULL;
     ssh->incoming_data_consumer.fn = ssh_process_incoming_data;
+    ssh->incoming_data_consumer.set = get_frontend_callback_set(frontend);
     ssh->incoming_data_consumer.ctx = ssh;
     ssh->incoming_data_consumer.queued = FALSE;
     ssh->incoming_pkt_consumer.fn = ssh_process_incoming_pkts;
+    ssh->incoming_pkt_consumer.set = get_frontend_callback_set(frontend);
     ssh->incoming_pkt_consumer.ctx = ssh;
     ssh->incoming_pkt_consumer.queued = FALSE;
-    pq_in_init(&ssh->pq_ssh1_login);
+    pq_in_init(&ssh->pq_ssh1_login, frontend);
     ssh->ssh1_login_icb.fn = do_ssh1_login;
+    ssh->ssh1_login_icb.set = get_frontend_callback_set(frontend);
     ssh->ssh1_login_icb.ctx = ssh;
     ssh->ssh1_login_icb.queued = FALSE;
-    pq_in_init(&ssh->pq_ssh1_connection);
+    pq_in_init(&ssh->pq_ssh1_connection, frontend);
     ssh->ssh1_connection_icb.fn = do_ssh1_connection;
+    ssh->ssh1_connection_icb.set = get_frontend_callback_set(frontend);
     ssh->ssh1_connection_icb.ctx = ssh;
     ssh->ssh1_connection_icb.queued = FALSE;
-    pq_in_init(&ssh->pq_ssh2_transport);
+    pq_in_init(&ssh->pq_ssh2_transport, frontend);
     ssh->ssh2_transport_icb.fn = do_ssh2_transport;
+    ssh->ssh2_transport_icb.set = get_frontend_callback_set(frontend);
     ssh->ssh2_transport_icb.ctx = ssh;
     ssh->ssh2_transport_icb.queued = FALSE;
-    pq_in_init(&ssh->pq_ssh2_userauth);
+    pq_in_init(&ssh->pq_ssh2_userauth, frontend);
     ssh->ssh2_userauth_icb.fn = do_ssh2_userauth;
+    ssh->ssh2_userauth_icb.set = get_frontend_callback_set(frontend);
     ssh->ssh2_userauth_icb.ctx = ssh;
     ssh->ssh2_userauth_icb.queued = FALSE;
-    pq_in_init(&ssh->pq_ssh2_connection);
+    pq_in_init(&ssh->pq_ssh2_connection, frontend);
     ssh->ssh2_connection_icb.fn = do_ssh2_connection;
+    ssh->ssh2_connection_icb.set = get_frontend_callback_set(frontend);
     ssh->ssh2_connection_icb.ctx = ssh;
     ssh->ssh2_connection_icb.queued = FALSE;
     bufchain_init(&ssh->user_input);
     ssh->user_input_consumer.fn = ssh_process_user_input;
+    ssh->user_input_consumer.set = get_frontend_callback_set(frontend);
     ssh->user_input_consumer.ctx = ssh;
     ssh->user_input_consumer.queued = FALSE;
     bufchain_init(&ssh->outgoing_data);
     ssh->outgoing_data_sender.fn = ssh_send_outgoing_data;
+    ssh->outgoing_data_sender.set = get_frontend_callback_set(frontend);
     ssh->outgoing_data_sender.ctx = ssh;
     ssh->outgoing_data_sender.queued = FALSE;
     ssh->current_user_input_fn = NULL;
@@ -9136,7 +9141,7 @@ static const char *ssh_init(Frontend *frontend, Backend **backend_handle,
     ssh->mainchan = NULL;
     ssh->throttled_all = 0;
     ssh->v1_stdout_throttling = 0;
-    pq_out_init(&ssh->outq);
+    pq_out_init(&ssh->outq, frontend);
     ssh->queueing = FALSE;
     ssh->qhead = ssh->qtail = NULL;
     ssh->deferred_rekey_reason = NULL;

+ 3 - 2
source/putty/ssh.h

@@ -89,6 +89,7 @@ typedef struct PktOut {
 typedef struct PacketQueueBase {
     PacketQueueNode end;
     struct IdempotentCallback *ic;
+    Frontend * frontend; // WINSCP
 } PacketQueueBase;
 
 typedef struct PktInQueue {
@@ -106,8 +107,8 @@ void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node);
 void pq_base_concatenate(PacketQueueBase *dest,
                          PacketQueueBase *q1, PacketQueueBase *q2);
 
-void pq_in_init(PktInQueue *pq);
-void pq_out_init(PktOutQueue *pq);
+void pq_in_init(PktInQueue *pq, Frontend * frontend); // WINSCP
+void pq_out_init(PktOutQueue *pq, Frontend * frontend); // WINSCP
 void pq_in_clear(PktInQueue *pq);
 void pq_out_clear(PktOutQueue *pq);
 

+ 2 - 1
source/putty/ssh1bpp.c

@@ -43,11 +43,12 @@ static const struct BinaryPacketProtocolVtable ssh1_bpp_vtable = {
     ssh1_bpp_queue_disconnect,
 };
 
-BinaryPacketProtocol *ssh1_bpp_new(void)
+BinaryPacketProtocol *ssh1_bpp_new(Frontend *frontend)
 {
     struct ssh1_bpp_state *s = snew(struct ssh1_bpp_state);
     memset(s, 0, sizeof(*s));
     s->bpp.vt = &ssh1_bpp_vtable;
+    s->bpp.frontend = frontend;
     ssh_bpp_common_setup(&s->bpp);
     return &s->bpp;
 }

+ 2 - 1
source/putty/ssh2bpp-bare.c

@@ -33,11 +33,12 @@ static const struct BinaryPacketProtocolVtable ssh2_bare_bpp_vtable = {
     ssh2_bpp_queue_disconnect, /* in sshcommon.c */
 };
 
-BinaryPacketProtocol *ssh2_bare_bpp_new(void)
+BinaryPacketProtocol *ssh2_bare_bpp_new(Frontend *frontend)
 {
     struct ssh2_bare_bpp_state *s = snew(struct ssh2_bare_bpp_state);
     memset(s, 0, sizeof(*s));
     s->bpp.vt = &ssh2_bare_bpp_vtable;
+    s->bpp.frontend = frontend;
     ssh_bpp_common_setup(&s->bpp);
     return &s->bpp;
 }

+ 3 - 1
source/putty/ssh2bpp.c

@@ -51,11 +51,13 @@ static const struct BinaryPacketProtocolVtable ssh2_bpp_vtable = {
     ssh2_bpp_queue_disconnect, /* in sshcommon.c */
 };
 
-BinaryPacketProtocol *ssh2_bpp_new(struct DataTransferStats *stats)
+BinaryPacketProtocol *ssh2_bpp_new(
+    Frontend *frontend, struct DataTransferStats *stats)
 {
     struct ssh2_bpp_state *s = snew(struct ssh2_bpp_state);
     memset(s, 0, sizeof(*s));
     s->bpp.vt = &ssh2_bpp_vtable;
+    s->bpp.frontend = frontend;
     s->stats = stats;
     ssh_bpp_common_setup(&s->bpp);
     return &s->bpp;

+ 5 - 3
source/putty/sshbpp.h

@@ -22,6 +22,7 @@ struct BinaryPacketProtocol {
     PacketLogSettings *pls;
     LogContext *logctx;
     Ssh ssh;
+    Frontend *frontend;
 
     /* ic_in_raw is filled in by the BPP (probably by calling
      * ssh_bpp_common_setup). The BPP's owner triggers it when data is
@@ -48,7 +49,7 @@ struct BinaryPacketProtocol {
  * does centralised parts of the freeing too. */
 void ssh_bpp_free(BinaryPacketProtocol *bpp);
 
-BinaryPacketProtocol *ssh1_bpp_new(void);
+BinaryPacketProtocol *ssh1_bpp_new(Frontend *frontend);
 void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
                          const struct ssh1_cipheralg *cipher,
                          const void *session_key);
@@ -92,7 +93,8 @@ struct DataTransferStats {
      ((stats)->direction.running = FALSE, TRUE) :       \
      ((stats)->direction.remaining -= (size), FALSE))
 
-BinaryPacketProtocol *ssh2_bpp_new(struct DataTransferStats *stats);
+BinaryPacketProtocol *ssh2_bpp_new(
+    Frontend *frontend, struct DataTransferStats *stats);
 void ssh2_bpp_new_outgoing_crypto(
     BinaryPacketProtocol *bpp,
     const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
@@ -104,7 +106,7 @@ void ssh2_bpp_new_incoming_crypto(
     const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
     const struct ssh_compression_alg *compression);
 
-BinaryPacketProtocol *ssh2_bare_bpp_new(void);
+BinaryPacketProtocol *ssh2_bare_bpp_new(Frontend *frontend);
 
 /*
  * The initial code to handle the SSH version exchange is also

+ 44 - 13
source/putty/sshcommon.c

@@ -50,25 +50,30 @@ void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node)
         queue_idempotent_callback(pqb->ic);
 }
 
+#ifndef WINSCP
 static PacketQueueNode pktin_freeq_head = {
     &pktin_freeq_head, &pktin_freeq_head, TRUE
 };
+#endif
 
-static void pktin_free_queue_callback(void *vctx)
+/*WINSCP static*/ void pktin_free_queue_callback(void *vctx)
 {
-    while (pktin_freeq_head.next != &pktin_freeq_head) {
-        PacketQueueNode *node = pktin_freeq_head.next;
+    struct callback_set * set = (struct callback_set *)vctx;
+    while (set->pktin_freeq_head->next != set->pktin_freeq_head) {
+        PacketQueueNode *node = set->pktin_freeq_head->next;
         PktIn *pktin = FROMFIELD(node, PktIn, qnode);
-        pktin_freeq_head.next = node->next;
+        set->pktin_freeq_head->next = node->next;
         sfree(pktin);
     }
 
-    pktin_freeq_head.prev = &pktin_freeq_head;
+    set->pktin_freeq_head->prev = set->pktin_freeq_head;
 }
 
+#ifndef WINSCP
 static IdempotentCallback ic_pktin_free = {
     pktin_free_queue_callback, NULL, FALSE
 };
+#endif
 
 static PktIn *pq_in_get(PacketQueueBase *pqb, int pop)
 {
@@ -77,15 +82,34 @@ static PktIn *pq_in_get(PacketQueueBase *pqb, int pop)
         return NULL;
 
     if (pop) {
+        #ifdef WINSCP
+        struct callback_set * set = get_frontend_callback_set(pqb->frontend);
+        assert(set != NULL);
+        if (set->ic_pktin_free == NULL)
+        {
+            set->pktin_freeq_head = snew(PacketQueueNode);
+            set->pktin_freeq_head->next = set->pktin_freeq_head;
+            set->pktin_freeq_head->prev = set->pktin_freeq_head;
+            set->pktin_freeq_head->on_free_queue = TRUE;
+
+            set->ic_pktin_free = snew(IdempotentCallback);
+            set->ic_pktin_free->fn = pktin_free_queue_callback;
+            set->ic_pktin_free->ctx = set;
+            set->ic_pktin_free->queued = FALSE;
+            set->ic_pktin_free->set = set;
+        }
+        #endif
+
         node->next->prev = node->prev;
         node->prev->next = node->next;
 
-        node->prev = pktin_freeq_head.prev;
-        node->next = &pktin_freeq_head;
+        node->prev = set->pktin_freeq_head->prev; // WINSCP
+        node->next = set->pktin_freeq_head; // WINSCP
         node->next->prev = node;
         node->prev->next = node;
         node->on_free_queue = TRUE;
-        queue_idempotent_callback(&ic_pktin_free);
+
+        queue_idempotent_callback(set->ic_pktin_free); // WINSCP
     }
 
     return FROMFIELD(node, PktIn, qnode);
@@ -106,16 +130,18 @@ static PktOut *pq_out_get(PacketQueueBase *pqb, int pop)
     return FROMFIELD(node, PktOut, qnode);
 }
 
-void pq_in_init(PktInQueue *pq)
+void pq_in_init(PktInQueue *pq, Frontend * frontend) // WINSCP
 {
     pq->pqb.ic = NULL;
+    pq->pqb.frontend = frontend;
     pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end;
     pq->get = pq_in_get;
 }
 
-void pq_out_init(PktOutQueue *pq)
+void pq_out_init(PktOutQueue *pq, Frontend * frontend) // WINSCP
 {
     pq->pqb.ic = NULL;
+    pq->pqb.frontend = frontend;
     pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end;
     pq->get = pq_out_get;
 }
@@ -649,18 +675,21 @@ static void ssh_bpp_output_packet_callback(void *context)
 
 void ssh_bpp_common_setup(BinaryPacketProtocol *bpp)
 {
-    pq_in_init(&bpp->in_pq);
-    pq_out_init(&bpp->out_pq);
+    pq_in_init(&bpp->in_pq, bpp->frontend); // WINSCP
+    pq_out_init(&bpp->out_pq, bpp->frontend); // WINSCP
+
     bpp->ic_in_raw.fn = ssh_bpp_input_raw_data_callback;
+    bpp->ic_in_raw.set = get_frontend_callback_set(bpp->frontend);
     bpp->ic_in_raw.ctx = bpp;
     bpp->ic_out_pq.fn = ssh_bpp_output_packet_callback;
+    bpp->ic_out_pq.set = get_frontend_callback_set(bpp->frontend);
     bpp->ic_out_pq.ctx = bpp;
     bpp->out_pq.pqb.ic = &bpp->ic_out_pq;
 }
 
 void ssh_bpp_free(BinaryPacketProtocol *bpp)
 {
-    delete_callbacks_for_context(bpp);
+    delete_callbacks_for_context(get_frontend_callback_set(bpp->frontend), bpp);
     bpp->vt->free(bpp);
 }
 
@@ -684,6 +713,7 @@ void ssh2_bpp_queue_disconnect(BinaryPacketProtocol *bpp,
 
 int ssh2_bpp_check_unimplemented(BinaryPacketProtocol *bpp, PktIn *pktin)
 {
+    #pragma warn -osh
     static const unsigned valid_bitmap[] = {
         SSH2_BITMAP_WORD(0),
         SSH2_BITMAP_WORD(1),
@@ -694,6 +724,7 @@ int ssh2_bpp_check_unimplemented(BinaryPacketProtocol *bpp, PktIn *pktin)
         SSH2_BITMAP_WORD(6),
         SSH2_BITMAP_WORD(7),
     };
+    #pragma warn +osh
 
     if (pktin->type < 0x100 &&
         !((valid_bitmap[pktin->type >> 5] >> (pktin->type & 0x1F)) & 1)) {

+ 1 - 0
source/putty/sshverstring.c

@@ -89,6 +89,7 @@ BinaryPacketProtocol *ssh_verstring_new(
 
     s->conf = conf_copy(conf);
     s->frontend = frontend;
+    s->bpp.frontend = frontend;
     s->our_protoversion = dupstr(protoversion);
     s->receiver = rcv;