Merge branch 'dbus-1.10'
[platform/upstream/dbus.git] / dbus / dbus-auth-script.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-auth-script.c Test DBusAuth using a special script file (internal to D-Bus implementation)
3  * 
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 #include <config.h>
24
25 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
26
27 #include "dbus-auth-script.h"
28
29 #include <stdio.h>
30
31 #include "dbus-auth.h"
32 #include "dbus-string.h"
33 #include "dbus-hash.h"
34 #include "dbus-credentials.h"
35 #include "dbus-internals.h"
36
37 /**
38  * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
39  * @ingroup  DBusInternals
40  * @brief DBusAuth unit test scripting
41  *
42  * The code in here is used for unit testing, it loads
43  * up a script that tests DBusAuth.
44  *
45  * @{
46  */
47
48 /* this is slightly different from the other append_quoted_string
49  * in dbus-message-builder.c
50  */
51 static dbus_bool_t
52 append_quoted_string (DBusString       *dest,
53                       const DBusString *quoted)
54 {
55   dbus_bool_t in_quotes = FALSE;
56   dbus_bool_t in_backslash = FALSE;
57   int i;
58
59   i = 0;
60   while (i < _dbus_string_get_length (quoted))
61     {
62       unsigned char b;
63
64       b = _dbus_string_get_byte (quoted, i);
65
66       if (in_backslash)
67         {
68           unsigned char a;
69           
70           if (b == 'r')
71             a = '\r';
72           else if (b == 'n')
73             a = '\n';
74           else if (b == '\\')
75             a = '\\';
76           else
77             {
78               _dbus_warn ("bad backslashed byte %c\n", b);
79               return FALSE;
80             }
81
82           if (!_dbus_string_append_byte (dest, a))
83             return FALSE;
84           
85           in_backslash = FALSE;
86         }
87       else if (b == '\\')
88         {
89           in_backslash = TRUE;
90         }
91       else if (in_quotes)
92         {
93           if (b == '\'')
94             in_quotes = FALSE;
95           else
96             {
97               if (!_dbus_string_append_byte (dest, b))
98                 return FALSE;
99             }
100         }
101       else
102         {
103           if (b == '\'')
104             in_quotes = TRUE;
105           else if (b == ' ' || b == '\n' || b == '\t')
106             break; /* end on whitespace if not quoted */
107           else
108             {
109               if (!_dbus_string_append_byte (dest, b))
110                 return FALSE;
111             }
112         }
113       
114       ++i;
115     }
116
117   return TRUE;
118 }
119
120 static dbus_bool_t
121 same_first_word (const DBusString *a,
122                  const DBusString *b)
123 {
124   int first_a_blank, first_b_blank;
125
126   _dbus_string_find_blank (a, 0, &first_a_blank);
127   _dbus_string_find_blank (b, 0, &first_b_blank);
128
129   if (first_a_blank != first_b_blank)
130     return FALSE;
131
132   return _dbus_string_equal_len (a, b, first_a_blank);
133 }
134
135 static DBusAuthState
136 auth_state_from_string (const DBusString *str)
137
138   if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT"))
139     return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
140   else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY"))
141     return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
142   else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND"))
143     return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
144   else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT"))
145     return DBUS_AUTH_STATE_NEED_DISCONNECT;
146   else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
147     return DBUS_AUTH_STATE_AUTHENTICATED;
148   else
149     return -1;
150 }
151
152 static const char*
153 auth_state_to_string (DBusAuthState state)
154 {
155   switch (state)
156     {
157     case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
158       return "WAITING_FOR_INPUT";
159     case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
160       return "WAITING_FOR_MEMORY";
161     case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
162       return "HAVE_BYTES_TO_SEND";
163     case DBUS_AUTH_STATE_NEED_DISCONNECT:
164       return "NEED_DISCONNECT";
165     case DBUS_AUTH_STATE_AUTHENTICATED:
166       return "AUTHENTICATED";
167     }
168
169   return "unknown";
170 }
171
172 static char **
173 split_string (DBusString *str)
174 {
175   int i, j, k, count, end;
176   char **array;
177
178   end = _dbus_string_get_length (str);
179
180   i = 0;
181   _dbus_string_skip_blank (str, i, &i);
182   for (count = 0; i < end; count++)
183     {
184       _dbus_string_find_blank (str, i, &i);
185       _dbus_string_skip_blank (str, i, &i);
186     }
187
188   array = dbus_new0 (char *, count + 1);
189   if (array == NULL)
190     return NULL;
191
192   i = 0;
193   _dbus_string_skip_blank (str, i, &i);
194   for (k = 0; k < count; k++)
195     {
196       _dbus_string_find_blank (str, i, &j);
197
198       array[k] = dbus_malloc (j - i + 1);
199       if (array[k] == NULL)
200         {
201           dbus_free_string_array (array);
202           return NULL;
203         }
204       memcpy (array[k],
205               _dbus_string_get_const_data_len (str, i, j - i), j - i);
206       array[k][j - i] = '\0';
207
208       _dbus_string_skip_blank (str, j, &i);
209     }
210   array[k] = NULL;
211
212   return array;
213 }
214
215 static void
216 auth_set_unix_credentials(DBusAuth  *auth,
217                           dbus_uid_t uid,
218                           dbus_pid_t pid)
219 {
220   DBusCredentials *credentials;
221
222   credentials = _dbus_credentials_new ();
223   if (credentials == NULL)
224     _dbus_assert_not_reached ("no memory");
225
226   if (uid != DBUS_UID_UNSET)
227     {
228       if (!_dbus_credentials_add_unix_uid (credentials, uid))
229         _dbus_assert_not_reached ("no memory");
230     }
231   if (pid != DBUS_PID_UNSET)
232     {
233       if (!_dbus_credentials_add_pid (credentials, pid))
234         _dbus_assert_not_reached ("no memory");
235     }
236   _dbus_auth_set_credentials (auth, credentials);
237
238   _dbus_credentials_unref (credentials);
239 }
240
241 /**
242  * Runs an "auth script" which is a script for testing the
243  * authentication protocol. Scripts send and receive data, and then
244  * include assertions about the state of both ends of the connection
245  * after processing the data. A script succeeds if these assertions
246  * hold.
247  *
248  * @param filename the file containing the script to run
249  * @returns #TRUE if the script succeeds, #FALSE otherwise
250  */
251 dbus_bool_t
252 _dbus_auth_script_run (const DBusString *filename)
253 {
254   DBusString file;
255   DBusError error = DBUS_ERROR_INIT;
256   DBusString line;
257   dbus_bool_t retval;
258   int line_no;
259   DBusAuth *auth;
260   DBusString from_auth;
261   DBusAuthState state;
262   DBusString context;
263   DBusString guid;
264   
265   retval = FALSE;
266   auth = NULL;
267
268   _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
269   _dbus_string_init_const (&context, "org_freedesktop_test");
270   
271   if (!_dbus_string_init (&file))
272     return FALSE;
273
274   if (!_dbus_string_init (&line))
275     {
276       _dbus_string_free (&file);
277       return FALSE;
278     }
279
280   if (!_dbus_string_init (&from_auth))
281     {
282       _dbus_string_free (&file);
283       _dbus_string_free (&line);
284       return FALSE;
285     }
286
287   if (!_dbus_file_get_contents (&file, filename, &error))    {
288       _dbus_warn ("Getting contents of %s failed: %s\n",
289                   _dbus_string_get_const_data (filename), error.message);
290       dbus_error_free (&error);
291       goto out;
292     }
293
294   state = DBUS_AUTH_STATE_NEED_DISCONNECT;
295   line_no = 0;
296
297  next_iteration:
298   while (_dbus_string_pop_line (&file, &line))
299     {      
300       line_no += 1;
301
302       /* _dbus_warn ("%s\n", _dbus_string_get_const_data (&line)); */
303       
304       _dbus_string_delete_leading_blanks (&line);
305
306       if (auth != NULL)
307         {
308           while ((state = _dbus_auth_do_work (auth)) ==
309                  DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
310             {
311               const DBusString *tmp;
312               if (_dbus_auth_get_bytes_to_send (auth, &tmp))
313                 {
314                   int count = _dbus_string_get_length (tmp);
315
316                   if (_dbus_string_copy (tmp, 0, &from_auth,
317                                          _dbus_string_get_length (&from_auth)))
318                     _dbus_auth_bytes_sent (auth, count);
319                 }
320             }
321         }
322       
323       if (_dbus_string_get_length (&line) == 0)
324         {
325           /* empty line */
326           goto next_iteration;
327         }
328       else if (_dbus_string_starts_with_c_str (&line,
329                                                "#"))
330         {
331           /* Ignore this comment */
332           goto next_iteration;
333         }
334 #ifdef DBUS_WIN
335       else if (_dbus_string_starts_with_c_str (&line,
336                                                "WIN_ONLY"))
337         {
338           /* Ignore this line */
339           goto next_iteration;
340         }
341       else if (_dbus_string_starts_with_c_str (&line,
342                                                "UNIX_ONLY"))
343         {
344           /* skip this file */
345           fprintf (stderr, "skipping unix only auth script\n");
346           retval = TRUE;
347           goto out;
348         }
349 #endif
350 #ifdef DBUS_UNIX
351       else if (_dbus_string_starts_with_c_str (&line,
352                                                "UNIX_ONLY"))
353         {
354           /* Ignore this line */
355           goto next_iteration;
356         }
357       else if (_dbus_string_starts_with_c_str (&line,
358                                                "WIN_ONLY"))
359         {
360           /* skip this file */
361           fprintf (stderr, "skipping windows only auth script\n");
362           retval = TRUE;
363           goto out;
364         }
365 #endif
366       else if (_dbus_string_starts_with_c_str (&line,
367                                                "CLIENT"))
368         {
369           DBusCredentials *creds;
370           
371           if (auth != NULL)
372             {
373               _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
374               goto out;
375             }
376
377           auth = _dbus_auth_client_new ();
378           if (auth == NULL)
379             {
380               _dbus_warn ("no memory to create DBusAuth\n");
381               goto out;
382             }
383
384           /* test ref/unref */
385           _dbus_auth_ref (auth);
386           _dbus_auth_unref (auth);
387
388           creds = _dbus_credentials_new_from_current_process ();
389           if (creds == NULL)
390             {
391               _dbus_warn ("no memory for credentials\n");
392               _dbus_auth_unref (auth);
393               auth = NULL;
394               goto out;
395             }
396               
397           if (!_dbus_auth_set_credentials (auth, creds))
398             {
399               _dbus_warn ("no memory for setting credentials\n");
400               _dbus_auth_unref (auth);
401               auth = NULL;
402               _dbus_credentials_unref (creds);
403               goto out;
404             }
405           
406           _dbus_credentials_unref (creds);
407         }
408       else if (_dbus_string_starts_with_c_str (&line,
409                                                "SERVER"))
410         {
411           DBusCredentials *creds;
412           
413           if (auth != NULL)
414             {
415               _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
416               goto out;
417             }
418
419           auth = _dbus_auth_server_new (&guid);
420           if (auth == NULL)
421             {
422               _dbus_warn ("no memory to create DBusAuth\n");
423               goto out;
424             }
425
426           /* test ref/unref */
427           _dbus_auth_ref (auth);
428           _dbus_auth_unref (auth);
429
430           creds = _dbus_credentials_new_from_current_process ();
431           if (creds == NULL)
432             {
433               _dbus_warn ("no memory for credentials\n");
434               _dbus_auth_unref (auth);
435               auth = NULL;
436               goto out;
437             }
438               
439           if (!_dbus_auth_set_credentials (auth, creds))
440             {
441               _dbus_warn ("no memory for setting credentials\n");
442               _dbus_auth_unref (auth);
443               auth = NULL;
444               _dbus_credentials_unref (creds);
445               goto out;
446             }
447           
448           _dbus_credentials_unref (creds);
449
450           _dbus_auth_set_context (auth, &context);
451         }
452       else if (auth == NULL)
453         {
454           _dbus_warn ("must specify CLIENT or SERVER\n");
455           goto out;
456
457         }
458       else if (_dbus_string_starts_with_c_str (&line,
459                                                "NO_CREDENTIALS"))
460         {
461           auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
462         }
463       else if (_dbus_string_starts_with_c_str (&line,
464                                                "ROOT_CREDENTIALS"))
465         {
466           auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
467         }
468       else if (_dbus_string_starts_with_c_str (&line,
469                                                "SILLY_CREDENTIALS"))
470         {
471           auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
472         }
473       else if (_dbus_string_starts_with_c_str (&line,
474                                                "ALLOWED_MECHS"))
475         {
476           char **mechs;
477
478           _dbus_string_delete_first_word (&line);
479           mechs = split_string (&line);
480           _dbus_auth_set_mechanisms (auth, (const char **) mechs);
481           dbus_free_string_array (mechs);
482         }
483       else if (_dbus_string_starts_with_c_str (&line,
484                                                "SEND"))
485         {
486           DBusString to_send;
487           
488           _dbus_string_delete_first_word (&line);
489
490           if (!_dbus_string_init (&to_send))
491             {
492               _dbus_warn ("no memory to allocate string\n");
493               goto out;
494             }
495
496           if (!append_quoted_string (&to_send, &line))
497             {
498               _dbus_warn ("failed to append quoted string line %d\n",
499                           line_no);
500               _dbus_string_free (&to_send);
501               goto out;
502             }
503
504           _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
505           
506           if (!_dbus_string_append (&to_send, "\r\n"))
507             {
508               _dbus_warn ("failed to append \r\n from line %d\n",
509                           line_no);
510               _dbus_string_free (&to_send);
511               goto out;
512             }
513
514           /* Replace USERID_HEX with our username in hex */
515           {
516             int where;
517             
518             if (_dbus_string_find (&to_send, 0,
519                                    "USERID_HEX", &where))
520               {
521                 DBusString username;
522
523                 if (!_dbus_string_init (&username))
524                   {
525                     _dbus_warn ("no memory for userid\n");
526                     _dbus_string_free (&to_send);
527                     goto out;
528                   }
529
530                 if (!_dbus_append_user_from_current_process (&username))
531                   {
532                     _dbus_warn ("no memory for userid\n");
533                     _dbus_string_free (&username);
534                     _dbus_string_free (&to_send);
535                     goto out;
536                   }
537
538                 _dbus_string_delete (&to_send, where, (int) strlen ("USERID_HEX"));
539                 
540                 if (!_dbus_string_hex_encode (&username, 0,
541                                               &to_send, where))
542                   {
543                     _dbus_warn ("no memory to subst USERID_HEX\n");
544                     _dbus_string_free (&username);
545                     _dbus_string_free (&to_send);
546                     goto out;
547                   }
548
549                 _dbus_string_free (&username);
550               }
551             else if (_dbus_string_find (&to_send, 0,
552                                         "USERNAME_HEX", &where))
553               {
554                 DBusString username;
555                 
556                 if (!_dbus_string_init (&username))
557                   {
558                     _dbus_warn ("no memory for username\n");
559                     _dbus_string_free (&to_send);
560                     goto out;
561                   }
562
563                 if (!_dbus_append_user_from_current_process (&username))
564                   {
565                     _dbus_warn ("no memory for username\n");
566                     _dbus_string_free (&username);
567                     _dbus_string_free (&to_send);
568                     goto out;
569                   }
570
571                 _dbus_string_delete (&to_send, where, (int) strlen ("USERNAME_HEX"));
572                 
573                 if (!_dbus_string_hex_encode (&username, 0,
574                                               &to_send, where))
575                   {
576                     _dbus_warn ("no memory to subst USERNAME_HEX\n");
577                     _dbus_string_free (&username);
578                     _dbus_string_free (&to_send);
579                     goto out;
580                   }
581
582                 _dbus_string_free (&username);
583               }
584           }
585
586           {
587             DBusString *buffer;
588
589             _dbus_auth_get_buffer (auth, &buffer);
590             if (!_dbus_string_copy (&to_send, 0,
591                                     buffer, _dbus_string_get_length (buffer)))
592               {
593                 _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
594                 _dbus_string_free (&to_send);
595                 _dbus_auth_return_buffer (auth, buffer);
596                 goto out;
597               }
598
599             _dbus_auth_return_buffer (auth, buffer);
600           }
601           
602           _dbus_string_free (&to_send);
603         }
604       else if (_dbus_string_starts_with_c_str (&line,
605                                                "EXPECT_STATE"))
606         {
607           DBusAuthState expected;
608           
609           _dbus_string_delete_first_word (&line);
610
611           expected = auth_state_from_string (&line);
612           if (expected < 0)
613             {
614               _dbus_warn ("bad auth state given to EXPECT_STATE\n");
615               goto parse_failed;
616             }
617
618           if (expected != state)
619             {
620               _dbus_warn ("expected auth state %s but got %s on line %d\n",
621                           auth_state_to_string (expected),
622                           auth_state_to_string (state),
623                           line_no);
624               goto out;
625             }
626         }
627       else if (_dbus_string_starts_with_c_str (&line,
628                                                "EXPECT_COMMAND"))
629         {
630           DBusString received;
631           
632           _dbus_string_delete_first_word (&line);
633
634           if (!_dbus_string_init (&received))
635             {
636               _dbus_warn ("no mem to allocate string received\n");
637               goto out;
638             }
639
640           if (!_dbus_string_pop_line (&from_auth, &received))
641             {
642               _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
643                           _dbus_string_get_const_data (&line), line_no);
644               _dbus_string_free (&received);
645               goto out;
646             }
647
648           if (!same_first_word (&received, &line))
649             {
650               _dbus_warn ("line %d expected command '%s' and got '%s'\n",
651                           line_no,
652                           _dbus_string_get_const_data (&line),
653                           _dbus_string_get_const_data (&received));
654               _dbus_string_free (&received);
655               goto out;
656             }
657           
658           _dbus_string_free (&received);
659         }
660       else if (_dbus_string_starts_with_c_str (&line,
661                                                "EXPECT_UNUSED"))
662         {
663           DBusString expected;
664           const DBusString *unused;
665           
666           _dbus_string_delete_first_word (&line);
667
668           if (!_dbus_string_init (&expected))
669             {
670               _dbus_warn ("no mem to allocate string expected\n");
671               goto out;
672             }
673
674           if (!append_quoted_string (&expected, &line))
675             {
676               _dbus_warn ("failed to append quoted string line %d\n",
677                           line_no);
678               _dbus_string_free (&expected);
679               goto out;
680             }
681
682           _dbus_auth_get_unused_bytes (auth, &unused);
683           
684           if (_dbus_string_equal (&expected, unused))
685             {
686               _dbus_auth_delete_unused_bytes (auth);
687               _dbus_string_free (&expected);
688             }
689           else
690             {
691               _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
692                           _dbus_string_get_const_data (&expected),
693                           _dbus_string_get_const_data (unused));
694               _dbus_string_free (&expected);
695               goto out;
696             }
697         }
698       else if (_dbus_string_starts_with_c_str (&line,
699                                                "EXPECT_HAVE_NO_CREDENTIALS"))
700         {
701           DBusCredentials *authorized_identity;
702           
703           authorized_identity = _dbus_auth_get_identity (auth);
704           if (!_dbus_credentials_are_anonymous (authorized_identity))
705             {
706               _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
707               goto out;
708             }
709         }
710       else if (_dbus_string_starts_with_c_str (&line,
711                                                "EXPECT_HAVE_SOME_CREDENTIALS"))
712         {
713           DBusCredentials *authorized_identity;
714           
715           authorized_identity = _dbus_auth_get_identity (auth);
716           if (_dbus_credentials_are_anonymous (authorized_identity))
717             {
718               _dbus_warn ("Expected to have some credentials, but we don't\n");
719               goto out;
720             }
721         }
722       else if (_dbus_string_starts_with_c_str (&line,
723                                                "EXPECT"))
724         {
725           DBusString expected;
726           
727           _dbus_string_delete_first_word (&line);
728
729           if (!_dbus_string_init (&expected))
730             {
731               _dbus_warn ("no mem to allocate string expected\n");
732               goto out;
733             }
734
735           if (!append_quoted_string (&expected, &line))
736             {
737               _dbus_warn ("failed to append quoted string line %d\n",
738                           line_no);
739               _dbus_string_free (&expected);
740               goto out;
741             }
742
743           if (_dbus_string_equal_len (&expected, &from_auth,
744                                       _dbus_string_get_length (&expected)))
745             {
746               _dbus_string_delete (&from_auth, 0,
747                                    _dbus_string_get_length (&expected));
748               _dbus_string_free (&expected);
749             }
750           else
751             {
752               _dbus_warn ("Expected exact string '%s' and have '%s'\n",
753                           _dbus_string_get_const_data (&expected),
754                           _dbus_string_get_const_data (&from_auth));
755               _dbus_string_free (&expected);
756               goto out;
757             }
758         }
759       else
760         goto parse_failed;
761
762       goto next_iteration; /* skip parse_failed */
763       
764     parse_failed:
765       {
766         _dbus_warn ("couldn't process line %d \"%s\"\n",
767                     line_no, _dbus_string_get_const_data (&line));
768         goto out;
769       }
770     }
771
772   if (auth == NULL)
773     {
774       _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
775       goto out;
776     }
777   else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
778     {
779       const DBusString *unused;
780
781       _dbus_auth_get_unused_bytes (auth, &unused);
782
783       if (_dbus_string_get_length (unused) > 0)
784         {
785           _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
786           goto out;
787         }
788     }
789
790   if (_dbus_string_get_length (&from_auth) > 0)
791     {
792       _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
793       _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
794       goto out;
795     }
796   
797   retval = TRUE;
798   
799  out:
800   if (auth)
801     _dbus_auth_unref (auth);
802
803   _dbus_string_free (&file);
804   _dbus_string_free (&line);
805   _dbus_string_free (&from_auth);
806   
807   return retval;
808 }
809
810 /** @} */
811 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */