diff options
author | Lars Ingebrigtsen <larsi@gnus.org> | 2016-02-15 18:24:08 +1100 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2016-02-15 18:24:08 +1100 |
commit | 9c74f2fea6bfa6bc38358835539944017cf35917 (patch) | |
tree | 17463dee36e640d38c302b3ef2c169b4e536e33c | |
parent | 40155283c380a795c1a0036a31e1b41ed1df0f38 (diff) | |
download | emacs-9c74f2fea6bfa6bc38358835539944017cf35917.tar.gz |
Call the network security manager after doing TLS negotiation
* lisp/net/network-stream.el (network-stream-open-tls):
Postpone NSM verification when running async.
* src/process.c (Fset_process_filter): This function doesn't
need to wait.
(connect_network_socket): Set the process status to "run" only
after TLS negotiation.
(wait_for_socket_fds): Take a name parameter for more debugging.
(wait_reading_process_output): Don't change status to "run"
unless TLS negotiation has finished.
(send_process): Wait for the process here instead of
send_process_string.
(connect_network_socket): Call the network security manager.
-rw-r--r-- | lisp/net/network-stream.el | 44 | ||||
-rw-r--r-- | src/process.c | 114 |
2 files changed, 102 insertions, 56 deletions
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el index b0d479f948e..1bba35ac81d 100644 --- a/lisp/net/network-stream.el +++ b/lisp/net/network-stream.el @@ -372,27 +372,29 @@ gnutls-boot (as returned by `gnutls-boot-parameters')." (plist-get parameters :nowait)) (open-tls-stream name buffer host service))) (eoc (plist-get parameters :end-of-command))) - ;; Check certificate validity etc. - (when (and (gnutls-available-p) stream) - (setq stream (nsm-verify-connection stream host service))) - (if (null stream) - (list nil nil nil 'plain) - ;; If we're using tls.el, we have to delete the output from - ;; openssl/gnutls-cli. - (when (and (not (gnutls-available-p)) - eoc) - (network-stream-get-response stream start eoc) - (goto-char (point-min)) - (when (re-search-forward eoc nil t) - (goto-char (match-beginning 0)) - (delete-region (point-min) (line-beginning-position)))) - (let ((capability-command (plist-get parameters :capability-command)) - (eo-capa (or (plist-get parameters :end-of-capability) - eoc))) - (list stream - (network-stream-get-response stream start eoc) - (network-stream-command stream capability-command eo-capa) - 'tls)))))) + (if (plist-get parameters :nowait) + (list stream nil nil 'tls) + ;; Check certificate validity etc. + (when (and (gnutls-available-p) stream) + (setq stream (nsm-verify-connection stream host service))) + (if (null stream) + (list nil nil nil 'plain) + ;; If we're using tls.el, we have to delete the output from + ;; openssl/gnutls-cli. + (when (and (not (gnutls-available-p)) + eoc) + (network-stream-get-response stream start eoc) + (goto-char (point-min)) + (when (re-search-forward eoc nil t) + (goto-char (match-beginning 0)) + (delete-region (point-min) (line-beginning-position)))) + (let ((capability-command (plist-get parameters :capability-command)) + (eo-capa (or (plist-get parameters :end-of-capability) + eoc))) + (list stream + (network-stream-get-response stream start eoc) + (network-stream-command stream capability-command eo-capa) + 'tls))))))) (defun network-stream-open-shell (name buffer host service parameters) (require 'format-spec) diff --git a/src/process.c b/src/process.c index 1dd52742e16..e8900715158 100644 --- a/src/process.c +++ b/src/process.c @@ -284,7 +284,7 @@ static Lisp_Object chan_process[FD_SETSIZE]; #ifdef HAVE_GETADDRINFO_A /* Pending DNS requests. */ static Lisp_Object dns_processes; -static void wait_for_socket_fds (Lisp_Object process); +static void wait_for_socket_fds (Lisp_Object process, char *name); #endif /* Alist of elements (NAME . PROCESS). */ @@ -1031,9 +1031,6 @@ The string argument is normally a multibyte string, except: CHECK_PROCESS (process); - if (NETCONN_P (process)) - wait_for_socket_fds (process); - p = XPROCESS (process); /* Don't signal an error if the process's input file descriptor @@ -1119,7 +1116,7 @@ DEFUN ("set-process-window-size", Fset_process_window_size, CHECK_PROCESS (process); if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "set-process-window-size"); /* All known platforms store window sizes as 'unsigned short'. */ CHECK_RANGED_INTEGER (height, 0, USHRT_MAX); @@ -1204,7 +1201,7 @@ list of keywords. */) #ifdef DATAGRAM_SOCKETS if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "process-contact"); if (DATAGRAM_CONN_P (process) && (EQ (key, Qt) || EQ (key, QCremote))) @@ -2436,7 +2433,7 @@ DEFUN ("process-datagram-address", Fprocess_datagram_address, Sprocess_datagram_ CHECK_PROCESS (process); if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "process-datagram-address"); if (!DATAGRAM_CONN_P (process)) return Qnil; @@ -2458,7 +2455,7 @@ Returns nil upon error setting address, ADDRESS otherwise. */) CHECK_PROCESS (process); if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "set-process-datagram-address"); if (!DATAGRAM_CONN_P (process)) return Qnil; @@ -2628,7 +2625,7 @@ OPTION is not a supported option, return nil instead; otherwise return t. */) if (!NETCONN1_P (p)) error ("Process is not a network process"); - wait_for_socket_fds (process); + wait_for_socket_fds (process, "set-network-process-option"); s = p->infd; if (s < 0) @@ -3332,16 +3329,49 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) { Lisp_Object boot, params = p->gnutls_boot_parameters; - p->gnutls_boot_parameters = Qnil; boot = Fgnutls_boot (proc, XCAR (params), XCDR (params)); - if (NILP (boot) || STRINGP (boot)) { - deactivate_process (proc); - if (NILP (boot)) - pset_status (p, list2 (Qfailed, - build_string ("TLS negotiation failed"))); - else - pset_status (p, list2 (Qfailed, boot)); - } + p->gnutls_boot_parameters = Qnil; + + if (NILP (boot) || STRINGP (boot)) + { + deactivate_process (proc); + if (NILP (boot)) + pset_status (p, list2 (Qfailed, + build_string ("TLS negotiation failed"))); + else + pset_status (p, list2 (Qfailed, boot)); + } + else + { + Lisp_Object result = Qt; + + if (!NILP (Ffboundp (Qnsm_verify_connection))) + result = call3 (Qnsm_verify_connection, + proc, + Fplist_get (contact, QChost), + Fplist_get (contact, QCservice)); + + if (NILP (result)) + { + pset_status (p, list2 (Qfailed, + build_string ("The Network Security Manager stopped the connections"))); + deactivate_process (proc); + } + else + { + /* If we cleared the connection wait mask before we did + the TLS setup, then we have to say that the process + is finally "open" here. */ + if (! FD_ISSET (p->outfd, &connect_wait_mask)) + { + pset_status (p, Qrun); + /* Execute the sentinel here. If we had relied on + status_notify to do it later, it will read input + from the process before calling the sentinel. */ + exec_sentinel (proc, build_string ("open\n")); + } + } + } } #endif @@ -4670,27 +4700,36 @@ check_for_dns (Lisp_Object proc) #endif /* HAVE_GETADDRINFO_A */ static void -wait_for_socket_fds (Lisp_Object process) +wait_for_socket_fds (Lisp_Object process, char *name) { while (XPROCESS (process)->infd < 0 && EQ (XPROCESS (process)->status, Qconnect)) - wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + { + printf("Waiting for socket from %s...\n", name); + wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + } } static void wait_while_connecting (Lisp_Object process) { while (EQ (XPROCESS (process)->status, Qconnect)) - wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + { + printf("Waiting for connection...\n"); + wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + } } static void wait_for_tls_negotiation (Lisp_Object process) { #ifdef HAVE_GNUTLS - while (EQ (XPROCESS (process)->status, Qrun) && + while (EQ (XPROCESS (process)->status, Qconnect) && !NILP (XPROCESS (process)->gnutls_boot_parameters)) - wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + { + printf("Waiting for TLS...\n"); + wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); + } #endif } @@ -5486,11 +5525,15 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, } else { - pset_status (p, Qrun); - /* Execute the sentinel here. If we had relied on - status_notify to do it later, it will read input - from the process before calling the sentinel. */ - exec_sentinel (proc, build_string ("open\n")); + if (NILP (p->gnutls_boot_parameters)) + { + pset_status (p, Qrun); + /* Execute the sentinel here. If we had relied on + status_notify to do it later, it will read input + from the process before calling the sentinel. */ + exec_sentinel (proc, build_string ("open\n")); + } + if (0 <= p->infd && !EQ (p->filter, Qt) && !EQ (p->command, Qt)) { @@ -5947,6 +5990,11 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, ssize_t rv; struct coding_system *coding; + if (NETCONN_P (proc)) { + wait_while_connecting (proc); + wait_for_tls_negotiation (proc); + } + if (p->raw_status_new) update_status (p); if (! EQ (p->status, Qrun)) @@ -6201,11 +6249,6 @@ Output from processes can arrive in between bunches. */) CHECK_STRING (string); proc = get_process (process); - if (NETCONN_P (proc)) { - wait_while_connecting (proc); - wait_for_tls_negotiation (proc); - } - send_process (proc, SSDATA (string), SBYTES (string), string); return Qnil; @@ -7081,7 +7124,7 @@ encode subprocess input. */) CHECK_PROCESS (process); if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "set-process-coding-system"); p = XPROCESS (process); @@ -7123,7 +7166,7 @@ suppressed. */) CHECK_PROCESS (process); if (NETCONN_P (process)) - wait_for_socket_fds (process); + wait_for_socket_fds (process, "set-process-filter-multibyte"); p = XPROCESS (process); if (NILP (flag)) @@ -7817,6 +7860,7 @@ syms_of_process (void) DEFSYM (QCnowait, ":nowait"); DEFSYM (QCsentinel, ":sentinel"); DEFSYM (QCtls_parameters, ":tls-parameters"); + DEFSYM (Qnsm_verify_connection, "nsm-verify-connection"); DEFSYM (QClog, ":log"); DEFSYM (QCnoquery, ":noquery"); DEFSYM (QCstop, ":stop"); |