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-internals.h"
00032 #include "dbus-userdb.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
00222 dbus_bool_t
00223 _dbus_auth_script_run (const DBusString *filename)
00224 {
00225 DBusString file;
00226 DBusError error;
00227 DBusString line;
00228 dbus_bool_t retval;
00229 int line_no;
00230 DBusAuth *auth;
00231 DBusString from_auth;
00232 DBusAuthState state;
00233 DBusString context;
00234 DBusString guid;
00235
00236 retval = FALSE;
00237 auth = NULL;
00238
00239 _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
00240 _dbus_string_init_const (&context, "org_freedesktop_test");
00241
00242 if (!_dbus_string_init (&file))
00243 return FALSE;
00244
00245 if (!_dbus_string_init (&line))
00246 {
00247 _dbus_string_free (&file);
00248 return FALSE;
00249 }
00250
00251 if (!_dbus_string_init (&from_auth))
00252 {
00253 _dbus_string_free (&file);
00254 _dbus_string_free (&line);
00255 return FALSE;
00256 }
00257
00258 dbus_error_init (&error);
00259 if (!_dbus_file_get_contents (&file, filename, &error)) {
00260 _dbus_warn ("Getting contents of %s failed: %s\n",
00261 _dbus_string_get_const_data (filename), error.message);
00262 dbus_error_free (&error);
00263 goto out;
00264 }
00265
00266 state = DBUS_AUTH_STATE_NEED_DISCONNECT;
00267 line_no = 0;
00268 next_iteration:
00269 while (_dbus_string_pop_line (&file, &line))
00270 {
00271 line_no += 1;
00272
00273 _dbus_string_delete_leading_blanks (&line);
00274
00275 if (auth != NULL)
00276 {
00277 while ((state = _dbus_auth_do_work (auth)) ==
00278 DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
00279 {
00280 const DBusString *tmp;
00281 if (_dbus_auth_get_bytes_to_send (auth, &tmp))
00282 {
00283 int count = _dbus_string_get_length (tmp);
00284
00285 if (_dbus_string_copy (tmp, 0, &from_auth,
00286 _dbus_string_get_length (&from_auth)))
00287 _dbus_auth_bytes_sent (auth, count);
00288 }
00289 }
00290 }
00291
00292 if (_dbus_string_get_length (&line) == 0)
00293 {
00294
00295 goto next_iteration;
00296 }
00297 else if (_dbus_string_starts_with_c_str (&line,
00298 "#"))
00299 {
00300
00301 goto next_iteration;
00302 }
00303 else if (_dbus_string_starts_with_c_str (&line,
00304 "CLIENT"))
00305 {
00306 DBusCredentials creds;
00307
00308 if (auth != NULL)
00309 {
00310 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
00311 goto out;
00312 }
00313
00314 auth = _dbus_auth_client_new ();
00315 if (auth == NULL)
00316 {
00317 _dbus_warn ("no memory to create DBusAuth\n");
00318 goto out;
00319 }
00320
00321
00322 _dbus_auth_ref (auth);
00323 _dbus_auth_unref (auth);
00324
00325 _dbus_credentials_from_current_process (&creds);
00326 _dbus_auth_set_credentials (auth, &creds);
00327 }
00328 else if (_dbus_string_starts_with_c_str (&line,
00329 "SERVER"))
00330 {
00331 DBusCredentials creds;
00332
00333 if (auth != NULL)
00334 {
00335 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
00336 goto out;
00337 }
00338
00339 auth = _dbus_auth_server_new (&guid);
00340 if (auth == NULL)
00341 {
00342 _dbus_warn ("no memory to create DBusAuth\n");
00343 goto out;
00344 }
00345
00346
00347 _dbus_auth_ref (auth);
00348 _dbus_auth_unref (auth);
00349
00350 _dbus_credentials_from_current_process (&creds);
00351 _dbus_auth_set_credentials (auth, &creds);
00352 _dbus_auth_set_context (auth, &context);
00353 }
00354 else if (auth == NULL)
00355 {
00356 _dbus_warn ("must specify CLIENT or SERVER\n");
00357 goto out;
00358
00359 }
00360 else if (_dbus_string_starts_with_c_str (&line,
00361 "NO_CREDENTIALS"))
00362 {
00363 DBusCredentials creds = { -1, -1, -1 };
00364 _dbus_auth_set_credentials (auth, &creds);
00365 }
00366 else if (_dbus_string_starts_with_c_str (&line,
00367 "ROOT_CREDENTIALS"))
00368 {
00369 DBusCredentials creds = { -1, 0, 0 };
00370 _dbus_auth_set_credentials (auth, &creds);
00371 }
00372 else if (_dbus_string_starts_with_c_str (&line,
00373 "SILLY_CREDENTIALS"))
00374 {
00375 DBusCredentials creds = { -1, 4312, 1232 };
00376 _dbus_auth_set_credentials (auth, &creds);
00377 }
00378 else if (_dbus_string_starts_with_c_str (&line,
00379 "ALLOWED_MECHS"))
00380 {
00381 char **mechs;
00382
00383 _dbus_string_delete_first_word (&line);
00384 mechs = split_string (&line);
00385 _dbus_auth_set_mechanisms (auth, (const char **) mechs);
00386 dbus_free_string_array (mechs);
00387 }
00388 else if (_dbus_string_starts_with_c_str (&line,
00389 "SEND"))
00390 {
00391 DBusString to_send;
00392
00393 _dbus_string_delete_first_word (&line);
00394
00395 if (!_dbus_string_init (&to_send))
00396 {
00397 _dbus_warn ("no memory to allocate string\n");
00398 goto out;
00399 }
00400
00401 if (!append_quoted_string (&to_send, &line))
00402 {
00403 _dbus_warn ("failed to append quoted string line %d\n",
00404 line_no);
00405 _dbus_string_free (&to_send);
00406 goto out;
00407 }
00408
00409 _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
00410
00411 if (!_dbus_string_append (&to_send, "\r\n"))
00412 {
00413 _dbus_warn ("failed to append \r\n from line %d\n",
00414 line_no);
00415 _dbus_string_free (&to_send);
00416 goto out;
00417 }
00418
00419
00420 {
00421 int where;
00422
00423 if (_dbus_string_find (&to_send, 0,
00424 "USERID_HEX", &where))
00425 {
00426 DBusString username;
00427
00428 if (!_dbus_string_init (&username))
00429 {
00430 _dbus_warn ("no memory for userid\n");
00431 _dbus_string_free (&to_send);
00432 goto out;
00433 }
00434
00435 if (!_dbus_string_append_uint (&username,
00436 _dbus_getuid ()))
00437 {
00438 _dbus_warn ("no memory for userid\n");
00439 _dbus_string_free (&username);
00440 _dbus_string_free (&to_send);
00441 goto out;
00442 }
00443
00444 _dbus_string_delete (&to_send, where, strlen ("USERID_HEX"));
00445
00446 if (!_dbus_string_hex_encode (&username, 0,
00447 &to_send, where))
00448 {
00449 _dbus_warn ("no memory to subst USERID_HEX\n");
00450 _dbus_string_free (&username);
00451 _dbus_string_free (&to_send);
00452 goto out;
00453 }
00454
00455 _dbus_string_free (&username);
00456 }
00457 else if (_dbus_string_find (&to_send, 0,
00458 "USERNAME_HEX", &where))
00459 {
00460 DBusString username;
00461 const DBusString *u;
00462
00463 if (!_dbus_string_init (&username))
00464 {
00465 _dbus_warn ("no memory for username\n");
00466 _dbus_string_free (&to_send);
00467 goto out;
00468 }
00469
00470 if (!_dbus_username_from_current_process (&u) ||
00471 !_dbus_string_copy (u, 0, &username,
00472 _dbus_string_get_length (&username)))
00473 {
00474 _dbus_warn ("no memory for username\n");
00475 _dbus_string_free (&username);
00476 _dbus_string_free (&to_send);
00477 goto out;
00478 }
00479
00480 _dbus_string_delete (&to_send, where, strlen ("USERNAME_HEX"));
00481
00482 if (!_dbus_string_hex_encode (&username, 0,
00483 &to_send, where))
00484 {
00485 _dbus_warn ("no memory to subst USERNAME_HEX\n");
00486 _dbus_string_free (&username);
00487 _dbus_string_free (&to_send);
00488 goto out;
00489 }
00490
00491 _dbus_string_free (&username);
00492 }
00493 }
00494
00495 {
00496 DBusString *buffer;
00497
00498 _dbus_auth_get_buffer (auth, &buffer);
00499 if (!_dbus_string_copy (&to_send, 0,
00500 buffer, _dbus_string_get_length (buffer)))
00501 {
00502 _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
00503 _dbus_string_free (&to_send);
00504 _dbus_auth_return_buffer (auth, buffer, 0);
00505 goto out;
00506 }
00507
00508 _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send));
00509 }
00510
00511 _dbus_string_free (&to_send);
00512 }
00513 else if (_dbus_string_starts_with_c_str (&line,
00514 "EXPECT_STATE"))
00515 {
00516 DBusAuthState expected;
00517
00518 _dbus_string_delete_first_word (&line);
00519
00520 expected = auth_state_from_string (&line);
00521 if (expected < 0)
00522 {
00523 _dbus_warn ("bad auth state given to EXPECT_STATE\n");
00524 goto parse_failed;
00525 }
00526
00527 if (expected != state)
00528 {
00529 _dbus_warn ("expected auth state %s but got %s on line %d\n",
00530 auth_state_to_string (expected),
00531 auth_state_to_string (state),
00532 line_no);
00533 goto out;
00534 }
00535 }
00536 else if (_dbus_string_starts_with_c_str (&line,
00537 "EXPECT_COMMAND"))
00538 {
00539 DBusString received;
00540
00541 _dbus_string_delete_first_word (&line);
00542
00543 if (!_dbus_string_init (&received))
00544 {
00545 _dbus_warn ("no mem to allocate string received\n");
00546 goto out;
00547 }
00548
00549 if (!_dbus_string_pop_line (&from_auth, &received))
00550 {
00551 _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
00552 _dbus_string_get_const_data (&line), line_no);
00553 _dbus_string_free (&received);
00554 goto out;
00555 }
00556
00557 if (!same_first_word (&received, &line))
00558 {
00559 _dbus_warn ("line %d expected command '%s' and got '%s'\n",
00560 line_no,
00561 _dbus_string_get_const_data (&line),
00562 _dbus_string_get_const_data (&received));
00563 _dbus_string_free (&received);
00564 goto out;
00565 }
00566
00567 _dbus_string_free (&received);
00568 }
00569 else if (_dbus_string_starts_with_c_str (&line,
00570 "EXPECT_UNUSED"))
00571 {
00572 DBusString expected;
00573 const DBusString *unused;
00574
00575 _dbus_string_delete_first_word (&line);
00576
00577 if (!_dbus_string_init (&expected))
00578 {
00579 _dbus_warn ("no mem to allocate string expected\n");
00580 goto out;
00581 }
00582
00583 if (!append_quoted_string (&expected, &line))
00584 {
00585 _dbus_warn ("failed to append quoted string line %d\n",
00586 line_no);
00587 _dbus_string_free (&expected);
00588 goto out;
00589 }
00590
00591 _dbus_auth_get_unused_bytes (auth, &unused);
00592
00593 if (_dbus_string_equal (&expected, unused))
00594 {
00595 _dbus_auth_delete_unused_bytes (auth);
00596 _dbus_string_free (&expected);
00597 }
00598 else
00599 {
00600 _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
00601 _dbus_string_get_const_data (&expected),
00602 _dbus_string_get_const_data (unused));
00603 _dbus_string_free (&expected);
00604 goto out;
00605 }
00606 }
00607 else if (_dbus_string_starts_with_c_str (&line,
00608 "EXPECT"))
00609 {
00610 DBusString expected;
00611
00612 _dbus_string_delete_first_word (&line);
00613
00614 if (!_dbus_string_init (&expected))
00615 {
00616 _dbus_warn ("no mem to allocate string expected\n");
00617 goto out;
00618 }
00619
00620 if (!append_quoted_string (&expected, &line))
00621 {
00622 _dbus_warn ("failed to append quoted string line %d\n",
00623 line_no);
00624 _dbus_string_free (&expected);
00625 goto out;
00626 }
00627
00628 if (_dbus_string_equal_len (&expected, &from_auth,
00629 _dbus_string_get_length (&expected)))
00630 {
00631 _dbus_string_delete (&from_auth, 0,
00632 _dbus_string_get_length (&expected));
00633 _dbus_string_free (&expected);
00634 }
00635 else
00636 {
00637 _dbus_warn ("Expected exact string '%s' and have '%s'\n",
00638 _dbus_string_get_const_data (&expected),
00639 _dbus_string_get_const_data (&from_auth));
00640 _dbus_string_free (&expected);
00641 goto out;
00642 }
00643 }
00644 else
00645 goto parse_failed;
00646
00647 goto next_iteration;
00648
00649 parse_failed:
00650 {
00651 _dbus_warn ("couldn't process line %d \"%s\"\n",
00652 line_no, _dbus_string_get_const_data (&line));
00653 goto out;
00654 }
00655 }
00656
00657 if (auth != NULL &&
00658 state == DBUS_AUTH_STATE_AUTHENTICATED)
00659 {
00660 const DBusString *unused;
00661
00662 _dbus_auth_get_unused_bytes (auth, &unused);
00663
00664 if (_dbus_string_get_length (unused) > 0)
00665 {
00666 _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
00667 goto out;
00668 }
00669 }
00670
00671 if (_dbus_string_get_length (&from_auth) > 0)
00672 {
00673 _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
00674 _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
00675 goto out;
00676 }
00677
00678 retval = TRUE;
00679
00680 out:
00681 if (auth)
00682 _dbus_auth_unref (auth);
00683
00684 _dbus_string_free (&file);
00685 _dbus_string_free (&line);
00686 _dbus_string_free (&from_auth);
00687
00688 return retval;
00689 }
00690
00692 #endif