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