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