aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2016-02-01 00:27:07 +0100
committerLars Ingebrigtsen2016-02-01 00:27:07 +0100
commit4ff81f8fac1270a829bb2725911bf6b614711257 (patch)
tree5c3a640b436037a3d2f6a4e8bb569c01cc9a3599 /src
parent9972329387b7f1e1a9b1c8713a1d5bbdd032de12 (diff)
downloademacs-4ff81f8fac1270a829bb2725911bf6b614711257.tar.gz
emacs-4ff81f8fac1270a829bb2725911bf6b614711257.zip
Further TLS async work
* gnutls.c (boot_error): New function to either signal an error or return an error code. (Fgnutls_boot): Don't signal errors when running asynchronously. * process.h (pset_status): Move here from process.c to be able to use from gnutls.c. * process.c (connect_network_socket): Do the TLS boot here when running asynchronously. (wait_reading_process_output): Rework the dns_processes handling for more safety.
Diffstat (limited to 'src')
-rw-r--r--src/gnutls.c54
-rw-r--r--src/process.c75
-rw-r--r--src/process.h6
3 files changed, 102 insertions, 33 deletions
diff --git a/src/gnutls.c b/src/gnutls.c
index 06459fb3ccd..a0b6e0df68b 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -1167,6 +1167,19 @@ emacs_gnutls_global_deinit (void)
1167} 1167}
1168#endif 1168#endif
1169 1169
1170/* VARARGS 1 */
1171static void
1172boot_error (struct Lisp_Process *p, const char *m, ...)
1173{
1174 va_list ap;
1175 va_start (ap, m);
1176 if (p->is_non_blocking_client)
1177 pset_status (p, Qfailed);
1178 else
1179 verror (m, ap);
1180}
1181
1182
1170DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, 1183DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1171 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST. 1184 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1172Currently only client mode is supported. Return a success/failure 1185Currently only client mode is supported. Return a success/failure
@@ -1246,16 +1259,23 @@ one trustfile (usually a CA bundle). */)
1246 Lisp_Object verify_error; 1259 Lisp_Object verify_error;
1247 Lisp_Object prime_bits; 1260 Lisp_Object prime_bits;
1248 Lisp_Object warnings; 1261 Lisp_Object warnings;
1262 struct Lisp_Process *p = XPROCESS (proc);
1249 1263
1250 CHECK_PROCESS (proc); 1264 CHECK_PROCESS (proc);
1251 CHECK_SYMBOL (type); 1265 CHECK_SYMBOL (type);
1252 CHECK_LIST (proplist); 1266 CHECK_LIST (proplist);
1253 1267
1254 if (NILP (Fgnutls_available_p ())) 1268 if (NILP (Fgnutls_available_p ()))
1255 error ("GnuTLS not available"); 1269 {
1270 boot_error (p, "GnuTLS not available");
1271 return Qnil;
1272 }
1256 1273
1257 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon)) 1274 if (!EQ (type, Qgnutls_x509pki) && !EQ (type, Qgnutls_anon))
1258 error ("Invalid GnuTLS credential type"); 1275 {
1276 boot_error (p, "Invalid GnuTLS credential type");
1277 return Qnil;
1278 }
1259 1279
1260 hostname = Fplist_get (proplist, QCgnutls_bootprop_hostname); 1280 hostname = Fplist_get (proplist, QCgnutls_bootprop_hostname);
1261 priority_string = Fplist_get (proplist, QCgnutls_bootprop_priority); 1281 priority_string = Fplist_get (proplist, QCgnutls_bootprop_priority);
@@ -1272,11 +1292,15 @@ one trustfile (usually a CA bundle). */)
1272 } 1292 }
1273 else if (NILP (Flistp (verify_error))) 1293 else if (NILP (Flistp (verify_error)))
1274 { 1294 {
1275 error ("gnutls-boot: invalid :verify_error parameter (not a list)"); 1295 boot_error (p, "gnutls-boot: invalid :verify_error parameter (not a list)");
1296 return Qnil;
1276 } 1297 }
1277 1298
1278 if (!STRINGP (hostname)) 1299 if (!STRINGP (hostname))
1279 error ("gnutls-boot: invalid :hostname parameter (not a string)"); 1300 {
1301 boot_error (p, "gnutls-boot: invalid :hostname parameter (not a string)");
1302 return Qnil;
1303 }
1280 c_hostname = SSDATA (hostname); 1304 c_hostname = SSDATA (hostname);
1281 1305
1282 state = XPROCESS (proc)->gnutls_state; 1306 state = XPROCESS (proc)->gnutls_state;
@@ -1384,7 +1408,8 @@ one trustfile (usually a CA bundle). */)
1384 else 1408 else
1385 { 1409 {
1386 emacs_gnutls_deinit (proc); 1410 emacs_gnutls_deinit (proc);
1387 error ("Invalid trustfile"); 1411 boot_error (p, "Invalid trustfile");
1412 return Qnil;
1388 } 1413 }
1389 } 1414 }
1390 1415
@@ -1408,7 +1433,8 @@ one trustfile (usually a CA bundle). */)
1408 else 1433 else
1409 { 1434 {
1410 emacs_gnutls_deinit (proc); 1435 emacs_gnutls_deinit (proc);
1411 error ("Invalid CRL file"); 1436 boot_error (p, "Invalid CRL file");
1437 return Qnil;
1412 } 1438 }
1413 } 1439 }
1414 1440
@@ -1437,8 +1463,9 @@ one trustfile (usually a CA bundle). */)
1437 else 1463 else
1438 { 1464 {
1439 emacs_gnutls_deinit (proc); 1465 emacs_gnutls_deinit (proc);
1440 error (STRINGP (keyfile) ? "Invalid client cert file" 1466 boot_error (p, STRINGP (keyfile) ? "Invalid client cert file"
1441 : "Invalid client key file"); 1467 : "Invalid client key file");
1468 return Qnil;
1442 } 1469 }
1443 } 1470 }
1444 } 1471 }
@@ -1528,8 +1555,9 @@ one trustfile (usually a CA bundle). */)
1528 || !NILP (Fmember (QCgnutls_bootprop_trustfiles, verify_error))) 1555 || !NILP (Fmember (QCgnutls_bootprop_trustfiles, verify_error)))
1529 { 1556 {
1530 emacs_gnutls_deinit (proc); 1557 emacs_gnutls_deinit (proc);
1531 error ("Certificate validation failed %s, verification code %x", 1558 boot_error (p, "Certificate validation failed %s, verification code %x",
1532 c_hostname, peer_verification); 1559 c_hostname, peer_verification);
1560 return Qnil;
1533 } 1561 }
1534 else 1562 else
1535 { 1563 {
@@ -1558,7 +1586,8 @@ one trustfile (usually a CA bundle). */)
1558 { 1586 {
1559 gnutls_x509_crt_deinit (gnutls_verify_cert); 1587 gnutls_x509_crt_deinit (gnutls_verify_cert);
1560 emacs_gnutls_deinit (proc); 1588 emacs_gnutls_deinit (proc);
1561 error ("No x509 certificate was found\n"); 1589 boot_error (p, "No x509 certificate was found\n");
1590 return Qnil;
1562 } 1591 }
1563 1592
1564 /* We only check the first certificate in the given chain. */ 1593 /* We only check the first certificate in the given chain. */
@@ -1586,7 +1615,8 @@ one trustfile (usually a CA bundle). */)
1586 { 1615 {
1587 gnutls_x509_crt_deinit (gnutls_verify_cert); 1616 gnutls_x509_crt_deinit (gnutls_verify_cert);
1588 emacs_gnutls_deinit (proc); 1617 emacs_gnutls_deinit (proc);
1589 error ("The x509 certificate does not match \"%s\"", c_hostname); 1618 boot_error (p, "The x509 certificate does not match \"%s\"", c_hostname);
1619 return Qnil;
1590 } 1620 }
1591 else 1621 else
1592 { 1622 {
diff --git a/src/process.c b/src/process.c
index 55264058340..afb98256ba5 100644
--- a/src/process.c
+++ b/src/process.c
@@ -385,11 +385,6 @@ pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
385 p->sentinel = NILP (val) ? Qinternal_default_process_sentinel : val; 385 p->sentinel = NILP (val) ? Qinternal_default_process_sentinel : val;
386} 386}
387static void 387static void
388pset_status (struct Lisp_Process *p, Lisp_Object val)
389{
390 p->status = val;
391}
392static void
393pset_tty_name (struct Lisp_Process *p, Lisp_Object val) 388pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
394{ 389{
395 p->tty_name = val; 390 p->tty_name = val;
@@ -3309,11 +3304,17 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
3309 3304
3310#ifdef HAVE_GNUTLS 3305#ifdef HAVE_GNUTLS
3311 if (!NILP (p->gnutls_async_parameters) && p->is_non_blocking_client) { 3306 if (!NILP (p->gnutls_async_parameters) && p->is_non_blocking_client) {
3312 Fgnutls_boot (proc, Fcar (p->gnutls_async_parameters), 3307 Lisp_Object params = p->gnutls_async_parameters, boot = Qnil;
3313 Fcdr (p->gnutls_async_parameters)); 3308
3314 p->gnutls_async_parameters = Qnil; 3309 p->gnutls_async_parameters = Qnil;
3310 boot = Fgnutls_boot (proc, Fcar (params), Fcdr (params));
3311 if (STRINGP (boot)) {
3312 pset_status (p, Qfailed);
3313 deactivate_process (proc);
3314 }
3315 } 3315 }
3316#endif 3316#endif
3317
3317} 3318}
3318 3319
3319 3320
@@ -3798,6 +3799,9 @@ usage: (make-network-process &rest ARGS) */)
3798#ifdef HAVE_GETADDRINFO_A 3799#ifdef HAVE_GETADDRINFO_A
3799 p->dns_requests = NULL; 3800 p->dns_requests = NULL;
3800#endif 3801#endif
3802#ifdef HAVE_GNUTLS
3803 p->gnutls_async_parameters = Qnil;
3804#endif
3801 3805
3802 unbind_to (count, Qnil); 3806 unbind_to (count, Qnil);
3803 3807
@@ -4545,13 +4549,12 @@ server_accept_connection (Lisp_Object server, int channel)
4545} 4549}
4546 4550
4547#ifdef HAVE_GETADDRINFO_A 4551#ifdef HAVE_GETADDRINFO_A
4548static int 4552static Lisp_Object
4549check_for_dns (Lisp_Object proc) 4553check_for_dns (Lisp_Object proc)
4550{ 4554{
4551 struct Lisp_Process *p = XPROCESS (proc); 4555 struct Lisp_Process *p = XPROCESS (proc);
4552 Lisp_Object ip_addresses = Qnil; 4556 Lisp_Object ip_addresses = Qnil;
4553 int ret = 0; 4557 int ret = 0;
4554 int connect = 0;
4555 4558
4556 /* Sanity check. */ 4559 /* Sanity check. */
4557 if (! p->dns_requests) 4560 if (! p->dns_requests)
@@ -4559,7 +4562,7 @@ check_for_dns (Lisp_Object proc)
4559 4562
4560 ret = gai_error (p->dns_requests[0]); 4563 ret = gai_error (p->dns_requests[0]);
4561 if (ret == EAI_INPROGRESS) 4564 if (ret == EAI_INPROGRESS)
4562 return 0; 4565 return Qt;
4563 4566
4564 /* We got a response. */ 4567 /* We got a response. */
4565 if (ret == 0) 4568 if (ret == 0)
@@ -4575,10 +4578,13 @@ check_for_dns (Lisp_Object proc)
4575 4578
4576 ip_addresses = Fnreverse (ip_addresses); 4579 ip_addresses = Fnreverse (ip_addresses);
4577 freeaddrinfo (p->dns_requests[0]->ar_result); 4580 freeaddrinfo (p->dns_requests[0]->ar_result);
4578 connect = 1;
4579 } 4581 }
4582 /* The DNS lookup failed. */
4580 else 4583 else
4581 pset_status (p, Qfailed); 4584 {
4585 pset_status (p, Qfailed);
4586 deactivate_process (proc);
4587 }
4582 4588
4583 xfree ((void *)p->dns_requests[0]->ar_request); 4589 xfree ((void *)p->dns_requests[0]->ar_request);
4584 xfree ((void *)p->dns_requests[0]->ar_name); 4590 xfree ((void *)p->dns_requests[0]->ar_name);
@@ -4587,10 +4593,7 @@ check_for_dns (Lisp_Object proc)
4587 xfree (p->dns_requests); 4593 xfree (p->dns_requests);
4588 p->dns_requests = NULL; 4594 p->dns_requests = NULL;
4589 4595
4590 if (connect) 4596 return ip_addresses;
4591 connect_network_socket (proc, ip_addresses);
4592
4593 return 1;
4594} 4597}
4595#endif /* HAVE_GETADDRINFO_A */ 4598#endif /* HAVE_GETADDRINFO_A */
4596 4599
@@ -4722,18 +4725,47 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4722#ifdef HAVE_GETADDRINFO_A 4725#ifdef HAVE_GETADDRINFO_A
4723 if (!NILP (dns_processes)) 4726 if (!NILP (dns_processes))
4724 { 4727 {
4725 Lisp_Object dns_list = dns_processes, dns; 4728 Lisp_Object dns_list = dns_processes, dns, ip_addresses,
4729 answers = Qnil, answer, new = Qnil;
4726 struct Lisp_Process *p; 4730 struct Lisp_Process *p;
4727 4731
4732 /* This is programmed in a somewhat awkward fashion because
4733 calling connect_network_socket might make us end up back
4734 here again, and we would have a race condition with
4735 segfaults. So first go through all pending requests and see
4736 whether we got any answers. */
4728 while (!NILP (dns_list)) 4737 while (!NILP (dns_list))
4729 { 4738 {
4730 dns = Fcar (dns_list); 4739 dns = Fcar (dns_list);
4731 dns_list = Fcdr (dns_list); 4740 dns_list = Fcdr (dns_list);
4732 p = XPROCESS (dns); 4741 p = XPROCESS (dns);
4733 if (p && p->dns_requests && 4742 if (p && p->dns_requests)
4734 (! wait_proc || p == wait_proc) && 4743 {
4735 check_for_dns (dns)) 4744 if (! wait_proc || p == wait_proc)
4736 dns_processes = Fdelq (dns, dns_processes); 4745 {
4746 ip_addresses = check_for_dns (dns);
4747 if (EQ (ip_addresses, Qt))
4748 new = Fcons (dns, new);
4749 else
4750 answers = Fcons (Fcons (dns, ip_addresses), answers);
4751 }
4752 else
4753 new = Fcons (dns, new);
4754 }
4755 }
4756
4757 /* Replace with the list of DNS requests still not responded
4758 to. */
4759 dns_processes = new;
4760
4761 /* Then continue the connection for the successful
4762 requests. */
4763 while (!NILP (answers))
4764 {
4765 answer = Fcar (answers);
4766 answers = Fcdr (answers);
4767 if (!NILP (Fcdr (answer)))
4768 connect_network_socket (Fcar (answer), Fcdr (answer));
4737 } 4769 }
4738 } 4770 }
4739#endif /* HAVE_GETADDRINFO_A */ 4771#endif /* HAVE_GETADDRINFO_A */
@@ -7685,6 +7717,7 @@ syms_of_process (void)
7685 7717
7686 staticpro (&Vprocess_alist); 7718 staticpro (&Vprocess_alist);
7687 staticpro (&deleted_pid_list); 7719 staticpro (&deleted_pid_list);
7720 staticpro (&dns_processes);
7688 7721
7689#endif /* subprocesses */ 7722#endif /* subprocesses */
7690 7723
diff --git a/src/process.h b/src/process.h
index eb34f5f0411..95c64fa73b7 100644
--- a/src/process.h
+++ b/src/process.h
@@ -210,6 +210,12 @@ pset_childp (struct Lisp_Process *p, Lisp_Object val)
210 p->childp = val; 210 p->childp = val;
211} 211}
212 212
213INLINE void
214pset_status (struct Lisp_Process *p, Lisp_Object val)
215{
216 p->status = val;
217}
218
213#ifdef HAVE_GNUTLS 219#ifdef HAVE_GNUTLS
214INLINE void 220INLINE void
215pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val) 221pset_gnutls_cred_type (struct Lisp_Process *p, Lisp_Object val)