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