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 return send_rejected (auth);
01206 }
01207
01208 _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
01209 DBUS_AUTH_NAME (auth),
01210 _dbus_string_get_const_data (data));
01211 }
01212
01213
01214 _dbus_credentials_clear (auth->desired_identity);
01215
01216
01217
01218 if (!_dbus_credentials_add_credential (auth->authorized_identity,
01219 DBUS_CREDENTIAL_UNIX_PROCESS_ID,
01220 auth->credentials))
01221 return FALSE;
01222
01223
01224 if (!send_ok (auth))
01225 return FALSE;
01226
01227 _dbus_verbose ("%s: authenticated client as anonymous\n",
01228 DBUS_AUTH_NAME (auth));
01229
01230 return TRUE;
01231 }
01232
01233 static void
01234 handle_server_shutdown_anonymous_mech (DBusAuth *auth)
01235 {
01236
01237 }
01238
01239 static dbus_bool_t
01240 handle_client_initial_response_anonymous_mech (DBusAuth *auth,
01241 DBusString *response)
01242 {
01243
01244
01245
01246
01247
01248
01249 DBusString plaintext;
01250
01251 if (!_dbus_string_init (&plaintext))
01252 return FALSE;
01253
01254 if (!_dbus_string_append (&plaintext,
01255 "libdbus " DBUS_VERSION_STRING))
01256 goto failed;
01257
01258 if (!_dbus_string_hex_encode (&plaintext, 0,
01259 response,
01260 _dbus_string_get_length (response)))
01261 goto failed;
01262
01263 _dbus_string_free (&plaintext);
01264
01265 return TRUE;
01266
01267 failed:
01268 _dbus_string_free (&plaintext);
01269 return FALSE;
01270 }
01271
01272 static dbus_bool_t
01273 handle_client_data_anonymous_mech (DBusAuth *auth,
01274 const DBusString *data)
01275 {
01276
01277 return TRUE;
01278 }
01279
01280 static void
01281 handle_client_shutdown_anonymous_mech (DBusAuth *auth)
01282 {
01283
01284 }
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 static const DBusAuthMechanismHandler
01298 all_mechanisms[] = {
01299 { "EXTERNAL",
01300 handle_server_data_external_mech,
01301 NULL, NULL,
01302 handle_server_shutdown_external_mech,
01303 handle_client_initial_response_external_mech,
01304 handle_client_data_external_mech,
01305 NULL, NULL,
01306 handle_client_shutdown_external_mech },
01307 { "DBUS_COOKIE_SHA1",
01308 handle_server_data_cookie_sha1_mech,
01309 NULL, NULL,
01310 handle_server_shutdown_cookie_sha1_mech,
01311 handle_client_initial_response_cookie_sha1_mech,
01312 handle_client_data_cookie_sha1_mech,
01313 NULL, NULL,
01314 handle_client_shutdown_cookie_sha1_mech },
01315 { "ANONYMOUS",
01316 handle_server_data_anonymous_mech,
01317 NULL, NULL,
01318 handle_server_shutdown_anonymous_mech,
01319 handle_client_initial_response_anonymous_mech,
01320 handle_client_data_anonymous_mech,
01321 NULL, NULL,
01322 handle_client_shutdown_anonymous_mech },
01323 { NULL, NULL }
01324 };
01325
01326 static const DBusAuthMechanismHandler*
01327 find_mech (const DBusString *name,
01328 char **allowed_mechs)
01329 {
01330 int i;
01331
01332 if (allowed_mechs != NULL &&
01333 !_dbus_string_array_contains ((const char**) allowed_mechs,
01334 _dbus_string_get_const_data (name)))
01335 return NULL;
01336
01337 i = 0;
01338 while (all_mechanisms[i].mechanism != NULL)
01339 {
01340 if (_dbus_string_equal_c_str (name,
01341 all_mechanisms[i].mechanism))
01342
01343 return &all_mechanisms[i];
01344
01345 ++i;
01346 }
01347
01348 return NULL;
01349 }
01350
01351 static dbus_bool_t
01352 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
01353 {
01354 DBusString auth_command;
01355
01356 if (!_dbus_string_init (&auth_command))
01357 return FALSE;
01358
01359 if (!_dbus_string_append (&auth_command,
01360 "AUTH "))
01361 {
01362 _dbus_string_free (&auth_command);
01363 return FALSE;
01364 }
01365
01366 if (!_dbus_string_append (&auth_command,
01367 mech->mechanism))
01368 {
01369 _dbus_string_free (&auth_command);
01370 return FALSE;
01371 }
01372
01373 if (mech->client_initial_response_func != NULL)
01374 {
01375 if (!_dbus_string_append (&auth_command, " "))
01376 {
01377 _dbus_string_free (&auth_command);
01378 return FALSE;
01379 }
01380
01381 if (!(* mech->client_initial_response_func) (auth, &auth_command))
01382 {
01383 _dbus_string_free (&auth_command);
01384 return FALSE;
01385 }
01386 }
01387
01388 if (!_dbus_string_append (&auth_command,
01389 "\r\n"))
01390 {
01391 _dbus_string_free (&auth_command);
01392 return FALSE;
01393 }
01394
01395 if (!_dbus_string_copy (&auth_command, 0,
01396 &auth->outgoing,
01397 _dbus_string_get_length (&auth->outgoing)))
01398 {
01399 _dbus_string_free (&auth_command);
01400 return FALSE;
01401 }
01402
01403 _dbus_string_free (&auth_command);
01404 shutdown_mech (auth);
01405 auth->mech = mech;
01406 goto_state (auth, &client_state_waiting_for_data);
01407
01408 return TRUE;
01409 }
01410
01411 static dbus_bool_t
01412 send_data (DBusAuth *auth, DBusString *data)
01413 {
01414 int old_len;
01415
01416 if (data == NULL || _dbus_string_get_length (data) == 0)
01417 return _dbus_string_append (&auth->outgoing, "DATA\r\n");
01418 else
01419 {
01420 old_len = _dbus_string_get_length (&auth->outgoing);
01421 if (!_dbus_string_append (&auth->outgoing, "DATA "))
01422 goto out;
01423
01424 if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
01425 _dbus_string_get_length (&auth->outgoing)))
01426 goto out;
01427
01428 if (!_dbus_string_append (&auth->outgoing, "\r\n"))
01429 goto out;
01430
01431 return TRUE;
01432
01433 out:
01434 _dbus_string_set_length (&auth->outgoing, old_len);
01435
01436 return FALSE;
01437 }
01438 }
01439
01440 static dbus_bool_t
01441 send_rejected (DBusAuth *auth)
01442 {
01443 DBusString command;
01444 DBusAuthServer *server_auth;
01445 int i;
01446
01447 if (!_dbus_string_init (&command))
01448 return FALSE;
01449
01450 if (!_dbus_string_append (&command,
01451 "REJECTED"))
01452 goto nomem;
01453
01454 i = 0;
01455 while (all_mechanisms[i].mechanism != NULL)
01456 {
01457 if (!_dbus_string_append (&command,
01458 " "))
01459 goto nomem;
01460
01461 if (!_dbus_string_append (&command,
01462 all_mechanisms[i].mechanism))
01463 goto nomem;
01464
01465 ++i;
01466 }
01467
01468 if (!_dbus_string_append (&command, "\r\n"))
01469 goto nomem;
01470
01471 if (!_dbus_string_copy (&command, 0, &auth->outgoing,
01472 _dbus_string_get_length (&auth->outgoing)))
01473 goto nomem;
01474
01475 shutdown_mech (auth);
01476
01477 _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
01478 server_auth = DBUS_AUTH_SERVER (auth);
01479 server_auth->failures += 1;
01480
01481 if (server_auth->failures >= server_auth->max_failures)
01482 goto_state (auth, &common_state_need_disconnect);
01483 else
01484 goto_state (auth, &server_state_waiting_for_auth);
01485
01486 _dbus_string_free (&command);
01487
01488 return TRUE;
01489
01490 nomem:
01491 _dbus_string_free (&command);
01492 return FALSE;
01493 }
01494
01495 static dbus_bool_t
01496 send_error (DBusAuth *auth, const char *message)
01497 {
01498 return _dbus_string_append_printf (&auth->outgoing,
01499 "ERROR \"%s\"\r\n", message);
01500 }
01501
01502 static dbus_bool_t
01503 send_ok (DBusAuth *auth)
01504 {
01505 int orig_len;
01506
01507 orig_len = _dbus_string_get_length (&auth->outgoing);
01508
01509 if (_dbus_string_append (&auth->outgoing, "OK ") &&
01510 _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
01511 0,
01512 &auth->outgoing,
01513 _dbus_string_get_length (&auth->outgoing)) &&
01514 _dbus_string_append (&auth->outgoing, "\r\n"))
01515 {
01516 goto_state (auth, &server_state_waiting_for_begin);
01517 return TRUE;
01518 }
01519 else
01520 {
01521 _dbus_string_set_length (&auth->outgoing, orig_len);
01522 return FALSE;
01523 }
01524 }
01525
01526 static dbus_bool_t
01527 send_begin (DBusAuth *auth)
01528 {
01529
01530 if (!_dbus_string_append (&auth->outgoing,
01531 "BEGIN\r\n"))
01532 return FALSE;
01533
01534 goto_state (auth, &common_state_authenticated);
01535 return TRUE;
01536 }
01537
01538 static dbus_bool_t
01539 process_ok(DBusAuth *auth,
01540 const DBusString *args_from_ok) {
01541
01542 int end_of_hex;
01543
01544
01545 _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
01546
01547
01548
01549 end_of_hex = 0;
01550 if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
01551 & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
01552 return FALSE;
01553
01554
01555 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
01556
01557 if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
01558 end_of_hex == 0)
01559 {
01560 _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
01561 end_of_hex, _dbus_string_get_length (args_from_ok));
01562 goto_state (auth, &common_state_need_disconnect);
01563 return TRUE;
01564 }
01565
01566 if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
01567 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
01568 return FALSE;
01569 }
01570
01571 _dbus_verbose ("Got GUID '%s' from the server\n",
01572 _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
01573
01574 if (auth->unix_fd_possible)
01575 return send_negotiate_unix_fd(auth);
01576
01577 _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
01578 return send_begin (auth);
01579 }
01580
01581 static dbus_bool_t
01582 send_cancel (DBusAuth *auth)
01583 {
01584 if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
01585 {
01586 goto_state (auth, &client_state_waiting_for_reject);
01587 return TRUE;
01588 }
01589 else
01590 return FALSE;
01591 }
01592
01593 static dbus_bool_t
01594 process_data (DBusAuth *auth,
01595 const DBusString *args,
01596 DBusAuthDataFunction data_func)
01597 {
01598 int end;
01599 DBusString decoded;
01600
01601 if (!_dbus_string_init (&decoded))
01602 return FALSE;
01603
01604 if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
01605 {
01606 _dbus_string_free (&decoded);
01607 return FALSE;
01608 }
01609
01610 if (_dbus_string_get_length (args) != end)
01611 {
01612 _dbus_string_free (&decoded);
01613 if (!send_error (auth, "Invalid hex encoding"))
01614 return FALSE;
01615
01616 return TRUE;
01617 }
01618
01619 #ifdef DBUS_ENABLE_VERBOSE_MODE
01620 if (_dbus_string_validate_ascii (&decoded, 0,
01621 _dbus_string_get_length (&decoded)))
01622 _dbus_verbose ("%s: data: '%s'\n",
01623 DBUS_AUTH_NAME (auth),
01624 _dbus_string_get_const_data (&decoded));
01625 #endif
01626
01627 if (!(* data_func) (auth, &decoded))
01628 {
01629 _dbus_string_free (&decoded);
01630 return FALSE;
01631 }
01632
01633 _dbus_string_free (&decoded);
01634 return TRUE;
01635 }
01636
01637 static dbus_bool_t
01638 send_negotiate_unix_fd (DBusAuth *auth)
01639 {
01640 if (!_dbus_string_append (&auth->outgoing,
01641 "NEGOTIATE_UNIX_FD\r\n"))
01642 return FALSE;
01643
01644 goto_state (auth, &client_state_waiting_for_agree_unix_fd);
01645 return TRUE;
01646 }
01647
01648 static dbus_bool_t
01649 send_agree_unix_fd (DBusAuth *auth)
01650 {
01651 _dbus_assert(auth->unix_fd_possible);
01652
01653 auth->unix_fd_negotiated = TRUE;
01654 _dbus_verbose("Agreed to UNIX FD passing\n");
01655
01656 if (!_dbus_string_append (&auth->outgoing,
01657 "AGREE_UNIX_FD\r\n"))
01658 return FALSE;
01659
01660 goto_state (auth, &server_state_waiting_for_begin);
01661 return TRUE;
01662 }
01663
01664 static dbus_bool_t
01665 handle_auth (DBusAuth *auth, const DBusString *args)
01666 {
01667 if (_dbus_string_get_length (args) == 0)
01668 {
01669
01670 if (!send_rejected (auth))
01671 return FALSE;
01672
01673 return TRUE;
01674 }
01675 else
01676 {
01677 int i;
01678 DBusString mech;
01679 DBusString hex_response;
01680
01681 _dbus_string_find_blank (args, 0, &i);
01682
01683 if (!_dbus_string_init (&mech))
01684 return FALSE;
01685
01686 if (!_dbus_string_init (&hex_response))
01687 {
01688 _dbus_string_free (&mech);
01689 return FALSE;
01690 }
01691
01692 if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
01693 goto failed;
01694
01695 _dbus_string_skip_blank (args, i, &i);
01696 if (!_dbus_string_copy (args, i, &hex_response, 0))
01697 goto failed;
01698
01699 auth->mech = find_mech (&mech, auth->allowed_mechs);
01700 if (auth->mech != NULL)
01701 {
01702 _dbus_verbose ("%s: Trying mechanism %s\n",
01703 DBUS_AUTH_NAME (auth),
01704 auth->mech->mechanism);
01705
01706 if (!process_data (auth, &hex_response,
01707 auth->mech->server_data_func))
01708 goto failed;
01709 }
01710 else
01711 {
01712
01713 _dbus_verbose ("%s: Unsupported mechanism %s\n",
01714 DBUS_AUTH_NAME (auth),
01715 _dbus_string_get_const_data (&mech));
01716
01717 if (!send_rejected (auth))
01718 goto failed;
01719 }
01720
01721 _dbus_string_free (&mech);
01722 _dbus_string_free (&hex_response);
01723
01724 return TRUE;
01725
01726 failed:
01727 auth->mech = NULL;
01728 _dbus_string_free (&mech);
01729 _dbus_string_free (&hex_response);
01730 return FALSE;
01731 }
01732 }
01733
01734 static dbus_bool_t
01735 handle_server_state_waiting_for_auth (DBusAuth *auth,
01736 DBusAuthCommand command,
01737 const DBusString *args)
01738 {
01739 switch (command)
01740 {
01741 case DBUS_AUTH_COMMAND_AUTH:
01742 return handle_auth (auth, args);
01743
01744 case DBUS_AUTH_COMMAND_CANCEL:
01745 case DBUS_AUTH_COMMAND_DATA:
01746 return send_error (auth, "Not currently in an auth conversation");
01747
01748 case DBUS_AUTH_COMMAND_BEGIN:
01749 goto_state (auth, &common_state_need_disconnect);
01750 return TRUE;
01751
01752 case DBUS_AUTH_COMMAND_ERROR:
01753 return send_rejected (auth);
01754
01755 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01756 return send_error (auth, "Need to authenticate first");
01757
01758 case DBUS_AUTH_COMMAND_REJECTED:
01759 case DBUS_AUTH_COMMAND_OK:
01760 case DBUS_AUTH_COMMAND_UNKNOWN:
01761 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01762 default:
01763 return send_error (auth, "Unknown command");
01764 }
01765 }
01766
01767 static dbus_bool_t
01768 handle_server_state_waiting_for_data (DBusAuth *auth,
01769 DBusAuthCommand command,
01770 const DBusString *args)
01771 {
01772 switch (command)
01773 {
01774 case DBUS_AUTH_COMMAND_AUTH:
01775 return send_error (auth, "Sent AUTH while another AUTH in progress");
01776
01777 case DBUS_AUTH_COMMAND_CANCEL:
01778 case DBUS_AUTH_COMMAND_ERROR:
01779 return send_rejected (auth);
01780
01781 case DBUS_AUTH_COMMAND_DATA:
01782 return process_data (auth, args, auth->mech->server_data_func);
01783
01784 case DBUS_AUTH_COMMAND_BEGIN:
01785 goto_state (auth, &common_state_need_disconnect);
01786 return TRUE;
01787
01788 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01789 return send_error (auth, "Need to authenticate first");
01790
01791 case DBUS_AUTH_COMMAND_REJECTED:
01792 case DBUS_AUTH_COMMAND_OK:
01793 case DBUS_AUTH_COMMAND_UNKNOWN:
01794 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01795 default:
01796 return send_error (auth, "Unknown command");
01797 }
01798 }
01799
01800 static dbus_bool_t
01801 handle_server_state_waiting_for_begin (DBusAuth *auth,
01802 DBusAuthCommand command,
01803 const DBusString *args)
01804 {
01805 switch (command)
01806 {
01807 case DBUS_AUTH_COMMAND_AUTH:
01808 return send_error (auth, "Sent AUTH while expecting BEGIN");
01809
01810 case DBUS_AUTH_COMMAND_DATA:
01811 return send_error (auth, "Sent DATA while expecting BEGIN");
01812
01813 case DBUS_AUTH_COMMAND_BEGIN:
01814 goto_state (auth, &common_state_authenticated);
01815 return TRUE;
01816
01817 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
01818 if (auth->unix_fd_possible)
01819 return send_agree_unix_fd(auth);
01820 else
01821 return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
01822
01823 case DBUS_AUTH_COMMAND_REJECTED:
01824 case DBUS_AUTH_COMMAND_OK:
01825 case DBUS_AUTH_COMMAND_UNKNOWN:
01826 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
01827 default:
01828 return send_error (auth, "Unknown command");
01829
01830 case DBUS_AUTH_COMMAND_CANCEL:
01831 case DBUS_AUTH_COMMAND_ERROR:
01832 return send_rejected (auth);
01833 }
01834 }
01835
01836
01837 static dbus_bool_t
01838 get_word (const DBusString *str,
01839 int *start,
01840 DBusString *word)
01841 {
01842 int i;
01843
01844 _dbus_string_skip_blank (str, *start, start);
01845 _dbus_string_find_blank (str, *start, &i);
01846
01847 if (i > *start)
01848 {
01849 if (!_dbus_string_copy_len (str, *start, i - *start, word, 0))
01850 return FALSE;
01851
01852 *start = i;
01853 }
01854
01855 return TRUE;
01856 }
01857
01858 static dbus_bool_t
01859 record_mechanisms (DBusAuth *auth,
01860 const DBusString *args)
01861 {
01862 int next;
01863 int len;
01864
01865 if (auth->already_got_mechanisms)
01866 return TRUE;
01867
01868 len = _dbus_string_get_length (args);
01869
01870 next = 0;
01871 while (next < len)
01872 {
01873 DBusString m;
01874 const DBusAuthMechanismHandler *mech;
01875
01876 if (!_dbus_string_init (&m))
01877 goto nomem;
01878
01879 if (!get_word (args, &next, &m))
01880 {
01881 _dbus_string_free (&m);
01882 goto nomem;
01883 }
01884
01885 mech = find_mech (&m, auth->allowed_mechs);
01886
01887 if (mech != NULL)
01888 {
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 if (mech != &all_mechanisms[0])
01899 {
01900 _dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
01901 DBUS_AUTH_NAME (auth), mech->mechanism);
01902
01903 if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
01904 (void*) mech))
01905 {
01906 _dbus_string_free (&m);
01907 goto nomem;
01908 }
01909 }
01910 else
01911 {
01912 _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n",
01913 DBUS_AUTH_NAME (auth), mech->mechanism);
01914 }
01915 }
01916 else
01917 {
01918 _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n",
01919 DBUS_AUTH_NAME (auth),
01920 _dbus_string_get_const_data (&m));
01921 }
01922
01923 _dbus_string_free (&m);
01924 }
01925
01926 auth->already_got_mechanisms = TRUE;
01927
01928 return TRUE;
01929
01930 nomem:
01931 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
01932
01933 return FALSE;
01934 }
01935
01936 static dbus_bool_t
01937 process_rejected (DBusAuth *auth, const DBusString *args)
01938 {
01939 const DBusAuthMechanismHandler *mech;
01940 DBusAuthClient *client;
01941
01942 client = DBUS_AUTH_CLIENT (auth);
01943
01944 if (!auth->already_got_mechanisms)
01945 {
01946 if (!record_mechanisms (auth, args))
01947 return FALSE;
01948 }
01949
01950 if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
01951 {
01952 mech = client->mechs_to_try->data;
01953
01954 if (!send_auth (auth, mech))
01955 return FALSE;
01956
01957 _dbus_list_pop_first (&client->mechs_to_try);
01958
01959 _dbus_verbose ("%s: Trying mechanism %s\n",
01960 DBUS_AUTH_NAME (auth),
01961 mech->mechanism);
01962 }
01963 else
01964 {
01965
01966 _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n",
01967 DBUS_AUTH_NAME (auth));
01968 goto_state (auth, &common_state_need_disconnect);
01969 }
01970
01971 return TRUE;
01972 }
01973
01974
01975 static dbus_bool_t
01976 handle_client_state_waiting_for_data (DBusAuth *auth,
01977 DBusAuthCommand command,
01978 const DBusString *args)
01979 {
01980 _dbus_assert (auth->mech != NULL);
01981
01982 switch (command)
01983 {
01984 case DBUS_AUTH_COMMAND_DATA:
01985 return process_data (auth, args, auth->mech->client_data_func);
01986
01987 case DBUS_AUTH_COMMAND_REJECTED:
01988 return process_rejected (auth, args);
01989
01990 case DBUS_AUTH_COMMAND_OK:
01991 return process_ok(auth, args);
01992
01993 case DBUS_AUTH_COMMAND_ERROR:
01994 return send_cancel (auth);
01995
01996 case DBUS_AUTH_COMMAND_AUTH:
01997 case DBUS_AUTH_COMMAND_CANCEL:
01998 case DBUS_AUTH_COMMAND_BEGIN:
01999 case DBUS_AUTH_COMMAND_UNKNOWN:
02000 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02001 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02002 default:
02003 return send_error (auth, "Unknown command");
02004 }
02005 }
02006
02007 static dbus_bool_t
02008 handle_client_state_waiting_for_ok (DBusAuth *auth,
02009 DBusAuthCommand command,
02010 const DBusString *args)
02011 {
02012 switch (command)
02013 {
02014 case DBUS_AUTH_COMMAND_REJECTED:
02015 return process_rejected (auth, args);
02016
02017 case DBUS_AUTH_COMMAND_OK:
02018 return process_ok(auth, args);
02019
02020 case DBUS_AUTH_COMMAND_DATA:
02021 case DBUS_AUTH_COMMAND_ERROR:
02022 return send_cancel (auth);
02023
02024 case DBUS_AUTH_COMMAND_AUTH:
02025 case DBUS_AUTH_COMMAND_CANCEL:
02026 case DBUS_AUTH_COMMAND_BEGIN:
02027 case DBUS_AUTH_COMMAND_UNKNOWN:
02028 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02029 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02030 default:
02031 return send_error (auth, "Unknown command");
02032 }
02033 }
02034
02035 static dbus_bool_t
02036 handle_client_state_waiting_for_reject (DBusAuth *auth,
02037 DBusAuthCommand command,
02038 const DBusString *args)
02039 {
02040 switch (command)
02041 {
02042 case DBUS_AUTH_COMMAND_REJECTED:
02043 return process_rejected (auth, args);
02044
02045 case DBUS_AUTH_COMMAND_AUTH:
02046 case DBUS_AUTH_COMMAND_CANCEL:
02047 case DBUS_AUTH_COMMAND_DATA:
02048 case DBUS_AUTH_COMMAND_BEGIN:
02049 case DBUS_AUTH_COMMAND_OK:
02050 case DBUS_AUTH_COMMAND_ERROR:
02051 case DBUS_AUTH_COMMAND_UNKNOWN:
02052 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02053 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02054 default:
02055 goto_state (auth, &common_state_need_disconnect);
02056 return TRUE;
02057 }
02058 }
02059
02060 static dbus_bool_t
02061 handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth,
02062 DBusAuthCommand command,
02063 const DBusString *args)
02064 {
02065 switch (command)
02066 {
02067 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
02068 _dbus_assert(auth->unix_fd_possible);
02069 auth->unix_fd_negotiated = TRUE;
02070 _dbus_verbose("Sucessfully negotiated UNIX FD passing\n");
02071 return send_begin (auth);
02072
02073 case DBUS_AUTH_COMMAND_ERROR:
02074 _dbus_assert(auth->unix_fd_possible);
02075 auth->unix_fd_negotiated = FALSE;
02076 _dbus_verbose("Failed to negotiate UNIX FD passing\n");
02077 return send_begin (auth);
02078
02079 case DBUS_AUTH_COMMAND_OK:
02080 case DBUS_AUTH_COMMAND_DATA:
02081 case DBUS_AUTH_COMMAND_REJECTED:
02082 case DBUS_AUTH_COMMAND_AUTH:
02083 case DBUS_AUTH_COMMAND_CANCEL:
02084 case DBUS_AUTH_COMMAND_BEGIN:
02085 case DBUS_AUTH_COMMAND_UNKNOWN:
02086 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
02087 default:
02088 return send_error (auth, "Unknown command");
02089 }
02090 }
02091
02095 typedef struct {
02096 const char *name;
02097 DBusAuthCommand command;
02098 } DBusAuthCommandName;
02099
02100 static const DBusAuthCommandName auth_command_names[] = {
02101 { "AUTH", DBUS_AUTH_COMMAND_AUTH },
02102 { "CANCEL", DBUS_AUTH_COMMAND_CANCEL },
02103 { "DATA", DBUS_AUTH_COMMAND_DATA },
02104 { "BEGIN", DBUS_AUTH_COMMAND_BEGIN },
02105 { "REJECTED", DBUS_AUTH_COMMAND_REJECTED },
02106 { "OK", DBUS_AUTH_COMMAND_OK },
02107 { "ERROR", DBUS_AUTH_COMMAND_ERROR },
02108 { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
02109 { "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
02110 };
02111
02112 static DBusAuthCommand
02113 lookup_command_from_name (DBusString *command)
02114 {
02115 int i;
02116
02117 for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++)
02118 {
02119 if (_dbus_string_equal_c_str (command,
02120 auth_command_names[i].name))
02121 return auth_command_names[i].command;
02122 }
02123
02124 return DBUS_AUTH_COMMAND_UNKNOWN;
02125 }
02126
02127 static void
02128 goto_state (DBusAuth *auth,
02129 const DBusAuthStateData *state)
02130 {
02131 _dbus_verbose ("%s: going from state %s to state %s\n",
02132 DBUS_AUTH_NAME (auth),
02133 auth->state->name,
02134 state->name);
02135
02136 auth->state = state;
02137 }
02138
02139
02140 static dbus_bool_t
02141 process_command (DBusAuth *auth)
02142 {
02143 DBusAuthCommand command;
02144 DBusString line;
02145 DBusString args;
02146 int eol;
02147 int i, j;
02148 dbus_bool_t retval;
02149
02150
02151
02152 retval = FALSE;
02153
02154 eol = 0;
02155 if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol))
02156 return FALSE;
02157
02158 if (!_dbus_string_init (&line))
02159 {
02160 auth->needed_memory = TRUE;
02161 return FALSE;
02162 }
02163
02164 if (!_dbus_string_init (&args))
02165 {
02166 _dbus_string_free (&line);
02167 auth->needed_memory = TRUE;
02168 return FALSE;
02169 }
02170
02171 if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0))
02172 goto out;
02173
02174 if (!_dbus_string_validate_ascii (&line, 0,
02175 _dbus_string_get_length (&line)))
02176 {
02177 _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n",
02178 DBUS_AUTH_NAME (auth));
02179 if (!send_error (auth, "Command contained non-ASCII"))
02180 goto out;
02181 else
02182 goto next_command;
02183 }
02184
02185 _dbus_verbose ("%s: got command \"%s\"\n",
02186 DBUS_AUTH_NAME (auth),
02187 _dbus_string_get_const_data (&line));
02188
02189 _dbus_string_find_blank (&line, 0, &i);
02190 _dbus_string_skip_blank (&line, i, &j);
02191
02192 if (j > i)
02193 _dbus_string_delete (&line, i, j - i);
02194
02195 if (!_dbus_string_move (&line, i, &args, 0))
02196 goto out;
02197
02198
02199
02200
02201
02202 command = lookup_command_from_name (&line);
02203 if (!(* auth->state->handler) (auth, command, &args))
02204 goto out;
02205
02206 next_command:
02207
02208
02209
02210
02211
02212 _dbus_string_delete (&auth->incoming, 0, eol);
02213
02214
02215 _dbus_string_delete (&auth->incoming, 0, 2);
02216
02217 retval = TRUE;
02218
02219 out:
02220 _dbus_string_free (&args);
02221 _dbus_string_free (&line);
02222
02223 if (!retval)
02224 auth->needed_memory = TRUE;
02225 else
02226 auth->needed_memory = FALSE;
02227
02228 return retval;
02229 }
02230
02231
02246 DBusAuth*
02247 _dbus_auth_server_new (const DBusString *guid)
02248 {
02249 DBusAuth *auth;
02250 DBusAuthServer *server_auth;
02251 DBusString guid_copy;
02252
02253 if (!_dbus_string_init (&guid_copy))
02254 return NULL;
02255
02256 if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
02257 {
02258 _dbus_string_free (&guid_copy);
02259 return NULL;
02260 }
02261
02262 auth = _dbus_auth_new (sizeof (DBusAuthServer));
02263 if (auth == NULL)
02264 {
02265 _dbus_string_free (&guid_copy);
02266 return NULL;
02267 }
02268
02269 auth->side = auth_side_server;
02270 auth->state = &server_state_waiting_for_auth;
02271
02272 server_auth = DBUS_AUTH_SERVER (auth);
02273
02274 server_auth->guid = guid_copy;
02275
02276
02277
02278
02279 server_auth->failures = 0;
02280 server_auth->max_failures = 6;
02281
02282 return auth;
02283 }
02284
02292 DBusAuth*
02293 _dbus_auth_client_new (void)
02294 {
02295 DBusAuth *auth;
02296 DBusString guid_str;
02297
02298 if (!_dbus_string_init (&guid_str))
02299 return NULL;
02300
02301 auth = _dbus_auth_new (sizeof (DBusAuthClient));
02302 if (auth == NULL)
02303 {
02304 _dbus_string_free (&guid_str);
02305 return NULL;
02306 }
02307
02308 DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
02309
02310 auth->side = auth_side_client;
02311 auth->state = &client_state_need_send_auth;
02312
02313
02314
02315 if (!send_auth (auth, &all_mechanisms[0]))
02316 {
02317 _dbus_auth_unref (auth);
02318 return NULL;
02319 }
02320
02321 return auth;
02322 }
02323
02330 DBusAuth *
02331 _dbus_auth_ref (DBusAuth *auth)
02332 {
02333 _dbus_assert (auth != NULL);
02334
02335 auth->refcount += 1;
02336
02337 return auth;
02338 }
02339
02345 void
02346 _dbus_auth_unref (DBusAuth *auth)
02347 {
02348 _dbus_assert (auth != NULL);
02349 _dbus_assert (auth->refcount > 0);
02350
02351 auth->refcount -= 1;
02352 if (auth->refcount == 0)
02353 {
02354 shutdown_mech (auth);
02355
02356 if (DBUS_AUTH_IS_CLIENT (auth))
02357 {
02358 _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
02359 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
02360 }
02361 else
02362 {
02363 _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
02364
02365 _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
02366 }
02367
02368 if (auth->keyring)
02369 _dbus_keyring_unref (auth->keyring);
02370
02371 _dbus_string_free (&auth->context);
02372 _dbus_string_free (&auth->challenge);
02373 _dbus_string_free (&auth->identity);
02374 _dbus_string_free (&auth->incoming);
02375 _dbus_string_free (&auth->outgoing);
02376
02377 dbus_free_string_array (auth->allowed_mechs);
02378
02379 _dbus_credentials_unref (auth->credentials);
02380 _dbus_credentials_unref (auth->authorized_identity);
02381 _dbus_credentials_unref (auth->desired_identity);
02382
02383 dbus_free (auth);
02384 }
02385 }
02386
02395 dbus_bool_t
02396 _dbus_auth_set_mechanisms (DBusAuth *auth,
02397 const char **mechanisms)
02398 {
02399 char **copy;
02400
02401 if (mechanisms != NULL)
02402 {
02403 copy = _dbus_dup_string_array (mechanisms);
02404 if (copy == NULL)
02405 return FALSE;
02406 }
02407 else
02408 copy = NULL;
02409
02410 dbus_free_string_array (auth->allowed_mechs);
02411
02412 auth->allowed_mechs = copy;
02413
02414 return TRUE;
02415 }
02416
02421 #define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL)
02422
02430 DBusAuthState
02431 _dbus_auth_do_work (DBusAuth *auth)
02432 {
02433 auth->needed_memory = FALSE;
02434
02435
02436 #define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE)
02437
02438 do
02439 {
02440 if (DBUS_AUTH_IN_END_STATE (auth))
02441 break;
02442
02443 if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
02444 _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
02445 {
02446 goto_state (auth, &common_state_need_disconnect);
02447 _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n",
02448 DBUS_AUTH_NAME (auth));
02449 break;
02450 }
02451 }
02452 while (process_command (auth));
02453
02454 if (auth->needed_memory)
02455 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
02456 else if (_dbus_string_get_length (&auth->outgoing) > 0)
02457 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
02458 else if (auth->state == &common_state_need_disconnect)
02459 return DBUS_AUTH_STATE_NEED_DISCONNECT;
02460 else if (auth->state == &common_state_authenticated)
02461 return DBUS_AUTH_STATE_AUTHENTICATED;
02462 else return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
02463 }
02464
02474 dbus_bool_t
02475 _dbus_auth_get_bytes_to_send (DBusAuth *auth,
02476 const DBusString **str)
02477 {
02478 _dbus_assert (auth != NULL);
02479 _dbus_assert (str != NULL);
02480
02481 *str = NULL;
02482
02483 if (_dbus_string_get_length (&auth->outgoing) == 0)
02484 return FALSE;
02485
02486 *str = &auth->outgoing;
02487
02488 return TRUE;
02489 }
02490
02499 void
02500 _dbus_auth_bytes_sent (DBusAuth *auth,
02501 int bytes_sent)
02502 {
02503 _dbus_verbose ("%s: Sent %d bytes of: %s\n",
02504 DBUS_AUTH_NAME (auth),
02505 bytes_sent,
02506 _dbus_string_get_const_data (&auth->outgoing));
02507
02508 _dbus_string_delete (&auth->outgoing,
02509 0, bytes_sent);
02510 }
02511
02519 void
02520 _dbus_auth_get_buffer (DBusAuth *auth,
02521 DBusString **buffer)
02522 {
02523 _dbus_assert (auth != NULL);
02524 _dbus_assert (!auth->buffer_outstanding);
02525
02526 *buffer = &auth->incoming;
02527
02528 auth->buffer_outstanding = TRUE;
02529 }
02530
02538 void
02539 _dbus_auth_return_buffer (DBusAuth *auth,
02540 DBusString *buffer,
02541 int bytes_read)
02542 {
02543 _dbus_assert (buffer == &auth->incoming);
02544 _dbus_assert (auth->buffer_outstanding);
02545
02546 auth->buffer_outstanding = FALSE;
02547 }
02548
02558 void
02559 _dbus_auth_get_unused_bytes (DBusAuth *auth,
02560 const DBusString **str)
02561 {
02562 if (!DBUS_AUTH_IN_END_STATE (auth))
02563 return;
02564
02565 *str = &auth->incoming;
02566 }
02567
02568
02575 void
02576 _dbus_auth_delete_unused_bytes (DBusAuth *auth)
02577 {
02578 if (!DBUS_AUTH_IN_END_STATE (auth))
02579 return;
02580
02581 _dbus_string_set_length (&auth->incoming, 0);
02582 }
02583
02592 dbus_bool_t
02593 _dbus_auth_needs_encoding (DBusAuth *auth)
02594 {
02595 if (auth->state != &common_state_authenticated)
02596 return FALSE;
02597
02598 if (auth->mech != NULL)
02599 {
02600 if (DBUS_AUTH_IS_CLIENT (auth))
02601 return auth->mech->client_encode_func != NULL;
02602 else
02603 return auth->mech->server_encode_func != NULL;
02604 }
02605 else
02606 return FALSE;
02607 }
02608
02619 dbus_bool_t
02620 _dbus_auth_encode_data (DBusAuth *auth,
02621 const DBusString *plaintext,
02622 DBusString *encoded)
02623 {
02624 _dbus_assert (plaintext != encoded);
02625
02626 if (auth->state != &common_state_authenticated)
02627 return FALSE;
02628
02629 if (_dbus_auth_needs_encoding (auth))
02630 {
02631 if (DBUS_AUTH_IS_CLIENT (auth))
02632 return (* auth->mech->client_encode_func) (auth, plaintext, encoded);
02633 else
02634 return (* auth->mech->server_encode_func) (auth, plaintext, encoded);
02635 }
02636 else
02637 {
02638 return _dbus_string_copy (plaintext, 0, encoded,
02639 _dbus_string_get_length (encoded));
02640 }
02641 }
02642
02651 dbus_bool_t
02652 _dbus_auth_needs_decoding (DBusAuth *auth)
02653 {
02654 if (auth->state != &common_state_authenticated)
02655 return FALSE;
02656
02657 if (auth->mech != NULL)
02658 {
02659 if (DBUS_AUTH_IS_CLIENT (auth))
02660 return auth->mech->client_decode_func != NULL;
02661 else
02662 return auth->mech->server_decode_func != NULL;
02663 }
02664 else
02665 return FALSE;
02666 }
02667
02668
02682 dbus_bool_t
02683 _dbus_auth_decode_data (DBusAuth *auth,
02684 const DBusString *encoded,
02685 DBusString *plaintext)
02686 {
02687 _dbus_assert (plaintext != encoded);
02688
02689 if (auth->state != &common_state_authenticated)
02690 return FALSE;
02691
02692 if (_dbus_auth_needs_decoding (auth))
02693 {
02694 if (DBUS_AUTH_IS_CLIENT (auth))
02695 return (* auth->mech->client_decode_func) (auth, encoded, plaintext);
02696 else
02697 return (* auth->mech->server_decode_func) (auth, encoded, plaintext);
02698 }
02699 else
02700 {
02701 return _dbus_string_copy (encoded, 0, plaintext,
02702 _dbus_string_get_length (plaintext));
02703 }
02704 }
02705
02714 dbus_bool_t
02715 _dbus_auth_set_credentials (DBusAuth *auth,
02716 DBusCredentials *credentials)
02717 {
02718 _dbus_credentials_clear (auth->credentials);
02719 return _dbus_credentials_add_credentials (auth->credentials,
02720 credentials);
02721 }
02722
02732 DBusCredentials*
02733 _dbus_auth_get_identity (DBusAuth *auth)
02734 {
02735 if (auth->state == &common_state_authenticated)
02736 {
02737 return auth->authorized_identity;
02738 }
02739 else
02740 {
02741
02742
02743
02744
02745 _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
02746 return auth->authorized_identity;
02747 }
02748 }
02749
02756 const char*
02757 _dbus_auth_get_guid_from_server (DBusAuth *auth)
02758 {
02759 _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
02760
02761 if (auth->state == &common_state_authenticated)
02762 return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
02763 else
02764 return NULL;
02765 }
02766
02775 dbus_bool_t
02776 _dbus_auth_set_context (DBusAuth *auth,
02777 const DBusString *context)
02778 {
02779 return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context),
02780 &auth->context, 0, _dbus_string_get_length (context));
02781 }
02782
02790 void
02791 _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
02792 {
02793 auth->unix_fd_possible = b;
02794 }
02795
02802 dbus_bool_t
02803 _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
02804 {
02805 return auth->unix_fd_negotiated;
02806 }
02807
02810