diff options
| author | Lars Ingebrigtsen | 2016-02-16 15:56:56 +1100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2016-02-16 15:56:56 +1100 |
| commit | ac6e085cf6b26257cfe181f17828432d414cb3a6 (patch) | |
| tree | 9d382588ce869a2b816373e278b2805ffbb90f59 /src/process.c | |
| parent | c43bb7f136ab9e9439a4b5c045040a12cbe8bda0 (diff) | |
| download | emacs-ac6e085cf6b26257cfe181f17828432d414cb3a6.tar.gz emacs-ac6e085cf6b26257cfe181f17828432d414cb3a6.zip | |
Implement asynch TLS negotiation
* src/gnutls.c (gnutls_try_handshake): Factor out into its own
function.
(emacs_gnutls_handshake): Use it.
(emacs_gnutls_read): Just return instead of retrying the handshake.
* src/process.c (finish_after_tls_connection): Factor out
into its own function.
(connect_network_socket): Use it.
(wait_reading_process_output): Retry TLS handshakes.
(wait_reading_process_output): Defer sentinel until TLS completes.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 131 |
1 files changed, 84 insertions, 47 deletions
diff --git a/src/process.c b/src/process.c index 9a3bcaed389..ec31ea87c7b 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -281,9 +281,7 @@ static int max_input_desc; | |||
| 281 | 281 | ||
| 282 | /* Indexed by descriptor, gives the process (if any) for that descriptor. */ | 282 | /* Indexed by descriptor, gives the process (if any) for that descriptor. */ |
| 283 | static Lisp_Object chan_process[FD_SETSIZE]; | 283 | static Lisp_Object chan_process[FD_SETSIZE]; |
| 284 | #ifdef HAVE_GETADDRINFO_A | ||
| 285 | static void wait_for_socket_fds (Lisp_Object process, char *name); | 284 | static void wait_for_socket_fds (Lisp_Object process, char *name); |
| 286 | #endif | ||
| 287 | 285 | ||
| 288 | /* Alist of elements (NAME . PROCESS). */ | 286 | /* Alist of elements (NAME . PROCESS). */ |
| 289 | static Lisp_Object Vprocess_alist; | 287 | static Lisp_Object Vprocess_alist; |
| @@ -3038,7 +3036,45 @@ void set_network_socket_coding_system (Lisp_Object proc) | |||
| 3038 | = !(!NILP (tem) || NILP (p->buffer) || !inherit_process_coding_system); | 3036 | = !(!NILP (tem) || NILP (p->buffer) || !inherit_process_coding_system); |
| 3039 | } | 3037 | } |
| 3040 | 3038 | ||
| 3041 | void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | 3039 | #ifdef HAVE_GNUTLS |
| 3040 | void | ||
| 3041 | finish_after_tls_connection (Lisp_Object proc) | ||
| 3042 | { | ||
| 3043 | struct Lisp_Process *p = XPROCESS (proc); | ||
| 3044 | Lisp_Object contact = p->childp; | ||
| 3045 | Lisp_Object result = Qt; | ||
| 3046 | |||
| 3047 | if (!NILP (Ffboundp (Qnsm_verify_connection))) | ||
| 3048 | result = call3 (Qnsm_verify_connection, | ||
| 3049 | proc, | ||
| 3050 | Fplist_get (contact, QChost), | ||
| 3051 | Fplist_get (contact, QCservice)); | ||
| 3052 | |||
| 3053 | if (NILP (result)) | ||
| 3054 | { | ||
| 3055 | pset_status (p, list2 (Qfailed, | ||
| 3056 | build_string ("The Network Security Manager stopped the connections"))); | ||
| 3057 | deactivate_process (proc); | ||
| 3058 | } | ||
| 3059 | else | ||
| 3060 | { | ||
| 3061 | /* If we cleared the connection wait mask before we did | ||
| 3062 | the TLS setup, then we have to say that the process | ||
| 3063 | is finally "open" here. */ | ||
| 3064 | if (! FD_ISSET (p->outfd, &connect_wait_mask)) | ||
| 3065 | { | ||
| 3066 | pset_status (p, Qrun); | ||
| 3067 | /* Execute the sentinel here. If we had relied on | ||
| 3068 | status_notify to do it later, it will read input | ||
| 3069 | from the process before calling the sentinel. */ | ||
| 3070 | exec_sentinel (proc, build_string ("open\n")); | ||
| 3071 | } | ||
| 3072 | } | ||
| 3073 | } | ||
| 3074 | #endif | ||
| 3075 | |||
| 3076 | void | ||
| 3077 | connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | ||
| 3042 | { | 3078 | { |
| 3043 | ptrdiff_t count = SPECPDL_INDEX (); | 3079 | ptrdiff_t count = SPECPDL_INDEX (); |
| 3044 | ptrdiff_t count1; | 3080 | ptrdiff_t count1; |
| @@ -3359,8 +3395,10 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | |||
| 3359 | boot = Fgnutls_boot (proc, XCAR (params), XCDR (params)); | 3395 | boot = Fgnutls_boot (proc, XCAR (params), XCDR (params)); |
| 3360 | p->gnutls_boot_parameters = Qnil; | 3396 | p->gnutls_boot_parameters = Qnil; |
| 3361 | 3397 | ||
| 3362 | if (NILP (boot) || STRINGP (boot) || | 3398 | if (p->gnutls_initstage == GNUTLS_STAGE_READY) |
| 3363 | p->gnutls_initstage != GNUTLS_STAGE_READY) | 3399 | /* Run sentinels, etc. */ |
| 3400 | finish_after_tls_connection (proc); | ||
| 3401 | else if (p->gnutls_initstage != GNUTLS_STAGE_HANDSHAKE_TRIED) | ||
| 3364 | { | 3402 | { |
| 3365 | deactivate_process (proc); | 3403 | deactivate_process (proc); |
| 3366 | if (NILP (boot)) | 3404 | if (NILP (boot)) |
| @@ -3369,37 +3407,6 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | |||
| 3369 | else | 3407 | else |
| 3370 | pset_status (p, list2 (Qfailed, boot)); | 3408 | pset_status (p, list2 (Qfailed, boot)); |
| 3371 | } | 3409 | } |
| 3372 | else | ||
| 3373 | { | ||
| 3374 | Lisp_Object result = Qt; | ||
| 3375 | |||
| 3376 | if (!NILP (Ffboundp (Qnsm_verify_connection))) | ||
| 3377 | result = call3 (Qnsm_verify_connection, | ||
| 3378 | proc, | ||
| 3379 | Fplist_get (contact, QChost), | ||
| 3380 | Fplist_get (contact, QCservice)); | ||
| 3381 | |||
| 3382 | if (NILP (result)) | ||
| 3383 | { | ||
| 3384 | pset_status (p, list2 (Qfailed, | ||
| 3385 | build_string ("The Network Security Manager stopped the connections"))); | ||
| 3386 | deactivate_process (proc); | ||
| 3387 | } | ||
| 3388 | else | ||
| 3389 | { | ||
| 3390 | /* If we cleared the connection wait mask before we did | ||
| 3391 | the TLS setup, then we have to say that the process | ||
| 3392 | is finally "open" here. */ | ||
| 3393 | if (! FD_ISSET (p->outfd, &connect_wait_mask)) | ||
| 3394 | { | ||
| 3395 | pset_status (p, Qrun); | ||
| 3396 | /* Execute the sentinel here. If we had relied on | ||
| 3397 | status_notify to do it later, it will read input | ||
| 3398 | from the process before calling the sentinel. */ | ||
| 3399 | exec_sentinel (proc, build_string ("open\n")); | ||
| 3400 | } | ||
| 3401 | } | ||
| 3402 | } | ||
| 3403 | } | 3410 | } |
| 3404 | #endif | 3411 | #endif |
| 3405 | 3412 | ||
| @@ -4747,8 +4754,8 @@ static void | |||
| 4747 | wait_for_tls_negotiation (Lisp_Object process) | 4754 | wait_for_tls_negotiation (Lisp_Object process) |
| 4748 | { | 4755 | { |
| 4749 | #ifdef HAVE_GNUTLS | 4756 | #ifdef HAVE_GNUTLS |
| 4750 | while (EQ (XPROCESS (process)->status, Qconnect) && | 4757 | while (XPROCESS (process)->gnutls_p && |
| 4751 | !NILP (XPROCESS (process)->gnutls_boot_parameters)) | 4758 | XPROCESS (process)->gnutls_initstage != GNUTLS_STAGE_READY) |
| 4752 | { | 4759 | { |
| 4753 | printf("Waiting for TLS...\n"); | 4760 | printf("Waiting for TLS...\n"); |
| 4754 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); | 4761 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); |
| @@ -4881,7 +4888,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4881 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) | 4888 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) |
| 4882 | break; | 4889 | break; |
| 4883 | 4890 | ||
| 4884 | #ifdef HAVE_GETADDRINFO_A | 4891 | #if defined (HAVE_GETADDRINFO_A) || defined (HAVE_GNUTLS) |
| 4885 | { | 4892 | { |
| 4886 | Lisp_Object ip_addresses; | 4893 | Lisp_Object ip_addresses; |
| 4887 | Lisp_Object process_list_head, aproc; | 4894 | Lisp_Object process_list_head, aproc; |
| @@ -4891,17 +4898,41 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4891 | { | 4898 | { |
| 4892 | p = XPROCESS (aproc); | 4899 | p = XPROCESS (aproc); |
| 4893 | 4900 | ||
| 4894 | if (p->dns_requests && | 4901 | if (! wait_proc || p == wait_proc) |
| 4895 | (! wait_proc || p == wait_proc)) | ||
| 4896 | { | 4902 | { |
| 4897 | ip_addresses = check_for_dns (aproc); | 4903 | #ifdef HAVE_GETADDRINFO_A |
| 4898 | if (!NILP (ip_addresses) && | 4904 | /* Check for pending DNS requests. */ |
| 4899 | !EQ (ip_addresses, Qt)) | 4905 | if (p->dns_requests) |
| 4900 | connect_network_socket (aproc, ip_addresses); | 4906 | { |
| 4907 | ip_addresses = check_for_dns (aproc); | ||
| 4908 | if (!NILP (ip_addresses) && | ||
| 4909 | !EQ (ip_addresses, Qt)) | ||
| 4910 | connect_network_socket (aproc, ip_addresses); | ||
| 4911 | } | ||
| 4912 | #endif | ||
| 4913 | #ifdef HAVE_GNUTLS | ||
| 4914 | /* Continue TLS negotiation. */ | ||
| 4915 | if (p->gnutls_initstage == GNUTLS_STAGE_HANDSHAKE_TRIED && | ||
| 4916 | p->is_non_blocking_client) | ||
| 4917 | { | ||
| 4918 | gnutls_try_handshake (p); | ||
| 4919 | p->gnutls_handshakes_tried++; | ||
| 4920 | |||
| 4921 | if (p->gnutls_initstage == GNUTLS_STAGE_READY) | ||
| 4922 | finish_after_tls_connection (aproc); | ||
| 4923 | else if (p->gnutls_handshakes_tried > | ||
| 4924 | GNUTLS_EMACS_HANDSHAKES_LIMIT) | ||
| 4925 | { | ||
| 4926 | deactivate_process (proc); | ||
| 4927 | pset_status (p, list2 (Qfailed, | ||
| 4928 | build_string ("TLS negotiation failed"))); | ||
| 4929 | } | ||
| 4930 | } | ||
| 4931 | #endif | ||
| 4901 | } | 4932 | } |
| 4902 | } | 4933 | } |
| 4903 | } | 4934 | } |
| 4904 | #endif /* HAVE_GETADDRINFO_A */ | 4935 | #endif /* GETADDRINFO_A or GNUTLS */ |
| 4905 | 4936 | ||
| 4906 | /* Compute time from now till when time limit is up. */ | 4937 | /* Compute time from now till when time limit is up. */ |
| 4907 | /* Exit if already run out. */ | 4938 | /* Exit if already run out. */ |
| @@ -5522,7 +5553,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5522 | } | 5553 | } |
| 5523 | else | 5554 | else |
| 5524 | { | 5555 | { |
| 5525 | if (NILP (p->gnutls_boot_parameters)) | 5556 | #ifdef HAVE_GNUTLS |
| 5557 | /* If we have an incompletely set up TLS connection, | ||
| 5558 | then defer the sentinel signalling until | ||
| 5559 | later. */ | ||
| 5560 | if (NILP (p->gnutls_boot_parameters) && | ||
| 5561 | !p->gnutls_p) | ||
| 5562 | #endif | ||
| 5526 | { | 5563 | { |
| 5527 | pset_status (p, Qrun); | 5564 | pset_status (p, Qrun); |
| 5528 | /* Execute the sentinel here. If we had relied on | 5565 | /* Execute the sentinel here. If we had relied on |