00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #ifdef DBUS_BUILD_TESTS
00026
00027 #include "dbus-auth-script.h"
00028 #include "dbus-auth.h"
00029 #include "dbus-string.h"
00030 #include "dbus-hash.h"
00031 #include "dbus-credentials.h"
00032 #include "dbus-internals.h"
00033
00045
00046
00047
00048 static dbus_bool_t
00049 append_quoted_string (DBusString *dest,
00050 const DBusString *quoted)
00051 {
00052 dbus_bool_t in_quotes = FALSE;
00053 dbus_bool_t in_backslash = FALSE;
00054 int i;
00055
00056 i = 0;
00057 while (i < _dbus_string_get_length (quoted))
00058 {
00059 unsigned char b;
00060
00061 b = _dbus_string_get_byte (quoted, i);
00062
00063 if (in_backslash)
00064 {
00065 unsigned char a;
00066
00067 if (b == 'r')
00068 a = '\r';
00069 else if (b == 'n')
00070 a = '\n';
00071 else if (b == '\\')
00072 a = '\\';
00073 else
00074 {
00075 _dbus_warn ("bad backslashed byte %c\n", b);
00076 return FALSE;
00077 }
00078
00079 if (!_dbus_string_append_byte (dest, a))
00080 return FALSE;
00081
00082 in_backslash = FALSE;
00083 }
00084 else if (b == '\\')
00085 {
00086 in_backslash = TRUE;
00087 }
00088 else if (in_quotes)
00089 {
00090 if (b == '\'')
00091 in_quotes = FALSE;
00092 else
00093 {
00094 if (!_dbus_string_append_byte (dest, b))
00095 return FALSE;
00096 }
00097 }
00098 else
00099 {
00100 if (b == '\'')
00101 in_quotes = TRUE;
00102 else if (b == ' ' || b == '\n' || b == '\t')
00103 break;
00104 else
00105 {
00106 if (!_dbus_string_append_byte (dest, b))
00107 return FALSE;
00108 }
00109 }
00110
00111 ++i;
00112 }
00113
00114 return TRUE;
00115 }
00116
00117 static dbus_bool_t
00118 same_first_word (const DBusString *a,
00119 const DBusString *b)
00120 {
00121 int first_a_blank, first_b_blank;
00122
00123 _dbus_string_find_blank (a, 0, &first_a_blank);
00124 _dbus_string_find_blank (b, 0, &first_b_blank);
00125
00126 if (first_a_blank != first_b_blank)
00127 return FALSE;
00128
00129 return _dbus_string_equal_len (a, b, first_a_blank);
00130 }
00131
00132 static DBusAuthState
00133 auth_state_from_string (const DBusString *str)
00134 {
00135 if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT"))
00136 return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
00137 else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY"))
00138 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
00139 else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND"))
00140 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
00141 else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT"))
00142 return DBUS_AUTH_STATE_NEED_DISCONNECT;
00143 else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
00144 return DBUS_AUTH_STATE_AUTHENTICATED;
00145 else
00146 return -1;
00147 }
00148
00149 static const char*
00150 auth_state_to_string (DBusAuthState state)
00151 {
00152 switch (state)
00153 {
00154 case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
00155 return "WAITING_FOR_INPUT";
00156 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
00157 return "WAITING_FOR_MEMORY";
00158 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
00159 return "HAVE_BYTES_TO_SEND";
00160 case DBUS_AUTH_STATE_NEED_DISCONNECT:
00161 return "NEED_DISCONNECT";
00162 case DBUS_AUTH_STATE_AUTHENTICATED:
00163 return "AUTHENTICATED";
00164 }
00165
00166 return "unknown";
00167 }
00168
00169 static char **
00170 split_string (DBusString *str)
00171 {
00172 int i, j, k, count, end;
00173 char **array;
00174
00175 end = _dbus_string_get_length (str);
00176
00177 i = 0;
00178 _dbus_string_skip_blank (str, i, &i);
00179 for (count = 0; i < end; count++)
00180 {
00181 _dbus_string_find_blank (str, i, &i);
00182 _dbus_string_skip_blank (str, i, &i);
00183 }
00184
00185 array = dbus_new0 (char *, count + 1);
00186 if (array == NULL)
00187 return NULL;
00188
00189 i = 0;
00190 _dbus_string_skip_blank (str, i, &i);
00191 for (k = 0; k < count; k++)
00192 {
00193 _dbus_string_find_blank (str, i, &j);
00194
00195 array[k] = dbus_malloc (j - i + 1);
00196 if (array[k] == NULL)
00197 {
00198 dbus_free_string_array (array);
00199 return NULL;
00200 }
00201 memcpy (array[k],
00202 _dbus_string_get_const_data_len (str, i, j - i), j - i);
00203 array[k][j - i] = '\0';
00204
00205 _dbus_string_skip_blank (str, j, &i);
00206 }
00207 array[k] = NULL;
00208
00209 return array;
00210 }
00211
00212 static void
00213 auth_set_unix_credentials(DBusAuth *auth,
00214 dbus_uid_t uid,
00215 dbus_pid_t pid)
00216 {
00217 DBusCredentials *credentials;
00218
00219 credentials = _dbus_credentials_new ();
00220 if (credentials == NULL)
00221 _dbus_assert_not_reached ("no memory");
00222
00223 if (uid != DBUS_UID_UNSET)
00224 _dbus_credentials_add_unix_uid (credentials, uid);
00225 if (pid != DBUS_PID_UNSET)
00226 _dbus_credentials_add_unix_pid (credentials, pid);
00227
00228 _dbus_auth_set_credentials (auth, credentials);
00229
00230 _dbus_credentials_unref (credentials);
00231 }
00232
00243 dbus_bool_t
00244 _dbus_auth_script_run (const DBusString *filename)
00245 {
00246 DBusString file;
00247 DBusError error;
00248 DBusString line;
00249 dbus_bool_t retval;
00250 int line_no;
00251 DBusAuth *auth;
00252 DBusString from_auth;
00253 DBusAuthState state;
00254 DBusString context;
00255 DBusString guid;
00256
00257 retval = FALSE;
00258 auth = NULL;
00259
00260 _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
00261 _dbus_string_init_const (&context, "org_freedesktop_test");
00262
00263 if (!_dbus_string_init (&file))
00264 return FALSE;
00265
00266 if (!_dbus_string_init (&line))
00267 {
00268 _dbus_string_free (&file);
00269 return FALSE;
00270 }
00271
00272 if (!_dbus_string_init (&from_auth))
00273 {
00274 _dbus_string_free (&file);
00275 _dbus_string_free (&line);
00276 return FALSE;
00277 }
00278
00279 dbus_error_init (&error);
00280 if (!_dbus_file_get_contents (&file, filename, &error)) {
00281 _dbus_warn ("Getting contents of %s failed: %s\n",
00282 _dbus_string_get_const_data (filename), error.message);
00283 dbus_error_free (&error);
00284 goto out;
00285 }
00286
00287 state = DBUS_AUTH_STATE_NEED_DISCONNECT;
00288 line_no = 0;
00289
00290 next_iteration:
00291 while (_dbus_string_pop_line (&file, &line))
00292 {
00293 line_no += 1;
00294
00295
00296
00297 _dbus_string_delete_leading_blanks (&line);
00298
00299 if (auth != NULL)
00300 {
00301 while ((state = _dbus_auth_do_work (auth)) ==
00302 DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
00303 {
00304 const DBusString *tmp;
00305 if (_dbus_auth_get_bytes_to_send (auth, &tmp))
00306 {
00307 int count = _dbus_string_get_length (tmp);
00308
00309 if (_dbus_string_copy (tmp, 0, &from_auth,
00310 _dbus_string_get_length (&from_auth)))
00311 _dbus_auth_bytes_sent (auth, count);
00312 }
00313 }
00314 }
00315
00316 if (_dbus_string_get_length (&line) == 0)
00317 {
00318
00319 goto next_iteration;
00320 }
00321 else if (_dbus_string_starts_with_c_str (&line,
00322 "#"))
00323 {
00324
00325 goto next_iteration;
00326 }
00327 #ifdef DBUS_WIN
00328 else if (_dbus_string_starts_with_c_str (&line,
00329 "WIN_ONLY"))
00330 {
00331
00332 goto next_iteration;
00333 }
00334 else if (_dbus_string_starts_with_c_str (&line,
00335 "UNIX_ONLY"))
00336 {
00337
00338 _dbus_warn ("skipping unix only auth script\n");
00339 retval = TRUE;
00340 goto out;
00341 }
00342 #endif
00343 #ifdef DBUS_UNIX
00344 else if (_dbus_string_starts_with_c_str (&line,
00345 "UNIX_ONLY"))
00346 {
00347
00348 goto next_iteration;
00349 }
00350 else if (_dbus_string_starts_with_c_str (&line,
00351 "WIN_ONLY"))
00352 {
00353
00354 _dbus_warn ("skipping windows only auth script\n");
00355 retval = TRUE;
00356 goto out;
00357 }
00358 #endif
00359 else if (_dbus_string_starts_with_c_str (&line,
00360 "CLIENT"))
00361 {
00362 DBusCredentials *creds;
00363
00364 if (auth != NULL)
00365 {
00366 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
00367 goto out;
00368 }
00369
00370 auth = _dbus_auth_client_new ();
00371 if (auth == NULL)
00372 {
00373 _dbus_warn ("no memory to create DBusAuth\n");
00374 goto out;
00375 }
00376
00377
00378 _dbus_auth_ref (auth);
00379 _dbus_auth_unref (auth);
00380
00381 creds = _dbus_credentials_new_from_current_process ();
00382 if (creds == NULL)
00383 {
00384 _dbus_warn ("no memory for credentials\n");
00385 _dbus_auth_unref (auth);
00386 auth = NULL;
00387 goto out;
00388 }
00389
00390 if (!_dbus_auth_set_credentials (auth, creds))
00391 {
00392 _dbus_warn ("no memory for setting credentials\n");
00393 _dbus_auth_unref (auth);
00394 auth = NULL;
00395 _dbus_credentials_unref (creds);
00396 goto out;
00397 }
00398
00399 _dbus_credentials_unref (creds);
00400 }
00401 else if (_dbus_string_starts_with_c_str (&line,
00402 "SERVER"))
00403 {
00404 DBusCredentials *creds;
00405
00406 if (auth != NULL)
00407 {
00408 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
00409 goto out;
00410 }
00411
00412 auth = _dbus_auth_server_new (&guid);
00413 if (auth == NULL)
00414 {
00415 _dbus_warn ("no memory to create DBusAuth\n");
00416 goto out;
00417 }
00418
00419
00420 _dbus_auth_ref (auth);
00421 _dbus_auth_unref (auth);
00422
00423 creds = _dbus_credentials_new_from_current_process ();
00424 if (creds == NULL)
00425 {
00426 _dbus_warn ("no memory for credentials\n");
00427 _dbus_auth_unref (auth);
00428 auth = NULL;
00429 goto out;
00430 }
00431
00432 if (!_dbus_auth_set_credentials (auth, creds))
00433 {
00434 _dbus_warn ("no memory for setting credentials\n");
00435 _dbus_auth_unref (auth);
00436 auth = NULL;
00437 _dbus_credentials_unref (creds);
00438 goto out;
00439 }
00440
00441 _dbus_credentials_unref (creds);
00442
00443 _dbus_auth_set_context (auth, &context);
00444 }
00445 else if (auth == NULL)
00446 {
00447 _dbus_warn ("must specify CLIENT or SERVER\n");
00448 goto out;
00449
00450 }
00451 else if (_dbus_string_starts_with_c_str (&line,
00452 "NO_CREDENTIALS"))
00453 {
00454 auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
00455 }
00456 else if (_dbus_string_starts_with_c_str (&line,
00457 "ROOT_CREDENTIALS"))
00458 {
00459 auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
00460 }
00461 else if (_dbus_string_starts_with_c_str (&line,
00462 "SILLY_CREDENTIALS"))
00463 {
00464 auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
00465 }
00466 else if (_dbus_string_starts_with_c_str (&line,
00467 "ALLOWED_MECHS"))
00468 {
00469 char **mechs;
00470
00471 _dbus_string_delete_first_word (&line);
00472 mechs = split_string (&line);
00473 _dbus_auth_set_mechanisms (auth, (const char **) mechs);
00474 dbus_free_string_array (mechs);
00475 }
00476 else if (_dbus_string_starts_with_c_str (&line,
00477 "SEND"))
00478 {
00479 DBusString to_send;
00480
00481 _dbus_string_delete_first_word (&line);
00482
00483 if (!_dbus_string_init (&to_send))
00484 {
00485 _dbus_warn ("no memory to allocate string\n");
00486 goto out;
00487 }
00488
00489 if (!append_quoted_string (&to_send, &line))
00490 {
00491 _dbus_warn ("failed to append quoted string line %d\n",
00492 line_no);
00493 _dbus_string_free (&to_send);
00494 goto out;
00495 }
00496
00497 _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
00498
00499 if (!_dbus_string_append (&to_send, "\r\n"))
00500 {
00501 _dbus_warn ("failed to append \r\n from line %d\n",
00502 line_no);
00503 _dbus_string_free (&to_send);
00504 goto out;
00505 }
00506
00507
00508 {
00509 int where;
00510
00511 if (_dbus_string_find (&to_send, 0,
00512 "USERID_HEX", &where))
00513 {
00514 DBusString username;
00515
00516 if (!_dbus_string_init (&username))
00517 {
00518 _dbus_warn ("no memory for userid\n");
00519 _dbus_string_free (&to_send);
00520 goto out;
00521 }
00522
00523 if (!_dbus_append_user_from_current_process (&username))
00524 {
00525 _dbus_warn ("no memory for userid\n");
00526 _dbus_string_free (&username);
00527 _dbus_string_free (&to_send);
00528 goto out;
00529 }
00530
00531 _dbus_string_delete (&to_send, where, strlen ("USERID_HEX"));
00532
00533 if (!_dbus_string_hex_encode (&username, 0,
00534 &to_send, where))
00535 {
00536 _dbus_warn ("no memory to subst USERID_HEX\n");
00537 _dbus_string_free (&username);
00538 _dbus_string_free (&to_send);
00539 goto out;
00540 }
00541
00542 _dbus_string_free (&username);
00543 }
00544 else if (_dbus_string_find (&to_send, 0,
00545 "USERNAME_HEX", &where))
00546 {
00547 DBusString username;
00548
00549 if (!_dbus_string_init (&username))
00550 {
00551 _dbus_warn ("no memory for username\n");
00552 _dbus_string_free (&to_send);
00553 goto out;
00554 }
00555
00556 if (!_dbus_append_user_from_current_process (&username))
00557 {
00558 _dbus_warn ("no memory for username\n");
00559 _dbus_string_free (&username);
00560 _dbus_string_free (&to_send);
00561 goto out;
00562 }
00563
00564 _dbus_string_delete (&to_send, where, strlen ("USERNAME_HEX"));
00565
00566 if (!_dbus_string_hex_encode (&username, 0,
00567 &to_send, where))
00568 {
00569 _dbus_warn ("no memory to subst USERNAME_HEX\n");
00570 _dbus_string_free (&username);
00571 _dbus_string_free (&to_send);
00572 goto out;
00573 }
00574
00575 _dbus_string_free (&username);
00576 }
00577 }
00578
00579 {
00580 DBusString *buffer;
00581
00582 _dbus_auth_get_buffer (auth, &buffer);
00583 if (!_dbus_string_copy (&to_send, 0,
00584 buffer, _dbus_string_get_length (buffer)))
00585 {
00586 _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
00587 _dbus_string_free (&to_send);
00588 _dbus_auth_return_buffer (auth, buffer, 0);
00589 goto out;
00590 }
00591
00592 _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send));
00593 }
00594
00595 _dbus_string_free (&to_send);
00596 }
00597 else if (_dbus_string_starts_with_c_str (&line,
00598 "EXPECT_STATE"))
00599 {
00600 DBusAuthState expected;
00601
00602 _dbus_string_delete_first_word (&line);
00603
00604 expected = auth_state_from_string (&line);
00605 if (expected < 0)
00606 {
00607 _dbus_warn ("bad auth state given to EXPECT_STATE\n");
00608 goto parse_failed;
00609 }
00610
00611 if (expected != state)
00612 {
00613 _dbus_warn ("expected auth state %s but got %s on line %d\n",
00614 auth_state_to_string (expected),
00615 auth_state_to_string (state),
00616 line_no);
00617 goto out;
00618 }
00619 }
00620 else if (_dbus_string_starts_with_c_str (&line,
00621 "EXPECT_COMMAND"))
00622 {
00623 DBusString received;
00624
00625 _dbus_string_delete_first_word (&line);
00626
00627 if (!_dbus_string_init (&received))
00628 {
00629 _dbus_warn ("no mem to allocate string received\n");
00630 goto out;
00631 }
00632
00633 if (!_dbus_string_pop_line (&from_auth, &received))
00634 {
00635 _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
00636 _dbus_string_get_const_data (&line), line_no);
00637 _dbus_string_free (&received);
00638 goto out;
00639 }
00640
00641 if (!same_first_word (&received, &line))
00642 {
00643 _dbus_warn ("line %d expected command '%s' and got '%s'\n",
00644 line_no,
00645 _dbus_string_get_const_data (&line),
00646 _dbus_string_get_const_data (&received));
00647 _dbus_string_free (&received);
00648 goto out;
00649 }
00650
00651 _dbus_string_free (&received);
00652 }
00653 else if (_dbus_string_starts_with_c_str (&line,
00654 "EXPECT_UNUSED"))
00655 {
00656 DBusString expected;
00657 const DBusString *unused;
00658
00659 _dbus_string_delete_first_word (&line);
00660
00661 if (!_dbus_string_init (&expected))
00662 {
00663 _dbus_warn ("no mem to allocate string expected\n");
00664 goto out;
00665 }
00666
00667 if (!append_quoted_string (&expected, &line))
00668 {
00669 _dbus_warn ("failed to append quoted string line %d\n",
00670 line_no);
00671 _dbus_string_free (&expected);
00672 goto out;
00673 }
00674
00675 _dbus_auth_get_unused_bytes (auth, &unused);
00676
00677 if (_dbus_string_equal (&expected, unused))
00678 {
00679 _dbus_auth_delete_unused_bytes (auth);
00680 _dbus_string_free (&expected);
00681 }
00682 else
00683 {
00684 _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
00685 _dbus_string_get_const_data (&expected),
00686 _dbus_string_get_const_data (unused));
00687 _dbus_string_free (&expected);
00688 goto out;
00689 }
00690 }
00691 else if (_dbus_string_starts_with_c_str (&line,
00692 "EXPECT_HAVE_NO_CREDENTIALS"))
00693 {
00694 DBusCredentials *authorized_identity;
00695
00696 authorized_identity = _dbus_auth_get_identity (auth);
00697 if (!_dbus_credentials_are_anonymous (authorized_identity))
00698 {
00699 _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
00700 goto out;
00701 }
00702 }
00703 else if (_dbus_string_starts_with_c_str (&line,
00704 "EXPECT_HAVE_SOME_CREDENTIALS"))
00705 {
00706 DBusCredentials *authorized_identity;
00707
00708 authorized_identity = _dbus_auth_get_identity (auth);
00709 if (_dbus_credentials_are_anonymous (authorized_identity))
00710 {
00711 _dbus_warn ("Expected to have some credentials, but we don't\n");
00712 goto out;
00713 }
00714 }
00715 else if (_dbus_string_starts_with_c_str (&line,
00716 "EXPECT"))
00717 {
00718 DBusString expected;
00719
00720 _dbus_string_delete_first_word (&line);
00721
00722 if (!_dbus_string_init (&expected))
00723 {
00724 _dbus_warn ("no mem to allocate string expected\n");
00725 goto out;
00726 }
00727
00728 if (!append_quoted_string (&expected, &line))
00729 {
00730 _dbus_warn ("failed to append quoted string line %d\n",
00731 line_no);
00732 _dbus_string_free (&expected);
00733 goto out;
00734 }
00735
00736 if (_dbus_string_equal_len (&expected, &from_auth,
00737 _dbus_string_get_length (&expected)))
00738 {
00739 _dbus_string_delete (&from_auth, 0,
00740 _dbus_string_get_length (&expected));
00741 _dbus_string_free (&expected);
00742 }
00743 else
00744 {
00745 _dbus_warn ("Expected exact string '%s' and have '%s'\n",
00746 _dbus_string_get_const_data (&expected),
00747 _dbus_string_get_const_data (&from_auth));
00748 _dbus_string_free (&expected);
00749 goto out;
00750 }
00751 }
00752 else
00753 goto parse_failed;
00754
00755 goto next_iteration;
00756
00757 parse_failed:
00758 {
00759 _dbus_warn ("couldn't process line %d \"%s\"\n",
00760 line_no, _dbus_string_get_const_data (&line));
00761 goto out;
00762 }
00763 }
00764
00765 if (auth == NULL)
00766 {
00767 _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
00768 goto out;
00769 }
00770 else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
00771 {
00772 const DBusString *unused;
00773
00774 _dbus_auth_get_unused_bytes (auth, &unused);
00775
00776 if (_dbus_string_get_length (unused) > 0)
00777 {
00778 _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
00779 goto out;
00780 }
00781 }
00782
00783 if (_dbus_string_get_length (&from_auth) > 0)
00784 {
00785 _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
00786 _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
00787 goto out;
00788 }
00789
00790 retval = TRUE;
00791
00792 out:
00793 if (auth)
00794 _dbus_auth_unref (auth);
00795
00796 _dbus_string_free (&file);
00797 _dbus_string_free (&line);
00798 _dbus_string_free (&from_auth);
00799
00800 return retval;
00801 }
00802
00804 #endif