1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-auth.c Authentication 3 * 4 * Copyright (C) 2002, 2003, 2004 Red Hat Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 #include "dbus-auth.h" 26 #include "dbus-string.h" 27 #include "dbus-list.h" 28 #include "dbus-internals.h" 29 #include "dbus-keyring.h" 30 #include "dbus-sha.h" 31 #include "dbus-protocol.h" 32 #include "dbus-credentials.h" 33 34 /** 35 * @defgroup DBusAuth Authentication 36 * @ingroup DBusInternals 37 * @brief DBusAuth object 38 * 39 * DBusAuth manages the authentication negotiation when a connection 40 * is first established, and also manage any encryption used over a 41 * connection. 42 * 43 * @todo some SASL profiles require sending the empty string as a 44 * challenge/response, but we don't currently allow that in our 45 * protocol. 46 * 47 * @todo right now sometimes both ends will block waiting for input 48 * from the other end, e.g. if there's an error during 49 * DBUS_COOKIE_SHA1. 50 * 51 * @todo the cookie keyring needs to be cached globally not just 52 * per-auth (which raises threadsafety issues too) 53 * 54 * @todo grep FIXME in dbus-auth.c 55 */ 56 57 /** 58 * @defgroup DBusAuthInternals Authentication implementation details 59 * @ingroup DBusInternals 60 * @brief DBusAuth implementation details 61 * 62 * Private details of authentication code. 63 * 64 * @{ 65 */ 66 67 /** 68 * This function appends an initial client response to the given string 69 */ 70 typedef dbus_bool_t (* DBusInitialResponseFunction) (DBusAuth *auth, 71 DBusString *response); 72 73 /** 74 * This function processes a block of data received from the peer. 75 * i.e. handles a DATA command. 76 */ 77 typedef dbus_bool_t (* DBusAuthDataFunction) (DBusAuth *auth, 78 const DBusString *data); 79 80 /** 81 * This function encodes a block of data from the peer. 82 */ 83 typedef dbus_bool_t (* DBusAuthEncodeFunction) (DBusAuth *auth, 84 const DBusString *data, 85 DBusString *encoded); 86 87 /** 88 * This function decodes a block of data from the peer. 89 */ 90 typedef dbus_bool_t (* DBusAuthDecodeFunction) (DBusAuth *auth, 91 const DBusString *data, 92 DBusString *decoded); 93 94 /** 95 * This function is called when the mechanism is abandoned. 96 */ 97 typedef void (* DBusAuthShutdownFunction) (DBusAuth *auth); 98 99 /** 100 * Virtual table representing a particular auth mechanism. 101 */ 102 typedef struct 103 { 104 const char *mechanism; /**< Name of the mechanism */ 105 DBusAuthDataFunction server_data_func; /**< Function on server side for DATA */ 106 DBusAuthEncodeFunction server_encode_func; /**< Function on server side to encode */ 107 DBusAuthDecodeFunction server_decode_func; /**< Function on server side to decode */ 108 DBusAuthShutdownFunction server_shutdown_func; /**< Function on server side to shut down */ 109 DBusInitialResponseFunction client_initial_response_func; /**< Function on client side to handle initial response */ 110 DBusAuthDataFunction client_data_func; /**< Function on client side for DATA */ 111 DBusAuthEncodeFunction client_encode_func; /**< Function on client side for encode */ 112 DBusAuthDecodeFunction client_decode_func; /**< Function on client side for decode */ 113 DBusAuthShutdownFunction client_shutdown_func; /**< Function on client side for shutdown */ 114 } DBusAuthMechanismHandler; 115 116 /** 117 * Enumeration for the known authentication commands. 118 */ 119 typedef enum { 120 DBUS_AUTH_COMMAND_AUTH, 121 DBUS_AUTH_COMMAND_CANCEL, 122 DBUS_AUTH_COMMAND_DATA, 123 DBUS_AUTH_COMMAND_BEGIN, 124 DBUS_AUTH_COMMAND_REJECTED, 125 DBUS_AUTH_COMMAND_OK, 126 DBUS_AUTH_COMMAND_ERROR, 127 DBUS_AUTH_COMMAND_UNKNOWN, 128 DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD, 129 DBUS_AUTH_COMMAND_AGREE_UNIX_FD 130 } DBusAuthCommand; 131 132 /** 133 * Auth state function, determines the reaction to incoming events for 134 * a particular state. Returns whether we had enough memory to 135 * complete the operation. 136 */ 137 typedef dbus_bool_t (* DBusAuthStateFunction) (DBusAuth *auth, 138 DBusAuthCommand command, 139 const DBusString *args); 140 141 /** 142 * Information about a auth state. 143 */ 144 typedef struct 145 { 146 const char *name; /**< Name of the state */ 147 DBusAuthStateFunction handler; /**< State function for this state */ 148 } DBusAuthStateData; 149 150 /** 151 * Internal members of DBusAuth. 152 */ 153 struct DBusAuth 154 { 155 int refcount; /**< reference count */ 156 const char *side; /**< Client or server */ 157 158 DBusString incoming; /**< Incoming data buffer */ 159 DBusString outgoing; /**< Outgoing data buffer */ 160 161 const DBusAuthStateData *state; /**< Current protocol state */ 162 163 const DBusAuthMechanismHandler *mech; /**< Current auth mechanism */ 164 165 DBusString identity; /**< Current identity we're authorizing 166 * as. 167 */ 168 169 DBusCredentials *credentials; /**< Credentials read from socket 170 */ 171 172 DBusCredentials *authorized_identity; /**< Credentials that are authorized */ 173 174 DBusCredentials *desired_identity; /**< Identity client has requested */ 175 176 DBusString context; /**< Cookie scope */ 177 DBusKeyring *keyring; /**< Keyring for cookie mechanism. */ 178 int cookie_id; /**< ID of cookie to use */ 179 DBusString challenge; /**< Challenge sent to client */ 180 181 char **allowed_mechs; /**< Mechanisms we're allowed to use, 182 * or #NULL if we can use any 183 */ 184 185 unsigned int needed_memory : 1; /**< We needed memory to continue since last 186 * successful getting something done 187 */ 188 unsigned int already_got_mechanisms : 1; /**< Client already got mech list */ 189 unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */ 190 unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */ 191 192 unsigned int unix_fd_possible : 1; /**< This side could do unix fd passing */ 193 unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */ 194 }; 195 196 /** 197 * "Subclass" of DBusAuth for client side 198 */ 199 typedef struct 200 { 201 DBusAuth base; /**< Parent class */ 202 203 DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */ 204 205 DBusString guid_from_server; /**< GUID received from server */ 206 207 } DBusAuthClient; 208 209 /** 210 * "Subclass" of DBusAuth for server side. 211 */ 212 typedef struct 213 { 214 DBusAuth base; /**< Parent class */ 215 216 int failures; /**< Number of times client has been rejected */ 217 int max_failures; /**< Number of times we reject before disconnect */ 218 219 DBusString guid; /**< Our globally unique ID in hex encoding */ 220 221 } DBusAuthServer; 222 223 static void goto_state (DBusAuth *auth, 224 const DBusAuthStateData *new_state); 225 static dbus_bool_t send_auth (DBusAuth *auth, 226 const DBusAuthMechanismHandler *mech); 227 static dbus_bool_t send_data (DBusAuth *auth, 228 DBusString *data); 229 static dbus_bool_t send_rejected (DBusAuth *auth); 230 static dbus_bool_t send_error (DBusAuth *auth, 231 const char *message); 232 static dbus_bool_t send_ok (DBusAuth *auth); 233 static dbus_bool_t send_begin (DBusAuth *auth); 234 static dbus_bool_t send_cancel (DBusAuth *auth); 235 static dbus_bool_t send_negotiate_unix_fd (DBusAuth *auth); 236 static dbus_bool_t send_agree_unix_fd (DBusAuth *auth); 237 238 /** 239 * Client states 240 */ 241 242 static dbus_bool_t handle_server_state_waiting_for_auth (DBusAuth *auth, 243 DBusAuthCommand command, 244 const DBusString *args); 245 static dbus_bool_t handle_server_state_waiting_for_data (DBusAuth *auth, 246 DBusAuthCommand command, 247 const DBusString *args); 248 static dbus_bool_t handle_server_state_waiting_for_begin (DBusAuth *auth, 249 DBusAuthCommand command, 250 const DBusString *args); 251 252 static const DBusAuthStateData server_state_waiting_for_auth = { 253 "WaitingForAuth", handle_server_state_waiting_for_auth 254 }; 255 static const DBusAuthStateData server_state_waiting_for_data = { 256 "WaitingForData", handle_server_state_waiting_for_data 257 }; 258 static const DBusAuthStateData server_state_waiting_for_begin = { 259 "WaitingForBegin", handle_server_state_waiting_for_begin 260 }; 261 262 /** 263 * Client states 264 */ 265 266 static dbus_bool_t handle_client_state_waiting_for_data (DBusAuth *auth, 267 DBusAuthCommand command, 268 const DBusString *args); 269 static dbus_bool_t handle_client_state_waiting_for_ok (DBusAuth *auth, 270 DBusAuthCommand command, 271 const DBusString *args); 272 static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *auth, 273 DBusAuthCommand command, 274 const DBusString *args); 275 static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth *auth, 276 DBusAuthCommand command, 277 const DBusString *args); 278 279 static const DBusAuthStateData client_state_need_send_auth = { 280 "NeedSendAuth", NULL 281 }; 282 static const DBusAuthStateData client_state_waiting_for_data = { 283 "WaitingForData", handle_client_state_waiting_for_data 284 }; 285 static const DBusAuthStateData client_state_waiting_for_ok = { 286 "WaitingForOK", handle_client_state_waiting_for_ok 287 }; 288 static const DBusAuthStateData client_state_waiting_for_reject = { 289 "WaitingForReject", handle_client_state_waiting_for_reject 290 }; 291 static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = { 292 "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd 293 }; 294 295 /** 296 * Common terminal states. Terminal states have handler == NULL. 297 */ 298 299 static const DBusAuthStateData common_state_authenticated = { 300 "Authenticated", NULL 301 }; 302 303 static const DBusAuthStateData common_state_need_disconnect = { 304 "NeedDisconnect", NULL 305 }; 306 307 static const char auth_side_client[] = "client"; 308 static const char auth_side_server[] = "server"; 309 /** 310 * @param auth the auth conversation 311 * @returns #TRUE if the conversation is the server side 312 */ 313 #define DBUS_AUTH_IS_SERVER(auth) ((auth)->side == auth_side_server) 314 /** 315 * @param auth the auth conversation 316 * @returns #TRUE if the conversation is the client side 317 */ 318 #define DBUS_AUTH_IS_CLIENT(auth) ((auth)->side == auth_side_client) 319 /** 320 * @param auth the auth conversation 321 * @returns auth cast to DBusAuthClient 322 */ 323 #define DBUS_AUTH_CLIENT(auth) ((DBusAuthClient*)(auth)) 324 /** 325 * @param auth the auth conversation 326 * @returns auth cast to DBusAuthServer 327 */ 328 #define DBUS_AUTH_SERVER(auth) ((DBusAuthServer*)(auth)) 329 330 /** 331 * The name of the auth ("client" or "server") 332 * @param auth the auth conversation 333 * @returns a string 334 */ 335 #define DBUS_AUTH_NAME(auth) ((auth)->side) 336 337 static DBusAuth* 338 _dbus_auth_new (int size) 339 { 340 DBusAuth *auth; 341 342 auth = dbus_malloc0 (size); 343 if (auth == NULL) 344 return NULL; 345 346 auth->refcount = 1; 347 348 auth->keyring = NULL; 349 auth->cookie_id = -1; 350 351 /* note that we don't use the max string length feature, 352 * because you can't use that feature if you're going to 353 * try to recover from out-of-memory (it creates 354 * what looks like unrecoverable inability to alloc 355 * more space in the string). But we do handle 356 * overlong buffers in _dbus_auth_do_work(). 357 */ 358 359 if (!_dbus_string_init (&auth->incoming)) 360 goto enomem_0; 361 362 if (!_dbus_string_init (&auth->outgoing)) 363 goto enomem_1; 364 365 if (!_dbus_string_init (&auth->identity)) 366 goto enomem_2; 367 368 if (!_dbus_string_init (&auth->context)) 369 goto enomem_3; 370 371 if (!_dbus_string_init (&auth->challenge)) 372 goto enomem_4; 373 374 /* default context if none is specified */ 375 if (!_dbus_string_append (&auth->context, "org_freedesktop_general")) 376 goto enomem_5; 377 378 auth->credentials = _dbus_credentials_new (); 379 if (auth->credentials == NULL) 380 goto enomem_6; 381 382 auth->authorized_identity = _dbus_credentials_new (); 383 if (auth->authorized_identity == NULL) 384 goto enomem_7; 385 386 auth->desired_identity = _dbus_credentials_new (); 387 if (auth->desired_identity == NULL) 388 goto enomem_8; 389 390 return auth; 391 392 #if 0 393 enomem_9: 394 _dbus_credentials_unref (auth->desired_identity); 395 #endif 396 enomem_8: 397 _dbus_credentials_unref (auth->authorized_identity); 398 enomem_7: 399 _dbus_credentials_unref (auth->credentials); 400 enomem_6: 401 /* last alloc was an append to context, which is freed already below */ ; 402 enomem_5: 403 _dbus_string_free (&auth->challenge); 404 enomem_4: 405 _dbus_string_free (&auth->context); 406 enomem_3: 407 _dbus_string_free (&auth->identity); 408 enomem_2: 409 _dbus_string_free (&auth->outgoing); 410 enomem_1: 411 _dbus_string_free (&auth->incoming); 412 enomem_0: 413 dbus_free (auth); 414 return NULL; 415 } 416 417 static void 418 shutdown_mech (DBusAuth *auth) 419 { 420 /* Cancel any auth */ 421 auth->already_asked_for_initial_response = FALSE; 422 _dbus_string_set_length (&auth->identity, 0); 423 424 _dbus_credentials_clear (auth->authorized_identity); 425 _dbus_credentials_clear (auth->desired_identity); 426 427 if (auth->mech != NULL) 428 { 429 _dbus_verbose ("%s: Shutting down mechanism %s\n", 430 DBUS_AUTH_NAME (auth), auth->mech->mechanism); 431 432 if (DBUS_AUTH_IS_CLIENT (auth)) 433 (* auth->mech->client_shutdown_func) (auth); 434 else 435 (* auth->mech->server_shutdown_func) (auth); 436 437 auth->mech = NULL; 438 } 439 } 440 441 /* 442 * DBUS_COOKIE_SHA1 mechanism 443 */ 444 445 /* Returns TRUE but with an empty string hash if the 446 * cookie_id isn't known. As with all this code 447 * TRUE just means we had enough memory. 448 */ 449 static dbus_bool_t 450 sha1_compute_hash (DBusAuth *auth, 451 int cookie_id, 452 const DBusString *server_challenge, 453 const DBusString *client_challenge, 454 DBusString *hash) 455 { 456 DBusString cookie; 457 DBusString to_hash; 458 dbus_bool_t retval; 459 460 _dbus_assert (auth->keyring != NULL); 461 462 retval = FALSE; 463 464 if (!_dbus_string_init (&cookie)) 465 return FALSE; 466 467 if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id, 468 &cookie)) 469 goto out_0; 470 471 if (_dbus_string_get_length (&cookie) == 0) 472 { 473 retval = TRUE; 474 goto out_0; 475 } 476 477 if (!_dbus_string_init (&to_hash)) 478 goto out_0; 479 480 if (!_dbus_string_copy (server_challenge, 0, 481 &to_hash, _dbus_string_get_length (&to_hash))) 482 goto out_1; 483 484 if (!_dbus_string_append (&to_hash, ":")) 485 goto out_1; 486 487 if (!_dbus_string_copy (client_challenge, 0, 488 &to_hash, _dbus_string_get_length (&to_hash))) 489 goto out_1; 490 491 if (!_dbus_string_append (&to_hash, ":")) 492 goto out_1; 493 494 if (!_dbus_string_copy (&cookie, 0, 495 &to_hash, _dbus_string_get_length (&to_hash))) 496 goto out_1; 497 498 if (!_dbus_sha_compute (&to_hash, hash)) 499 goto out_1; 500 501 retval = TRUE; 502 503 out_1: 504 _dbus_string_zero (&to_hash); 505 _dbus_string_free (&to_hash); 506 out_0: 507 _dbus_string_zero (&cookie); 508 _dbus_string_free (&cookie); 509 return retval; 510 } 511 512 /** http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of 513 * entropy, we use 128. This is the number of bytes in the random 514 * challenge. 515 */ 516 #define N_CHALLENGE_BYTES (128/8) 517 518 static dbus_bool_t 519 sha1_handle_first_client_response (DBusAuth *auth, 520 const DBusString *data) 521 { 522 /* We haven't sent a challenge yet, we're expecting a desired 523 * username from the client. 524 */ 525 DBusString tmp; 526 DBusString tmp2; 527 dbus_bool_t retval; 528 DBusError error; 529 530 retval = FALSE; 531 532 _dbus_string_set_length (&auth->challenge, 0); 533 534 if (_dbus_string_get_length (data) > 0) 535 { 536 if (_dbus_string_get_length (&auth->identity) > 0) 537 { 538 /* Tried to send two auth identities, wtf */ 539 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n", 540 DBUS_AUTH_NAME (auth)); 541 return send_rejected (auth); 542 } 543 else 544 { 545 /* this is our auth identity */ 546 if (!_dbus_string_copy (data, 0, &auth->identity, 0)) 547 return FALSE; 548 } 549 } 550 551 if (!_dbus_credentials_add_from_user (auth->desired_identity, data)) 552 { 553 _dbus_verbose ("%s: Did not get a valid username from client\n", 554 DBUS_AUTH_NAME (auth)); 555 return send_rejected (auth); 556 } 557 558 if (!_dbus_string_init (&tmp)) 559 return FALSE; 560 561 if (!_dbus_string_init (&tmp2)) 562 { 563 _dbus_string_free (&tmp); 564 return FALSE; 565 } 566 567 /* we cache the keyring for speed, so here we drop it if it's the 568 * wrong one. FIXME caching the keyring here is useless since we use 569 * a different DBusAuth for every connection. 570 */ 571 if (auth->keyring && 572 !_dbus_keyring_is_for_credentials (auth->keyring, 573 auth->desired_identity)) 574 { 575 _dbus_keyring_unref (auth->keyring); 576 auth->keyring = NULL; 577 } 578 579 if (auth->keyring == NULL) 580 { 581 dbus_error_init (&error); 582 auth->keyring = _dbus_keyring_new_for_credentials (auth->desired_identity, 583 &auth->context, 584 &error); 585 586 if (auth->keyring == NULL) 587 { 588 if (dbus_error_has_name (&error, 589 DBUS_ERROR_NO_MEMORY)) 590 { 591 dbus_error_free (&error); 592 goto out; 593 } 594 else 595 { 596 _DBUS_ASSERT_ERROR_IS_SET (&error); 597 _dbus_verbose ("%s: Error loading keyring: %s\n", 598 DBUS_AUTH_NAME (auth), error.message); 599 if (send_rejected (auth)) 600 retval = TRUE; /* retval is only about mem */ 601 dbus_error_free (&error); 602 goto out; 603 } 604 } 605 else 606 { 607 _dbus_assert (!dbus_error_is_set (&error)); 608 } 609 } 610 611 _dbus_assert (auth->keyring != NULL); 612 613 dbus_error_init (&error); 614 auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error); 615 if (auth->cookie_id < 0) 616 { 617 _DBUS_ASSERT_ERROR_IS_SET (&error); 618 _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n", 619 DBUS_AUTH_NAME (auth), error.message); 620 if (send_rejected (auth)) 621 retval = TRUE; 622 dbus_error_free (&error); 623 goto out; 624 } 625 else 626 { 627 _dbus_assert (!dbus_error_is_set (&error)); 628 } 629 630 if (!_dbus_string_copy (&auth->context, 0, 631 &tmp2, _dbus_string_get_length (&tmp2))) 632 goto out; 633 634 if (!_dbus_string_append (&tmp2, " ")) 635 goto out; 636 637 if (!_dbus_string_append_int (&tmp2, auth->cookie_id)) 638 goto out; 639 640 if (!_dbus_string_append (&tmp2, " ")) 641 goto out; 642 643 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES)) 644 goto out; 645 646 _dbus_string_set_length (&auth->challenge, 0); 647 if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0)) 648 goto out; 649 650 if (!_dbus_string_hex_encode (&tmp, 0, &tmp2, 651 _dbus_string_get_length (&tmp2))) 652 goto out; 653 654 if (!send_data (auth, &tmp2)) 655 goto out; 656 657 goto_state (auth, &server_state_waiting_for_data); 658 retval = TRUE; 659 660 out: 661 _dbus_string_zero (&tmp); 662 _dbus_string_free (&tmp); 663 _dbus_string_zero (&tmp2); 664 _dbus_string_free (&tmp2); 665 666 return retval; 667 } 668 669 static dbus_bool_t 670 sha1_handle_second_client_response (DBusAuth *auth, 671 const DBusString *data) 672 { 673 /* We are expecting a response which is the hex-encoded client 674 * challenge, space, then SHA-1 hash of the concatenation of our 675 * challenge, ":", client challenge, ":", secret key, all 676 * hex-encoded. 677 */ 678 int i; 679 DBusString client_challenge; 680 DBusString client_hash; 681 dbus_bool_t retval; 682 DBusString correct_hash; 683 684 retval = FALSE; 685 686 if (!_dbus_string_find_blank (data, 0, &i)) 687 { 688 _dbus_verbose ("%s: no space separator in client response\n", 689 DBUS_AUTH_NAME (auth)); 690 return send_rejected (auth); 691 } 692 693 if (!_dbus_string_init (&client_challenge)) 694 goto out_0; 695 696 if (!_dbus_string_init (&client_hash)) 697 goto out_1; 698 699 if (!_dbus_string_copy_len (data, 0, i, &client_challenge, 700 0)) 701 goto out_2; 702 703 _dbus_string_skip_blank (data, i, &i); 704 705 if (!_dbus_string_copy_len (data, i, 706 _dbus_string_get_length (data) - i, 707 &client_hash, 708 0)) 709 goto out_2; 710 711 if (_dbus_string_get_length (&client_challenge) == 0 || 712 _dbus_string_get_length (&client_hash) == 0) 713 { 714 _dbus_verbose ("%s: zero-length client challenge or hash\n", 715 DBUS_AUTH_NAME (auth)); 716 if (send_rejected (auth)) 717 retval = TRUE; 718 goto out_2; 719 } 720 721 if (!_dbus_string_init (&correct_hash)) 722 goto out_2; 723 724 if (!sha1_compute_hash (auth, auth->cookie_id, 725 &auth->challenge, 726 &client_challenge, 727 &correct_hash)) 728 goto out_3; 729 730 /* if cookie_id was invalid, then we get an empty hash */ 731 if (_dbus_string_get_length (&correct_hash) == 0) 732 { 733 if (send_rejected (auth)) 734 retval = TRUE; 735 goto out_3; 736 } 737 738 if (!_dbus_string_equal (&client_hash, &correct_hash)) 739 { 740 if (send_rejected (auth)) 741 retval = TRUE; 742 goto out_3; 743 } 744 745 if (!_dbus_credentials_add_credentials (auth->authorized_identity, 746 auth->desired_identity)) 747 goto out_3; 748 749 /* Copy process ID from the socket credentials if it's there 750 */ 751 if (!_dbus_credentials_add_credential (auth->authorized_identity, 752 DBUS_CREDENTIAL_UNIX_PROCESS_ID, 753 auth->credentials)) 754 goto out_3; 755 756 if (!send_ok (auth)) 757 goto out_3; 758 759 _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n", 760 DBUS_AUTH_NAME (auth)); 761 762 retval = TRUE; 763 764 out_3: 765 _dbus_string_zero (&correct_hash); 766 _dbus_string_free (&correct_hash); 767 out_2: 768 _dbus_string_zero (&client_hash); 769 _dbus_string_free (&client_hash); 770 out_1: 771 _dbus_string_free (&client_challenge); 772 out_0: 773 return retval; 774 } 775 776 static dbus_bool_t 777 handle_server_data_cookie_sha1_mech (DBusAuth *auth, 778 const DBusString *data) 779 { 780 if (auth->cookie_id < 0) 781 return sha1_handle_first_client_response (auth, data); 782 else 783 return sha1_handle_second_client_response (auth, data); 784 } 785 786 static void 787 handle_server_shutdown_cookie_sha1_mech (DBusAuth *auth) 788 { 789 auth->cookie_id = -1; 790 _dbus_string_set_length (&auth->challenge, 0); 791 } 792 793 static dbus_bool_t 794 handle_client_initial_response_cookie_sha1_mech (DBusAuth *auth, 795 DBusString *response) 796 { 797 DBusString username; 798 dbus_bool_t retval; 799 800 retval = FALSE; 801 802 if (!_dbus_string_init (&username)) 803 return FALSE; 804 805 if (!_dbus_append_user_from_current_process (&username)) 806 goto out_0; 807 808 if (!_dbus_string_hex_encode (&username, 0, 809 response, 810 _dbus_string_get_length (response))) 811 goto out_0; 812 813 retval = TRUE; 814 815 out_0: 816 _dbus_string_free (&username); 817 818 return retval; 819 } 820 821 static dbus_bool_t 822 handle_client_data_cookie_sha1_mech (DBusAuth *auth, 823 const DBusString *data) 824 { 825 /* The data we get from the server should be the cookie context 826 * name, the cookie ID, and the server challenge, separated by 827 * spaces. We send back our challenge string and the correct hash. 828 */ 829 dbus_bool_t retval; 830 DBusString context; 831 DBusString cookie_id_str; 832 DBusString server_challenge; 833 DBusString client_challenge; 834 DBusString correct_hash; 835 DBusString tmp; 836 int i, j; 837 long val; 838 839 retval = FALSE; 840 841 if (!_dbus_string_find_blank (data, 0, &i)) 842 { 843 if (send_error (auth, 844 "Server did not send context/ID/challenge properly")) 845 retval = TRUE; 846 goto out_0; 847 } 848 849 if (!_dbus_string_init (&context)) 850 goto out_0; 851 852 if (!_dbus_string_copy_len (data, 0, i, 853 &context, 0)) 854 goto out_1; 855 856 _dbus_string_skip_blank (data, i, &i); 857 if (!_dbus_string_find_blank (data, i, &j)) 858 { 859 if (send_error (auth, 860 "Server did not send context/ID/challenge properly")) 861 retval = TRUE; 862 goto out_1; 863 } 864 865 if (!_dbus_string_init (&cookie_id_str)) 866 goto out_1; 867 868 if (!_dbus_string_copy_len (data, i, j - i, 869 &cookie_id_str, 0)) 870 goto out_2; 871 872 if (!_dbus_string_init (&server_challenge)) 873 goto out_2; 874 875 i = j; 876 _dbus_string_skip_blank (data, i, &i); 877 j = _dbus_string_get_length (data); 878 879 if (!_dbus_string_copy_len (data, i, j - i, 880 &server_challenge, 0)) 881 goto out_3; 882 883 if (!_dbus_keyring_validate_context (&context)) 884 { 885 if (send_error (auth, "Server sent invalid cookie context")) 886 retval = TRUE; 887 goto out_3; 888 } 889 890 if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL)) 891 { 892 if (send_error (auth, "Could not parse cookie ID as an integer")) 893 retval = TRUE; 894 goto out_3; 895 } 896 897 if (_dbus_string_get_length (&server_challenge) == 0) 898 { 899 if (send_error (auth, "Empty server challenge string")) 900 retval = TRUE; 901 goto out_3; 902 } 903 904 if (auth->keyring == NULL) 905 { 906 DBusError error; 907 908 dbus_error_init (&error); 909 auth->keyring = _dbus_keyring_new_for_credentials (NULL, 910 &context, 911 &error); 912 913 if (auth->keyring == NULL) 914 { 915 if (dbus_error_has_name (&error, 916 DBUS_ERROR_NO_MEMORY)) 917 { 918 dbus_error_free (&error); 919 goto out_3; 920 } 921 else 922 { 923 _DBUS_ASSERT_ERROR_IS_SET (&error); 924 925 _dbus_verbose ("%s: Error loading keyring: %s\n", 926 DBUS_AUTH_NAME (auth), error.message); 927 928 if (send_error (auth, "Could not load cookie file")) 929 retval = TRUE; /* retval is only about mem */ 930 931 dbus_error_free (&error); 932 goto out_3; 933 } 934 } 935 else 936 { 937 _dbus_assert (!dbus_error_is_set (&error)); 938 } 939 } 940 941 _dbus_assert (auth->keyring != NULL); 942 943 if (!_dbus_string_init (&tmp)) 944 goto out_3; 945 946 if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES)) 947 goto out_4; 948 949 if (!_dbus_string_init (&client_challenge)) 950 goto out_4; 951 952 if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0)) 953 goto out_5; 954 955 if (!_dbus_string_init (&correct_hash)) 956 goto out_5; 957 958 if (!sha1_compute_hash (auth, val, 959 &server_challenge, 960 &client_challenge, 961 &correct_hash)) 962 goto out_6; 963 964 if (_dbus_string_get_length (&correct_hash) == 0) 965 { 966 /* couldn't find the cookie ID or something */ 967 if (send_error (auth, "Don't have the requested cookie ID")) 968 retval = TRUE; 969 goto out_6; 970 } 971 972 _dbus_string_set_length (&tmp, 0); 973 974 if (!_dbus_string_copy (&client_challenge, 0, &tmp, 975 _dbus_string_get_length (&tmp))) 976 goto out_6; 977 978 if (!_dbus_string_append (&tmp, " ")) 979 goto out_6; 980 981 if (!_dbus_string_copy (&correct_hash, 0, &tmp, 982 _dbus_string_get_length (&tmp))) 983 goto out_6; 984 985 if (!send_data (auth, &tmp)) 986 goto out_6; 987 988 retval = TRUE; 989 990 out_6: 991 _dbus_string_zero (&correct_hash); 992 _dbus_string_free (&correct_hash); 993 out_5: 994 _dbus_string_free (&client_challenge); 995 out_4: 996 _dbus_string_zero (&tmp); 997 _dbus_string_free (&tmp); 998 out_3: 999 _dbus_string_free (&server_challenge); 1000 out_2: 1001 _dbus_string_free (&cookie_id_str); 1002 out_1: 1003 _dbus_string_free (&context); 1004 out_0: 1005 return retval; 1006 } 1007 1008 static void 1009 handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth) 1010 { 1011 auth->cookie_id = -1; 1012 _dbus_string_set_length (&auth->challenge, 0); 1013 } 1014 1015 /* 1016 * EXTERNAL mechanism 1017 */ 1018 1019 static dbus_bool_t 1020 handle_server_data_external_mech (DBusAuth *auth, 1021 const DBusString *data) 1022 { 1023 if (_dbus_credentials_are_anonymous (auth->credentials)) 1024 { 1025 _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n", 1026 DBUS_AUTH_NAME (auth)); 1027 return send_rejected (auth); 1028 } 1029 1030 if (_dbus_string_get_length (data) > 0) 1031 { 1032 if (_dbus_string_get_length (&auth->identity) > 0) 1033 { 1034 /* Tried to send two auth identities, wtf */ 1035 _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n", 1036 DBUS_AUTH_NAME (auth)); 1037 return send_rejected (auth); 1038 } 1039 else 1040 { 1041 /* this is our auth identity */ 1042 if (!_dbus_string_copy (data, 0, &auth->identity, 0)) 1043 return FALSE; 1044 } 1045 } 1046 1047 /* Poke client for an auth identity, if none given */ 1048 if (_dbus_string_get_length (&auth->identity) == 0 && 1049 !auth->already_asked_for_initial_response) 1050 { 1051 if (send_data (auth, NULL)) 1052 { 1053 _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n", 1054 DBUS_AUTH_NAME (auth)); 1055 auth->already_asked_for_initial_response = TRUE; 1056 goto_state (auth, &server_state_waiting_for_data); 1057 return TRUE; 1058 } 1059 else 1060 return FALSE; 1061 } 1062 1063 _dbus_credentials_clear (auth->desired_identity); 1064 1065 /* If auth->identity is still empty here, then client 1066 * responded with an empty string after we poked it for 1067 * an initial response. This means to try to auth the 1068 * identity provided in the credentials. 1069 */ 1070 if (_dbus_string_get_length (&auth->identity) == 0) 1071 { 1072 if (!_dbus_credentials_add_credentials (auth->desired_identity, 1073 auth->credentials)) 1074 { 1075 return FALSE; /* OOM */ 1076 } 1077 } 1078 else 1079 { 1080 if (!_dbus_credentials_add_from_user (auth->desired_identity, 1081 &auth->identity)) 1082 { 1083 _dbus_verbose ("%s: could not get credentials from uid string\n", 1084 DBUS_AUTH_NAME (auth)); 1085 return send_rejected (auth); 1086 } 1087 } 1088 1089 if (_dbus_credentials_are_anonymous (auth->desired_identity)) 1090 { 1091 _dbus_verbose ("%s: desired user %s is no good\n", 1092 DBUS_AUTH_NAME (auth), 1093 _dbus_string_get_const_data (&auth->identity)); 1094 return send_rejected (auth); 1095 } 1096 1097 if (_dbus_credentials_are_superset (auth->credentials, 1098 auth->desired_identity)) 1099 { 1100 /* client has authenticated */ 1101 if (!_dbus_credentials_add_credentials (auth->authorized_identity, 1102 auth->desired_identity)) 1103 return FALSE; 1104 1105 /* also copy process ID from the socket credentials 1106 */ 1107 if (!_dbus_credentials_add_credential (auth->authorized_identity, 1108 DBUS_CREDENTIAL_UNIX_PROCESS_ID, 1109 auth->credentials)) 1110 return FALSE; 1111 1112 /* also copy audit data from the socket credentials 1113 */ 1114 if (!_dbus_credentials_add_credential (auth->authorized_identity, 1115 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, 1116 auth->credentials)) 1117 return FALSE; 1118 1119 if (!send_ok (auth)) 1120 return FALSE; 1121 1122 _dbus_verbose ("%s: authenticated client based on socket credentials\n", 1123 DBUS_AUTH_NAME (auth)); 1124 1125 return TRUE; 1126 } 1127 else 1128 { 1129 _dbus_verbose ("%s: desired identity not found in socket credentials\n", 1130 DBUS_AUTH_NAME (auth)); 1131 return send_rejected (auth); 1132 } 1133 } 1134 1135 static void 1136 handle_server_shutdown_external_mech (DBusAuth *auth) 1137 { 1138 1139 } 1140 1141 static dbus_bool_t 1142 handle_client_initial_response_external_mech (DBusAuth *auth, 1143 DBusString *response) 1144 { 1145 /* We always append our UID as an initial response, so the server 1146 * doesn't have to send back an empty challenge to check whether we 1147 * want to specify an identity. i.e. this avoids a round trip that 1148 * the spec for the EXTERNAL mechanism otherwise requires. 1149 */ 1150 DBusString plaintext; 1151 1152 if (!_dbus_string_init (&plaintext)) 1153 return FALSE; 1154 1155 if (!_dbus_append_user_from_current_process (&plaintext)) 1156 goto failed; 1157 1158 if (!_dbus_string_hex_encode (&plaintext, 0, 1159 response, 1160 _dbus_string_get_length (response))) 1161 goto failed; 1162 1163 _dbus_string_free (&plaintext); 1164 1165 return TRUE; 1166 1167 failed: 1168 _dbus_string_free (&plaintext); 1169 return FALSE; 1170 } 1171 1172 static dbus_bool_t 1173 handle_client_data_external_mech (DBusAuth *auth, 1174 const DBusString *data) 1175 { 1176 1177 return TRUE; 1178 } 1179 1180 static void 1181 handle_client_shutdown_external_mech (DBusAuth *auth) 1182 { 1183 1184 } 1185 1186 /* 1187 * ANONYMOUS mechanism 1188 */ 1189 1190 static dbus_bool_t 1191 handle_server_data_anonymous_mech (DBusAuth *auth, 1192 const DBusString *data) 1193 { 1194 if (_dbus_string_get_length (data) > 0) 1195 { 1196 /* Client is allowed to send "trace" data, the only defined 1197 * meaning is that if it contains '@' it is an email address, 1198 * and otherwise it is anything else, and it's supposed to be 1199 * UTF-8 1200 */ 1201 if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data))) 1202 { 1203 _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n", 1204 DBUS_AUTH_NAME (auth)); 1205 return send_rejected (auth); 1206 } 1207 1208 _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n", 1209 DBUS_AUTH_NAME (auth), 1210 _dbus_string_get_const_data (data)); 1211 } 1212 1213 /* We want to be anonymous (clear in case some other protocol got midway through I guess) */ 1214 _dbus_credentials_clear (auth->desired_identity); 1215 1216 /* Copy process ID from the socket credentials 1217 */ 1218 if (!_dbus_credentials_add_credential (auth->authorized_identity, 1219 DBUS_CREDENTIAL_UNIX_PROCESS_ID, 1220 auth->credentials)) 1221 return FALSE; 1222 1223 /* Anonymous is always allowed */ 1224 if (!send_ok (auth)) 1225 return FALSE; 1226 1227 _dbus_verbose ("%s: authenticated client as anonymous\n", 1228 DBUS_AUTH_NAME (auth)); 1229 1230 return TRUE; 1231 } 1232 1233 static void 1234 handle_server_shutdown_anonymous_mech (DBusAuth *auth) 1235 { 1236 1237 } 1238 1239 static dbus_bool_t 1240 handle_client_initial_response_anonymous_mech (DBusAuth *auth, 1241 DBusString *response) 1242 { 1243 /* Our initial response is a "trace" string which must be valid UTF-8 1244 * and must be an email address if it contains '@'. 1245 * We just send the dbus implementation info, like a user-agent or 1246 * something, because... why not. There's nothing guaranteed here 1247 * though, we could change it later. 1248 */ 1249 DBusString plaintext; 1250 1251 if (!_dbus_string_init (&plaintext)) 1252 return FALSE; 1253 1254 if (!_dbus_string_append (&plaintext, 1255 "libdbus " DBUS_VERSION_STRING)) 1256 goto failed; 1257 1258 if (!_dbus_string_hex_encode (&plaintext, 0, 1259 response, 1260 _dbus_string_get_length (response))) 1261 goto failed; 1262 1263 _dbus_string_free (&plaintext); 1264 1265 return TRUE; 1266 1267 failed: 1268 _dbus_string_free (&plaintext); 1269 return FALSE; 1270 } 1271 1272 static dbus_bool_t 1273 handle_client_data_anonymous_mech (DBusAuth *auth, 1274 const DBusString *data) 1275 { 1276 1277 return TRUE; 1278 } 1279 1280 static void 1281 handle_client_shutdown_anonymous_mech (DBusAuth *auth) 1282 { 1283 1284 } 1285 1286 /* Put mechanisms here in order of preference. 1287 * Right now we have: 1288 * 1289 * - EXTERNAL checks socket credentials (or in the future, other info from the OS) 1290 * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE 1291 * - ANONYMOUS checks nothing but doesn't auth the person as a user 1292 * 1293 * We might ideally add a mechanism to chain to Cyrus SASL so we can 1294 * use its mechanisms as well. 1295 * 1296 */ 1297 static const DBusAuthMechanismHandler 1298 all_mechanisms[] = { 1299 { "EXTERNAL", 1300 handle_server_data_external_mech, 1301 NULL, NULL, 1302 handle_server_shutdown_external_mech, 1303 handle_client_initial_response_external_mech, 1304 handle_client_data_external_mech, 1305 NULL, NULL, 1306 handle_client_shutdown_external_mech }, 1307 { "DBUS_COOKIE_SHA1", 1308 handle_server_data_cookie_sha1_mech, 1309 NULL, NULL, 1310 handle_server_shutdown_cookie_sha1_mech, 1311 handle_client_initial_response_cookie_sha1_mech, 1312 handle_client_data_cookie_sha1_mech, 1313 NULL, NULL, 1314 handle_client_shutdown_cookie_sha1_mech }, 1315 { "ANONYMOUS", 1316 handle_server_data_anonymous_mech, 1317 NULL, NULL, 1318 handle_server_shutdown_anonymous_mech, 1319 handle_client_initial_response_anonymous_mech, 1320 handle_client_data_anonymous_mech, 1321 NULL, NULL, 1322 handle_client_shutdown_anonymous_mech }, 1323 { NULL, NULL } 1324 }; 1325 1326 static const DBusAuthMechanismHandler* 1327 find_mech (const DBusString *name, 1328 char **allowed_mechs) 1329 { 1330 int i; 1331 1332 if (allowed_mechs != NULL && 1333 !_dbus_string_array_contains ((const char**) allowed_mechs, 1334 _dbus_string_get_const_data (name))) 1335 return NULL; 1336 1337 i = 0; 1338 while (all_mechanisms[i].mechanism != NULL) 1339 { 1340 if (_dbus_string_equal_c_str (name, 1341 all_mechanisms[i].mechanism)) 1342 1343 return &all_mechanisms[i]; 1344 1345 ++i; 1346 } 1347 1348 return NULL; 1349 } 1350 1351 static dbus_bool_t 1352 send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech) 1353 { 1354 DBusString auth_command; 1355 1356 if (!_dbus_string_init (&auth_command)) 1357 return FALSE; 1358 1359 if (!_dbus_string_append (&auth_command, 1360 "AUTH ")) 1361 { 1362 _dbus_string_free (&auth_command); 1363 return FALSE; 1364 } 1365 1366 if (!_dbus_string_append (&auth_command, 1367 mech->mechanism)) 1368 { 1369 _dbus_string_free (&auth_command); 1370 return FALSE; 1371 } 1372 1373 if (mech->client_initial_response_func != NULL) 1374 { 1375 if (!_dbus_string_append (&auth_command, " ")) 1376 { 1377 _dbus_string_free (&auth_command); 1378 return FALSE; 1379 } 1380 1381 if (!(* mech->client_initial_response_func) (auth, &auth_command)) 1382 { 1383 _dbus_string_free (&auth_command); 1384 return FALSE; 1385 } 1386 } 1387 1388 if (!_dbus_string_append (&auth_command, 1389 "\r\n")) 1390 { 1391 _dbus_string_free (&auth_command); 1392 return FALSE; 1393 } 1394 1395 if (!_dbus_string_copy (&auth_command, 0, 1396 &auth->outgoing, 1397 _dbus_string_get_length (&auth->outgoing))) 1398 { 1399 _dbus_string_free (&auth_command); 1400 return FALSE; 1401 } 1402 1403 _dbus_string_free (&auth_command); 1404 shutdown_mech (auth); 1405 auth->mech = mech; 1406 goto_state (auth, &client_state_waiting_for_data); 1407 1408 return TRUE; 1409 } 1410 1411 static dbus_bool_t 1412 send_data (DBusAuth *auth, DBusString *data) 1413 { 1414 int old_len; 1415 1416 if (data == NULL || _dbus_string_get_length (data) == 0) 1417 return _dbus_string_append (&auth->outgoing, "DATA\r\n"); 1418 else 1419 { 1420 old_len = _dbus_string_get_length (&auth->outgoing); 1421 if (!_dbus_string_append (&auth->outgoing, "DATA ")) 1422 goto out; 1423 1424 if (!_dbus_string_hex_encode (data, 0, &auth->outgoing, 1425 _dbus_string_get_length (&auth->outgoing))) 1426 goto out; 1427 1428 if (!_dbus_string_append (&auth->outgoing, "\r\n")) 1429 goto out; 1430 1431 return TRUE; 1432 1433 out: 1434 _dbus_string_set_length (&auth->outgoing, old_len); 1435 1436 return FALSE; 1437 } 1438 } 1439 1440 static dbus_bool_t 1441 send_rejected (DBusAuth *auth) 1442 { 1443 DBusString command; 1444 DBusAuthServer *server_auth; 1445 int i; 1446 1447 if (!_dbus_string_init (&command)) 1448 return FALSE; 1449 1450 if (!_dbus_string_append (&command, 1451 "REJECTED")) 1452 goto nomem; 1453 1454 i = 0; 1455 while (all_mechanisms[i].mechanism != NULL) 1456 { 1457 if (!_dbus_string_append (&command, 1458 " ")) 1459 goto nomem; 1460 1461 if (!_dbus_string_append (&command, 1462 all_mechanisms[i].mechanism)) 1463 goto nomem; 1464 1465 ++i; 1466 } 1467 1468 if (!_dbus_string_append (&command, "\r\n")) 1469 goto nomem; 1470 1471 if (!_dbus_string_copy (&command, 0, &auth->outgoing, 1472 _dbus_string_get_length (&auth->outgoing))) 1473 goto nomem; 1474 1475 shutdown_mech (auth); 1476 1477 _dbus_assert (DBUS_AUTH_IS_SERVER (auth)); 1478 server_auth = DBUS_AUTH_SERVER (auth); 1479 server_auth->failures += 1; 1480 1481 if (server_auth->failures >= server_auth->max_failures) 1482 goto_state (auth, &common_state_need_disconnect); 1483 else 1484 goto_state (auth, &server_state_waiting_for_auth); 1485 1486 _dbus_string_free (&command); 1487 1488 return TRUE; 1489 1490 nomem: 1491 _dbus_string_free (&command); 1492 return FALSE; 1493 } 1494 1495 static dbus_bool_t 1496 send_error (DBusAuth *auth, const char *message) 1497 { 1498 return _dbus_string_append_printf (&auth->outgoing, 1499 "ERROR \"%s\"\r\n", message); 1500 } 1501 1502 static dbus_bool_t 1503 send_ok (DBusAuth *auth) 1504 { 1505 int orig_len; 1506 1507 orig_len = _dbus_string_get_length (&auth->outgoing); 1508 1509 if (_dbus_string_append (&auth->outgoing, "OK ") && 1510 _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid, 1511 0, 1512 &auth->outgoing, 1513 _dbus_string_get_length (&auth->outgoing)) && 1514 _dbus_string_append (&auth->outgoing, "\r\n")) 1515 { 1516 goto_state (auth, &server_state_waiting_for_begin); 1517 return TRUE; 1518 } 1519 else 1520 { 1521 _dbus_string_set_length (&auth->outgoing, orig_len); 1522 return FALSE; 1523 } 1524 } 1525 1526 static dbus_bool_t 1527 send_begin (DBusAuth *auth) 1528 { 1529 1530 if (!_dbus_string_append (&auth->outgoing, 1531 "BEGIN\r\n")) 1532 return FALSE; 1533 1534 goto_state (auth, &common_state_authenticated); 1535 return TRUE; 1536 } 1537 1538 static dbus_bool_t 1539 process_ok(DBusAuth *auth, 1540 const DBusString *args_from_ok) { 1541 1542 int end_of_hex; 1543 1544 /* "args_from_ok" should be the GUID, whitespace already pulled off the front */ 1545 _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0); 1546 1547 /* We decode the hex string to binary, using guid_from_server as scratch... */ 1548 1549 end_of_hex = 0; 1550 if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex, 1551 & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) 1552 return FALSE; 1553 1554 /* now clear out the scratch */ 1555 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0); 1556 1557 if (end_of_hex != _dbus_string_get_length (args_from_ok) || 1558 end_of_hex == 0) 1559 { 1560 _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n", 1561 end_of_hex, _dbus_string_get_length (args_from_ok)); 1562 goto_state (auth, &common_state_need_disconnect); 1563 return TRUE; 1564 } 1565 1566 if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) { 1567 _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0); 1568 return FALSE; 1569 } 1570 1571 _dbus_verbose ("Got GUID '%s' from the server\n", 1572 _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server)); 1573 1574 if (auth->unix_fd_possible) 1575 return send_negotiate_unix_fd(auth); 1576 1577 _dbus_verbose("Not negotiating unix fd passing, since not possible\n"); 1578 return send_begin (auth); 1579 } 1580 1581 static dbus_bool_t 1582 send_cancel (DBusAuth *auth) 1583 { 1584 if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n")) 1585 { 1586 goto_state (auth, &client_state_waiting_for_reject); 1587 return TRUE; 1588 } 1589 else 1590 return FALSE; 1591 } 1592 1593 static dbus_bool_t 1594 process_data (DBusAuth *auth, 1595 const DBusString *args, 1596 DBusAuthDataFunction data_func) 1597 { 1598 int end; 1599 DBusString decoded; 1600 1601 if (!_dbus_string_init (&decoded)) 1602 return FALSE; 1603 1604 if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0)) 1605 { 1606 _dbus_string_free (&decoded); 1607 return FALSE; 1608 } 1609 1610 if (_dbus_string_get_length (args) != end) 1611 { 1612 _dbus_string_free (&decoded); 1613 if (!send_error (auth, "Invalid hex encoding")) 1614 return FALSE; 1615 1616 return TRUE; 1617 } 1618 1619 #ifdef DBUS_ENABLE_VERBOSE_MODE 1620 if (_dbus_string_validate_ascii (&decoded, 0, 1621 _dbus_string_get_length (&decoded))) 1622 _dbus_verbose ("%s: data: '%s'\n", 1623 DBUS_AUTH_NAME (auth), 1624 _dbus_string_get_const_data (&decoded)); 1625 #endif 1626 1627 if (!(* data_func) (auth, &decoded)) 1628 { 1629 _dbus_string_free (&decoded); 1630 return FALSE; 1631 } 1632 1633 _dbus_string_free (&decoded); 1634 return TRUE; 1635 } 1636 1637 static dbus_bool_t 1638 send_negotiate_unix_fd (DBusAuth *auth) 1639 { 1640 if (!_dbus_string_append (&auth->outgoing, 1641 "NEGOTIATE_UNIX_FD\r\n")) 1642 return FALSE; 1643 1644 goto_state (auth, &client_state_waiting_for_agree_unix_fd); 1645 return TRUE; 1646 } 1647 1648 static dbus_bool_t 1649 send_agree_unix_fd (DBusAuth *auth) 1650 { 1651 _dbus_assert(auth->unix_fd_possible); 1652 1653 auth->unix_fd_negotiated = TRUE; 1654 _dbus_verbose("Agreed to UNIX FD passing\n"); 1655 1656 if (!_dbus_string_append (&auth->outgoing, 1657 "AGREE_UNIX_FD\r\n")) 1658 return FALSE; 1659 1660 goto_state (auth, &server_state_waiting_for_begin); 1661 return TRUE; 1662 } 1663 1664 static dbus_bool_t 1665 handle_auth (DBusAuth *auth, const DBusString *args) 1666 { 1667 if (_dbus_string_get_length (args) == 0) 1668 { 1669 /* No args to the auth, send mechanisms */ 1670 if (!send_rejected (auth)) 1671 return FALSE; 1672 1673 return TRUE; 1674 } 1675 else 1676 { 1677 int i; 1678 DBusString mech; 1679 DBusString hex_response; 1680 1681 _dbus_string_find_blank (args, 0, &i); 1682 1683 if (!_dbus_string_init (&mech)) 1684 return FALSE; 1685 1686 if (!_dbus_string_init (&hex_response)) 1687 { 1688 _dbus_string_free (&mech); 1689 return FALSE; 1690 } 1691 1692 if (!_dbus_string_copy_len (args, 0, i, &mech, 0)) 1693 goto failed; 1694 1695 _dbus_string_skip_blank (args, i, &i); 1696 if (!_dbus_string_copy (args, i, &hex_response, 0)) 1697 goto failed; 1698 1699 auth->mech = find_mech (&mech, auth->allowed_mechs); 1700 if (auth->mech != NULL) 1701 { 1702 _dbus_verbose ("%s: Trying mechanism %s\n", 1703 DBUS_AUTH_NAME (auth), 1704 auth->mech->mechanism); 1705 1706 if (!process_data (auth, &hex_response, 1707 auth->mech->server_data_func)) 1708 goto failed; 1709 } 1710 else 1711 { 1712 /* Unsupported mechanism */ 1713 _dbus_verbose ("%s: Unsupported mechanism %s\n", 1714 DBUS_AUTH_NAME (auth), 1715 _dbus_string_get_const_data (&mech)); 1716 1717 if (!send_rejected (auth)) 1718 goto failed; 1719 } 1720 1721 _dbus_string_free (&mech); 1722 _dbus_string_free (&hex_response); 1723 1724 return TRUE; 1725 1726 failed: 1727 auth->mech = NULL; 1728 _dbus_string_free (&mech); 1729 _dbus_string_free (&hex_response); 1730 return FALSE; 1731 } 1732 } 1733 1734 static dbus_bool_t 1735 handle_server_state_waiting_for_auth (DBusAuth *auth, 1736 DBusAuthCommand command, 1737 const DBusString *args) 1738 { 1739 switch (command) 1740 { 1741 case DBUS_AUTH_COMMAND_AUTH: 1742 return handle_auth (auth, args); 1743 1744 case DBUS_AUTH_COMMAND_CANCEL: 1745 case DBUS_AUTH_COMMAND_DATA: 1746 return send_error (auth, "Not currently in an auth conversation"); 1747 1748 case DBUS_AUTH_COMMAND_BEGIN: 1749 goto_state (auth, &common_state_need_disconnect); 1750 return TRUE; 1751 1752 case DBUS_AUTH_COMMAND_ERROR: 1753 return send_rejected (auth); 1754 1755 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 1756 return send_error (auth, "Need to authenticate first"); 1757 1758 case DBUS_AUTH_COMMAND_REJECTED: 1759 case DBUS_AUTH_COMMAND_OK: 1760 case DBUS_AUTH_COMMAND_UNKNOWN: 1761 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 1762 default: 1763 return send_error (auth, "Unknown command"); 1764 } 1765 } 1766 1767 static dbus_bool_t 1768 handle_server_state_waiting_for_data (DBusAuth *auth, 1769 DBusAuthCommand command, 1770 const DBusString *args) 1771 { 1772 switch (command) 1773 { 1774 case DBUS_AUTH_COMMAND_AUTH: 1775 return send_error (auth, "Sent AUTH while another AUTH in progress"); 1776 1777 case DBUS_AUTH_COMMAND_CANCEL: 1778 case DBUS_AUTH_COMMAND_ERROR: 1779 return send_rejected (auth); 1780 1781 case DBUS_AUTH_COMMAND_DATA: 1782 return process_data (auth, args, auth->mech->server_data_func); 1783 1784 case DBUS_AUTH_COMMAND_BEGIN: 1785 goto_state (auth, &common_state_need_disconnect); 1786 return TRUE; 1787 1788 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 1789 return send_error (auth, "Need to authenticate first"); 1790 1791 case DBUS_AUTH_COMMAND_REJECTED: 1792 case DBUS_AUTH_COMMAND_OK: 1793 case DBUS_AUTH_COMMAND_UNKNOWN: 1794 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 1795 default: 1796 return send_error (auth, "Unknown command"); 1797 } 1798 } 1799 1800 static dbus_bool_t 1801 handle_server_state_waiting_for_begin (DBusAuth *auth, 1802 DBusAuthCommand command, 1803 const DBusString *args) 1804 { 1805 switch (command) 1806 { 1807 case DBUS_AUTH_COMMAND_AUTH: 1808 return send_error (auth, "Sent AUTH while expecting BEGIN"); 1809 1810 case DBUS_AUTH_COMMAND_DATA: 1811 return send_error (auth, "Sent DATA while expecting BEGIN"); 1812 1813 case DBUS_AUTH_COMMAND_BEGIN: 1814 goto_state (auth, &common_state_authenticated); 1815 return TRUE; 1816 1817 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 1818 if (auth->unix_fd_possible) 1819 return send_agree_unix_fd(auth); 1820 else 1821 return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible"); 1822 1823 case DBUS_AUTH_COMMAND_REJECTED: 1824 case DBUS_AUTH_COMMAND_OK: 1825 case DBUS_AUTH_COMMAND_UNKNOWN: 1826 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 1827 default: 1828 return send_error (auth, "Unknown command"); 1829 1830 case DBUS_AUTH_COMMAND_CANCEL: 1831 case DBUS_AUTH_COMMAND_ERROR: 1832 return send_rejected (auth); 1833 } 1834 } 1835 1836 /* return FALSE if no memory, TRUE if all OK */ 1837 static dbus_bool_t 1838 get_word (const DBusString *str, 1839 int *start, 1840 DBusString *word) 1841 { 1842 int i; 1843 1844 _dbus_string_skip_blank (str, *start, start); 1845 _dbus_string_find_blank (str, *start, &i); 1846 1847 if (i > *start) 1848 { 1849 if (!_dbus_string_copy_len (str, *start, i - *start, word, 0)) 1850 return FALSE; 1851 1852 *start = i; 1853 } 1854 1855 return TRUE; 1856 } 1857 1858 static dbus_bool_t 1859 record_mechanisms (DBusAuth *auth, 1860 const DBusString *args) 1861 { 1862 int next; 1863 int len; 1864 1865 if (auth->already_got_mechanisms) 1866 return TRUE; 1867 1868 len = _dbus_string_get_length (args); 1869 1870 next = 0; 1871 while (next < len) 1872 { 1873 DBusString m; 1874 const DBusAuthMechanismHandler *mech; 1875 1876 if (!_dbus_string_init (&m)) 1877 goto nomem; 1878 1879 if (!get_word (args, &next, &m)) 1880 { 1881 _dbus_string_free (&m); 1882 goto nomem; 1883 } 1884 1885 mech = find_mech (&m, auth->allowed_mechs); 1886 1887 if (mech != NULL) 1888 { 1889 /* FIXME right now we try mechanisms in the order 1890 * the server lists them; should we do them in 1891 * some more deterministic order? 1892 * 1893 * Probably in all_mechanisms order, our order of 1894 * preference. Of course when the server is us, 1895 * it lists things in that order anyhow. 1896 */ 1897 1898 if (mech != &all_mechanisms[0]) 1899 { 1900 _dbus_verbose ("%s: Adding mechanism %s to list we will try\n", 1901 DBUS_AUTH_NAME (auth), mech->mechanism); 1902 1903 if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try, 1904 (void*) mech)) 1905 { 1906 _dbus_string_free (&m); 1907 goto nomem; 1908 } 1909 } 1910 else 1911 { 1912 _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n", 1913 DBUS_AUTH_NAME (auth), mech->mechanism); 1914 } 1915 } 1916 else 1917 { 1918 _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n", 1919 DBUS_AUTH_NAME (auth), 1920 _dbus_string_get_const_data (&m)); 1921 } 1922 1923 _dbus_string_free (&m); 1924 } 1925 1926 auth->already_got_mechanisms = TRUE; 1927 1928 return TRUE; 1929 1930 nomem: 1931 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); 1932 1933 return FALSE; 1934 } 1935 1936 static dbus_bool_t 1937 process_rejected (DBusAuth *auth, const DBusString *args) 1938 { 1939 const DBusAuthMechanismHandler *mech; 1940 DBusAuthClient *client; 1941 1942 client = DBUS_AUTH_CLIENT (auth); 1943 1944 if (!auth->already_got_mechanisms) 1945 { 1946 if (!record_mechanisms (auth, args)) 1947 return FALSE; 1948 } 1949 1950 if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL) 1951 { 1952 mech = client->mechs_to_try->data; 1953 1954 if (!send_auth (auth, mech)) 1955 return FALSE; 1956 1957 _dbus_list_pop_first (&client->mechs_to_try); 1958 1959 _dbus_verbose ("%s: Trying mechanism %s\n", 1960 DBUS_AUTH_NAME (auth), 1961 mech->mechanism); 1962 } 1963 else 1964 { 1965 /* Give up */ 1966 _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n", 1967 DBUS_AUTH_NAME (auth)); 1968 goto_state (auth, &common_state_need_disconnect); 1969 } 1970 1971 return TRUE; 1972 } 1973 1974 1975 static dbus_bool_t 1976 handle_client_state_waiting_for_data (DBusAuth *auth, 1977 DBusAuthCommand command, 1978 const DBusString *args) 1979 { 1980 _dbus_assert (auth->mech != NULL); 1981 1982 switch (command) 1983 { 1984 case DBUS_AUTH_COMMAND_DATA: 1985 return process_data (auth, args, auth->mech->client_data_func); 1986 1987 case DBUS_AUTH_COMMAND_REJECTED: 1988 return process_rejected (auth, args); 1989 1990 case DBUS_AUTH_COMMAND_OK: 1991 return process_ok(auth, args); 1992 1993 case DBUS_AUTH_COMMAND_ERROR: 1994 return send_cancel (auth); 1995 1996 case DBUS_AUTH_COMMAND_AUTH: 1997 case DBUS_AUTH_COMMAND_CANCEL: 1998 case DBUS_AUTH_COMMAND_BEGIN: 1999 case DBUS_AUTH_COMMAND_UNKNOWN: 2000 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 2001 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 2002 default: 2003 return send_error (auth, "Unknown command"); 2004 } 2005 } 2006 2007 static dbus_bool_t 2008 handle_client_state_waiting_for_ok (DBusAuth *auth, 2009 DBusAuthCommand command, 2010 const DBusString *args) 2011 { 2012 switch (command) 2013 { 2014 case DBUS_AUTH_COMMAND_REJECTED: 2015 return process_rejected (auth, args); 2016 2017 case DBUS_AUTH_COMMAND_OK: 2018 return process_ok(auth, args); 2019 2020 case DBUS_AUTH_COMMAND_DATA: 2021 case DBUS_AUTH_COMMAND_ERROR: 2022 return send_cancel (auth); 2023 2024 case DBUS_AUTH_COMMAND_AUTH: 2025 case DBUS_AUTH_COMMAND_CANCEL: 2026 case DBUS_AUTH_COMMAND_BEGIN: 2027 case DBUS_AUTH_COMMAND_UNKNOWN: 2028 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 2029 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 2030 default: 2031 return send_error (auth, "Unknown command"); 2032 } 2033 } 2034 2035 static dbus_bool_t 2036 handle_client_state_waiting_for_reject (DBusAuth *auth, 2037 DBusAuthCommand command, 2038 const DBusString *args) 2039 { 2040 switch (command) 2041 { 2042 case DBUS_AUTH_COMMAND_REJECTED: 2043 return process_rejected (auth, args); 2044 2045 case DBUS_AUTH_COMMAND_AUTH: 2046 case DBUS_AUTH_COMMAND_CANCEL: 2047 case DBUS_AUTH_COMMAND_DATA: 2048 case DBUS_AUTH_COMMAND_BEGIN: 2049 case DBUS_AUTH_COMMAND_OK: 2050 case DBUS_AUTH_COMMAND_ERROR: 2051 case DBUS_AUTH_COMMAND_UNKNOWN: 2052 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 2053 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 2054 default: 2055 goto_state (auth, &common_state_need_disconnect); 2056 return TRUE; 2057 } 2058 } 2059 2060 static dbus_bool_t 2061 handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth, 2062 DBusAuthCommand command, 2063 const DBusString *args) 2064 { 2065 switch (command) 2066 { 2067 case DBUS_AUTH_COMMAND_AGREE_UNIX_FD: 2068 _dbus_assert(auth->unix_fd_possible); 2069 auth->unix_fd_negotiated = TRUE; 2070 _dbus_verbose("Successfully negotiated UNIX FD passing\n"); 2071 return send_begin (auth); 2072 2073 case DBUS_AUTH_COMMAND_ERROR: 2074 _dbus_assert(auth->unix_fd_possible); 2075 auth->unix_fd_negotiated = FALSE; 2076 _dbus_verbose("Failed to negotiate UNIX FD passing\n"); 2077 return send_begin (auth); 2078 2079 case DBUS_AUTH_COMMAND_OK: 2080 case DBUS_AUTH_COMMAND_DATA: 2081 case DBUS_AUTH_COMMAND_REJECTED: 2082 case DBUS_AUTH_COMMAND_AUTH: 2083 case DBUS_AUTH_COMMAND_CANCEL: 2084 case DBUS_AUTH_COMMAND_BEGIN: 2085 case DBUS_AUTH_COMMAND_UNKNOWN: 2086 case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD: 2087 default: 2088 return send_error (auth, "Unknown command"); 2089 } 2090 } 2091 2092 /** 2093 * Mapping from command name to enum 2094 */ 2095 typedef struct { 2096 const char *name; /**< Name of the command */ 2097 DBusAuthCommand command; /**< Corresponding enum */ 2098 } DBusAuthCommandName; 2099 2100 static const DBusAuthCommandName auth_command_names[] = { 2101 { "AUTH", DBUS_AUTH_COMMAND_AUTH }, 2102 { "CANCEL", DBUS_AUTH_COMMAND_CANCEL }, 2103 { "DATA", DBUS_AUTH_COMMAND_DATA }, 2104 { "BEGIN", DBUS_AUTH_COMMAND_BEGIN }, 2105 { "REJECTED", DBUS_AUTH_COMMAND_REJECTED }, 2106 { "OK", DBUS_AUTH_COMMAND_OK }, 2107 { "ERROR", DBUS_AUTH_COMMAND_ERROR }, 2108 { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD }, 2109 { "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD } 2110 }; 2111 2112 static DBusAuthCommand 2113 lookup_command_from_name (DBusString *command) 2114 { 2115 int i; 2116 2117 for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++) 2118 { 2119 if (_dbus_string_equal_c_str (command, 2120 auth_command_names[i].name)) 2121 return auth_command_names[i].command; 2122 } 2123 2124 return DBUS_AUTH_COMMAND_UNKNOWN; 2125 } 2126 2127 static void 2128 goto_state (DBusAuth *auth, 2129 const DBusAuthStateData *state) 2130 { 2131 _dbus_verbose ("%s: going from state %s to state %s\n", 2132 DBUS_AUTH_NAME (auth), 2133 auth->state->name, 2134 state->name); 2135 2136 auth->state = state; 2137 } 2138 2139 /* returns whether to call it again right away */ 2140 static dbus_bool_t 2141 process_command (DBusAuth *auth) 2142 { 2143 DBusAuthCommand command; 2144 DBusString line; 2145 DBusString args; 2146 int eol; 2147 int i, j; 2148 dbus_bool_t retval; 2149 2150 /* _dbus_verbose ("%s: trying process_command()\n"); */ 2151 2152 retval = FALSE; 2153 2154 eol = 0; 2155 if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol)) 2156 return FALSE; 2157 2158 if (!_dbus_string_init (&line)) 2159 { 2160 auth->needed_memory = TRUE; 2161 return FALSE; 2162 } 2163 2164 if (!_dbus_string_init (&args)) 2165 { 2166 _dbus_string_free (&line); 2167 auth->needed_memory = TRUE; 2168 return FALSE; 2169 } 2170 2171 if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0)) 2172 goto out; 2173 2174 if (!_dbus_string_validate_ascii (&line, 0, 2175 _dbus_string_get_length (&line))) 2176 { 2177 _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n", 2178 DBUS_AUTH_NAME (auth)); 2179 if (!send_error (auth, "Command contained non-ASCII")) 2180 goto out; 2181 else 2182 goto next_command; 2183 } 2184 2185 _dbus_verbose ("%s: got command \"%s\"\n", 2186 DBUS_AUTH_NAME (auth), 2187 _dbus_string_get_const_data (&line)); 2188 2189 _dbus_string_find_blank (&line, 0, &i); 2190 _dbus_string_skip_blank (&line, i, &j); 2191 2192 if (j > i) 2193 _dbus_string_delete (&line, i, j - i); 2194 2195 if (!_dbus_string_move (&line, i, &args, 0)) 2196 goto out; 2197 2198 /* FIXME 1.0 we should probably validate that only the allowed 2199 * chars are in the command name 2200 */ 2201 2202 command = lookup_command_from_name (&line); 2203 if (!(* auth->state->handler) (auth, command, &args)) 2204 goto out; 2205 2206 next_command: 2207 2208 /* We've succeeded in processing the whole command so drop it out 2209 * of the incoming buffer and return TRUE to try another command. 2210 */ 2211 2212 _dbus_string_delete (&auth->incoming, 0, eol); 2213 2214 /* kill the \r\n */ 2215 _dbus_string_delete (&auth->incoming, 0, 2); 2216 2217 retval = TRUE; 2218 2219 out: 2220 _dbus_string_free (&args); 2221 _dbus_string_free (&line); 2222 2223 if (!retval) 2224 auth->needed_memory = TRUE; 2225 else 2226 auth->needed_memory = FALSE; 2227 2228 return retval; 2229 } 2230 2231 2232 /** @} */ 2233 2234 /** 2235 * @addtogroup DBusAuth 2236 * @{ 2237 */ 2238 2239 /** 2240 * Creates a new auth conversation object for the server side. 2241 * See doc/dbus-sasl-profile.txt for full details on what 2242 * this object does. 2243 * 2244 * @returns the new object or #NULL if no memory 2245 */ 2246 DBusAuth* 2247 _dbus_auth_server_new (const DBusString *guid) 2248 { 2249 DBusAuth *auth; 2250 DBusAuthServer *server_auth; 2251 DBusString guid_copy; 2252 2253 if (!_dbus_string_init (&guid_copy)) 2254 return NULL; 2255 2256 if (!_dbus_string_copy (guid, 0, &guid_copy, 0)) 2257 { 2258 _dbus_string_free (&guid_copy); 2259 return NULL; 2260 } 2261 2262 auth = _dbus_auth_new (sizeof (DBusAuthServer)); 2263 if (auth == NULL) 2264 { 2265 _dbus_string_free (&guid_copy); 2266 return NULL; 2267 } 2268 2269 auth->side = auth_side_server; 2270 auth->state = &server_state_waiting_for_auth; 2271 2272 server_auth = DBUS_AUTH_SERVER (auth); 2273 2274 server_auth->guid = guid_copy; 2275 2276 /* perhaps this should be per-mechanism with a lower 2277 * max 2278 */ 2279 server_auth->failures = 0; 2280 server_auth->max_failures = 6; 2281 2282 return auth; 2283 } 2284 2285 /** 2286 * Creates a new auth conversation object for the client side. 2287 * See doc/dbus-sasl-profile.txt for full details on what 2288 * this object does. 2289 * 2290 * @returns the new object or #NULL if no memory 2291 */ 2292 DBusAuth* 2293 _dbus_auth_client_new (void) 2294 { 2295 DBusAuth *auth; 2296 DBusString guid_str; 2297 2298 if (!_dbus_string_init (&guid_str)) 2299 return NULL; 2300 2301 auth = _dbus_auth_new (sizeof (DBusAuthClient)); 2302 if (auth == NULL) 2303 { 2304 _dbus_string_free (&guid_str); 2305 return NULL; 2306 } 2307 2308 DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str; 2309 2310 auth->side = auth_side_client; 2311 auth->state = &client_state_need_send_auth; 2312 2313 /* Start the auth conversation by sending AUTH for our default 2314 * mechanism */ 2315 if (!send_auth (auth, &all_mechanisms[0])) 2316 { 2317 _dbus_auth_unref (auth); 2318 return NULL; 2319 } 2320 2321 return auth; 2322 } 2323 2324 /** 2325 * Increments the refcount of an auth object. 2326 * 2327 * @param auth the auth conversation 2328 * @returns the auth conversation 2329 */ 2330 DBusAuth * 2331 _dbus_auth_ref (DBusAuth *auth) 2332 { 2333 _dbus_assert (auth != NULL); 2334 2335 auth->refcount += 1; 2336 2337 return auth; 2338 } 2339 2340 /** 2341 * Decrements the refcount of an auth object. 2342 * 2343 * @param auth the auth conversation 2344 */ 2345 void 2346 _dbus_auth_unref (DBusAuth *auth) 2347 { 2348 _dbus_assert (auth != NULL); 2349 _dbus_assert (auth->refcount > 0); 2350 2351 auth->refcount -= 1; 2352 if (auth->refcount == 0) 2353 { 2354 shutdown_mech (auth); 2355 2356 if (DBUS_AUTH_IS_CLIENT (auth)) 2357 { 2358 _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server); 2359 _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try); 2360 } 2361 else 2362 { 2363 _dbus_assert (DBUS_AUTH_IS_SERVER (auth)); 2364 2365 _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid); 2366 } 2367 2368 if (auth->keyring) 2369 _dbus_keyring_unref (auth->keyring); 2370 2371 _dbus_string_free (&auth->context); 2372 _dbus_string_free (&auth->challenge); 2373 _dbus_string_free (&auth->identity); 2374 _dbus_string_free (&auth->incoming); 2375 _dbus_string_free (&auth->outgoing); 2376 2377 dbus_free_string_array (auth->allowed_mechs); 2378 2379 _dbus_credentials_unref (auth->credentials); 2380 _dbus_credentials_unref (auth->authorized_identity); 2381 _dbus_credentials_unref (auth->desired_identity); 2382 2383 dbus_free (auth); 2384 } 2385 } 2386 2387 /** 2388 * Sets an array of authentication mechanism names 2389 * that we are willing to use. 2390 * 2391 * @param auth the auth conversation 2392 * @param mechanisms #NULL-terminated array of mechanism names 2393 * @returns #FALSE if no memory 2394 */ 2395 dbus_bool_t 2396 _dbus_auth_set_mechanisms (DBusAuth *auth, 2397 const char **mechanisms) 2398 { 2399 char **copy; 2400 2401 if (mechanisms != NULL) 2402 { 2403 copy = _dbus_dup_string_array (mechanisms); 2404 if (copy == NULL) 2405 return FALSE; 2406 } 2407 else 2408 copy = NULL; 2409 2410 dbus_free_string_array (auth->allowed_mechs); 2411 2412 auth->allowed_mechs = copy; 2413 2414 return TRUE; 2415 } 2416 2417 /** 2418 * @param auth the auth conversation object 2419 * @returns #TRUE if we're in a final state 2420 */ 2421 #define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL) 2422 2423 /** 2424 * Analyzes buffered input and moves the auth conversation forward, 2425 * returning the new state of the auth conversation. 2426 * 2427 * @param auth the auth conversation 2428 * @returns the new state 2429 */ 2430 DBusAuthState 2431 _dbus_auth_do_work (DBusAuth *auth) 2432 { 2433 auth->needed_memory = FALSE; 2434 2435 /* Max amount we'll buffer up before deciding someone's on crack */ 2436 #define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE) 2437 2438 do 2439 { 2440 if (DBUS_AUTH_IN_END_STATE (auth)) 2441 break; 2442 2443 if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER || 2444 _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER) 2445 { 2446 goto_state (auth, &common_state_need_disconnect); 2447 _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n", 2448 DBUS_AUTH_NAME (auth)); 2449 break; 2450 } 2451 } 2452 while (process_command (auth)); 2453 2454 if (auth->needed_memory) 2455 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY; 2456 else if (_dbus_string_get_length (&auth->outgoing) > 0) 2457 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; 2458 else if (auth->state == &common_state_need_disconnect) 2459 return DBUS_AUTH_STATE_NEED_DISCONNECT; 2460 else if (auth->state == &common_state_authenticated) 2461 return DBUS_AUTH_STATE_AUTHENTICATED; 2462 else return DBUS_AUTH_STATE_WAITING_FOR_INPUT; 2463 } 2464 2465 /** 2466 * Gets bytes that need to be sent to the peer we're conversing with. 2467 * After writing some bytes, _dbus_auth_bytes_sent() must be called 2468 * to notify the auth object that they were written. 2469 * 2470 * @param auth the auth conversation 2471 * @param str return location for a ref to the buffer to send 2472 * @returns #FALSE if nothing to send 2473 */ 2474 dbus_bool_t 2475 _dbus_auth_get_bytes_to_send (DBusAuth *auth, 2476 const DBusString **str) 2477 { 2478 _dbus_assert (auth != NULL); 2479 _dbus_assert (str != NULL); 2480 2481 *str = NULL; 2482 2483 if (_dbus_string_get_length (&auth->outgoing) == 0) 2484 return FALSE; 2485 2486 *str = &auth->outgoing; 2487 2488 return TRUE; 2489 } 2490 2491 /** 2492 * Notifies the auth conversation object that 2493 * the given number of bytes of the outgoing buffer 2494 * have been written out. 2495 * 2496 * @param auth the auth conversation 2497 * @param bytes_sent number of bytes written out 2498 */ 2499 void 2500 _dbus_auth_bytes_sent (DBusAuth *auth, 2501 int bytes_sent) 2502 { 2503 _dbus_verbose ("%s: Sent %d bytes of: %s\n", 2504 DBUS_AUTH_NAME (auth), 2505 bytes_sent, 2506 _dbus_string_get_const_data (&auth->outgoing)); 2507 2508 _dbus_string_delete (&auth->outgoing, 2509 0, bytes_sent); 2510 } 2511 2512 /** 2513 * Get a buffer to be used for reading bytes from the peer we're conversing 2514 * with. Bytes should be appended to this buffer. 2515 * 2516 * @param auth the auth conversation 2517 * @param buffer return location for buffer to append bytes to 2518 */ 2519 void 2520 _dbus_auth_get_buffer (DBusAuth *auth, 2521 DBusString **buffer) 2522 { 2523 _dbus_assert (auth != NULL); 2524 _dbus_assert (!auth->buffer_outstanding); 2525 2526 *buffer = &auth->incoming; 2527 2528 auth->buffer_outstanding = TRUE; 2529 } 2530 2531 /** 2532 * Returns a buffer with new data read into it. 2533 * 2534 * @param auth the auth conversation 2535 * @param buffer the buffer being returned 2536 * @param bytes_read number of new bytes added 2537 */ 2538 void 2539 _dbus_auth_return_buffer (DBusAuth *auth, 2540 DBusString *buffer, 2541 int bytes_read) 2542 { 2543 _dbus_assert (buffer == &auth->incoming); 2544 _dbus_assert (auth->buffer_outstanding); 2545 2546 auth->buffer_outstanding = FALSE; 2547 } 2548 2549 /** 2550 * Returns leftover bytes that were not used as part of the auth 2551 * conversation. These bytes will be part of the message stream 2552 * instead. This function may not be called until authentication has 2553 * succeeded. 2554 * 2555 * @param auth the auth conversation 2556 * @param str return location for pointer to string of unused bytes 2557 */ 2558 void 2559 _dbus_auth_get_unused_bytes (DBusAuth *auth, 2560 const DBusString **str) 2561 { 2562 if (!DBUS_AUTH_IN_END_STATE (auth)) 2563 return; 2564 2565 *str = &auth->incoming; 2566 } 2567 2568 2569 /** 2570 * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes() 2571 * after we've gotten them and successfully moved them elsewhere. 2572 * 2573 * @param auth the auth conversation 2574 */ 2575 void 2576 _dbus_auth_delete_unused_bytes (DBusAuth *auth) 2577 { 2578 if (!DBUS_AUTH_IN_END_STATE (auth)) 2579 return; 2580 2581 _dbus_string_set_length (&auth->incoming, 0); 2582 } 2583 2584 /** 2585 * Called post-authentication, indicates whether we need to encode 2586 * the message stream with _dbus_auth_encode_data() prior to 2587 * sending it to the peer. 2588 * 2589 * @param auth the auth conversation 2590 * @returns #TRUE if we need to encode the stream 2591 */ 2592 dbus_bool_t 2593 _dbus_auth_needs_encoding (DBusAuth *auth) 2594 { 2595 if (auth->state != &common_state_authenticated) 2596 return FALSE; 2597 2598 if (auth->mech != NULL) 2599 { 2600 if (DBUS_AUTH_IS_CLIENT (auth)) 2601 return auth->mech->client_encode_func != NULL; 2602 else 2603 return auth->mech->server_encode_func != NULL; 2604 } 2605 else 2606 return FALSE; 2607 } 2608 2609 /** 2610 * Called post-authentication, encodes a block of bytes for sending to 2611 * the peer. If no encoding was negotiated, just copies the bytes 2612 * (you can avoid this by checking _dbus_auth_needs_encoding()). 2613 * 2614 * @param auth the auth conversation 2615 * @param plaintext the plain text data 2616 * @param encoded initialized string to where encoded data is appended 2617 * @returns #TRUE if we had enough memory and successfully encoded 2618 */ 2619 dbus_bool_t 2620 _dbus_auth_encode_data (DBusAuth *auth, 2621 const DBusString *plaintext, 2622 DBusString *encoded) 2623 { 2624 _dbus_assert (plaintext != encoded); 2625 2626 if (auth->state != &common_state_authenticated) 2627 return FALSE; 2628 2629 if (_dbus_auth_needs_encoding (auth)) 2630 { 2631 if (DBUS_AUTH_IS_CLIENT (auth)) 2632 return (* auth->mech->client_encode_func) (auth, plaintext, encoded); 2633 else 2634 return (* auth->mech->server_encode_func) (auth, plaintext, encoded); 2635 } 2636 else 2637 { 2638 return _dbus_string_copy (plaintext, 0, encoded, 2639 _dbus_string_get_length (encoded)); 2640 } 2641 } 2642 2643 /** 2644 * Called post-authentication, indicates whether we need to decode 2645 * the message stream with _dbus_auth_decode_data() after 2646 * receiving it from the peer. 2647 * 2648 * @param auth the auth conversation 2649 * @returns #TRUE if we need to encode the stream 2650 */ 2651 dbus_bool_t 2652 _dbus_auth_needs_decoding (DBusAuth *auth) 2653 { 2654 if (auth->state != &common_state_authenticated) 2655 return FALSE; 2656 2657 if (auth->mech != NULL) 2658 { 2659 if (DBUS_AUTH_IS_CLIENT (auth)) 2660 return auth->mech->client_decode_func != NULL; 2661 else 2662 return auth->mech->server_decode_func != NULL; 2663 } 2664 else 2665 return FALSE; 2666 } 2667 2668 2669 /** 2670 * Called post-authentication, decodes a block of bytes received from 2671 * the peer. If no encoding was negotiated, just copies the bytes (you 2672 * can avoid this by checking _dbus_auth_needs_decoding()). 2673 * 2674 * @todo 1.0? We need to be able to distinguish "out of memory" error 2675 * from "the data is hosed" error. 2676 * 2677 * @param auth the auth conversation 2678 * @param encoded the encoded data 2679 * @param plaintext initialized string where decoded data is appended 2680 * @returns #TRUE if we had enough memory and successfully decoded 2681 */ 2682 dbus_bool_t 2683 _dbus_auth_decode_data (DBusAuth *auth, 2684 const DBusString *encoded, 2685 DBusString *plaintext) 2686 { 2687 _dbus_assert (plaintext != encoded); 2688 2689 if (auth->state != &common_state_authenticated) 2690 return FALSE; 2691 2692 if (_dbus_auth_needs_decoding (auth)) 2693 { 2694 if (DBUS_AUTH_IS_CLIENT (auth)) 2695 return (* auth->mech->client_decode_func) (auth, encoded, plaintext); 2696 else 2697 return (* auth->mech->server_decode_func) (auth, encoded, plaintext); 2698 } 2699 else 2700 { 2701 return _dbus_string_copy (encoded, 0, plaintext, 2702 _dbus_string_get_length (plaintext)); 2703 } 2704 } 2705 2706 /** 2707 * Sets credentials received via reliable means from the operating 2708 * system. 2709 * 2710 * @param auth the auth conversation 2711 * @param credentials the credentials received 2712 * @returns #FALSE on OOM 2713 */ 2714 dbus_bool_t 2715 _dbus_auth_set_credentials (DBusAuth *auth, 2716 DBusCredentials *credentials) 2717 { 2718 _dbus_credentials_clear (auth->credentials); 2719 return _dbus_credentials_add_credentials (auth->credentials, 2720 credentials); 2721 } 2722 2723 /** 2724 * Gets the identity we authorized the client as. Apps may have 2725 * different policies as to what identities they allow. 2726 * 2727 * Returned credentials are not a copy and should not be modified 2728 * 2729 * @param auth the auth conversation 2730 * @returns the credentials we've authorized BY REFERENCE do not modify 2731 */ 2732 DBusCredentials* 2733 _dbus_auth_get_identity (DBusAuth *auth) 2734 { 2735 if (auth->state == &common_state_authenticated) 2736 { 2737 return auth->authorized_identity; 2738 } 2739 else 2740 { 2741 /* FIXME instead of this, keep an empty credential around that 2742 * doesn't require allocation or something 2743 */ 2744 /* return empty credentials */ 2745 _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity)); 2746 return auth->authorized_identity; 2747 } 2748 } 2749 2750 /** 2751 * Gets the GUID from the server if we've authenticated; gets 2752 * #NULL otherwise. 2753 * @param auth the auth object 2754 * @returns the GUID in ASCII hex format 2755 */ 2756 const char* 2757 _dbus_auth_get_guid_from_server (DBusAuth *auth) 2758 { 2759 _dbus_assert (DBUS_AUTH_IS_CLIENT (auth)); 2760 2761 if (auth->state == &common_state_authenticated) 2762 return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server); 2763 else 2764 return NULL; 2765 } 2766 2767 /** 2768 * Sets the "authentication context" which scopes cookies 2769 * with the DBUS_COOKIE_SHA1 auth mechanism for example. 2770 * 2771 * @param auth the auth conversation 2772 * @param context the context 2773 * @returns #FALSE if no memory 2774 */ 2775 dbus_bool_t 2776 _dbus_auth_set_context (DBusAuth *auth, 2777 const DBusString *context) 2778 { 2779 return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context), 2780 &auth->context, 0, _dbus_string_get_length (context)); 2781 } 2782 2783 /** 2784 * Sets whether unix fd passing is potentially on the transport and 2785 * hence shall be negotiated. 2786 * 2787 * @param auth the auth conversation 2788 * @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE 2789 */ 2790 void 2791 _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b) 2792 { 2793 auth->unix_fd_possible = b; 2794 } 2795 2796 /** 2797 * Queries whether unix fd passing was successfully negotiated. 2798 * 2799 * @param auth the auth conversion 2800 * @returns #TRUE when unix fd passing was negotiated. 2801 */ 2802 dbus_bool_t 2803 _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth) 2804 { 2805 return auth->unix_fd_negotiated; 2806 } 2807 2808 /** @} */ 2809 2810 /* tests in dbus-auth-util.c */ 2811