From: Ted Zlatanov Date: Mon, 9 Apr 2012 12:46:16 +0000 (-0400) Subject: Limit number of GnuTLS handshakes per connection. X-Git-Tag: emacs-24.2.90~471^2~368^2~3 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a18ecafa99e7e7c3caa35ed68dd8a7b9b5d2b8e3;p=emacs.git Limit number of GnuTLS handshakes per connection. * gnutls.c (gnutls_log_function2i): Convenience log function. (emacs_gnutls_read): Use new log functions, `gnutls_handshakes_tried' process member, and `GNUTLS_EMACS_HANDSHAKES_LIMIT' to limit the number of handshake attempts per process (connection). * gnutls.h: Add `GNUTLS_EMACS_HANDSHAKES_LIMIT' upper limit. Add convenience `GNUTLS_LOG2i' macro. * process.c (make_process): * process.h: Add integer `gnutls_handshakes_tried' member to process struct. --- diff --git a/src/ChangeLog b/src/ChangeLog index 7c3dd115c5b..f7889d99335 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2012-04-09 Teodor Zlatanov + + * process.c (make_process): + * process.h: Add integer `gnutls_handshakes_tried' member to + process struct. + + * gnutls.h: Add `GNUTLS_EMACS_HANDSHAKES_LIMIT' upper limit. Add + convenience `GNUTLS_LOG2i' macro. + + * gnutls.c (gnutls_log_function2i): Convenience log function. + (emacs_gnutls_read): Use new log functions, + `gnutls_handshakes_tried' process member, and + `GNUTLS_EMACS_HANDSHAKES_LIMIT' to limit the number of handshake + attempts per process (connection). + 2012-04-09 Chong Yidong * eval.c (Fuser_variable_p, user_variable_p_eh) diff --git a/src/gnutls.c b/src/gnutls.c index 6b5cb47001b..70eea3b0b89 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -247,18 +247,27 @@ init_gnutls_functions (Lisp_Object libraries) #endif /* !WINDOWSNT */ +/* Function to log a simple message. */ static void gnutls_log_function (int level, const char* string) { message ("gnutls.c: [%d] %s", level, string); } +/* Function to log a message and a string. */ static void gnutls_log_function2 (int level, const char* string, const char* extra) { message ("gnutls.c: [%d] %s %s", level, string, extra); } +/* Function to log a message and an integer. */ +static void +gnutls_log_function2i (int level, const char* string, int extra) +{ + message ("gnutls.c: [%d] %s %d", level, string, extra); +} + static int emacs_gnutls_handshake (struct Lisp_Process *proc) { @@ -399,10 +408,25 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, EMACS_INT nbyte) ssize_t rtnval; gnutls_session_t state = proc->gnutls_state; + int log_level = proc->gnutls_log_level; + if (proc->gnutls_initstage != GNUTLS_STAGE_READY) { - emacs_gnutls_handshake (proc); - return -1; + /* If the handshake count is under the limit, try the handshake + again and increment the handshake count. This count is kept + per process (connection), not globally. */ + if (proc->gnutls_handshakes_tried < GNUTLS_EMACS_HANDSHAKES_LIMIT) + { + proc->gnutls_handshakes_tried++; + emacs_gnutls_handshake (proc); + GNUTLS_LOG2i (5, log_level, "Retried handshake", + proc->gnutls_handshakes_tried); + return -1; + } + + GNUTLS_LOG (2, log_level, "Giving up on handshake; resetting retries"); + proc->gnutls_handshakes_tried = 0; + return 0; } rtnval = fn_gnutls_record_recv (state, buf, nbyte); if (rtnval >= 0) diff --git a/src/gnutls.h b/src/gnutls.h index 474da77aec5..37b9a2eb4df 100644 --- a/src/gnutls.h +++ b/src/gnutls.h @@ -23,6 +23,9 @@ along with GNU Emacs. If not, see . */ #include #include +/* This limits the attempts to handshake per process (connection). */ +#define GNUTLS_EMACS_HANDSHAKES_LIMIT 100 + typedef enum { /* Initialization stages. */ @@ -53,6 +56,8 @@ typedef enum #define GNUTLS_LOG2(level, max, string, extra) do { if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); } } while (0) +#define GNUTLS_LOG2i(level, max, string, extra) do { if (level <= max) { gnutls_log_function2i (level, "(Emacs) " string, extra); } } while (0) + extern EMACS_INT emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, EMACS_INT nbyte); extern EMACS_INT diff --git a/src/process.c b/src/process.c index f2f33a9eafc..dc43191ebef 100644 --- a/src/process.c +++ b/src/process.c @@ -640,7 +640,10 @@ make_process (Lisp_Object name) #ifdef HAVE_GNUTLS p->gnutls_initstage = GNUTLS_STAGE_EMPTY; + /* Default log level. */ p->gnutls_log_level = 0; + /* GnuTLS handshakes attempted for this connection. */ + p->gnutls_handshakes_tried = 0; p->gnutls_p = 0; p->gnutls_state = NULL; p->gnutls_x509_cred = NULL; diff --git a/src/process.h b/src/process.h index 9efde261386..3eb94cb196b 100644 --- a/src/process.h +++ b/src/process.h @@ -134,6 +134,7 @@ struct Lisp_Process gnutls_certificate_client_credentials gnutls_x509_cred; gnutls_anon_client_credentials_t gnutls_anon_cred; int gnutls_log_level; + int gnutls_handshakes_tried; int gnutls_p; #endif };