aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2019-08-23 04:49:52 +0200
committerLars Ingebrigtsen2019-08-23 04:49:52 +0200
commit53cb3d3e0ddb666dc5b7774957ca863c668213cb (patch)
tree011cf32acf25b0cd86debf5b3c22be289e60bd87 /src
parentb4d3a882a8423e81c418fc56b7a9677f5582fcc7 (diff)
parent29d485fb768fbe375d60fd80cb2dbdbd90f3becc (diff)
downloademacs-53cb3d3e0ddb666dc5b7774957ca863c668213cb.tar.gz
emacs-53cb3d3e0ddb666dc5b7774957ca863c668213cb.zip
Merge remote-tracking branch 'origin/netsec'
Diffstat (limited to 'src')
-rw-r--r--src/gnutls.c190
-rw-r--r--src/process.c108
2 files changed, 281 insertions, 17 deletions
diff --git a/src/gnutls.c b/src/gnutls.c
index 267ba9aba35..ce977d901c6 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -44,6 +44,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
44# define HAVE_GNUTLS_EXT__DUMBFW 44# define HAVE_GNUTLS_EXT__DUMBFW
45#endif 45#endif
46 46
47#if GNUTLS_VERSION_NUMBER >= 0x030400
48# define HAVE_GNUTLS_ETM_STATUS
49#endif
50
47/* gnutls_mac_get_nonce_size was added in GnuTLS 3.2.0, but was 51/* gnutls_mac_get_nonce_size was added in GnuTLS 3.2.0, but was
48 exported only since 3.3.0. */ 52 exported only since 3.3.0. */
49#if GNUTLS_VERSION_NUMBER >= 0x030300 53#if GNUTLS_VERSION_NUMBER >= 0x030300
@@ -159,6 +163,8 @@ DEF_DLL_FN (int, gnutls_x509_crt_check_hostname,
159DEF_DLL_FN (int, gnutls_x509_crt_check_issuer, 163DEF_DLL_FN (int, gnutls_x509_crt_check_issuer,
160 (gnutls_x509_crt_t, gnutls_x509_crt_t)); 164 (gnutls_x509_crt_t, gnutls_x509_crt_t));
161DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t)); 165DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
166DEF_DLL_DN (int, gnutls_x509_crt_export,
167 (gnutls_x509_crt_t, gnutls_x509_crt_fmt_t, void *, size_t *));
162DEF_DLL_FN (int, gnutls_x509_crt_import, 168DEF_DLL_FN (int, gnutls_x509_crt_import,
163 (gnutls_x509_crt_t, const gnutls_datum_t *, 169 (gnutls_x509_crt_t, const gnutls_datum_t *,
164 gnutls_x509_crt_fmt_t)); 170 gnutls_x509_crt_fmt_t));
@@ -180,6 +186,9 @@ DEF_DLL_FN (int, gnutls_x509_crt_get_dn,
180 (gnutls_x509_crt_t, char *, size_t *)); 186 (gnutls_x509_crt_t, char *, size_t *));
181DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm, 187DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm,
182 (gnutls_x509_crt_t, unsigned int *)); 188 (gnutls_x509_crt_t, unsigned int *));
189DEF_DLL_FN (int, gnutls_x509_crt_print,
190 (gnutls_x509_crt_t, gnutls_certificate_print_formats_t,
191 gnutls_datum_t *));
183DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name, 192DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name,
184 (gnutls_pk_algorithm_t)); 193 (gnutls_pk_algorithm_t));
185DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param, 194DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param,
@@ -208,6 +217,11 @@ DEF_DLL_FN (const char *, gnutls_cipher_get_name,
208 (gnutls_cipher_algorithm_t)); 217 (gnutls_cipher_algorithm_t));
209DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t)); 218DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
210DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t)); 219DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
220DEF_DLL_FN (gnutls_compression_method_t, gnutls_compression_get,
221 (gnutls_session_t));
222DEF_DLL_FN (const char *, gnutls_compression_get_name,
223 (gnutls_compression_method_t));
224DEF_DLL_FN (unsigned, gnutls_safe_renegotiation_status, (gnutls_session_t));
211 225
212# ifdef HAVE_GNUTLS3 226# ifdef HAVE_GNUTLS3
213DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t)); 227DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t));
@@ -250,6 +264,9 @@ DEF_DLL_FN (int, gnutls_aead_cipher_decrypt,
250 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *, 264 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
251 size_t, size_t, const void *, size_t, void *, size_t *)); 265 size_t, size_t, const void *, size_t, void *, size_t *));
252# endif 266# endif
267# ifdef HAVE_GNUTLS_ETM_STATUS
268DEF_DLL_FN (unsigned, gnutls_session_etm_status, (gnutls_session_t));
269# endif
253DEF_DLL_FN (int, gnutls_hmac_init, 270DEF_DLL_FN (int, gnutls_hmac_init,
254 (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t)); 271 (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t));
255DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t)); 272DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t));
@@ -322,6 +339,7 @@ init_gnutls_functions (void)
322 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname); 339 LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname);
323 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer); 340 LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer);
324 LOAD_DLL_FN (library, gnutls_x509_crt_deinit); 341 LOAD_DLL_FN (library, gnutls_x509_crt_deinit);
342 LOAD_DLL_FN (library, gnutls_x509_crt_export);
325 LOAD_DLL_FN (library, gnutls_x509_crt_import); 343 LOAD_DLL_FN (library, gnutls_x509_crt_import);
326 LOAD_DLL_FN (library, gnutls_x509_crt_init); 344 LOAD_DLL_FN (library, gnutls_x509_crt_init);
327 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint); 345 LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint);
@@ -332,6 +350,7 @@ init_gnutls_functions (void)
332 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time); 350 LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time);
333 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn); 351 LOAD_DLL_FN (library, gnutls_x509_crt_get_dn);
334 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm); 352 LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm);
353 LOAD_DLL_FN (library, gnutls_x509_crt_print)
335 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name); 354 LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name);
336 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param); 355 LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param);
337 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id); 356 LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id);
@@ -349,6 +368,9 @@ init_gnutls_functions (void)
349 LOAD_DLL_FN (library, gnutls_cipher_get_name); 368 LOAD_DLL_FN (library, gnutls_cipher_get_name);
350 LOAD_DLL_FN (library, gnutls_mac_get); 369 LOAD_DLL_FN (library, gnutls_mac_get);
351 LOAD_DLL_FN (library, gnutls_mac_get_name); 370 LOAD_DLL_FN (library, gnutls_mac_get_name);
371 LOAD_DLL_FN (library, gnutls_compression_get);
372 LOAD_DLL_FN (library, gnutls_compression_get_name);
373 LOAD_DLL_FN (library, gnutls_safe_renegotiation_status);
352# ifdef HAVE_GNUTLS3 374# ifdef HAVE_GNUTLS3
353 LOAD_DLL_FN (library, gnutls_rnd); 375 LOAD_DLL_FN (library, gnutls_rnd);
354 LOAD_DLL_FN (library, gnutls_mac_list); 376 LOAD_DLL_FN (library, gnutls_mac_list);
@@ -380,6 +402,9 @@ init_gnutls_functions (void)
380 LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt); 402 LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt);
381 LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt); 403 LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt);
382# endif 404# endif
405# ifdef HAVE_GNUTLS_ETM_STATUS
406 LOAD_DLL_FN (library, gnutls_session_etm_status);
407# endif
383 LOAD_DLL_FN (library, gnutls_hmac_init); 408 LOAD_DLL_FN (library, gnutls_hmac_init);
384 LOAD_DLL_FN (library, gnutls_hmac_get_len); 409 LOAD_DLL_FN (library, gnutls_hmac_get_len);
385 LOAD_DLL_FN (library, gnutls_hmac); 410 LOAD_DLL_FN (library, gnutls_hmac);
@@ -437,6 +462,9 @@ init_gnutls_functions (void)
437# define gnutls_kx_get_name fn_gnutls_kx_get_name 462# define gnutls_kx_get_name fn_gnutls_kx_get_name
438# define gnutls_mac_get fn_gnutls_mac_get 463# define gnutls_mac_get fn_gnutls_mac_get
439# define gnutls_mac_get_name fn_gnutls_mac_get_name 464# define gnutls_mac_get_name fn_gnutls_mac_get_name
465# define gnutls_compression_get fn_gnutls_compression_get
466# define gnutls_compression_get_name fn_gnutls_compression_get_name
467# define gnutls_safe_renegotiation_status fn_gnutls_safe_renegotiation_status;
440# define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name 468# define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
441# define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param 469# define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
442# define gnutls_priority_set_direct fn_gnutls_priority_set_direct 470# define gnutls_priority_set_direct fn_gnutls_priority_set_direct
@@ -456,6 +484,7 @@ init_gnutls_functions (void)
456# define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname 484# define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
457# define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer 485# define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
458# define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit 486# define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
487# define gnutls_x509_crt_export fn_gnutls_x509_crt_export
459# define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time 488# define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
460# define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn 489# define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
461# define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time 490# define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
@@ -464,6 +493,7 @@ init_gnutls_functions (void)
464# define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id 493# define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
465# define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id 494# define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
466# define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm 495# define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
496# define gnutls_x509_crt_print fn_gnutls_x509_crt_print
467# define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial 497# define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
468# define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm 498# define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
469# define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id 499# define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
@@ -501,6 +531,9 @@ init_gnutls_functions (void)
501# define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init 531# define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
502# define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit 532# define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
503# endif 533# endif
534# ifdef HAVE_GNUTLS_ETM_STATUS
535# define gnutls_session_etm_status fn_gnutls_session_etm_status
536# endif
504# define gnutls_hmac_init fn_gnutls_hmac_init 537# define gnutls_hmac_init fn_gnutls_hmac_init
505# define gnutls_hmac_get_len fn_gnutls_hmac_get_len 538# define gnutls_hmac_get_len fn_gnutls_hmac_get_len
506# define gnutls_hmac fn_gnutls_hmac 539# define gnutls_hmac fn_gnutls_hmac
@@ -1041,7 +1074,34 @@ gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
1041} 1074}
1042 1075
1043static Lisp_Object 1076static Lisp_Object
1044gnutls_certificate_details (gnutls_x509_crt_t cert) 1077emacs_gnutls_certificate_export_pem (gnutls_x509_crt_t cert)
1078{
1079 size_t size = 0;
1080 int err = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, NULL, &size);
1081 check_memory_full (err);
1082
1083 if (err == GNUTLS_E_SHORT_MEMORY_BUFFER)
1084 {
1085 unsigned char *buf = xmalloc(size * sizeof (unsigned char));
1086 err = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, buf, &size);
1087 check_memory_full (err);
1088
1089 if (err < GNUTLS_E_SUCCESS)
1090 {
1091 xfree (buf);
1092 error ("GnuTLS certificate export error: %s", emacs_gnutls_strerror (err));
1093 }
1094
1095 return build_string(buf);
1096 }
1097 else if (err < GNUTLS_E_SUCCESS)
1098 error ("GnuTLS certificate export error: %s", emacs_gnutls_strerror (err));
1099
1100 return Qnil;
1101}
1102
1103static Lisp_Object
1104emacs_gnutls_certificate_details (gnutls_x509_crt_t cert)
1045{ 1105{
1046 Lisp_Object res = Qnil; 1106 Lisp_Object res = Qnil;
1047 int err; 1107 int err;
@@ -1209,6 +1269,10 @@ gnutls_certificate_details (gnutls_x509_crt_t cert)
1209 xfree (buf); 1269 xfree (buf);
1210 } 1270 }
1211 1271
1272 /* PEM */
1273 res = nconc2 (res, list2 (intern (":pem"),
1274 emacs_gnutls_certificate_export_pem(cert)));
1275
1212 return res; 1276 return res;
1213} 1277}
1214 1278
@@ -1246,6 +1310,29 @@ DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_descri
1246 if (EQ (status_symbol, intern (":no-host-match"))) 1310 if (EQ (status_symbol, intern (":no-host-match")))
1247 return build_string ("certificate host does not match hostname"); 1311 return build_string ("certificate host does not match hostname");
1248 1312
1313 if (EQ (status_symbol, intern (":signature-failure")))
1314 return build_string ("certificate signature could not be verified");
1315
1316 if (EQ (status_symbol, intern (":revocation-data-superseded")))
1317 return build_string ("certificate revocation data are old and have been "
1318 "superseded");
1319
1320 if (EQ (status_symbol, intern (":revocation-data-issued-in-future")))
1321 return build_string ("certificate revocation data have a future issue date");
1322
1323 if (EQ (status_symbol, intern (":signer-constraints-failure")))
1324 return build_string ("certificate ");
1325
1326 if (EQ (status_symbol, intern (":purpose-mismatch")))
1327 return build_string ("certificate does not match the intended purpose");
1328
1329 if (EQ (status_symbol, intern (":missing-ocsp-status")))
1330 return build_string ("certificate requires the server to send a OCSP "
1331 "certificate status, but no status was received");
1332
1333 if (EQ (status_symbol, intern (":invalid-ocsp-status")))
1334 return build_string ("the received OCSP certificate status is invalid");
1335
1249 return Qnil; 1336 return Qnil;
1250} 1337}
1251 1338
@@ -1297,6 +1384,35 @@ returned as the :certificate entry. */)
1297 if (verification & GNUTLS_CERT_EXPIRED) 1384 if (verification & GNUTLS_CERT_EXPIRED)
1298 warnings = Fcons (intern (":expired"), warnings); 1385 warnings = Fcons (intern (":expired"), warnings);
1299 1386
1387#if GNUTLS_VERSION_NUMBER >= 0x030100
1388 if (verification & GNUTLS_CERT_SIGNATURE_FAILURE)
1389 warnings = Fcons (intern (":signature-failure"), warnings);
1390
1391# if GNUTLS_VERSION_NUMBER >= 0x030114
1392 if (verification & GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED)
1393 warnings = Fcons (intern (":revocation-data-superseded"), warnings);
1394
1395 if (verification & GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE)
1396 warnings = Fcons (intern (":revocation-data-issued-in-future"), warnings);
1397
1398 if (verification & GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE)
1399 warnings = Fcons (intern (":signer-constraints-failure"), warnings);
1400
1401# if GNUTLS_VERSION_NUMBER >= 0x030400
1402 if (verification & GNUTLS_CERT_PURPOSE_MISMATCH)
1403 warnings = Fcons (intern (":purpose-mismatch"), warnings);
1404
1405# if GNUTLS_VERSION_NUMBER >= 0x030501
1406 if (verification & GNUTLS_CERT_MISSING_OCSP_STATUS)
1407 warnings = Fcons (intern (":missing-ocsp-status"), warnings);
1408
1409 if (verification & GNUTLS_CERT_INVALID_OCSP_STATUS)
1410 warnings = Fcons (intern (":invalid-ocsp-status"), warnings);
1411# endif
1412# endif
1413# endif
1414#endif
1415
1300 if (XPROCESS (proc)->gnutls_extra_peer_verification & 1416 if (XPROCESS (proc)->gnutls_extra_peer_verification &
1301 CERTIFICATE_NOT_MATCHING) 1417 CERTIFICATE_NOT_MATCHING)
1302 warnings = Fcons (intern (":no-host-match"), warnings); 1418 warnings = Fcons (intern (":no-host-match"), warnings);
@@ -1319,7 +1435,7 @@ returned as the :certificate entry. */)
1319 1435
1320 /* Return all the certificates in a list. */ 1436 /* Return all the certificates in a list. */
1321 for (int i = 0; i < XPROCESS (proc)->gnutls_certificates_length; i++) 1437 for (int i = 0; i < XPROCESS (proc)->gnutls_certificates_length; i++)
1322 certs = nconc2 (certs, list1 (gnutls_certificate_details 1438 certs = nconc2 (certs, list1 (emacs_gnutls_certificate_details
1323 (XPROCESS (proc)->gnutls_certificates[i]))); 1439 (XPROCESS (proc)->gnutls_certificates[i])));
1324 1440
1325 result = nconc2 (result, list2 (intern (":certificates"), certs)); 1441 result = nconc2 (result, list2 (intern (":certificates"), certs));
@@ -1364,6 +1480,26 @@ returned as the :certificate entry. */)
1364 build_string (gnutls_mac_get_name 1480 build_string (gnutls_mac_get_name
1365 (gnutls_mac_get (state))))); 1481 (gnutls_mac_get (state)))));
1366 1482
1483 /* Compression name. */
1484 result = nconc2
1485 (result, list2 (intern (":compression"),
1486 build_string (gnutls_compression_get_name
1487 (gnutls_compression_get (state)))));
1488
1489 /* Encrypt-then-MAC. */
1490 result = nconc2
1491 (result, list2 (intern (":encrypt-then-mac"),
1492#ifdef HAVE_GNUTLS_ETM_STATUS
1493 gnutls_session_etm_status (state) ? Qt : Qnil
1494#else
1495 Qnil
1496#endif
1497 ));
1498
1499 /* Renegotiation Indication */
1500 result = nconc2
1501 (result, list2 (intern (":safe-renegotiation"),
1502 gnutls_safe_renegotiation_status (state) ? Qt : Qnil));
1367 1503
1368 return result; 1504 return result;
1369} 1505}
@@ -1425,6 +1561,55 @@ boot_error (struct Lisp_Process *p, const char *m, ...)
1425 va_end (ap); 1561 va_end (ap);
1426} 1562}
1427 1563
1564DEFUN ("gnutls-format-certificate", Fgnutls_format_certificate, Sgnutls_format_certificate, 1, 1, 0,
1565 doc: /* Format a X.509 certificate to a string.
1566
1567Given a PEM-encoded X.509 certificate CERT, returns a human-readable
1568string representation. */)
1569 (Lisp_Object cert)
1570{
1571 CHECK_STRING (cert);
1572
1573 int err;
1574 gnutls_x509_crt_t crt;
1575
1576 err = gnutls_x509_crt_init (&crt);
1577 check_memory_full (err);
1578 if (err < GNUTLS_E_SUCCESS)
1579 error ("gnutls-format-certificate error: %s", emacs_gnutls_strerror (err));
1580
1581 unsigned char *crt_buf = SDATA (cert);
1582 gnutls_datum_t crt_data = { crt_buf, strlen (crt_buf) };
1583 err = gnutls_x509_crt_import (crt, &crt_data, GNUTLS_X509_FMT_PEM);
1584 check_memory_full (err);
1585 if (err < GNUTLS_E_SUCCESS)
1586 {
1587 gnutls_x509_crt_deinit (crt);
1588 error ("gnutls-format-certificate error: %s", emacs_gnutls_strerror (err));
1589 }
1590
1591 gnutls_datum_t out;
1592 err = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &out);
1593 check_memory_full (err);
1594 if (err < GNUTLS_E_SUCCESS)
1595 {
1596 gnutls_x509_crt_deinit (crt);
1597 error ("gnutls-format-certificate error: %s", emacs_gnutls_strerror (err));
1598 }
1599
1600 char *out_buf = xmalloc ((out.size + 1) * sizeof (char));
1601 memset (out_buf, 0, (out.size + 1) * sizeof (char));
1602 memcpy (out_buf, out.data, out.size);
1603
1604 xfree (out.data);
1605 gnutls_x509_crt_deinit (crt);
1606
1607 Lisp_Object result = build_string (out_buf);
1608 xfree (out_buf);
1609
1610 return result;
1611}
1612
1428Lisp_Object 1613Lisp_Object
1429gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist) 1614gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1430{ 1615{
@@ -2706,6 +2891,7 @@ syms_of_gnutls (void)
2706 defsubr (&Sgnutls_bye); 2891 defsubr (&Sgnutls_bye);
2707 defsubr (&Sgnutls_peer_status); 2892 defsubr (&Sgnutls_peer_status);
2708 defsubr (&Sgnutls_peer_status_warning_describe); 2893 defsubr (&Sgnutls_peer_status_warning_describe);
2894 defsubr (&Sgnutls_format_certificate);
2709 2895
2710#ifdef HAVE_GNUTLS3 2896#ifdef HAVE_GNUTLS3
2711 defsubr (&Sgnutls_ciphers); 2897 defsubr (&Sgnutls_ciphers);
diff --git a/src/process.c b/src/process.c
index 066edbc83d6..7097b7ace17 100644
--- a/src/process.c
+++ b/src/process.c
@@ -276,6 +276,10 @@ static int read_process_output (Lisp_Object, int);
276static void create_pty (Lisp_Object); 276static void create_pty (Lisp_Object);
277static void exec_sentinel (Lisp_Object, Lisp_Object); 277static void exec_sentinel (Lisp_Object, Lisp_Object);
278 278
279static Lisp_Object
280network_lookup_address_info_1 (Lisp_Object host, const char *service,
281 struct addrinfo *hints, struct addrinfo **res);
282
279/* Number of bits set in connect_wait_mask. */ 283/* Number of bits set in connect_wait_mask. */
280static int num_pending_connects; 284static int num_pending_connects;
281 285
@@ -4106,7 +4110,7 @@ usage: (make-network-process &rest ARGS) */)
4106 if (!NILP (host)) 4110 if (!NILP (host))
4107 { 4111 {
4108 struct addrinfo *res, *lres; 4112 struct addrinfo *res, *lres;
4109 int ret; 4113 Lisp_Object msg;
4110 4114
4111 maybe_quit (); 4115 maybe_quit ();
4112 4116
@@ -4115,20 +4119,11 @@ usage: (make-network-process &rest ARGS) */)
4115 hints.ai_family = family; 4119 hints.ai_family = family;
4116 hints.ai_socktype = socktype; 4120 hints.ai_socktype = socktype;
4117 4121
4118 ret = getaddrinfo (SSDATA (host), portstring, &hints, &res); 4122 msg = network_lookup_address_info_1 (host, portstring, &hints, &res);
4119 if (ret) 4123 if (!EQ(msg, Qt))
4120#ifdef HAVE_GAI_STRERROR 4124 {
4121 { 4125 error ("%s", SSDATA (msg));
4122 synchronize_system_messages_locale (); 4126 }
4123 char const *str = gai_strerror (ret);
4124 if (! NILP (Vlocale_coding_system))
4125 str = SSDATA (code_convert_string_norecord
4126 (build_string (str), Vlocale_coding_system, 0));
4127 error ("%s/%s %s", SSDATA (host), portstring, str);
4128 }
4129#else
4130 error ("%s/%s getaddrinfo error %d", SSDATA (host), portstring, ret);
4131#endif
4132 4127
4133 for (lres = res; lres; lres = lres->ai_next) 4128 for (lres = res; lres; lres = lres->ai_next)
4134 addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); 4129 addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos);
@@ -4576,6 +4571,88 @@ Data that is unavailable is returned as nil. */)
4576#endif 4571#endif
4577} 4572}
4578 4573
4574static Lisp_Object
4575network_lookup_address_info_1 (Lisp_Object host, const char *service,
4576 struct addrinfo *hints, struct addrinfo **res)
4577{
4578 Lisp_Object msg = Qt;
4579 int ret;
4580
4581 if (STRING_MULTIBYTE (host) && SBYTES (host) != SCHARS (host))
4582 error ("Non-ASCII hostname %s detected, please use puny-encode-domain",
4583 SSDATA (host));
4584 ret = getaddrinfo (SSDATA (host), service, hints, res);
4585 if (ret)
4586 {
4587 if (service == NULL)
4588 service = "0";
4589#ifdef HAVE_GAI_STRERROR
4590 synchronize_system_messages_locale ();
4591 char const *str = gai_strerror (ret);
4592 if (! NILP (Vlocale_coding_system))
4593 str = SSDATA (code_convert_string_norecord
4594 (build_string (str), Vlocale_coding_system, 0));
4595 AUTO_STRING (format, "%s/%s %s");
4596 msg = CALLN (Fformat, format, host, build_string (service), build_string (str));
4597#else
4598 AUTO_STRING (format, "%s/%s getaddrinfo error %d");
4599 msg = CALLN (Fformat, format, host, build_string (service), make_number (ret));
4600#endif
4601 }
4602 return msg;
4603}
4604
4605DEFUN ("network-lookup-address-info", Fnetwork_lookup_address_info,
4606 Snetwork_lookup_address_info, 1, 2, 0,
4607 doc: /* Look up ip address info of NAME.
4608Optional parameter FAMILY controls whether to look up IPv4 or IPv6
4609addresses. The default of nil means both, symbol `ipv4' means IPv4
4610only, symbol `ipv6' means IPv6 only. Returns a list of addresses, or
4611nil if none were found. Each address is a vector of integers. */)
4612 (Lisp_Object name, Lisp_Object family)
4613{
4614 Lisp_Object addresses = Qnil;
4615 Lisp_Object msg = Qnil;
4616
4617 struct addrinfo *res, *lres;
4618 struct addrinfo hints;
4619
4620 memset (&hints, 0, sizeof hints);
4621 if (EQ (family, Qnil))
4622 hints.ai_family = AF_UNSPEC;
4623 else if (EQ (family, Qipv4))
4624 hints.ai_family = AF_INET;
4625 else if (EQ (family, Qipv6))
4626#ifdef AF_INET6
4627 hints.ai_family = AF_INET6;
4628#else
4629 /* If we don't support IPv6, querying will never work anyway */
4630 return addresses;
4631#endif
4632 else
4633 error ("Unsupported lookup type");
4634 hints.ai_socktype = SOCK_DGRAM;
4635
4636 msg = network_lookup_address_info_1 (name, NULL, &hints, &res);
4637 if (!EQ(msg, Qt))
4638 {
4639 message ("%s", SSDATA(msg));
4640 }
4641 else
4642 {
4643 for (lres = res; lres; lres = lres->ai_next)
4644 {
4645 addresses = Fcons (conv_sockaddr_to_lisp
4646 (lres->ai_addr, lres->ai_addrlen),
4647 addresses);
4648 }
4649 addresses = Fnreverse (addresses);
4650
4651 freeaddrinfo (res);
4652 }
4653 return addresses;
4654}
4655
4579/* Turn off input and output for process PROC. */ 4656/* Turn off input and output for process PROC. */
4580 4657
4581static void 4658static void
@@ -8345,6 +8422,7 @@ returns non-`nil'. */);
8345 defsubr (&Sset_network_process_option); 8422 defsubr (&Sset_network_process_option);
8346 defsubr (&Smake_network_process); 8423 defsubr (&Smake_network_process);
8347 defsubr (&Sformat_network_address); 8424 defsubr (&Sformat_network_address);
8425 defsubr (&Snetwork_lookup_address_info);
8348 defsubr (&Snetwork_interface_list); 8426 defsubr (&Snetwork_interface_list);
8349 defsubr (&Snetwork_interface_info); 8427 defsubr (&Snetwork_interface_info);
8350#ifdef DATAGRAM_SOCKETS 8428#ifdef DATAGRAM_SOCKETS