00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus-auth.h"
00026 #include "dbus-string.h"
00027 #include "dbus-list.h"
00028 #include "dbus-internals.h"
00029 #include "dbus-keyring.h"
00030 #include "dbus-sha.h"
00031 #include "dbus-protocol.h"
00032 #include "dbus-credentials.h"
00033
00070 typedef dbus_bool_t (* DBusInitialResponseFunction) (DBusAuth *auth,
00071 DBusString *response);
00072
00077 typedef dbus_bool_t (* DBusAuthDataFunction) (DBusAuth *auth,
00078 const DBusString *data);
00079
00083 typedef dbus_bool_t (* DBusAuthEncodeFunction) (DBusAuth *auth,
00084 const DBusString *data,
00085 DBusString *encoded);
00086
00090 typedef dbus_bool_t (* DBusAuthDecodeFunction) (DBusAuth *auth,
00091 const DBusString *data,
00092 DBusString *decoded);
00093
00097 typedef void (* DBusAuthShutdownFunction) (DBusAuth *auth);
00098
00102 typedef struct
00103 {
00104 const char *mechanism;
00105 DBusAuthDataFunction server_data_func;
00106 DBusAuthEncodeFunction server_encode_func;
00107 DBusAuthDecodeFunction server_decode_func;
00108 DBusAuthShutdownFunction server_shutdown_func;
00109 DBusInitialResponseFunction client_initial_response_func;
00110 DBusAuthDataFunction client_data_func;
00111 DBusAuthEncodeFunction client_encode_func;
00112 DBusAuthDecodeFunction client_decode_func;
00113 DBusAuthShutdownFunction client_shutdown_func;
00114 } DBusAuthMechanismHandler;
00115
00119 typedef enum {
00120 DBUS_AUTH_COMMAND_AUTH,
00121 DBUS_AUTH_COMMAND_CANCEL,
00122 DBUS_AUTH_COMMAND_DATA,
00123 DBUS_AUTH_COMMAND_BEGIN,
00124 DBUS_AUTH_COMMAND_REJECTED,
00125 DBUS_AUTH_COMMAND_OK,
00126 DBUS_AUTH_COMMAND_ERROR,
00127 DBUS_AUTH_COMMAND_UNKNOWN,
00128 DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD,
00129 DBUS_AUTH_COMMAND_AGREE_UNIX_FD
00130 } DBusAuthCommand;
00131
00137 typedef dbus_bool_t (* DBusAuthStateFunction) (DBusAuth *auth,
00138 DBusAuthCommand command,
00139 const DBusString *args);
00140
00144 typedef struct
00145 {
00146 const char *name;
00147 DBusAuthStateFunction handler;
00148 } DBusAuthStateData;
00149
00153 struct DBusAuth
00154 {
00155 int refcount;
00156 const char *side;
00158 DBusString incoming;
00159 DBusString outgoing;
00161 const DBusAuthStateData *state;
00163 const DBusAuthMechanismHandler *mech;
00165 DBusString identity;
00169 DBusCredentials *credentials;
00172 DBusCredentials *authorized_identity;
00174 DBusCredentials *desired_identity;
00176 DBusString context;
00177 DBusKeyring *keyring;
00178 int cookie_id;
00179 DBusString challenge;
00181 char **allowed_mechs;
00185 unsigned int needed_memory : 1;
00188 unsigned int already_got_mechanisms : 1;
00189 unsigned int already_asked_for_initial_response : 1;
00190 unsigned int buffer_outstanding : 1;
00192 unsigned int unix_fd_possible : 1;
00193 unsigned int unix_fd_negotiated : 1;
00194 };
00195
00199 typedef struct
00200 {
00201 DBusAuth base;
00203 DBusList *mechs_to_try;
00205 DBusString guid_from_server;
00207 } DBusAuthClient;
00208
00212 typedef struct
00213 {
00214 DBusAuth base;
00216 int failures;
00217 int max_failures;
00219 DBusString guid;
00221 } DBusAuthServer;
00222
00223 static void goto_state (DBusAuth *auth,
00224 const DBusAuthStateData *new_state);
00225 static dbus_bool_t send_auth (DBusAuth *auth,
00226 const DBusAuthMechanismHandler *mech);
00227 static dbus_bool_t send_data (DBusAuth *auth,
00228 DBusString *data);
00229 static dbus_bool_t send_rejected (DBusAuth *auth);
00230 static dbus_bool_t send_error (DBusAuth *auth,
00231 const char *message);
00232 static dbus_bool_t send_ok (DBusAuth *auth);
00233 static dbus_bool_t send_begin (DBusAuth *auth);
00234 static dbus_bool_t send_cancel (DBusAuth *auth);
00235 static dbus_bool_t send_negotiate_unix_fd (DBusAuth *auth);
00236 static dbus_bool_t send_agree_unix_fd (DBusAuth *auth);
00237
00242 static dbus_bool_t handle_server_state_waiting_for_auth (DBusAuth *auth,
00243 DBusAuthCommand command,
00244 const DBusString *args);
00245 static dbus_bool_t handle_server_state_waiting_for_data (DBusAuth *auth,
00246 DBusAuthCommand command,
00247 const DBusString *args);
00248 static dbus_bool_t handle_server_state_waiting_for_begin (DBusAuth *auth,
00249 DBusAuthCommand command,
00250 const DBusString *args);
00251
00252 static const DBusAuthStateData server_state_waiting_for_auth = {
00253 "WaitingForAuth", handle_server_state_waiting_for_auth
00254 };
00255 static const DBusAuthStateData server_state_waiting_for_data = {
00256 "WaitingForData", handle_server_state_waiting_for_data
00257 };
00258 static const DBusAuthStateData server_state_waiting_for_begin = {
00259 "WaitingForBegin", handle_server_state_waiting_for_begin
00260 };
00261
00266 static dbus_bool_t handle_client_state_waiting_for_data (DBusAuth *auth,
00267 DBusAuthCommand command,
00268 const DBusString *args);
00269 static dbus_bool_t handle_client_state_waiting_for_ok (DBusAuth *auth,
00270 DBusAuthCommand command,
00271 const DBusString *args);
00272 static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *auth,
00273 DBusAuthCommand command,
00274 const DBusString *args);
00275 static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth *auth,
00276 DBusAuthCommand command,
00277 const DBusString *args);
00278
00279 static const DBusAuthStateData client_state_need_send_auth = {
00280 "NeedSendAuth", NULL
00281 };
00282 static const DBusAuthStateData client_state_waiting_for_data = {
00283 "WaitingForData", handle_client_state_waiting_for_data
00284 };
00285
00286
00287 _DBUS_GNUC_UNUSED
00288 static const DBusAuthStateData client_state_waiting_for_ok = {
00289 "WaitingForOK", handle_client_state_waiting_for_ok
00290 };
00291 static const DBusAuthStateData client_state_waiting_for_reject = {
00292 "WaitingForReject", handle_client_state_waiting_for_reject
00293 };
00294 static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = {
00295 "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd
00296 };
00297
00302 static const DBusAuthStateData common_state_authenticated = {
00303 "Authenticated", NULL
00304 };
00305
00306 static const DBusAuthStateData common_state_need_disconnect = {
00307 "NeedDisconnect", NULL
00308 };
00309
00310 static const char auth_side_client[] = "client";
00311 static const char auth_side_server[] = "server";
00316 #define DBUS_AUTH_IS_SERVER(auth) ((auth)->side == auth_side_server)
00317
00321 #define DBUS_AUTH_IS_CLIENT(auth) ((auth)->side == auth_side_client)
00322
00326 #define DBUS_AUTH_CLIENT(auth) ((DBusAuthClient*)(auth))
00327
00331 #define DBUS_AUTH_SERVER(auth) ((DBusAuthServer*)(auth))
00332
00338 #define DBUS_AUTH_NAME(auth) ((auth)->side)
00339
00340 static DBusAuth*
00341 _dbus_auth_new (int size)
00342 {
00343 DBusAuth *auth;
00344
00345 auth = dbus_malloc0 (size);
00346 if (auth == NULL)
00347 return NULL;
00348
00349 auth->refcount = 1;
00350
00351 auth->keyring = NULL;
00352 auth->cookie_id = -1;
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 if (!_dbus_string_init (&auth->incoming))
00363 goto enomem_0;
00364
00365 if (!_dbus_string_init (&auth->outgoing))
00366 goto enomem_1;
00367
00368 if (!_dbus_string_init (&auth->identity))
00369 goto enomem_2;
00370
00371 if (!_dbus_string_init (&auth->context))
00372 goto enomem_3;
00373
00374 if (!_dbus_string_init (&auth->challenge))
00375 goto enomem_4;
00376
00377
00378 if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
00379 goto enomem_5;
00380
00381 auth->credentials = _dbus_credentials_new ();
00382 if (auth->credentials == NULL)
00383 goto enomem_6;
00384
00385 auth->authorized_identity = _dbus_credentials_new ();
00386 if (auth->authorized_identity == NULL)
00387 goto enomem_7;
00388
00389 auth->desired_identity = _dbus_credentials_new ();
00390 if (auth->desired_identity == NULL)
00391 goto enomem_8;
00392
00393 return auth;
00394
00395 #if 0
00396 enomem_9:
00397 _dbus_credentials_unref (auth->desired_identity);
00398 #endif
00399 enomem_8:
00400 _dbus_credentials_unref (auth->authorized_identity);
00401 enomem_7:
00402 _dbus_credentials_unref (auth->credentials);
00403 enomem_6:
00404 ;
00405 enomem_5:
00406 _dbus_string_free (&auth->challenge);
00407 enomem_4:
00408 _dbus_string_free (&auth->context);
00409 enomem_3:
00410 _dbus_string_free (&auth->identity);
00411 enomem_2:
00412 _dbus_string_free (&auth->outgoing);
00413 enomem_1:
00414 _dbus_string_free (&auth->incoming);
00415 enomem_0:
00416 dbus_free (auth);
00417 return NULL;
00418 }
00419
00420 static void
00421 shutdown_mech (DBusAuth *auth)
00422 {
00423
00424 auth->already_asked_for_initial_response = FALSE;
00425 _dbus_string_set_length (&auth->identity, 0);
00426
00427 _dbus_credentials_clear (auth->authorized_identity);
00428 _dbus_credentials_clear (auth->desired_identity);
00429
00430 if (auth->mech != NULL)
00431 {
00432 _dbus_verbose ("%s: Shutting down mechanism %s\n",
00433 DBUS_AUTH_NAME (auth), auth->mech->mechanism);
00434
00435 if (DBUS_AUTH_IS_CLIENT (auth))
00436 (* auth->mech->client_shutdown_func) (auth);
00437 else
00438 (* auth->mech->server_shutdown_func) (auth);
00439
00440 auth->mech = NULL;
00441 }
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 static dbus_bool_t
00453 sha1_compute_hash (DBusAuth *auth,
00454 int cookie_id,
00455 const DBusString *server_challenge,
00456 const DBusString *client_challenge,
00457 DBusString *hash)
00458 {
00459 DBusString cookie;
00460 DBusString to_hash;
00461 dbus_bool_t retval;
00462
00463 _dbus_assert (auth->keyring != NULL);
00464
00465 retval = FALSE;
00466
00467 if (!_dbus_string_init (&cookie))
00468 return FALSE;
00469
00470 if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id,
00471 &cookie))
00472 goto out_0;
00473
00474 if (_dbus_string_get_length (&cookie) == 0)
00475 {
00476 retval = TRUE;
00477 goto out_0;
00478 }
00479
00480 if (!_dbus_string_init (&to_hash))
00481 goto out_0;
00482
00483 if (!_dbus_string_copy (server_challenge, 0,
00484 &to_hash, _dbus_string_get_length (&to_hash)))
00485 goto out_1;
00486
00487 if (!_dbus_string_append (&to_hash, ":"))
00488 goto out_1;
00489
00490 if (!_dbus_string_copy (client_challenge, 0,
00491 &to_hash, _dbus_string_get_length (&to_hash)))
00492 goto out_1;
00493
00494 if (!_dbus_string_append (&to_hash, ":"))
00495 goto out_1;
00496
00497 if (!_dbus_string_copy (&cookie, 0,
00498 &to_hash, _dbus_string_get_length (&to_hash)))
00499 goto out_1;
00500
00501 if (!_dbus_sha_compute (&to_hash, hash))
00502 goto out_1;
00503
00504 retval = TRUE;
00505
00506 out_1:
00507 _dbus_string_zero (&to_hash);
00508 _dbus_string_free (&to_hash);
00509 out_0:
00510 _dbus_string_zero (&cookie);
00511 _dbus_string_free (&cookie);
00512 return retval;
00513 }
00514
00519 #define N_CHALLENGE_BYTES (128/8)
00520
00521 static dbus_bool_t
00522 sha1_handle_first_client_response (DBusAuth *auth,
00523 const DBusString *data)
00524 {
00525
00526
00527
00528 DBusString tmp;
00529 DBusString tmp2;
00530 dbus_bool_t retval = FALSE;
00531 DBusError error = DBUS_ERROR_INIT;
00532
00533 _dbus_string_set_length (&auth->challenge, 0);
00534
00535 if (_dbus_string_get_length (data) > 0)
00536 {
00537 if (_dbus_string_get_length (&auth->identity) > 0)
00538 {
00539
00540 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
00541 DBUS_AUTH_NAME (auth));
00542 return send_rejected (auth);
00543 }
00544 else
00545 {
00546
00547 if (!_dbus_string_copy (data, 0, &auth->identity, 0))
00548 return FALSE;
00549 }
00550 }
00551
00552 if (!_dbus_credentials_add_from_user (auth->desired_identity, data))
00553 {
00554 _dbus_verbose ("%s: Did not get a valid username from client\n",
00555 DBUS_AUTH_NAME (auth));
00556 return send_rejected (auth);
00557 }
00558
00559 if (!_dbus_string_init (&tmp))
00560 return FALSE;
00561
00562 if (!_dbus_string_init (&tmp2))
00563 {
00564 _dbus_string_free (&tmp);
00565 return FALSE;
00566 }
00567
00568
00569
00570
00571
00572 if (auth->keyring &&
00573 !_dbus_keyring_is_for_credentials (auth->keyring,
00574 auth->desired_identity))
00575 {
00576 _dbus_keyring_unref (auth->keyring);
00577 auth->keyring = NULL;
00578 }
00579
00580 if (auth->keyring == NULL)
00581 {
00582 auth->keyring = _dbus_keyring_new_for_credentials (auth->desired_identity,
00583 &auth->context,
00584 &error);
00585
00586 if (auth->keyring == NULL)
00587 {
00588 if (dbus_error_has_name (&error,
00589 DBUS_ERROR_NO_MEMORY))
00590 {
00591 dbus_error_free (&error);
00592 goto out;
00593 }
00594 else
00595 {
00596 _DBUS_ASSERT_ERROR_IS_SET (&error);
00597 _dbus_verbose ("%s: Error loading keyring: %s\n",
00598 DBUS_AUTH_NAME (auth), error.message);
00599 if (send_rejected (auth))
00600 retval = TRUE;
00601 dbus_error_free (&error);
00602 goto out;
00603 }
00604 }
00605 else
00606 {
00607 _dbus_assert (!dbus_error_is_set (&error));
00608 }
00609 }
00610
00611 _dbus_assert (auth->keyring != NULL);
00612
00613 auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error);
00614 if (auth->cookie_id < 0)
00615 {
00616 _DBUS_ASSERT_ERROR_IS_SET (&error);
00617 _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n",
00618 DBUS_AUTH_NAME (auth), error.message);
00619 if (send_rejected (auth))
00620 retval = TRUE;
00621 dbus_error_free (&error);
00622 goto out;
00623 }
00624 else
00625 {
00626 _dbus_assert (!dbus_error_is_set (&error));
00627 }
00628
00629 if (!_dbus_string_copy (&auth->context, 0,
00630 &tmp2, _dbus_string_get_length (&tmp2)))
00631 goto out;
00632
00633 if (!_dbus_string_append (&tmp2, " "))
00634 goto out;
00635
00636 if (!_dbus_string_append_int (&tmp2, auth->cookie_id))
00637 goto out;
00638
00639 if (!_dbus_string_append (&tmp2, " "))
00640 goto out;
00641
00642 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES, &error))
00643 {
00644 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00645 {
00646 dbus_error_free (&error);
00647 goto out;
00648 }
00649 else
00650 {
00651 _DBUS_ASSERT_ERROR_IS_SET (&error);
00652 _dbus_verbose ("%s: Error generating challenge: %s\n",
00653 DBUS_AUTH_NAME (auth), error.message);
00654 if (send_rejected (auth))
00655 retval = TRUE;
00656
00657 dbus_error_free (&error);
00658 goto out;
00659 }
00660 }
00661
00662 _dbus_string_set_length (&auth->challenge, 0);
00663 if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0))
00664 goto out;
00665
00666 if (!_dbus_string_hex_encode (&tmp, 0, &tmp2,
00667 _dbus_string_get_length (&tmp2)))
00668 goto out;
00669
00670 if (!send_data (auth, &tmp2))
00671 goto out;
00672
00673 goto_state (auth, &server_state_waiting_for_data);
00674 retval = TRUE;
00675
00676 out:
00677 _dbus_string_zero (&tmp);
00678 _dbus_string_free (&tmp);
00679 _dbus_string_zero (&tmp2);
00680 _dbus_string_free (&tmp2);
00681
00682 return retval;
00683 }
00684
00685 static dbus_bool_t
00686 sha1_handle_second_client_response (DBusAuth *auth,
00687 const DBusString *data)
00688 {
00689
00690
00691
00692
00693
00694 int i;
00695 DBusString client_challenge;
00696 DBusString client_hash;
00697 dbus_bool_t retval;
00698 DBusString correct_hash;
00699
00700 retval = FALSE;
00701
00702 if (!_dbus_string_find_blank (data, 0, &i))
00703 {
00704 _dbus_verbose ("%s: no space separator in client response\n",
00705 DBUS_AUTH_NAME (auth));
00706 return send_rejected (auth);
00707 }
00708
00709 if (!_dbus_string_init (&client_challenge))
00710 goto out_0;
00711
00712 if (!_dbus_string_init (&client_hash))
00713 goto out_1;
00714
00715 if (!_dbus_string_copy_len (data, 0, i, &client_challenge,
00716 0))
00717 goto out_2;
00718
00719 _dbus_string_skip_blank (data, i, &i);
00720
00721 if (!_dbus_string_copy_len (data, i,
00722 _dbus_string_get_length (data) - i,
00723 &client_hash,
00724 0))
00725 goto out_2;
00726
00727 if (_dbus_string_get_length (&client_challenge) == 0 ||
00728 _dbus_string_get_length (&client_hash) == 0)
00729 {
00730 _dbus_verbose ("%s: zero-length client challenge or hash\n",
00731 DBUS_AUTH_NAME (auth));
00732 if (send_rejected (auth))
00733 retval = TRUE;
00734 goto out_2;
00735 }
00736
00737 if (!_dbus_string_init (&correct_hash))
00738 goto out_2;
00739
00740 if (!sha1_compute_hash (auth, auth->cookie_id,
00741 &auth->challenge,
00742 &client_challenge,
00743 &correct_hash))
00744 goto out_3;
00745
00746
00747 if (_dbus_string_get_length (&correct_hash) == 0)
00748 {
00749 if (send_rejected (auth))
00750 retval = TRUE;
00751 goto out_3;
00752 }
00753
00754 if (!_dbus_string_equal (&client_hash, &correct_hash))
00755 {
00756 if (send_rejected (auth))
00757 retval = TRUE;
00758 goto out_3;
00759 }
00760
00761 if (!_dbus_credentials_add_credentials (auth->authorized_identity,
00762 auth->desired_identity))
00763 goto out_3;
00764
00765
00766
00767 if (!_dbus_credentials_add_credential (auth->authorized_identity,
00768 DBUS_CREDENTIAL_UNIX_PROCESS_ID,
00769 auth->credentials))
00770 goto out_3;
00771
00772 if (!send_ok (auth))
00773 goto out_3;
00774
00775 _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n",
00776 DBUS_AUTH_NAME (auth));
00777
00778 retval = TRUE;
00779
00780 out_3:
00781 _dbus_string_zero (&correct_hash);
00782 _dbus_string_free (&correct_hash);
00783 out_2:
00784 _dbus_string_zero (&client_hash);
00785 _dbus_string_free (&client_hash);
00786 out_1:
00787 _dbus_string_free (&client_challenge);
00788 out_0:
00789 return retval;
00790 }
00791
00792 static dbus_bool_t
00793 handle_server_data_cookie_sha1_mech (DBusAuth *auth,
00794 const DBusString *data)
00795 {
00796 if (auth->cookie_id < 0)
00797 return sha1_handle_first_client_response (auth, data);
00798 else
00799 return sha1_handle_second_client_response (auth, data);
00800 }
00801
00802 static void
00803 handle_server_shutdown_cookie_sha1_mech (DBusAuth *auth)
00804 {
00805 auth->cookie_id = -1;
00806 _dbus_string_set_length (&auth->challenge, 0);
00807 }
00808
00809 static dbus_bool_t
00810 handle_client_initial_response_cookie_sha1_mech (DBusAuth *auth,
00811 DBusString *response)
00812 {
00813 DBusString username;
00814 dbus_bool_t retval;
00815
00816 retval = FALSE;
00817
00818 if (!_dbus_string_init (&username))
00819 return FALSE;
00820
00821 if (!_dbus_append_user_from_current_process (&username))
00822 goto out_0;
00823
00824 if (!_dbus_string_hex_encode (&username, 0,
00825 response,
00826 _dbus_string_get_length (response)))
00827 goto out_0;
00828
00829 retval = TRUE;
00830
00831 out_0:
00832 _dbus_string_free (&username);
00833
00834 return retval;
00835 }
00836
00837 static dbus_bool_t
00838 handle_client_data_cookie_sha1_mech (DBusAuth *auth,
00839 const DBusString *data)
00840 {
00841
00842
00843
00844
00845 dbus_bool_t retval = FALSE;
00846 DBusString context;
00847 DBusString cookie_id_str;
00848 DBusString server_challenge;
00849 DBusString client_challenge;
00850 DBusString correct_hash;
00851 DBusString tmp;
00852 int i, j;
00853 long val;
00854 DBusError error = DBUS_ERROR_INIT;
00855
00856 if (!_dbus_string_find_blank (data, 0, &i))
00857 {
00858 if (send_error (auth,
00859 "Server did not send context/ID/challenge properly"))
00860 retval = TRUE;
00861 goto out_0;
00862 }
00863
00864 if (!_dbus_string_init (&context))
00865 goto out_0;
00866
00867 if (!_dbus_string_copy_len (data, 0, i,
00868 &context, 0))
00869 goto out_1;
00870
00871 _dbus_string_skip_blank (data, i, &i);
00872 if (!_dbus_string_find_blank (data, i, &j))
00873 {
00874 if (send_error (auth,
00875 "Server did not send context/ID/challenge properly"))
00876 retval = TRUE;
00877 goto out_1;
00878 }
00879
00880 if (!_dbus_string_init (&cookie_id_str))
00881 goto out_1;
00882
00883 if (!_dbus_string_copy_len (data, i, j - i,
00884 &cookie_id_str, 0))
00885 goto out_2;
00886
00887 if (!_dbus_string_init (&server_challenge))
00888 goto out_2;
00889
00890 i = j;
00891 _dbus_string_skip_blank (data, i, &i);
00892 j = _dbus_string_get_length (data);
00893
00894 if (!_dbus_string_copy_len (data, i, j - i,
00895 &server_challenge, 0))
00896 goto out_3;
00897
00898 if (!_dbus_keyring_validate_context (&context))
00899 {
00900 if (send_error (auth, "Server sent invalid cookie context"))
00901 retval = TRUE;
00902 goto out_3;
00903 }
00904
00905 if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL))
00906 {
00907 if (send_error (auth, "Could not parse cookie ID as an integer"))
00908 retval = TRUE;
00909 goto out_3;
00910 }
00911
00912 if (_dbus_string_get_length (&server_challenge) == 0)
00913 {
00914 if (send_error (auth, "Empty server challenge string"))
00915 retval = TRUE;
00916 goto out_3;
00917 }
00918
00919 if (auth->keyring == NULL)
00920 {
00921 auth->keyring = _dbus_keyring_new_for_credentials (NULL,
00922 &context,
00923 &error);
00924
00925 if (auth->keyring == NULL)
00926 {
00927 if (dbus_error_has_name (&error,
00928 DBUS_ERROR_NO_MEMORY))
00929 {
00930 dbus_error_free (&error);
00931 goto out_3;
00932 }
00933 else
00934 {
00935 _DBUS_ASSERT_ERROR_IS_SET (&error);
00936
00937 _dbus_verbose ("%s: Error loading keyring: %s\n",
00938 DBUS_AUTH_NAME (auth), error.message);
00939
00940 if (send_error (auth, "Could not load cookie file"))
00941 retval = TRUE;
00942
00943 dbus_error_free (&error);
00944 goto out_3;
00945 }
00946 }
00947 else
00948 {
00949 _dbus_assert (!dbus_error_is_set (&error));
00950 }
00951 }
00952
00953 _dbus_assert (auth->keyring != NULL);
00954
00955 if (!_dbus_string_init (&tmp))
00956 goto out_3;
00957
00958 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES, &error))
00959 {
00960 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00961 {
00962 dbus_error_free (&error);
00963 goto out_4;
00964 }
00965 else
00966 {
00967 _DBUS_ASSERT_ERROR_IS_SET (&error);
00968
00969 _dbus_verbose ("%s: Failed to generate challenge: %s\n",
00970 DBUS_AUTH_NAME (auth), error.message);
00971
00972 if (send_error (auth, "Failed to generate challenge"))
00973 retval = TRUE;
00974
00975 dbus_error_free (&error);
00976 goto out_4;
00977 }
00978 }
00979
00980 if (!_dbus_string_init (&client_challenge))
00981 goto out_4;
00982
00983 if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0))
00984 goto out_5;
00985
00986 if (!_dbus_string_init (&correct_hash))
00987 goto out_5;
00988
00989 if (!sha1_compute_hash (auth, val,
00990 &server_challenge,
00991 &client_challenge,
00992 &correct_hash))
00993 goto out_6;
00994
00995 if (_dbus_string_get_length (&correct_hash) == 0)
00996 {
00997
00998 if (send_error (auth, "Don't have the requested cookie ID"))
00999 retval = TRUE;
01000 goto out_6;
01001 }
01002
01003 _dbus_string_set_length (&tmp, 0);
01004
01005 if (!_dbus_string_copy (&client_challenge, 0, &tmp,
01006 _dbus_string_get_length (&tmp)))
01007 goto out_6;
01008
01009 if (!_dbus_string_append (&tmp, " "))
01010 goto out_6;
01011
01012 if (!_dbus_string_copy (&correct_hash, 0, &tmp,
01013 _dbus_string_get_length (&tmp)))
01014 goto out_6;
01015
01016 if (!send_data (auth, &tmp))
01017 goto out_6;
01018
01019 retval = TRUE;
01020
01021 out_6:
01022 _dbus_string_zero (&correct_hash);
01023 _dbus_string_free (&correct_hash);
01024 out_5:
01025 _dbus_string_free (&client_challenge);
01026 out_4:
01027 _dbus_string_zero (&tmp);
01028 _dbus_string_free (&tmp);
01029 out_3:
01030 _dbus_string_free (&server_challenge);
01031 out_2:
01032 _dbus_string_free (&cookie_id_str);
01033 out_1:
01034 _dbus_string_free (&context);
01035 out_0:
01036 return retval;
01037 }
01038
01039 static void
01040 handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)
01041 {
01042 auth->cookie_id = -1;
01043 _dbus_string_set_length (&auth->challenge, 0);
01044 }
01045
01046
01047
01048
01049
01050 static dbus_bool_t
01051 handle_server_data_external_mech (DBusAuth *auth,
01052 const DBusString *data)
01053 {
01054 if (_dbus_credentials_are_anonymous (auth->credentials))
01055 {
01056 _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
01057 DBUS_AUTH_NAME (auth));
01058 return send_rejected (auth);
01059 }
01060
01061 if (_dbus_string_get_length (data) > 0)
01062 {
01063 if (_dbus_string_get_length (&auth->identity) > 0)
01064 {
01065
01066 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
01067 DBUS_AUTH_NAME (auth));
01068 return send_rejected (auth);
01069 }
01070 else
01071 {
01072
01073 if (!_dbus_string_copy (data, 0, &auth->identity, 0))
01074 return FALSE;
01075 }
01076 }
01077
01078
01079 if (_dbus_string_get_length (&auth->identity) == 0 &&
01080 !auth->already_asked_for_initial_response)
01081 {
01082 if (send_data (auth, NULL))
01083 {
01084 _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n",
01085 DBUS_AUTH_NAME (auth));
01086 auth->already_asked_for_initial_response = TRUE;
01087 goto_state (auth, &server_state_waiting_for_data);
01088 return TRUE;
01089 }
01090 else
01091 return FALSE;
01092 }
01093
01094 _dbus_credentials_clear (auth->desired_identity);
01095
01096
01097
01098
01099
01100
01101 if (_dbus_string_get_length (&auth->identity) == 0)
01102 {
01103 if (!_dbus_credentials_add_credentials (auth->desired_identity,
01104 auth->credentials))
01105 {
01106 return FALSE;
01107 }
01108 }
01109 else
01110 {
01111 if (!_dbus_credentials_add_from_user (auth->desired_identity,
01112 &auth->identity))
01113 {
01114 _dbus_verbose ("%s: could not get credentials from uid string\n",
01115 DBUS_AUTH_NAME (auth));
01116 return send_rejected (auth);
01117 }
01118 }
01119
01120 if (_dbus_credentials_are_anonymous (auth->desired_identity))
01121 {
01122 _dbus_verbose ("%s: desired user %s is no good\n",
01123 DBUS_AUTH_NAME (auth),
01124 _dbus_string_get_const_data (&auth->identity));
01125 return send_rejected (auth);
01126 }
01127
01128 if (_dbus_credentials_are_superset (auth->credentials,
01129 auth->desired_identity))
01130 {
01131
01132 if (!_dbus_credentials_add_credentials (auth->authorized_identity,
01133 auth->desired_identity))
01134 return FALSE;
01135
01136
01137
01138 if (!_dbus_credentials_add_credential (auth->authorized_identity,
01139 DBUS_CREDENTIAL_UNIX_PROCESS_ID,
01140 auth->credentials))
01141 return FALSE;
01142
01143 if (!_dbus_credentials_add_credential (auth->authorized_identity,
01144 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
01145 auth->credentials))
01146 return FALSE;
01147
01148 if (!_dbus_credentials_add_credential (auth->authorized_identity,
01149 DBUS_CREDENTIAL_LINUX_SECURITY_LABEL,
01150 auth->credentials))
01151 return FALSE;
01152
01153 if (!send_ok (auth))
01154 return FALSE;
01155
01156 _dbus_verbose ("%s: authenticated client based on socket credentials\n",
01157 DBUS_AUTH_NAME (auth));
01158
01159 return TRUE;
01160 }
01161 else
01162 {
01163 _dbus_verbose ("%s: desired identity not found in socket credentials\n",
01164 DBUS_AUTH_NAME (auth));
01165 return send_rejected (auth);
01166 }
01167 }
01168
01169 static void
01170 handle_server_shutdown_external_mech (DBusAuth *auth)
01171 {
01172
01173 }
01174
01175 static dbus_bool_t
01176 handle_client_initial_response_external_mech (DBusAuth *auth,
01177 DBusString *response)
01178 {
01179
01180
01181
01182
01183
01184 DBusString plaintext;
01185
01186 if (!_dbus_string_init (&plaintext))
01187 return FALSE;
01188
01189 if (!_dbus_append_user_from_current_process (&plaintext))
01190 goto failed;
01191
01192 if (!_dbus_string_hex_encode (&plaintext, 0,
01193 response,
01194 _dbus_string_get_length (response)))
01195 goto failed;
01196
01197 _dbus_string_free (&plaintext);
01198
01199 return TRUE;
01200
01201 failed:
01202 _dbus_string_free (&plaintext);
01203 return FALSE;
01204 }
01205
01206 static dbus_bool_t
01207 handle_client_data_external_mech (DBusAuth *auth,
01208 const DBusString *data)
01209 {
01210
01211 return TRUE;
01212 }
01213
01214 static void
01215 handle_client_shutdown_external_mech (DBusAuth *auth)
01216 {
01217
01218 }
01219
01220
01221
01222
01223
01224 static dbus_bool_t
01225 handle_server_data_anonymous_mech (DBusAuth *auth,
01226 const DBusString *data)
01227 {
01228 if (_dbus_string_get_length (data) > 0)
01229 {
01230
01231
01232
01233
01234
01235 if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data)))
01236 {
01237 _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n",
01238 DBUS_AUTH_NAME (auth));
01239 return send_rejected (auth);
01240 }
01241
01242 _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
01243 DBUS_AUTH_NAME (auth),
01244 _dbus_string_get_const_data (data));
01245 }
01246
01247
01248 _dbus_credentials_clear (auth->desired_identity);
01249
01250
01251
01252 if (!_dbus_credentials_add_credential (auth->authorized_identity,
01253 DBUS_CREDENTIAL_UNIX_PROCESS_ID,
01254 auth->credentials))
01255 return FALSE;
01256
01257
01258 if (!send_ok (auth))
01259 return FALSE;
01260
01261 _dbus_verbose ("%s: authenticated client as anonymous\n",
01262 DBUS_AUTH_NAME (auth));
01263
01264 return TRUE;
01265 }
01266
01267 static void
01268 handle_server_shutdown_anonymous_mech (DBusAuth *auth)
01269 {
01270
01271 }
01272
01273 static dbus_bool_t
01274 handle_client_initial_response_anonymous_mech (DBusAuth *auth,
01275 DBusString *response)
01276 {
01277
01278
01279
01280
01281
01282
01283 DBusString plaintext;
01284
01285 if (!_dbus_string_init (&plaintext))
01286 return FALSE;
01287
01288 if (!_dbus_string_append (&plaintext,
01289 "libdbus " DBUS_VERSION_STRING))
01290 goto failed;
01291
01292 if (!_dbus_string_hex_encode (&plaintext, 0,
01293 response,
01294 _dbus_string_get_length (response)))
01295 goto failed;
01296
01297 _dbus_string_free (&plaintext);
01298
01299 return TRUE;
01300
01301 failed:
01302 _dbus_string_free (&plaintext);
01303 return FALSE;
01304 }
01305
01306 static dbus_bool_t
01307 handle_client_data_anonymous_mech (DBusAuth *auth,
01308 const DBusString *data)
01309 {
01310
01311 return TRUE;
01312 }
01313
01314 static void
01315 handle_client_shutdown_anonymous_mech (DBusAuth *auth)
01316 {
01317
01318 }
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 static const DBusAuthMechanismHandler
01332 all_mechanisms[] = {
01333 { "EXTERNAL",
01334 handle_server_data_external_mech,
01335 NULL, NULL,
01336 handle_server_shutdown_external_mech,
01337 handle_client_initial_response_external_mech,
01338 handle_client_data_external_mech,
01339 NULL, NULL,
01340 handle_client_shutdown_external_mech },
01341 { "DBUS_COOKIE_SHA1",
01342 handle_server_data_cookie_sha1_mech,
01343 NULL, NULL,
01344 handle_server_shutdown_cookie_sha1_mech,
01345 handle_client_initial_response_cookie_sha1_mech,
01346 handle_client_data_cookie_sha1_mech,
01347 NULL, NULL,
01348 handle_client_shutdown_cookie_sha1_mech },
01349 { "ANONYMOUS",
01350 handle_server_data_anonymous_mech,
01351 NULL, NULL,
01352 handle_server_shutdown_anonymous_mech,
01353 handle_client_initial_response_anonymous_mech,
01354 handle_client_data_anonymous_mech,
01355 NULL, NULL,
01356 handle_client_shutdown_anonymous_mech },
01357 { NULL, NULL }
01358 };
01359
01360 static const DBusAuthMechanismHandler*
01361 find_mech (const DBusString *name,
01362 char **allowed_mechs)
01363 {
01364 int i;
01365
01366 if (allowed_mechs != NULL &&
01367 !_dbus_string_array_contains ((const char**) allowed_mechs,
01368 _dbus_string_get_const_data (name)))
01369 return NULL;
01370
01371 i = 0;
01372 while (all_mechanisms[i].mechanism != NULL)
01373 {
01374 if (_dbus_string_equal_c_str (name,
01375 all_mechanisms[i].mechanism))
01376
01377 return &all_mechanisms[i];
01378
01379 ++i;
01380 }
01381
01382 return NULL;
01383 }
01384
01385 static dbus_bool_t
01386 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
01387 {
01388 DBusString auth_command;
01389
01390 if (!_dbus_string_init (&auth_command))
01391 return FALSE;
01392
01393 if (!_dbus_string_append (&auth_command,
01394 "AUTH "))
01395 {
01396 _dbus_string_free (&auth_command);
01397 return FALSE;
01398 }
01399
01400 if (!_dbus_string_append (&auth_command,
01401 mech->mechanism))
01402 {
01403 _dbus_string_free (&auth_command);
01404 return FALSE;
01405 }
01406
01407 if (mech->client_initial_response_func != NULL)
01408 {
01409 if (!_dbus_string_append (&auth_command, " "))
01410 {
01411 _dbus_string_free (&auth_command);
01412 return FALSE;
01413 }
01414
01415 if (!(* mech->client_initial_response_func) (auth, &auth_command))
01416 {
01417 _dbus_string_free (&auth_command);
01418 return FALSE;
01419 }
01420 }
01421
01422 if (!_dbus_string_append (&auth_command,
01423 "\r\n"))
01424 {
01425 _dbus_string_free (&auth_command);
01426 return FALSE;
01427 }
01428
01429 if (!_dbus_string_copy (&auth_command, 0,
01430 &auth->outgoing,
01431 _dbus_string_get_length (&auth->outgoing)))
01432 {
01433 _dbus_string_free (&auth_command);
01434 return FALSE;
01435 }
01436
01437 _dbus_string_free (&auth_command);
01438 shutdown_mech (auth);
01439 auth->mech = mech;
01440 goto_state (auth, &client_state_waiting_for_data);
01441
01442 return TRUE;
01443 }
01444
01445 static dbus_bool_t
01446 send_data (DBusAuth *auth, DBusString *data)
01447 {
01448 int old_len;
01449
01450 if (data == NULL || _dbus_string_get_length (data) == 0)
01451 return _dbus_string_append (&auth->outgoing, "DATA\r\n");
01452 else
01453 {
01454 old_len = _dbus_string_get_length (&auth->outgoing);
01455 if (!_dbus_string_append (&auth->outgoing, "DATA "))
01456 goto out;
01457
01458 if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
01459 _dbus_string_get_length (&auth->outgoing)))
01460 goto out;
01461
01462 if (!_dbus_string_append (&auth->outgoing, "\r\n"))
01463 goto out;
01464
01465 return TRUE;
01466
01467 out:
01468 _dbus_string_set_length (&auth->outgoing, old_len);
01469
01470 return FALSE;
01471 }
01472 }
01473
01474 static dbus_bool_t
01475 send_rejected (DBusAuth *auth)
01476 {
01477 DBusString command;
01478 DBusAuthServer *server_auth;
01479 int i;
01480
01481 if (!_dbus_string_init (&command))
01482 return FALSE;
01483
01484 if (!_dbus_string_append (&command,
01485 "REJECTED"))
01486 goto nomem;
01487
01488 i = 0;
01489 while (all_mechanisms[i].mechanism != NULL)
01490 {
01491 if (!_dbus_string_append (&command,
01492 " "))
01493 goto nomem;
01494
01495 if (!_dbus_string_append (&command,
01496 all_mechanisms[i].mechanism))
01497 goto nomem;
01498
01499 ++i;
01500 }
01501
01502 if (!_dbus_string_append (&command, "\r\n"))
01503 goto nomem;
01504
01505 if (!_dbus_string_copy (&command, 0, &auth->outgoing,
01506 _dbus_string_get_length (&auth->outgoing)))
01507 goto nomem;
01508
01509 shutdown_mech (auth);
01510
01511 _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
01512 server_auth = DBUS_AUTH_SERVER (auth);
01513 server_auth->failures += 1;
01514
01515 if (server_auth->failures >= server_auth->max_failures)
01516 goto_state (auth, &common_state_need_disconnect);
01517 else
01518 goto_state (auth, &server_state_waiting_for_auth);
01519
01520 _dbus_string_free (&command);
01521
01522 return TRUE;
01523
01524 nomem:
01525 _dbus_string_free (&command);
01526 return FALSE;
01527 }
01528
01529 static dbus_bool_t
01530 send_error (DBusAuth *auth, const char *message)
01531 {
01532 return _dbus_string_append_printf (&auth->outgoing,
01533 "ERROR \"%s\"\r\n", message);
01534 }
01535
01536 static dbus_bool_t
01537 send_ok (DBusAuth *auth)
01538 {
01539 int orig_len;
01540
01541 orig_len = _dbus_string_get_length (&auth->outgoing);
01542
01543 if (_dbus_string_append (&auth->outgoing, "OK ") &&
01544 _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
01545 0,
01546 &auth->outgoing,
01547 _dbus_string_get_length (&auth->outgoing)) &&
01548 _dbus_string_append (&auth->outgoing, "\r\n"))
01549 {
01550 goto_state (auth, &server_state_waiting_for_begin);
01551 return TRUE;
01552 }
01553 else
01554 {
01555 _dbus_string_set_length (&auth->outgoing, orig_len);
01556 return FALSE;
01557 }
01558 }
01559
01560 static dbus_bool_t
01561 send_begin (DBusAuth *auth)
01562 {
01563
01564 if (!_dbus_string_append (&auth->outgoing,
01565 "BEGIN\r\n"))
01566 return FALSE;
01567
01568 goto_state (auth, &common_state_authenticated);
01569 return TRUE;
01570 }
01571
01572 static dbus_bool_t
01573 process_ok(DBusAuth *auth,
01574 const DBusString *args_from_ok) {
01575
01576 int end_of_hex;
01577
01578
01579 _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
01580
01581
01582
01583 end_of_hex = 0;
01584 if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
01585 & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
01586 return FALSE;
01587
01588
01589 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
01590
01591 if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
01592 end_of_hex == 0)
01593 {
01594 _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
01595 end_of_hex, _dbus_string_get_length (args_from_ok));
01596 goto_state (auth, &common_state_need_disconnect);
01597 return TRUE;
01598 }
01599
01600 if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
01601 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
01602 return FALSE;
01603 }
01604
01605 _dbus_verbose ("Got GUID '%s' from the server\n",
01606 _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
01607
01608 if (auth->unix_fd_possible)
01609 return send_negotiate_unix_fd(auth);
01610
01611 _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
01612 return send_begin (auth);
01613 }
01614
01615 static dbus_bool_t
01616 send_cancel (DBusAuth *auth)
01617 {
01618 if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
01619 {
01620 goto_state (auth, &client_state_waiting_for_reject);
01621 return TRUE;
01622 }
01623 else
01624 return FALSE;
01625 }
01626
01627 static dbus_bool_t
01628 process_data (DBusAuth *auth,
01629 const DBusString *args,
01630 DBusAuthDataFunction data_func)
01631 {
01632 int end;
01633 DBusString decoded;
01634
01635 if (!_dbus_string_init (&decoded))
01636 return FALSE;
01637
01638 if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
01639 {
01640 _dbus_string_free (&decoded);
01641 return FALSE;
01642 }
01643
01644 if (_dbus_string_get_length (args) != end)
01645 {
01646 _dbus_string_free (&decoded);
01647 if (!send_error (auth, "Invalid hex encoding"))
01648 return FALSE;
01649
01650 return TRUE;
01651 }
01652
01653 #ifdef DBUS_ENABLE_VERBOSE_MODE
01654 if (_dbus_string_validate_ascii (&decoded, 0,
01655 _dbus_string_get_length (&decoded)))
01656 _dbus_verbose ("%s: data: '%s'\n",
01657 DBUS_AUTH_NAME (auth),
01658 _dbus_string_get_const_data (&decoded));
01659 #endif
01660
01661 if (!(* data_func) (auth, &decoded))
01662 {
01663 _dbus_string_free (&decoded);
01664 return FALSE;
01665 }
01666
01667 _dbus_string_free (&decoded);
01668 return TRUE;
01669 }
01670
01671 static dbus_bool_t
01672 send_negotiate_unix_fd (DBusAuth *auth)
01673 {
01674 if (!_dbus_string_append (&auth->outgoing,
01675 "NEGOTIATE_UNIX_FD\r\n"))
01676 return FALSE;
01677
01678 goto_state (auth, &client_state_waiting_for_agree_unix_fd);
01679 return TRUE;
01680 }
01681
01682 static dbus_bool_t
01683 send_agree_unix_fd (DBusAuth *auth)
01684 {
01685 _dbus_assert(auth->unix_fd_possible);
01686
01687 auth->unix_fd_negotiated = TRUE;
01688 _dbus_verbose("Agreed to UNIX FD passing\n");
01689
01690 if (!_dbus_string_append (&auth->outgoing,
01691 "AGREE_UNIX_FD\r\n"))
01692 return FALSE;
01693
01694 goto_state (auth, &server_state_waiting_for_begin);
01695 return TRUE;
01696 }
01697
01698 static dbus_bool_t
01699 handle_auth (DBusAuth *auth, const DBusString *args)
01700 {
01701 if (_dbus_string_get_length (args) == 0)
01702 {
01703
01704 if (!send_rejected (auth))
01705 return FALSE;
01706
01707 return TRUE;
01708 }
01709 else
01710 {
01711 int i;
01712 DBusString mech;
01713 DBusString hex_response;
01714
01715 _dbus_string_find_blank (args, 0, &i);
01716
01717 if (!_dbus_string_init (&mech))
01718 return FALSE;
01719
01720 if (!_dbus_string_init (&hex_response))
01721 {
01722 _dbus_string_free (&mech);
01723 return FALSE;
01724 }
01725
01726 if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
01727 goto failed;
01728
01729 _dbus_string_skip_blank (args, i, &i);
01730 if (!_dbus_string_copy (args, i, &hex_response, 0))
01731 goto failed;
01732
01733 auth->mech = find_mech (&mech, auth->allowed_mechs);
01734 if (auth->mech != NULL)
01735 {
01736 _dbus_verbose ("%s: Trying mechanism %s\n",
01737 DBUS_AUTH_NAME (auth),
01738 auth->mech->mechanism);
01739
01740 if (!process_data (auth, &hex_response,
01741 auth->mech->server_data_func))
01742 goto failed;
01743 }
01744 else
01745 {
01746
01747 _dbus_verbose ("%s: Unsupported mechanism %s\n",
01748 DBUS_AUTH_NAME (auth),
01749 _dbus_string_get_const_data (&mech));
01750
01751 if (!send_rejected (auth))
01752 goto failed;
01753 }
01754
01755 _dbus_string_free (&mech);
01756 _dbus_string_free (&hex_response);
01757
01758 return TRUE;
01759
01760 failed:
01761 auth->mech = NULL;
01762 _dbus_string_free (&mech);
01763 _dbus_string_free (&hex_response);
01764 return FALSE;
01765 }
01766 }
01767
01768 static dbus_bool_t
01769 handle_server_state_waiting_for_auth (DBusAuth *auth,
01770 DBusAuthCommand command,
01771 const DBusString *args)
01772 {
01773 switch (command)
01774 {
01775 case DBUS_AUTH_COMMAND_AUTH:
01776 return handle_auth (auth, args);
01777
01778 case DBUS_AUTH_COMMAND_CANCEL:
01779 case DBUS_AUTH_COMMAND_DATA:
01780 return send_error (auth, "Not currently in an auth conversation");
01781
01782 case DBUS_AUTH_COMMAND_BEGIN:
01783 goto_state (auth, &common_state_need_disconnect);
01784 return TRUE;
01785
01786 case DBUS_AUTH_COMMAND_ERROR:
01787 return send_rejected (auth);
01788
01789 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01790 return send_error (auth, "Need to authenticate first");
01791
01792 case DBUS_AUTH_COMMAND_REJECTED:
01793 case DBUS_AUTH_COMMAND_OK:
01794 case DBUS_AUTH_COMMAND_UNKNOWN:
01795 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01796 default:
01797 return send_error (auth, "Unknown command");
01798 }
01799 }
01800
01801 static dbus_bool_t
01802 handle_server_state_waiting_for_data (DBusAuth *auth,
01803 DBusAuthCommand command,
01804 const DBusString *args)
01805 {
01806 switch (command)
01807 {
01808 case DBUS_AUTH_COMMAND_AUTH:
01809 return send_error (auth, "Sent AUTH while another AUTH in progress");
01810
01811 case DBUS_AUTH_COMMAND_CANCEL:
01812 case DBUS_AUTH_COMMAND_ERROR:
01813 return send_rejected (auth);
01814
01815 case DBUS_AUTH_COMMAND_DATA:
01816 return process_data (auth, args, auth->mech->server_data_func);
01817
01818 case DBUS_AUTH_COMMAND_BEGIN:
01819 goto_state (auth, &common_state_need_disconnect);
01820 return TRUE;
01821
01822 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01823 return send_error (auth, "Need to authenticate first");
01824
01825 case DBUS_AUTH_COMMAND_REJECTED:
01826 case DBUS_AUTH_COMMAND_OK:
01827 case DBUS_AUTH_COMMAND_UNKNOWN:
01828 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01829 default:
01830 return send_error (auth, "Unknown command");
01831 }
01832 }
01833
01834 static dbus_bool_t
01835 handle_server_state_waiting_for_begin (DBusAuth *auth,
01836 DBusAuthCommand command,
01837 const DBusString *args)
01838 {
01839 switch (command)
01840 {
01841 case DBUS_AUTH_COMMAND_AUTH:
01842 return send_error (auth, "Sent AUTH while expecting BEGIN");
01843
01844 case DBUS_AUTH_COMMAND_DATA:
01845 return send_error (auth, "Sent DATA while expecting BEGIN");
01846
01847 case DBUS_AUTH_COMMAND_BEGIN:
01848 goto_state (auth, &common_state_authenticated);
01849 return TRUE;
01850
01851 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01852 if (auth->unix_fd_possible)
01853 return send_agree_unix_fd(auth);
01854 else
01855 return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
01856
01857 case DBUS_AUTH_COMMAND_REJECTED:
01858 case DBUS_AUTH_COMMAND_OK:
01859 case DBUS_AUTH_COMMAND_UNKNOWN:
01860 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01861 default:
01862 return send_error (auth, "Unknown command");
01863
01864 case DBUS_AUTH_COMMAND_CANCEL:
01865 case DBUS_AUTH_COMMAND_ERROR:
01866 return send_rejected (auth);
01867 }
01868 }
01869
01870
01871 static dbus_bool_t
01872 get_word (const DBusString *str,
01873 int *start,
01874 DBusString *word)
01875 {
01876 int i;
01877
01878 _dbus_string_skip_blank (str, *start, start);
01879 _dbus_string_find_blank (str, *start, &i);
01880
01881 if (i > *start)
01882 {
01883 if (!_dbus_string_copy_len (str, *start, i - *start, word, 0))
01884 return FALSE;
01885
01886 *start = i;
01887 }
01888
01889 return TRUE;
01890 }
01891
01892 static dbus_bool_t
01893 record_mechanisms (DBusAuth *auth,
01894 const DBusString *args)
01895 {
01896 int next;
01897 int len;
01898
01899 if (auth->already_got_mechanisms)
01900 return TRUE;
01901
01902 len = _dbus_string_get_length (args);
01903
01904 next = 0;
01905 while (next < len)
01906 {
01907 DBusString m;
01908 const DBusAuthMechanismHandler *mech;
01909
01910 if (!_dbus_string_init (&m))
01911 goto nomem;
01912
01913 if (!get_word (args, &next, &m))
01914 {
01915 _dbus_string_free (&m);
01916 goto nomem;
01917 }
01918
01919 mech = find_mech (&m, auth->allowed_mechs);
01920
01921 if (mech != NULL)
01922 {
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932 if (mech != &all_mechanisms[0])
01933 {
01934 _dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
01935 DBUS_AUTH_NAME (auth), mech->mechanism);
01936
01937 if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
01938 (void*) mech))
01939 {
01940 _dbus_string_free (&m);
01941 goto nomem;
01942 }
01943 }
01944 else
01945 {
01946 _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n",
01947 DBUS_AUTH_NAME (auth), mech->mechanism);
01948 }
01949 }
01950 else
01951 {
01952 _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n",
01953 DBUS_AUTH_NAME (auth),
01954 _dbus_string_get_const_data (&m));
01955 }
01956
01957 _dbus_string_free (&m);
01958 }
01959
01960 auth->already_got_mechanisms = TRUE;
01961
01962 return TRUE;
01963
01964 nomem:
01965 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
01966
01967 return FALSE;
01968 }
01969
01970 static dbus_bool_t
01971 process_rejected (DBusAuth *auth, const DBusString *args)
01972 {
01973 const DBusAuthMechanismHandler *mech;
01974 DBusAuthClient *client;
01975
01976 client = DBUS_AUTH_CLIENT (auth);
01977
01978 if (!auth->already_got_mechanisms)
01979 {
01980 if (!record_mechanisms (auth, args))
01981 return FALSE;
01982 }
01983
01984 if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
01985 {
01986 mech = client->mechs_to_try->data;
01987
01988 if (!send_auth (auth, mech))
01989 return FALSE;
01990
01991 _dbus_list_pop_first (&client->mechs_to_try);
01992
01993 _dbus_verbose ("%s: Trying mechanism %s\n",
01994 DBUS_AUTH_NAME (auth),
01995 mech->mechanism);
01996 }
01997 else
01998 {
01999
02000 _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n",
02001 DBUS_AUTH_NAME (auth));
02002 goto_state (auth, &common_state_need_disconnect);
02003 }
02004
02005 return TRUE;
02006 }
02007
02008
02009 static dbus_bool_t
02010 handle_client_state_waiting_for_data (DBusAuth *auth,
02011 DBusAuthCommand command,
02012 const DBusString *args)
02013 {
02014 _dbus_assert (auth->mech != NULL);
02015
02016 switch (command)
02017 {
02018 case DBUS_AUTH_COMMAND_DATA:
02019 return process_data (auth, args, auth->mech->client_data_func);
02020
02021 case DBUS_AUTH_COMMAND_REJECTED:
02022 return process_rejected (auth, args);
02023
02024 case DBUS_AUTH_COMMAND_OK:
02025 return process_ok(auth, args);
02026
02027 case DBUS_AUTH_COMMAND_ERROR:
02028 return send_cancel (auth);
02029
02030 case DBUS_AUTH_COMMAND_AUTH:
02031 case DBUS_AUTH_COMMAND_CANCEL:
02032 case DBUS_AUTH_COMMAND_BEGIN:
02033 case DBUS_AUTH_COMMAND_UNKNOWN:
02034 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02035 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02036 default:
02037 return send_error (auth, "Unknown command");
02038 }
02039 }
02040
02041 static dbus_bool_t
02042 handle_client_state_waiting_for_ok (DBusAuth *auth,
02043 DBusAuthCommand command,
02044 const DBusString *args)
02045 {
02046 switch (command)
02047 {
02048 case DBUS_AUTH_COMMAND_REJECTED:
02049 return process_rejected (auth, args);
02050
02051 case DBUS_AUTH_COMMAND_OK:
02052 return process_ok(auth, args);
02053
02054 case DBUS_AUTH_COMMAND_DATA:
02055 case DBUS_AUTH_COMMAND_ERROR:
02056 return send_cancel (auth);
02057
02058 case DBUS_AUTH_COMMAND_AUTH:
02059 case DBUS_AUTH_COMMAND_CANCEL:
02060 case DBUS_AUTH_COMMAND_BEGIN:
02061 case DBUS_AUTH_COMMAND_UNKNOWN:
02062 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02063 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02064 default:
02065 return send_error (auth, "Unknown command");
02066 }
02067 }
02068
02069 static dbus_bool_t
02070 handle_client_state_waiting_for_reject (DBusAuth *auth,
02071 DBusAuthCommand command,
02072 const DBusString *args)
02073 {
02074 switch (command)
02075 {
02076 case DBUS_AUTH_COMMAND_REJECTED:
02077 return process_rejected (auth, args);
02078
02079 case DBUS_AUTH_COMMAND_AUTH:
02080 case DBUS_AUTH_COMMAND_CANCEL:
02081 case DBUS_AUTH_COMMAND_DATA:
02082 case DBUS_AUTH_COMMAND_BEGIN:
02083 case DBUS_AUTH_COMMAND_OK:
02084 case DBUS_AUTH_COMMAND_ERROR:
02085 case DBUS_AUTH_COMMAND_UNKNOWN:
02086 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02087 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02088 default:
02089 goto_state (auth, &common_state_need_disconnect);
02090 return TRUE;
02091 }
02092 }
02093
02094 static dbus_bool_t
02095 handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth,
02096 DBusAuthCommand command,
02097 const DBusString *args)
02098 {
02099 switch (command)
02100 {
02101 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02102 _dbus_assert(auth->unix_fd_possible);
02103 auth->unix_fd_negotiated = TRUE;
02104 _dbus_verbose("Successfully negotiated UNIX FD passing\n");
02105 return send_begin (auth);
02106
02107 case DBUS_AUTH_COMMAND_ERROR:
02108 _dbus_assert(auth->unix_fd_possible);
02109 auth->unix_fd_negotiated = FALSE;
02110 _dbus_verbose("Failed to negotiate UNIX FD passing\n");
02111 return send_begin (auth);
02112
02113 case DBUS_AUTH_COMMAND_OK:
02114 case DBUS_AUTH_COMMAND_DATA:
02115 case DBUS_AUTH_COMMAND_REJECTED:
02116 case DBUS_AUTH_COMMAND_AUTH:
02117 case DBUS_AUTH_COMMAND_CANCEL:
02118 case DBUS_AUTH_COMMAND_BEGIN:
02119 case DBUS_AUTH_COMMAND_UNKNOWN:
02120 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02121 default:
02122 return send_error (auth, "Unknown command");
02123 }
02124 }
02125
02129 typedef struct {
02130 const char *name;
02131 DBusAuthCommand command;
02132 } DBusAuthCommandName;
02133
02134 static const DBusAuthCommandName auth_command_names[] = {
02135 { "AUTH", DBUS_AUTH_COMMAND_AUTH },
02136 { "CANCEL", DBUS_AUTH_COMMAND_CANCEL },
02137 { "DATA", DBUS_AUTH_COMMAND_DATA },
02138 { "BEGIN", DBUS_AUTH_COMMAND_BEGIN },
02139 { "REJECTED", DBUS_AUTH_COMMAND_REJECTED },
02140 { "OK", DBUS_AUTH_COMMAND_OK },
02141 { "ERROR", DBUS_AUTH_COMMAND_ERROR },
02142 { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
02143 { "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
02144 };
02145
02146 static DBusAuthCommand
02147 lookup_command_from_name (DBusString *command)
02148 {
02149 int i;
02150
02151 for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++)
02152 {
02153 if (_dbus_string_equal_c_str (command,
02154 auth_command_names[i].name))
02155 return auth_command_names[i].command;
02156 }
02157
02158 return DBUS_AUTH_COMMAND_UNKNOWN;
02159 }
02160
02161 static void
02162 goto_state (DBusAuth *auth,
02163 const DBusAuthStateData *state)
02164 {
02165 _dbus_verbose ("%s: going from state %s to state %s\n",
02166 DBUS_AUTH_NAME (auth),
02167 auth->state->name,
02168 state->name);
02169
02170 auth->state = state;
02171 }
02172
02173
02174 static dbus_bool_t
02175 process_command (DBusAuth *auth)
02176 {
02177 DBusAuthCommand command;
02178 DBusString line;
02179 DBusString args;
02180 int eol;
02181 int i, j;
02182 dbus_bool_t retval;
02183
02184
02185
02186 retval = FALSE;
02187
02188 eol = 0;
02189 if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol))
02190 return FALSE;
02191
02192 if (!_dbus_string_init (&line))
02193 {
02194 auth->needed_memory = TRUE;
02195 return FALSE;
02196 }
02197
02198 if (!_dbus_string_init (&args))
02199 {
02200 _dbus_string_free (&line);
02201 auth->needed_memory = TRUE;
02202 return FALSE;
02203 }
02204
02205 if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0))
02206 goto out;
02207
02208 if (!_dbus_string_validate_ascii (&line, 0,
02209 _dbus_string_get_length (&line)))
02210 {
02211 _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n",
02212 DBUS_AUTH_NAME (auth));
02213 if (!send_error (auth, "Command contained non-ASCII"))
02214 goto out;
02215 else
02216 goto next_command;
02217 }
02218
02219 _dbus_verbose ("%s: got command \"%s\"\n",
02220 DBUS_AUTH_NAME (auth),
02221 _dbus_string_get_const_data (&line));
02222
02223 _dbus_string_find_blank (&line, 0, &i);
02224 _dbus_string_skip_blank (&line, i, &j);
02225
02226 if (j > i)
02227 _dbus_string_delete (&line, i, j - i);
02228
02229 if (!_dbus_string_move (&line, i, &args, 0))
02230 goto out;
02231
02232
02233
02234
02235
02236 command = lookup_command_from_name (&line);
02237 if (!(* auth->state->handler) (auth, command, &args))
02238 goto out;
02239
02240 next_command:
02241
02242
02243
02244
02245
02246 _dbus_string_delete (&auth->incoming, 0, eol);
02247
02248
02249 _dbus_string_delete (&auth->incoming, 0, 2);
02250
02251 retval = TRUE;
02252
02253 out:
02254 _dbus_string_free (&args);
02255 _dbus_string_free (&line);
02256
02257 if (!retval)
02258 auth->needed_memory = TRUE;
02259 else
02260 auth->needed_memory = FALSE;
02261
02262 return retval;
02263 }
02264
02265
02280 DBusAuth*
02281 _dbus_auth_server_new (const DBusString *guid)
02282 {
02283 DBusAuth *auth;
02284 DBusAuthServer *server_auth;
02285 DBusString guid_copy;
02286
02287 if (!_dbus_string_init (&guid_copy))
02288 return NULL;
02289
02290 if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
02291 {
02292 _dbus_string_free (&guid_copy);
02293 return NULL;
02294 }
02295
02296 auth = _dbus_auth_new (sizeof (DBusAuthServer));
02297 if (auth == NULL)
02298 {
02299 _dbus_string_free (&guid_copy);
02300 return NULL;
02301 }
02302
02303 auth->side = auth_side_server;
02304 auth->state = &server_state_waiting_for_auth;
02305
02306 server_auth = DBUS_AUTH_SERVER (auth);
02307
02308 server_auth->guid = guid_copy;
02309
02310
02311
02312
02313 server_auth->failures = 0;
02314 server_auth->max_failures = 6;
02315
02316 return auth;
02317 }
02318
02326 DBusAuth*
02327 _dbus_auth_client_new (void)
02328 {
02329 DBusAuth *auth;
02330 DBusString guid_str;
02331
02332 if (!_dbus_string_init (&guid_str))
02333 return NULL;
02334
02335 auth = _dbus_auth_new (sizeof (DBusAuthClient));
02336 if (auth == NULL)
02337 {
02338 _dbus_string_free (&guid_str);
02339 return NULL;
02340 }
02341
02342 DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
02343
02344 auth->side = auth_side_client;
02345 auth->state = &client_state_need_send_auth;
02346
02347
02348
02349 if (!send_auth (auth, &all_mechanisms[0]))
02350 {
02351 _dbus_auth_unref (auth);
02352 return NULL;
02353 }
02354
02355 return auth;
02356 }
02357
02364 DBusAuth *
02365 _dbus_auth_ref (DBusAuth *auth)
02366 {
02367 _dbus_assert (auth != NULL);
02368
02369 auth->refcount += 1;
02370
02371 return auth;
02372 }
02373
02379 void
02380 _dbus_auth_unref (DBusAuth *auth)
02381 {
02382 _dbus_assert (auth != NULL);
02383 _dbus_assert (auth->refcount > 0);
02384
02385 auth->refcount -= 1;
02386 if (auth->refcount == 0)
02387 {
02388 shutdown_mech (auth);
02389
02390 if (DBUS_AUTH_IS_CLIENT (auth))
02391 {
02392 _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
02393 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
02394 }
02395 else
02396 {
02397 _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
02398
02399 _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
02400 }
02401
02402 if (auth->keyring)
02403 _dbus_keyring_unref (auth->keyring);
02404
02405 _dbus_string_free (&auth->context);
02406 _dbus_string_free (&auth->challenge);
02407 _dbus_string_free (&auth->identity);
02408 _dbus_string_free (&auth->incoming);
02409 _dbus_string_free (&auth->outgoing);
02410
02411 dbus_free_string_array (auth->allowed_mechs);
02412
02413 _dbus_credentials_unref (auth->credentials);
02414 _dbus_credentials_unref (auth->authorized_identity);
02415 _dbus_credentials_unref (auth->desired_identity);
02416
02417 dbus_free (auth);
02418 }
02419 }
02420
02429 dbus_bool_t
02430 _dbus_auth_set_mechanisms (DBusAuth *auth,
02431 const char **mechanisms)
02432 {
02433 char **copy;
02434
02435 if (mechanisms != NULL)
02436 {
02437 copy = _dbus_dup_string_array (mechanisms);
02438 if (copy == NULL)
02439 return FALSE;
02440 }
02441 else
02442 copy = NULL;
02443
02444 dbus_free_string_array (auth->allowed_mechs);
02445
02446 auth->allowed_mechs = copy;
02447
02448 return TRUE;
02449 }
02450
02455 #define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL)
02456
02464 DBusAuthState
02465 _dbus_auth_do_work (DBusAuth *auth)
02466 {
02467 auth->needed_memory = FALSE;
02468
02469
02470 #define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE)
02471
02472 do
02473 {
02474 if (DBUS_AUTH_IN_END_STATE (auth))
02475 break;
02476
02477 if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
02478 _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
02479 {
02480 goto_state (auth, &common_state_need_disconnect);
02481 _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n",
02482 DBUS_AUTH_NAME (auth));
02483 break;
02484 }
02485 }
02486 while (process_command (auth));
02487
02488 if (auth->needed_memory)
02489 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
02490 else if (_dbus_string_get_length (&auth->outgoing) > 0)
02491 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
02492 else if (auth->state == &common_state_need_disconnect)
02493 return DBUS_AUTH_STATE_NEED_DISCONNECT;
02494 else if (auth->state == &common_state_authenticated)
02495 return DBUS_AUTH_STATE_AUTHENTICATED;
02496 else return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
02497 }
02498
02508 dbus_bool_t
02509 _dbus_auth_get_bytes_to_send (DBusAuth *auth,
02510 const DBusString **str)
02511 {
02512 _dbus_assert (auth != NULL);
02513 _dbus_assert (str != NULL);
02514
02515 *str = NULL;
02516
02517 if (_dbus_string_get_length (&auth->outgoing) == 0)
02518 return FALSE;
02519
02520 *str = &auth->outgoing;
02521
02522 return TRUE;
02523 }
02524
02533 void
02534 _dbus_auth_bytes_sent (DBusAuth *auth,
02535 int bytes_sent)
02536 {
02537 _dbus_verbose ("%s: Sent %d bytes of: %s\n",
02538 DBUS_AUTH_NAME (auth),
02539 bytes_sent,
02540 _dbus_string_get_const_data (&auth->outgoing));
02541
02542 _dbus_string_delete (&auth->outgoing,
02543 0, bytes_sent);
02544 }
02545
02553 void
02554 _dbus_auth_get_buffer (DBusAuth *auth,
02555 DBusString **buffer)
02556 {
02557 _dbus_assert (auth != NULL);
02558 _dbus_assert (!auth->buffer_outstanding);
02559
02560 *buffer = &auth->incoming;
02561
02562 auth->buffer_outstanding = TRUE;
02563 }
02564
02571 void
02572 _dbus_auth_return_buffer (DBusAuth *auth,
02573 DBusString *buffer)
02574 {
02575 _dbus_assert (buffer == &auth->incoming);
02576 _dbus_assert (auth->buffer_outstanding);
02577
02578 auth->buffer_outstanding = FALSE;
02579 }
02580
02590 void
02591 _dbus_auth_get_unused_bytes (DBusAuth *auth,
02592 const DBusString **str)
02593 {
02594 if (!DBUS_AUTH_IN_END_STATE (auth))
02595 return;
02596
02597 *str = &auth->incoming;
02598 }
02599
02600
02607 void
02608 _dbus_auth_delete_unused_bytes (DBusAuth *auth)
02609 {
02610 if (!DBUS_AUTH_IN_END_STATE (auth))
02611 return;
02612
02613 _dbus_string_set_length (&auth->incoming, 0);
02614 }
02615
02624 dbus_bool_t
02625 _dbus_auth_needs_encoding (DBusAuth *auth)
02626 {
02627 if (auth->state != &common_state_authenticated)
02628 return FALSE;
02629
02630 if (auth->mech != NULL)
02631 {
02632 if (DBUS_AUTH_IS_CLIENT (auth))
02633 return auth->mech->client_encode_func != NULL;
02634 else
02635 return auth->mech->server_encode_func != NULL;
02636 }
02637 else
02638 return FALSE;
02639 }
02640
02651 dbus_bool_t
02652 _dbus_auth_encode_data (DBusAuth *auth,
02653 const DBusString *plaintext,
02654 DBusString *encoded)
02655 {
02656 _dbus_assert (plaintext != encoded);
02657
02658 if (auth->state != &common_state_authenticated)
02659 return FALSE;
02660
02661 if (_dbus_auth_needs_encoding (auth))
02662 {
02663 if (DBUS_AUTH_IS_CLIENT (auth))
02664 return (* auth->mech->client_encode_func) (auth, plaintext, encoded);
02665 else
02666 return (* auth->mech->server_encode_func) (auth, plaintext, encoded);
02667 }
02668 else
02669 {
02670 return _dbus_string_copy (plaintext, 0, encoded,
02671 _dbus_string_get_length (encoded));
02672 }
02673 }
02674
02683 dbus_bool_t
02684 _dbus_auth_needs_decoding (DBusAuth *auth)
02685 {
02686 if (auth->state != &common_state_authenticated)
02687 return FALSE;
02688
02689 if (auth->mech != NULL)
02690 {
02691 if (DBUS_AUTH_IS_CLIENT (auth))
02692 return auth->mech->client_decode_func != NULL;
02693 else
02694 return auth->mech->server_decode_func != NULL;
02695 }
02696 else
02697 return FALSE;
02698 }
02699
02700
02714 dbus_bool_t
02715 _dbus_auth_decode_data (DBusAuth *auth,
02716 const DBusString *encoded,
02717 DBusString *plaintext)
02718 {
02719 _dbus_assert (plaintext != encoded);
02720
02721 if (auth->state != &common_state_authenticated)
02722 return FALSE;
02723
02724 if (_dbus_auth_needs_decoding (auth))
02725 {
02726 if (DBUS_AUTH_IS_CLIENT (auth))
02727 return (* auth->mech->client_decode_func) (auth, encoded, plaintext);
02728 else
02729 return (* auth->mech->server_decode_func) (auth, encoded, plaintext);
02730 }
02731 else
02732 {
02733 return _dbus_string_copy (encoded, 0, plaintext,
02734 _dbus_string_get_length (plaintext));
02735 }
02736 }
02737
02746 dbus_bool_t
02747 _dbus_auth_set_credentials (DBusAuth *auth,
02748 DBusCredentials *credentials)
02749 {
02750 _dbus_credentials_clear (auth->credentials);
02751 return _dbus_credentials_add_credentials (auth->credentials,
02752 credentials);
02753 }
02754
02764 DBusCredentials*
02765 _dbus_auth_get_identity (DBusAuth *auth)
02766 {
02767 if (auth->state == &common_state_authenticated)
02768 {
02769 return auth->authorized_identity;
02770 }
02771 else
02772 {
02773
02774
02775
02776
02777 _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
02778 return auth->authorized_identity;
02779 }
02780 }
02781
02788 const char*
02789 _dbus_auth_get_guid_from_server (DBusAuth *auth)
02790 {
02791 _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
02792
02793 if (auth->state == &common_state_authenticated)
02794 return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
02795 else
02796 return NULL;
02797 }
02798
02807 dbus_bool_t
02808 _dbus_auth_set_context (DBusAuth *auth,
02809 const DBusString *context)
02810 {
02811 return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context),
02812 &auth->context, 0, _dbus_string_get_length (context));
02813 }
02814
02822 void
02823 _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
02824 {
02825 auth->unix_fd_possible = b;
02826 }
02827
02834 dbus_bool_t
02835 _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
02836 {
02837 return auth->unix_fd_negotiated;
02838 }
02839
02842