Main Page | Modules | Data Structures | Directories | 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 Wed Mar 30 21:15:19 2005 for D-BUS by  doxygen 1.4.1