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