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