diff options
| author | Lars Magne Ingebrigtsen | 2010-10-04 00:37:37 +0200 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2010-10-04 00:37:37 +0200 |
| commit | c1ae068bbb12dfadbe5f7198fa6584e9c4d7d054 (patch) | |
| tree | 7a2bcf8d2422a6bbfdb6214ae14aebb81e626bb9 /src | |
| parent | 5589b70e5789a355d1aa88b469acdaac423ccbbb (diff) | |
| download | emacs-c1ae068bbb12dfadbe5f7198fa6584e9c4d7d054.tar.gz emacs-c1ae068bbb12dfadbe5f7198fa6584e9c4d7d054.zip | |
Rework the gnutls boot interface.
From Teodor Zlatanov.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 12 | ||||
| -rw-r--r-- | src/gnutls.c | 153 | ||||
| -rw-r--r-- | src/gnutls.h | 2 |
3 files changed, 130 insertions, 37 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index c8fb869c583..960602a6d08 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2010-10-03 Teodor Zlatanov <tzz@lifelogs.com> | ||
| 2 | |||
| 3 | * gnutls.h (GNUTLS_LOG2): Convenience macro. | ||
| 4 | |||
| 5 | * gnutls.c: Add property list symbol holders. | ||
| 6 | (emacs_gnutls_handshake): Clarify how sockets are passed to | ||
| 7 | GnuTLS. | ||
| 8 | (gnutls_log_function2): Convenience function using GNUTLS_LOG2. | ||
| 9 | (Fgnutls_boot): Get all parameters from a plist. Require trustfiles | ||
| 10 | and keyfiles to be a list of file names. Default to "NORMAL" for | ||
| 11 | the priority string. Improve logging. | ||
| 12 | |||
| 1 | 2010-10-03 Glenn Morris <rgm@gnu.org> | 13 | 2010-10-03 Glenn Morris <rgm@gnu.org> |
| 2 | 14 | ||
| 3 | * fileio.c (Vdirectory_sep_char): Remove. | 15 | * fileio.c (Vdirectory_sep_char): Remove. |
diff --git a/src/gnutls.c b/src/gnutls.c index f765abe92e8..0913e1a3d2f 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -32,6 +32,13 @@ Lisp_Object Qgnutls_e_interrupted, Qgnutls_e_again, | |||
| 32 | Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake; | 32 | Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake; |
| 33 | int global_initialized; | 33 | int global_initialized; |
| 34 | 34 | ||
| 35 | /* The following are for the property list of `gnutls-boot'. */ | ||
| 36 | Lisp_Object Qgnutls_bootprop_priority; | ||
| 37 | Lisp_Object Qgnutls_bootprop_trustfiles; | ||
| 38 | Lisp_Object Qgnutls_bootprop_keyfiles; | ||
| 39 | Lisp_Object Qgnutls_bootprop_callbacks; | ||
| 40 | Lisp_Object Qgnutls_bootprop_loglevel; | ||
| 41 | |||
| 35 | static void | 42 | static void |
| 36 | emacs_gnutls_handshake (struct Lisp_Process *proc) | 43 | emacs_gnutls_handshake (struct Lisp_Process *proc) |
| 37 | { | 44 | { |
| @@ -43,6 +50,9 @@ emacs_gnutls_handshake (struct Lisp_Process *proc) | |||
| 43 | 50 | ||
| 44 | if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET) | 51 | if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET) |
| 45 | { | 52 | { |
| 53 | /* This is how GnuTLS takes sockets: as file descriptors passed | ||
| 54 | in. For an Emacs process socket, infd and outfd are the | ||
| 55 | same but we use this two-argument version for clarity. */ | ||
| 46 | gnutls_transport_set_ptr2 (state, | 56 | gnutls_transport_set_ptr2 (state, |
| 47 | (gnutls_transport_ptr_t) (long) proc->infd, | 57 | (gnutls_transport_ptr_t) (long) proc->infd, |
| 48 | (gnutls_transport_ptr_t) (long) proc->outfd); | 58 | (gnutls_transport_ptr_t) (long) proc->outfd); |
| @@ -271,20 +281,29 @@ gnutls_log_function (int level, const char* string) | |||
| 271 | message ("gnutls.c: [%d] %s", level, string); | 281 | message ("gnutls.c: [%d] %s", level, string); |
| 272 | } | 282 | } |
| 273 | 283 | ||
| 274 | DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 7, 0, | 284 | static void |
| 275 | doc: /* Initialize client-mode GnuTLS for process PROC. | 285 | gnutls_log_function2 (int level, const char* string, const char* extra) |
| 286 | { | ||
| 287 | message ("gnutls.c: [%d] %s %s", level, string, extra); | ||
| 288 | } | ||
| 289 | |||
| 290 | DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, | ||
| 291 | doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST. | ||
| 276 | Currently only client mode is supported. Returns a success/failure | 292 | Currently only client mode is supported. Returns a success/failure |
| 277 | value you can check with `gnutls-errorp'. | 293 | value you can check with `gnutls-errorp'. |
| 278 | 294 | ||
| 279 | PRIORITY-STRING is a string describing the priority. | 295 | TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'. |
| 280 | TYPE is either `gnutls-anon' or `gnutls-x509pki'. | 296 | PROPLIST is a property list with the following keys: |
| 281 | TRUSTFILE is a PEM encoded trust file for `gnutls-x509pki'. | 297 | |
| 282 | KEYFILE is ... for `gnutls-x509pki' (TODO). | 298 | :priority is a GnuTLS priority string, defaults to "NORMAL". |
| 283 | CALLBACK is ... for `gnutls-x509pki' (TODO). | 299 | :trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'. |
| 284 | LOGLEVEL is the debug level requested from GnuTLS, try 4. | 300 | :keyfiles is a list of PEM-encoded key files for `gnutls-x509pki'. |
| 301 | :callbacks is an alist of callback functions (TODO). | ||
| 302 | :loglevel is the debug level requested from GnuTLS, try 4. | ||
| 285 | 303 | ||
| 286 | LOGLEVEL will be set for this process AND globally for GnuTLS. So if | 304 | The debug level will be set for this process AND globally for GnuTLS. |
| 287 | you set it higher or lower at any point, it affects global debugging. | 305 | So if you set it higher or lower at any point, it affects global |
| 306 | debugging. | ||
| 288 | 307 | ||
| 289 | Note that the priority is set on the client. The server does not use | 308 | Note that the priority is set on the client. The server does not use |
| 290 | the protocols's priority except for disabling protocols that were not | 309 | the protocols's priority except for disabling protocols that were not |
| @@ -295,11 +314,9 @@ functions are used. This function allocates resources which can only | |||
| 295 | be deallocated by calling `gnutls-deinit' or by calling it again. | 314 | be deallocated by calling `gnutls-deinit' or by calling it again. |
| 296 | 315 | ||
| 297 | Each authentication type may need additional information in order to | 316 | Each authentication type may need additional information in order to |
| 298 | work. For X.509 PKI (`gnutls-x509pki'), you need TRUSTFILE and | 317 | work. For X.509 PKI (`gnutls-x509pki'), you probably need at least |
| 299 | KEYFILE and optionally CALLBACK. */) | 318 | one trustfile (usually a CA bundle). */) |
| 300 | (Lisp_Object proc, Lisp_Object priority_string, Lisp_Object type, | 319 | (Lisp_Object proc, Lisp_Object type, Lisp_Object proplist) |
| 301 | Lisp_Object trustfile, Lisp_Object keyfile, Lisp_Object callback, | ||
| 302 | Lisp_Object loglevel) | ||
| 303 | { | 320 | { |
| 304 | int ret = GNUTLS_E_SUCCESS; | 321 | int ret = GNUTLS_E_SUCCESS; |
| 305 | 322 | ||
| @@ -312,10 +329,25 @@ KEYFILE and optionally CALLBACK. */) | |||
| 312 | gnutls_certificate_credentials_t x509_cred; | 329 | gnutls_certificate_credentials_t x509_cred; |
| 313 | gnutls_anon_client_credentials_t anon_cred; | 330 | gnutls_anon_client_credentials_t anon_cred; |
| 314 | Lisp_Object global_init; | 331 | Lisp_Object global_init; |
| 332 | char* priority_string_ptr = "NORMAL"; /* default priority string. */ | ||
| 333 | Lisp_Object tail; | ||
| 334 | |||
| 335 | /* Placeholders for the property list elements. */ | ||
| 336 | Lisp_Object priority_string; | ||
| 337 | Lisp_Object trustfiles; | ||
| 338 | Lisp_Object keyfiles; | ||
| 339 | Lisp_Object callbacks; | ||
| 340 | Lisp_Object loglevel; | ||
| 315 | 341 | ||
| 316 | CHECK_PROCESS (proc); | 342 | CHECK_PROCESS (proc); |
| 317 | CHECK_SYMBOL (type); | 343 | CHECK_SYMBOL (type); |
| 318 | CHECK_STRING (priority_string); | 344 | CHECK_LIST (proplist); |
| 345 | |||
| 346 | priority_string = Fplist_get (proplist, Qgnutls_bootprop_priority); | ||
| 347 | trustfiles = Fplist_get (proplist, Qgnutls_bootprop_trustfiles); | ||
| 348 | keyfiles = Fplist_get (proplist, Qgnutls_bootprop_keyfiles); | ||
| 349 | callbacks = Fplist_get (proplist, Qgnutls_bootprop_callbacks); | ||
| 350 | loglevel = Fplist_get (proplist, Qgnutls_bootprop_loglevel); | ||
| 319 | 351 | ||
| 320 | state = XPROCESS (proc)->gnutls_state; | 352 | state = XPROCESS (proc)->gnutls_state; |
| 321 | XPROCESS (proc)->gnutls_p = 1; | 353 | XPROCESS (proc)->gnutls_p = 1; |
| @@ -394,29 +426,49 @@ KEYFILE and optionally CALLBACK. */) | |||
| 394 | 426 | ||
| 395 | if (EQ (type, Qgnutls_x509pki)) | 427 | if (EQ (type, Qgnutls_x509pki)) |
| 396 | { | 428 | { |
| 397 | if (STRINGP (trustfile)) | 429 | for (tail = trustfiles; !NILP (tail); tail = Fcdr (tail)) |
| 398 | { | 430 | { |
| 399 | GNUTLS_LOG (1, max_log_level, "setting the trustfile"); | 431 | Lisp_Object trustfile = Fcar (tail); |
| 400 | ret = gnutls_certificate_set_x509_trust_file | 432 | if (STRINGP (trustfile)) |
| 401 | (x509_cred, | 433 | { |
| 402 | SDATA (trustfile), | 434 | GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ", |
| 403 | file_format); | 435 | SDATA (trustfile)); |
| 404 | 436 | ret = gnutls_certificate_set_x509_trust_file | |
| 405 | if (ret < GNUTLS_E_SUCCESS) | 437 | (x509_cred, |
| 406 | return gnutls_make_error (ret); | 438 | SDATA (trustfile), |
| 407 | } | 439 | file_format); |
| 440 | |||
| 441 | if (ret < GNUTLS_E_SUCCESS) | ||
| 442 | return gnutls_make_error (ret); | ||
| 443 | } | ||
| 444 | else | ||
| 445 | { | ||
| 446 | error ("Sorry, GnuTLS can't use non-string trustfile %s", | ||
| 447 | trustfile); | ||
| 448 | } | ||
| 449 | } | ||
| 408 | 450 | ||
| 409 | if (STRINGP (keyfile)) | 451 | for (tail = keyfiles; !NILP (tail); tail = Fcdr (tail)) |
| 410 | { | 452 | { |
| 411 | GNUTLS_LOG (1, max_log_level, "setting the keyfile"); | 453 | Lisp_Object keyfile = Fcar (tail); |
| 412 | ret = gnutls_certificate_set_x509_crl_file | 454 | if (STRINGP (keyfile)) |
| 413 | (x509_cred, | 455 | { |
| 414 | SDATA (keyfile), | 456 | GNUTLS_LOG2 (1, max_log_level, "setting the keyfile: ", |
| 415 | file_format); | 457 | SDATA (keyfile)); |
| 416 | 458 | ret = gnutls_certificate_set_x509_crl_file | |
| 417 | if (ret < GNUTLS_E_SUCCESS) | 459 | (x509_cred, |
| 418 | return gnutls_make_error (ret); | 460 | SDATA (keyfile), |
| 419 | } | 461 | file_format); |
| 462 | |||
| 463 | if (ret < GNUTLS_E_SUCCESS) | ||
| 464 | return gnutls_make_error (ret); | ||
| 465 | } | ||
| 466 | else | ||
| 467 | { | ||
| 468 | error ("Sorry, GnuTLS can't use non-string keyfile %s", | ||
| 469 | keyfile); | ||
| 470 | } | ||
| 471 | } | ||
| 420 | } | 472 | } |
| 421 | 473 | ||
| 422 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES; | 474 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES; |
| @@ -432,10 +484,22 @@ KEYFILE and optionally CALLBACK. */) | |||
| 432 | 484 | ||
| 433 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT; | 485 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT; |
| 434 | 486 | ||
| 487 | if (STRINGP (priority_string)) | ||
| 488 | { | ||
| 489 | priority_string_ptr = (char*) SDATA (priority_string); | ||
| 490 | GNUTLS_LOG2 (1, max_log_level, "got non-default priority string:", | ||
| 491 | priority_string_ptr); | ||
| 492 | } | ||
| 493 | else | ||
| 494 | { | ||
| 495 | GNUTLS_LOG2 (1, max_log_level, "using default priority string:", | ||
| 496 | priority_string_ptr); | ||
| 497 | } | ||
| 498 | |||
| 435 | GNUTLS_LOG (1, max_log_level, "setting the priority string"); | 499 | GNUTLS_LOG (1, max_log_level, "setting the priority string"); |
| 436 | 500 | ||
| 437 | ret = gnutls_priority_set_direct (state, | 501 | ret = gnutls_priority_set_direct (state, |
| 438 | (char*) SDATA (priority_string), | 502 | priority_string_ptr, |
| 439 | NULL); | 503 | NULL); |
| 440 | 504 | ||
| 441 | if (ret < GNUTLS_E_SUCCESS) | 505 | if (ret < GNUTLS_E_SUCCESS) |
| @@ -514,6 +578,21 @@ syms_of_gnutls (void) | |||
| 514 | Qgnutls_x509pki = intern_c_string ("gnutls-x509pki"); | 578 | Qgnutls_x509pki = intern_c_string ("gnutls-x509pki"); |
| 515 | staticpro (&Qgnutls_x509pki); | 579 | staticpro (&Qgnutls_x509pki); |
| 516 | 580 | ||
| 581 | Qgnutls_bootprop_priority = intern_c_string ("priority"); | ||
| 582 | staticpro (&Qgnutls_bootprop_priority); | ||
| 583 | |||
| 584 | Qgnutls_bootprop_trustfiles = intern_c_string ("trustfiles"); | ||
| 585 | staticpro (&Qgnutls_bootprop_trustfiles); | ||
| 586 | |||
| 587 | Qgnutls_bootprop_keyfiles = intern_c_string ("keyfiles"); | ||
| 588 | staticpro (&Qgnutls_bootprop_keyfiles); | ||
| 589 | |||
| 590 | Qgnutls_bootprop_callbacks = intern_c_string ("callbacks"); | ||
| 591 | staticpro (&Qgnutls_bootprop_callbacks); | ||
| 592 | |||
| 593 | Qgnutls_bootprop_loglevel = intern_c_string ("loglevel"); | ||
| 594 | staticpro (&Qgnutls_bootprop_loglevel); | ||
| 595 | |||
| 517 | Qgnutls_e_interrupted = intern_c_string ("gnutls-e-interrupted"); | 596 | Qgnutls_e_interrupted = intern_c_string ("gnutls-e-interrupted"); |
| 518 | staticpro (&Qgnutls_e_interrupted); | 597 | staticpro (&Qgnutls_e_interrupted); |
| 519 | Fput (Qgnutls_e_interrupted, Qgnutls_code, | 598 | Fput (Qgnutls_e_interrupted, Qgnutls_code, |
diff --git a/src/gnutls.h b/src/gnutls.h index bcf9776963f..2669317e97a 100644 --- a/src/gnutls.h +++ b/src/gnutls.h | |||
| @@ -48,6 +48,8 @@ typedef enum | |||
| 48 | 48 | ||
| 49 | #define GNUTLS_LOG(level, max, string) if (level <= max) { gnutls_log_function (level, "(Emacs) " string); } | 49 | #define GNUTLS_LOG(level, max, string) if (level <= max) { gnutls_log_function (level, "(Emacs) " string); } |
| 50 | 50 | ||
| 51 | #define GNUTLS_LOG2(level, max, string, extra) if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); } | ||
| 52 | |||
| 51 | int | 53 | int |
| 52 | emacs_gnutls_write (int fildes, struct Lisp_Process *proc, char *buf, | 54 | emacs_gnutls_write (int fildes, struct Lisp_Process *proc, char *buf, |
| 53 | unsigned int nbyte); | 55 | unsigned int nbyte); |