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