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