00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "dbus-auth.h"
00024 #include "dbus-string.h"
00025 #include "dbus-list.h"
00026 #include "dbus-internals.h"
00027 #include "dbus-keyring.h"
00028 #include "dbus-sha.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-userdb.h"
00031
00068 typedef dbus_bool_t (* DBusInitialResponseFunction) (DBusAuth *auth,
00069 DBusString *response);
00070
00075 typedef dbus_bool_t (* DBusAuthDataFunction) (DBusAuth *auth,
00076 const DBusString *data);
00077
00081 typedef dbus_bool_t (* DBusAuthEncodeFunction) (DBusAuth *auth,
00082 const DBusString *data,
00083 DBusString *encoded);
00084
00088 typedef dbus_bool_t (* DBusAuthDecodeFunction) (DBusAuth *auth,
00089 const DBusString *data,
00090 DBusString *decoded);
00091
00095 typedef void (* DBusAuthShutdownFunction) (DBusAuth *auth);
00096
00100 typedef struct
00101 {
00102 const char *mechanism;
00103 DBusAuthDataFunction server_data_func;
00104 DBusAuthEncodeFunction server_encode_func;
00105 DBusAuthDecodeFunction server_decode_func;
00106 DBusAuthShutdownFunction server_shutdown_func;
00107 DBusInitialResponseFunction client_initial_response_func;
00108 DBusAuthDataFunction client_data_func;
00109 DBusAuthEncodeFunction client_encode_func;
00110 DBusAuthDecodeFunction client_decode_func;
00111 DBusAuthShutdownFunction client_shutdown_func;
00112 } DBusAuthMechanismHandler;
00113
00117 typedef enum {
00118 DBUS_AUTH_COMMAND_AUTH,
00119 DBUS_AUTH_COMMAND_CANCEL,
00120 DBUS_AUTH_COMMAND_DATA,
00121 DBUS_AUTH_COMMAND_BEGIN,
00122 DBUS_AUTH_COMMAND_REJECTED,
00123 DBUS_AUTH_COMMAND_OK,
00124 DBUS_AUTH_COMMAND_ERROR,
00125 DBUS_AUTH_COMMAND_UNKNOWN
00126 } DBusAuthCommand;
00127
00133 typedef dbus_bool_t (* DBusAuthStateFunction) (DBusAuth *auth,
00134 DBusAuthCommand command,
00135 const DBusString *args);
00136
00140 typedef struct
00141 {
00142 const char *name;
00143 DBusAuthStateFunction handler;
00144 } DBusAuthStateData;
00145
00149 struct DBusAuth
00150 {
00151 int refcount;
00152 const char *side;
00154 DBusString incoming;
00155 DBusString outgoing;
00157 const DBusAuthStateData *state;
00159 const DBusAuthMechanismHandler *mech;
00161 DBusString identity;
00165 DBusCredentials credentials;
00169 DBusCredentials authorized_identity;
00171 DBusCredentials desired_identity;
00173 DBusString context;
00174 DBusKeyring *keyring;
00175 int cookie_id;
00176 DBusString challenge;
00178 char **allowed_mechs;
00182 unsigned int needed_memory : 1;
00185 unsigned int already_got_mechanisms : 1;
00186 unsigned int already_asked_for_initial_response : 1;
00187 unsigned int buffer_outstanding : 1;
00188 };
00189
00193 typedef struct
00194 {
00195 DBusAuth base;
00197 DBusList *mechs_to_try;
00199 DBusString guid_from_server;
00201 } DBusAuthClient;
00202
00206 typedef struct
00207 {
00208 DBusAuth base;
00210 int failures;
00211 int max_failures;
00213 DBusString guid;
00215 } DBusAuthServer;
00216
00217 static void goto_state (DBusAuth *auth,
00218 const DBusAuthStateData *new_state);
00219 static dbus_bool_t send_auth (DBusAuth *auth,
00220 const DBusAuthMechanismHandler *mech);
00221 static dbus_bool_t send_data (DBusAuth *auth,
00222 DBusString *data);
00223 static dbus_bool_t send_rejected (DBusAuth *auth);
00224 static dbus_bool_t send_error (DBusAuth *auth,
00225 const char *message);
00226 static dbus_bool_t send_ok (DBusAuth *auth);
00227 static dbus_bool_t send_begin (DBusAuth *auth,
00228 const DBusString *args_from_ok);
00229 static dbus_bool_t send_cancel (DBusAuth *auth);
00230
00235 static dbus_bool_t handle_server_state_waiting_for_auth (DBusAuth *auth,
00236 DBusAuthCommand command,
00237 const DBusString *args);
00238 static dbus_bool_t handle_server_state_waiting_for_data (DBusAuth *auth,
00239 DBusAuthCommand command,
00240 const DBusString *args);
00241 static dbus_bool_t handle_server_state_waiting_for_begin (DBusAuth *auth,
00242 DBusAuthCommand command,
00243 const DBusString *args);
00244
00245 static const DBusAuthStateData server_state_waiting_for_auth = {
00246 "WaitingForAuth", handle_server_state_waiting_for_auth
00247 };
00248 static const DBusAuthStateData server_state_waiting_for_data = {
00249 "WaitingForData", handle_server_state_waiting_for_data
00250 };
00251 static const DBusAuthStateData server_state_waiting_for_begin = {
00252 "WaitingForBegin", handle_server_state_waiting_for_begin
00253 };
00254
00259 static dbus_bool_t handle_client_state_waiting_for_data (DBusAuth *auth,
00260 DBusAuthCommand command,
00261 const DBusString *args);
00262 static dbus_bool_t handle_client_state_waiting_for_ok (DBusAuth *auth,
00263 DBusAuthCommand command,
00264 const DBusString *args);
00265 static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *auth,
00266 DBusAuthCommand command,
00267 const DBusString *args);
00268
00269 static const DBusAuthStateData client_state_need_send_auth = {
00270 "NeedSendAuth", NULL
00271 };
00272 static const DBusAuthStateData client_state_waiting_for_data = {
00273 "WaitingForData", handle_client_state_waiting_for_data
00274 };
00275 static const DBusAuthStateData client_state_waiting_for_ok = {
00276 "WaitingForOK", handle_client_state_waiting_for_ok
00277 };
00278 static const DBusAuthStateData client_state_waiting_for_reject = {
00279 "WaitingForReject", handle_client_state_waiting_for_reject
00280 };
00281
00286 static const DBusAuthStateData common_state_authenticated = {
00287 "Authenticated", NULL
00288 };
00289
00290 static const DBusAuthStateData common_state_need_disconnect = {
00291 "NeedDisconnect", NULL
00292 };
00293
00294 static const char auth_side_client[] = "client";
00295 static const char auth_side_server[] = "server";
00300 #define DBUS_AUTH_IS_SERVER(auth) ((auth)->side == auth_side_server)
00301
00305 #define DBUS_AUTH_IS_CLIENT(auth) ((auth)->side == auth_side_client)
00306
00310 #define DBUS_AUTH_CLIENT(auth) ((DBusAuthClient*)(auth))
00311
00315 #define DBUS_AUTH_SERVER(auth) ((DBusAuthServer*)(auth))
00316
00322 #define DBUS_AUTH_NAME(auth) ((auth)->side)
00323
00324 static DBusAuth*
00325 _dbus_auth_new (int size)
00326 {
00327 DBusAuth *auth;
00328
00329 auth = dbus_malloc0 (size);
00330 if (auth == NULL)
00331 return NULL;
00332
00333 auth->refcount = 1;
00334
00335 _dbus_credentials_clear (&auth->credentials);
00336 _dbus_credentials_clear (&auth->authorized_identity);
00337 _dbus_credentials_clear (&auth->desired_identity);
00338
00339 auth->keyring = NULL;
00340 auth->cookie_id = -1;
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 if (!_dbus_string_init (&auth->incoming))
00351 goto enomem_0;
00352
00353 if (!_dbus_string_init (&auth->outgoing))
00354 goto enomem_1;
00355
00356 if (!_dbus_string_init (&auth->identity))
00357 goto enomem_2;
00358
00359 if (!_dbus_string_init (&auth->context))
00360 goto enomem_3;
00361
00362 if (!_dbus_string_init (&auth->challenge))
00363 goto enomem_4;
00364
00365
00366 if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
00367 goto enomem_5;
00368
00369 return auth;
00370
00371 enomem_5:
00372 _dbus_string_free (&auth->challenge);
00373 enomem_4:
00374 _dbus_string_free (&auth->context);
00375 enomem_3:
00376 _dbus_string_free (&auth->identity);
00377 enomem_2:
00378 _dbus_string_free (&auth->outgoing);
00379 enomem_1:
00380 _dbus_string_free (&auth->incoming);
00381 enomem_0:
00382 dbus_free (auth);
00383 return NULL;
00384 }
00385
00386 static void
00387 shutdown_mech (DBusAuth *auth)
00388 {
00389
00390 auth->already_asked_for_initial_response = FALSE;
00391 _dbus_string_set_length (&auth->identity, 0);
00392
00393 _dbus_credentials_clear (&auth->authorized_identity);
00394 _dbus_credentials_clear (&auth->desired_identity);
00395
00396 if (auth->mech != NULL)
00397 {
00398 _dbus_verbose ("%s: Shutting down mechanism %s\n",
00399 DBUS_AUTH_NAME (auth), auth->mech->mechanism);
00400
00401 if (DBUS_AUTH_IS_CLIENT (auth))
00402 (* auth->mech->client_shutdown_func) (auth);
00403 else
00404 (* auth->mech->server_shutdown_func) (auth);
00405
00406 auth->mech = NULL;
00407 }
00408 }
00409
00410
00411
00412
00413
00414 static dbus_bool_t
00415 sha1_compute_hash (DBusAuth *auth,
00416 int cookie_id,
00417 const DBusString *server_challenge,
00418 const DBusString *client_challenge,
00419 DBusString *hash)
00420 {
00421 DBusString cookie;
00422 DBusString to_hash;
00423 dbus_bool_t retval;
00424
00425 _dbus_assert (auth->keyring != NULL);
00426
00427 retval = FALSE;
00428
00429 if (!_dbus_string_init (&cookie))
00430 return FALSE;
00431
00432 if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id,
00433 &cookie))
00434 goto out_0;
00435
00436 if (_dbus_string_get_length (&cookie) == 0)
00437 {
00438 retval = TRUE;
00439 goto out_0;
00440 }
00441
00442 if (!_dbus_string_init (&to_hash))
00443 goto out_0;
00444
00445 if (!_dbus_string_copy (server_challenge, 0,
00446 &to_hash, _dbus_string_get_length (&to_hash)))
00447 goto out_1;
00448
00449 if (!_dbus_string_append (&to_hash, ":"))
00450 goto out_1;
00451
00452 if (!_dbus_string_copy (client_challenge, 0,
00453 &to_hash, _dbus_string_get_length (&to_hash)))
00454 goto out_1;
00455
00456 if (!_dbus_string_append (&to_hash, ":"))
00457 goto out_1;
00458
00459 if (!_dbus_string_copy (&cookie, 0,
00460 &to_hash, _dbus_string_get_length (&to_hash)))
00461 goto out_1;
00462
00463 if (!_dbus_sha_compute (&to_hash, hash))
00464 goto out_1;
00465
00466 retval = TRUE;
00467
00468 out_1:
00469 _dbus_string_zero (&to_hash);
00470 _dbus_string_free (&to_hash);
00471 out_0:
00472 _dbus_string_zero (&cookie);
00473 _dbus_string_free (&cookie);
00474 return retval;
00475 }
00476
00481 #define N_CHALLENGE_BYTES (128/8)
00482
00483 static dbus_bool_t
00484 sha1_handle_first_client_response (DBusAuth *auth,
00485 const DBusString *data)
00486 {
00487
00488
00489
00490 DBusString tmp;
00491 DBusString tmp2;
00492 dbus_bool_t retval;
00493 DBusError error;
00494
00495 retval = FALSE;
00496
00497 _dbus_string_set_length (&auth->challenge, 0);
00498
00499 if (_dbus_string_get_length (data) > 0)
00500 {
00501 if (_dbus_string_get_length (&auth->identity) > 0)
00502 {
00503
00504 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
00505 DBUS_AUTH_NAME (auth));
00506 return send_rejected (auth);
00507 }
00508 else
00509 {
00510
00511 if (!_dbus_string_copy (data, 0, &auth->identity, 0))
00512 return FALSE;
00513 }
00514 }
00515
00516 if (!_dbus_credentials_from_username (data, &auth->desired_identity))
00517 {
00518 _dbus_verbose ("%s: Did not get a valid username from client\n",
00519 DBUS_AUTH_NAME (auth));
00520 return send_rejected (auth);
00521 }
00522
00523 if (!_dbus_string_init (&tmp))
00524 return FALSE;
00525
00526 if (!_dbus_string_init (&tmp2))
00527 {
00528 _dbus_string_free (&tmp);
00529 return FALSE;
00530 }
00531
00532
00533
00534
00535
00536 if (auth->keyring &&
00537 !_dbus_keyring_is_for_user (auth->keyring,
00538 data))
00539 {
00540 _dbus_keyring_unref (auth->keyring);
00541 auth->keyring = NULL;
00542 }
00543
00544 if (auth->keyring == NULL)
00545 {
00546 dbus_error_init (&error);
00547 auth->keyring = _dbus_keyring_new_homedir (data,
00548 &auth->context,
00549 &error);
00550
00551 if (auth->keyring == NULL)
00552 {
00553 if (dbus_error_has_name (&error,
00554 DBUS_ERROR_NO_MEMORY))
00555 {
00556 dbus_error_free (&error);
00557 goto out;
00558 }
00559 else
00560 {
00561 _DBUS_ASSERT_ERROR_IS_SET (&error);
00562 _dbus_verbose ("%s: Error loading keyring: %s\n",
00563 DBUS_AUTH_NAME (auth), error.message);
00564 if (send_rejected (auth))
00565 retval = TRUE;
00566 dbus_error_free (&error);
00567 goto out;
00568 }
00569 }
00570 else
00571 {
00572 _dbus_assert (!dbus_error_is_set (&error));
00573 }
00574 }
00575
00576 _dbus_assert (auth->keyring != NULL);
00577
00578 dbus_error_init (&error);
00579 auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error);
00580 if (auth->cookie_id < 0)
00581 {
00582 _DBUS_ASSERT_ERROR_IS_SET (&error);
00583 _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n",
00584 DBUS_AUTH_NAME (auth), error.message);
00585 if (send_rejected (auth))
00586 retval = TRUE;
00587 dbus_error_free (&error);
00588 goto out;
00589 }
00590 else
00591 {
00592 _dbus_assert (!dbus_error_is_set (&error));
00593 }
00594
00595 if (!_dbus_string_copy (&auth->context, 0,
00596 &tmp2, _dbus_string_get_length (&tmp2)))
00597 goto out;
00598
00599 if (!_dbus_string_append (&tmp2, " "))
00600 goto out;
00601
00602 if (!_dbus_string_append_int (&tmp2, auth->cookie_id))
00603 goto out;
00604
00605 if (!_dbus_string_append (&tmp2, " "))
00606 goto out;
00607
00608 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
00609 goto out;
00610
00611 _dbus_string_set_length (&auth->challenge, 0);
00612 if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0))
00613 goto out;
00614
00615 if (!_dbus_string_hex_encode (&tmp, 0, &tmp2,
00616 _dbus_string_get_length (&tmp2)))
00617 goto out;
00618
00619 if (!send_data (auth, &tmp2))
00620 goto out;
00621
00622 goto_state (auth, &server_state_waiting_for_data);
00623 retval = TRUE;
00624
00625 out:
00626 _dbus_string_zero (&tmp);
00627 _dbus_string_free (&tmp);
00628 _dbus_string_zero (&tmp2);
00629 _dbus_string_free (&tmp2);
00630
00631 return retval;
00632 }
00633
00634 static dbus_bool_t
00635 sha1_handle_second_client_response (DBusAuth *auth,
00636 const DBusString *data)
00637 {
00638
00639
00640
00641
00642
00643 int i;
00644 DBusString client_challenge;
00645 DBusString client_hash;
00646 dbus_bool_t retval;
00647 DBusString correct_hash;
00648
00649 retval = FALSE;
00650
00651 if (!_dbus_string_find_blank (data, 0, &i))
00652 {
00653 _dbus_verbose ("%s: no space separator in client response\n",
00654 DBUS_AUTH_NAME (auth));
00655 return send_rejected (auth);
00656 }
00657
00658 if (!_dbus_string_init (&client_challenge))
00659 goto out_0;
00660
00661 if (!_dbus_string_init (&client_hash))
00662 goto out_1;
00663
00664 if (!_dbus_string_copy_len (data, 0, i, &client_challenge,
00665 0))
00666 goto out_2;
00667
00668 _dbus_string_skip_blank (data, i, &i);
00669
00670 if (!_dbus_string_copy_len (data, i,
00671 _dbus_string_get_length (data) - i,
00672 &client_hash,
00673 0))
00674 goto out_2;
00675
00676 if (_dbus_string_get_length (&client_challenge) == 0 ||
00677 _dbus_string_get_length (&client_hash) == 0)
00678 {
00679 _dbus_verbose ("%s: zero-length client challenge or hash\n",
00680 DBUS_AUTH_NAME (auth));
00681 if (send_rejected (auth))
00682 retval = TRUE;
00683 goto out_2;
00684 }
00685
00686 if (!_dbus_string_init (&correct_hash))
00687 goto out_2;
00688
00689 if (!sha1_compute_hash (auth, auth->cookie_id,
00690 &auth->challenge,
00691 &client_challenge,
00692 &correct_hash))
00693 goto out_3;
00694
00695
00696 if (_dbus_string_get_length (&correct_hash) == 0)
00697 {
00698 if (send_rejected (auth))
00699 retval = TRUE;
00700 goto out_3;
00701 }
00702
00703 if (!_dbus_string_equal (&client_hash, &correct_hash))
00704 {
00705 if (send_rejected (auth))
00706 retval = TRUE;
00707 goto out_3;
00708 }
00709
00710 if (!send_ok (auth))
00711 goto out_3;
00712
00713 _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT" using DBUS_COOKIE_SHA1\n",
00714 DBUS_AUTH_NAME (auth), auth->desired_identity.uid);
00715
00716 auth->authorized_identity = auth->desired_identity;
00717 retval = TRUE;
00718
00719 out_3:
00720 _dbus_string_zero (&correct_hash);
00721 _dbus_string_free (&correct_hash);
00722 out_2:
00723 _dbus_string_zero (&client_hash);
00724 _dbus_string_free (&client_hash);
00725 out_1:
00726 _dbus_string_free (&client_challenge);
00727 out_0:
00728 return retval;
00729 }
00730
00731 static dbus_bool_t
00732 handle_server_data_cookie_sha1_mech (DBusAuth *auth,
00733 const DBusString *data)
00734 {
00735 if (auth->cookie_id < 0)
00736 return sha1_handle_first_client_response (auth, data);
00737 else
00738 return sha1_handle_second_client_response (auth, data);
00739 }
00740
00741 static void
00742 handle_server_shutdown_cookie_sha1_mech (DBusAuth *auth)
00743 {
00744 auth->cookie_id = -1;
00745 _dbus_string_set_length (&auth->challenge, 0);
00746 }
00747
00748 static dbus_bool_t
00749 handle_client_initial_response_cookie_sha1_mech (DBusAuth *auth,
00750 DBusString *response)
00751 {
00752 const DBusString *username;
00753 dbus_bool_t retval;
00754
00755 retval = FALSE;
00756
00757 if (!_dbus_username_from_current_process (&username))
00758 goto out_0;
00759
00760 if (!_dbus_string_hex_encode (username, 0,
00761 response,
00762 _dbus_string_get_length (response)))
00763 goto out_0;
00764
00765 retval = TRUE;
00766
00767 out_0:
00768 return retval;
00769 }
00770
00771 static dbus_bool_t
00772 handle_client_data_cookie_sha1_mech (DBusAuth *auth,
00773 const DBusString *data)
00774 {
00775
00776
00777
00778
00779 dbus_bool_t retval;
00780 DBusString context;
00781 DBusString cookie_id_str;
00782 DBusString server_challenge;
00783 DBusString client_challenge;
00784 DBusString correct_hash;
00785 DBusString tmp;
00786 int i, j;
00787 long val;
00788
00789 retval = FALSE;
00790
00791 if (!_dbus_string_find_blank (data, 0, &i))
00792 {
00793 if (send_error (auth,
00794 "Server did not send context/ID/challenge properly"))
00795 retval = TRUE;
00796 goto out_0;
00797 }
00798
00799 if (!_dbus_string_init (&context))
00800 goto out_0;
00801
00802 if (!_dbus_string_copy_len (data, 0, i,
00803 &context, 0))
00804 goto out_1;
00805
00806 _dbus_string_skip_blank (data, i, &i);
00807 if (!_dbus_string_find_blank (data, i, &j))
00808 {
00809 if (send_error (auth,
00810 "Server did not send context/ID/challenge properly"))
00811 retval = TRUE;
00812 goto out_1;
00813 }
00814
00815 if (!_dbus_string_init (&cookie_id_str))
00816 goto out_1;
00817
00818 if (!_dbus_string_copy_len (data, i, j - i,
00819 &cookie_id_str, 0))
00820 goto out_2;
00821
00822 if (!_dbus_string_init (&server_challenge))
00823 goto out_2;
00824
00825 i = j;
00826 _dbus_string_skip_blank (data, i, &i);
00827 j = _dbus_string_get_length (data);
00828
00829 if (!_dbus_string_copy_len (data, i, j - i,
00830 &server_challenge, 0))
00831 goto out_3;
00832
00833 if (!_dbus_keyring_validate_context (&context))
00834 {
00835 if (send_error (auth, "Server sent invalid cookie context"))
00836 retval = TRUE;
00837 goto out_3;
00838 }
00839
00840 if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL))
00841 {
00842 if (send_error (auth, "Could not parse cookie ID as an integer"))
00843 retval = TRUE;
00844 goto out_3;
00845 }
00846
00847 if (_dbus_string_get_length (&server_challenge) == 0)
00848 {
00849 if (send_error (auth, "Empty server challenge string"))
00850 retval = TRUE;
00851 goto out_3;
00852 }
00853
00854 if (auth->keyring == NULL)
00855 {
00856 DBusError error;
00857
00858 dbus_error_init (&error);
00859 auth->keyring = _dbus_keyring_new_homedir (NULL,
00860 &context,
00861 &error);
00862
00863 if (auth->keyring == NULL)
00864 {
00865 if (dbus_error_has_name (&error,
00866 DBUS_ERROR_NO_MEMORY))
00867 {
00868 dbus_error_free (&error);
00869 goto out_3;
00870 }
00871 else
00872 {
00873 _DBUS_ASSERT_ERROR_IS_SET (&error);
00874
00875 _dbus_verbose ("%s: Error loading keyring: %s\n",
00876 DBUS_AUTH_NAME (auth), error.message);
00877
00878 if (send_error (auth, "Could not load cookie file"))
00879 retval = TRUE;
00880
00881 dbus_error_free (&error);
00882 goto out_3;
00883 }
00884 }
00885 else
00886 {
00887 _dbus_assert (!dbus_error_is_set (&error));
00888 }
00889 }
00890
00891 _dbus_assert (auth->keyring != NULL);
00892
00893 if (!_dbus_string_init (&tmp))
00894 goto out_3;
00895
00896 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
00897 goto out_4;
00898
00899 if (!_dbus_string_init (&client_challenge))
00900 goto out_4;
00901
00902 if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0))
00903 goto out_5;
00904
00905 if (!_dbus_string_init (&correct_hash))
00906 goto out_5;
00907
00908 if (!sha1_compute_hash (auth, val,
00909 &server_challenge,
00910 &client_challenge,
00911 &correct_hash))
00912 goto out_6;
00913
00914 if (_dbus_string_get_length (&correct_hash) == 0)
00915 {
00916
00917 if (send_error (auth, "Don't have the requested cookie ID"))
00918 retval = TRUE;
00919 goto out_6;
00920 }
00921
00922 _dbus_string_set_length (&tmp, 0);
00923
00924 if (!_dbus_string_copy (&client_challenge, 0, &tmp,
00925 _dbus_string_get_length (&tmp)))
00926 goto out_6;
00927
00928 if (!_dbus_string_append (&tmp, " "))
00929 goto out_6;
00930
00931 if (!_dbus_string_copy (&correct_hash, 0, &tmp,
00932 _dbus_string_get_length (&tmp)))
00933 goto out_6;
00934
00935 if (!send_data (auth, &tmp))
00936 goto out_6;
00937
00938 retval = TRUE;
00939
00940 out_6:
00941 _dbus_string_zero (&correct_hash);
00942 _dbus_string_free (&correct_hash);
00943 out_5:
00944 _dbus_string_free (&client_challenge);
00945 out_4:
00946 _dbus_string_zero (&tmp);
00947 _dbus_string_free (&tmp);
00948 out_3:
00949 _dbus_string_free (&server_challenge);
00950 out_2:
00951 _dbus_string_free (&cookie_id_str);
00952 out_1:
00953 _dbus_string_free (&context);
00954 out_0:
00955 return retval;
00956 }
00957
00958 static void
00959 handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)
00960 {
00961 auth->cookie_id = -1;
00962 _dbus_string_set_length (&auth->challenge, 0);
00963 }
00964
00965 static dbus_bool_t
00966 handle_server_data_external_mech (DBusAuth *auth,
00967 const DBusString *data)
00968 {
00969 if (auth->credentials.uid == DBUS_UID_UNSET)
00970 {
00971 _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
00972 DBUS_AUTH_NAME (auth));
00973 return send_rejected (auth);
00974 }
00975
00976 if (_dbus_string_get_length (data) > 0)
00977 {
00978 if (_dbus_string_get_length (&auth->identity) > 0)
00979 {
00980
00981 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
00982 DBUS_AUTH_NAME (auth));
00983 return send_rejected (auth);
00984 }
00985 else
00986 {
00987
00988 if (!_dbus_string_copy (data, 0, &auth->identity, 0))
00989 return FALSE;
00990 }
00991 }
00992
00993
00994 if (_dbus_string_get_length (&auth->identity) == 0 &&
00995 !auth->already_asked_for_initial_response)
00996 {
00997 if (send_data (auth, NULL))
00998 {
00999 _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n",
01000 DBUS_AUTH_NAME (auth));
01001 auth->already_asked_for_initial_response = TRUE;
01002 return TRUE;
01003 }
01004 else
01005 return FALSE;
01006 }
01007
01008 _dbus_credentials_clear (&auth->desired_identity);
01009
01010
01011
01012
01013
01014
01015 if (_dbus_string_get_length (&auth->identity) == 0)
01016 {
01017 auth->desired_identity.uid = auth->credentials.uid;
01018 }
01019 else
01020 {
01021 if (!_dbus_parse_uid (&auth->identity,
01022 &auth->desired_identity.uid))
01023 {
01024 _dbus_verbose ("%s: could not get credentials from uid string\n",
01025 DBUS_AUTH_NAME (auth));
01026 return send_rejected (auth);
01027 }
01028 }
01029
01030 if (auth->desired_identity.uid == DBUS_UID_UNSET)
01031 {
01032 _dbus_verbose ("%s: desired user %s is no good\n",
01033 DBUS_AUTH_NAME (auth),
01034 _dbus_string_get_const_data (&auth->identity));
01035 return send_rejected (auth);
01036 }
01037
01038 if (_dbus_credentials_match (&auth->desired_identity,
01039 &auth->credentials))
01040 {
01041
01042 if (!send_ok (auth))
01043 return FALSE;
01044
01045 _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT
01046 " matching socket credentials UID "DBUS_UID_FORMAT"\n",
01047 DBUS_AUTH_NAME (auth),
01048 auth->desired_identity.uid,
01049 auth->credentials.uid);
01050
01051 auth->authorized_identity.pid = auth->credentials.pid;
01052 auth->authorized_identity.uid = auth->desired_identity.uid;
01053 return TRUE;
01054 }
01055 else
01056 {
01057 _dbus_verbose ("%s: credentials uid="DBUS_UID_FORMAT
01058 " gid="DBUS_GID_FORMAT
01059 " do not allow uid="DBUS_UID_FORMAT
01060 " gid="DBUS_GID_FORMAT"\n",
01061 DBUS_AUTH_NAME (auth),
01062 auth->credentials.uid, auth->credentials.gid,
01063 auth->desired_identity.uid, auth->desired_identity.gid);
01064 return send_rejected (auth);
01065 }
01066 }
01067
01068 static void
01069 handle_server_shutdown_external_mech (DBusAuth *auth)
01070 {
01071
01072 }
01073
01074 static dbus_bool_t
01075 handle_client_initial_response_external_mech (DBusAuth *auth,
01076 DBusString *response)
01077 {
01078
01079
01080
01081
01082
01083 DBusString plaintext;
01084
01085 if (!_dbus_string_init (&plaintext))
01086 return FALSE;
01087
01088 if (!_dbus_string_append_uint (&plaintext,
01089 _dbus_getuid ()))
01090 goto failed;
01091
01092 if (!_dbus_string_hex_encode (&plaintext, 0,
01093 response,
01094 _dbus_string_get_length (response)))
01095 goto failed;
01096
01097 _dbus_string_free (&plaintext);
01098
01099 return TRUE;
01100
01101 failed:
01102 _dbus_string_free (&plaintext);
01103 return FALSE;
01104 }
01105
01106 static dbus_bool_t
01107 handle_client_data_external_mech (DBusAuth *auth,
01108 const DBusString *data)
01109 {
01110
01111 return TRUE;
01112 }
01113
01114 static void
01115 handle_client_shutdown_external_mech (DBusAuth *auth)
01116 {
01117
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 static const DBusAuthMechanismHandler
01130 all_mechanisms[] = {
01131 { "EXTERNAL",
01132 handle_server_data_external_mech,
01133 NULL, NULL,
01134 handle_server_shutdown_external_mech,
01135 handle_client_initial_response_external_mech,
01136 handle_client_data_external_mech,
01137 NULL, NULL,
01138 handle_client_shutdown_external_mech },
01139 { "DBUS_COOKIE_SHA1",
01140 handle_server_data_cookie_sha1_mech,
01141 NULL, NULL,
01142 handle_server_shutdown_cookie_sha1_mech,
01143 handle_client_initial_response_cookie_sha1_mech,
01144 handle_client_data_cookie_sha1_mech,
01145 NULL, NULL,
01146 handle_client_shutdown_cookie_sha1_mech },
01147 { NULL, NULL }
01148 };
01149
01150 static const DBusAuthMechanismHandler*
01151 find_mech (const DBusString *name,
01152 char **allowed_mechs)
01153 {
01154 int i;
01155
01156 if (allowed_mechs != NULL &&
01157 !_dbus_string_array_contains ((const char**) allowed_mechs,
01158 _dbus_string_get_const_data (name)))
01159 return NULL;
01160
01161 i = 0;
01162 while (all_mechanisms[i].mechanism != NULL)
01163 {
01164 if (_dbus_string_equal_c_str (name,
01165 all_mechanisms[i].mechanism))
01166
01167 return &all_mechanisms[i];
01168
01169 ++i;
01170 }
01171
01172 return NULL;
01173 }
01174
01175 static dbus_bool_t
01176 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
01177 {
01178 DBusString auth_command;
01179
01180 if (!_dbus_string_init (&auth_command))
01181 return FALSE;
01182
01183 if (!_dbus_string_append (&auth_command,
01184 "AUTH "))
01185 {
01186 _dbus_string_free (&auth_command);
01187 return FALSE;
01188 }
01189
01190 if (!_dbus_string_append (&auth_command,
01191 mech->mechanism))
01192 {
01193 _dbus_string_free (&auth_command);
01194 return FALSE;
01195 }
01196
01197 if (mech->client_initial_response_func != NULL)
01198 {
01199 if (!_dbus_string_append (&auth_command, " "))
01200 {
01201 _dbus_string_free (&auth_command);
01202 return FALSE;
01203 }
01204
01205 if (!(* mech->client_initial_response_func) (auth, &auth_command))
01206 {
01207 _dbus_string_free (&auth_command);
01208 return FALSE;
01209 }
01210 }
01211
01212 if (!_dbus_string_append (&auth_command,
01213 "\r\n"))
01214 {
01215 _dbus_string_free (&auth_command);
01216 return FALSE;
01217 }
01218
01219 if (!_dbus_string_copy (&auth_command, 0,
01220 &auth->outgoing,
01221 _dbus_string_get_length (&auth->outgoing)))
01222 {
01223 _dbus_string_free (&auth_command);
01224 return FALSE;
01225 }
01226
01227 _dbus_string_free (&auth_command);
01228 shutdown_mech (auth);
01229 auth->mech = mech;
01230 goto_state (auth, &client_state_waiting_for_data);
01231
01232 return TRUE;
01233 }
01234
01235 static dbus_bool_t
01236 send_data (DBusAuth *auth, DBusString *data)
01237 {
01238 int old_len;
01239
01240 if (data == NULL || _dbus_string_get_length (data) == 0)
01241 return _dbus_string_append (&auth->outgoing, "DATA\r\n");
01242 else
01243 {
01244 old_len = _dbus_string_get_length (&auth->outgoing);
01245 if (!_dbus_string_append (&auth->outgoing, "DATA "))
01246 goto out;
01247
01248 if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
01249 _dbus_string_get_length (&auth->outgoing)))
01250 goto out;
01251
01252 if (!_dbus_string_append (&auth->outgoing, "\r\n"))
01253 goto out;
01254
01255 return TRUE;
01256
01257 out:
01258 _dbus_string_set_length (&auth->outgoing, old_len);
01259
01260 return FALSE;
01261 }
01262 }
01263
01264 static dbus_bool_t
01265 send_rejected (DBusAuth *auth)
01266 {
01267 DBusString command;
01268 DBusAuthServer *server_auth;
01269 int i;
01270
01271 if (!_dbus_string_init (&command))
01272 return FALSE;
01273
01274 if (!_dbus_string_append (&command,
01275 "REJECTED"))
01276 goto nomem;
01277
01278 i = 0;
01279 while (all_mechanisms[i].mechanism != NULL)
01280 {
01281 if (!_dbus_string_append (&command,
01282 " "))
01283 goto nomem;
01284
01285 if (!_dbus_string_append (&command,
01286 all_mechanisms[i].mechanism))
01287 goto nomem;
01288
01289 ++i;
01290 }
01291
01292 if (!_dbus_string_append (&command, "\r\n"))
01293 goto nomem;
01294
01295 if (!_dbus_string_copy (&command, 0, &auth->outgoing,
01296 _dbus_string_get_length (&auth->outgoing)))
01297 goto nomem;
01298
01299 shutdown_mech (auth);
01300
01301 _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
01302 server_auth = DBUS_AUTH_SERVER (auth);
01303 server_auth->failures += 1;
01304
01305 if (server_auth->failures >= server_auth->max_failures)