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.0
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_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           /* empty line */
00255           goto next_iteration;
00256         }
00257       else if (_dbus_string_starts_with_c_str (&line,
00258                                                "#"))
00259         {
00260           /* Ignore this comment */
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           /* test ref/unref */
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           /* test ref/unref */
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           /* Replace USERID_BASE64 with our username in base64 */
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; /* skip parse_failed */
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 /* DBUS_BUILD_TESTS */

Generated on Sun Mar 21 03:52:03 2004 for D-BUS by doxygen 1.3.6-20040222