Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-auth-script.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-auth-script.c Test DBusAuth using a special script file (internal to D-BUS implementation) 00003 * 00004 * Copyright (C) 2003 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 /* this is slightly different from the other append_quoted_string 00047 * in dbus-message-builder.c 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; /* end on whitespace if not quoted */ 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 /* empty line */ 00294 goto next_iteration; 00295 } 00296 else if (_dbus_string_starts_with_c_str (&line, 00297 "#")) 00298 { 00299 /* Ignore this comment */ 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 /* test ref/unref */ 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 /* test ref/unref */ 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 /* Replace USERID_HEX with our username in hex */ 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; /* skip parse_failed */ 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 /* DBUS_BUILD_TESTS */

Generated on Tue Oct 12 02:07:52 2004 for D-BUS by doxygen 1.3.7