1 /*****************************************************************************
2 * kwallet.c: KWallet keystore module
3 *****************************************************************************
4 * Copyright © 2015-2016 VLC authors, VideoLAN and VideoLabs
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
25 #include <vlc_common.h>
26 #include <vlc_keystore.h>
28 #include <vlc_plugin.h>
29 #include <vlc_strings.h>
30 #include <vlc_interrupt.h>
31 #include <vlc_memstream.h>
33 #include <dbus/dbus.h>
44 static int Open( vlc_object_t
* );
45 static void Close( vlc_object_t
* );
48 set_shortname( N_("KWallet keystore") )
49 set_description( N_("Secrets are stored via KWallet") )
50 set_category( CAT_ADVANCED
)
51 set_subcategory( SUBCAT_ADVANCED_MISC
)
52 set_capability( "keystore", 100 )
53 set_callbacks( Open
, Close
)
56 /* kwallet is the kde keyring. *
57 * There are several entry categories, *
58 * but we only use the "Password" category. *
59 * It is juste a simple Entry name ( or key ) *
60 * associated with a secret. *
61 * Keys are urls formated with : *
63 * _ User ( optional ) *
65 * _ Port ( optional ) *
66 * _ Path ( optional ) *
67 * _ Realm ( binary encrypted ) ( optional ) *
68 * _ Authtype ( binary encrypted ) ( optional ) *
69 * Secrets are binary encrypted strings */
71 static const char* psz_folder
= VLC_KEYSTORE_NAME
;
72 static const char* psz_kwallet_interface
= "org.kde.KWallet";
74 #define DBUS_INSTANCE_PREFIX "instance"
75 #define KWALLET_APP_ID "org.videolan.kwallet"
78 * There are two kwallet services :
79 * kwallet and kwallet5 */
81 /* These services have the same interfaces and methods *
82 * but not the same addresses and paths */
91 static const char *ppsz_sAddr
[SERVICE_MAX
] = {
96 static const char *ppsz_sPath
[SERVICE_MAX
] = {
101 typedef struct vlc_keystore_sys
103 DBusConnection
* connection
;
104 int i_sid
; /* service ID */
110 /* takes all values in the values of vlc_keystore_entry *
111 * and formats them in a url key */
113 values2key( const char* const* ppsz_values
, bool b_search
)
115 char* psz_b64_realm
= NULL
;
116 char* psz_b64_auth
= NULL
;
117 bool b_state
= false;
119 if ( ( !ppsz_values
[KEY_PROTOCOL
] || !ppsz_values
[KEY_SERVER
] )
123 struct vlc_memstream ms
;
124 if ( vlc_memstream_open( &ms
) )
127 /* Protocol section */
128 if ( ppsz_values
[KEY_PROTOCOL
] )
129 vlc_memstream_printf( &ms
, "%s://", ppsz_values
[KEY_PROTOCOL
] );
131 vlc_memstream_printf( &ms
, "*://" );
134 if ( ppsz_values
[KEY_USER
] )
135 vlc_memstream_printf( &ms
, "%s@", ppsz_values
[KEY_USER
] );
137 vlc_memstream_printf( &ms
, "*" );
140 if ( ppsz_values
[KEY_SERVER
] )
141 vlc_memstream_printf( &ms
, "%s", ppsz_values
[KEY_SERVER
] );
143 vlc_memstream_printf( &ms
, "*" );
146 if ( ppsz_values
[KEY_PORT
] )
147 vlc_memstream_printf( &ms
, ":%s", ppsz_values
[KEY_PORT
] );
149 vlc_memstream_printf( &ms
, "*" );
152 if( ppsz_values
[KEY_PATH
] )
154 if( ppsz_values
[KEY_PATH
][0] != '/' )
155 vlc_memstream_putc( &ms
, '/' );
157 vlc_memstream_puts( &ms
, ppsz_values
[KEY_PATH
] );
160 vlc_memstream_printf( &ms
, "*" );
162 /* Realm and authtype section */
163 if ( ppsz_values
[KEY_REALM
] || ppsz_values
[KEY_AUTHTYPE
] || b_search
)
165 vlc_memstream_printf( &ms
, "?" );
168 if ( ppsz_values
[KEY_REALM
] || b_search
)
170 if ( ppsz_values
[KEY_REALM
] )
172 psz_b64_realm
= vlc_b64_encode_binary( ( uint8_t* )ppsz_values
[KEY_REALM
],
173 strlen(ppsz_values
[KEY_REALM
] ) );
174 if ( !psz_b64_realm
)
176 vlc_memstream_printf( &ms
, "realm=%s", psz_b64_realm
);
179 vlc_memstream_printf( &ms
, "*" );
181 if ( ppsz_values
[KEY_AUTHTYPE
] )
182 vlc_memstream_printf( &ms
, "&" );
185 /* Authtype section */
186 if ( ppsz_values
[KEY_AUTHTYPE
] || b_search
)
189 if ( ppsz_values
[KEY_AUTHTYPE
] )
191 psz_b64_auth
= vlc_b64_encode_binary( ( uint8_t* )ppsz_values
[KEY_AUTHTYPE
],
192 strlen(ppsz_values
[KEY_AUTHTYPE
] ) );
195 vlc_memstream_printf( &ms
, "authtype=%s", psz_b64_auth
);
198 vlc_memstream_printf( &ms
, "*" );
206 free( psz_b64_realm
);
207 free( psz_b64_auth
);
208 if ( vlc_memstream_flush( &ms
) != 0 )
210 char *psz_key
= vlc_memstream_close( &ms
) == 0 ? ms
.ptr
: NULL
;
219 /* Take an url key and splits it into vlc_keystore_entry values */
221 key2values( char* psz_key
, vlc_keystore_entry
* p_entry
)
224 int i_ret
= VLC_ENOMEM
;
226 for ( int inc
= 0 ; inc
< KEY_MAX
; ++inc
)
227 p_entry
->ppsz_values
[inc
] = NULL
;
229 vlc_UrlParse( &url
, psz_key
);
231 if ( url
.psz_protocol
&& !( p_entry
->ppsz_values
[KEY_PROTOCOL
] =
232 strdup( url
.psz_protocol
) ) )
234 if ( url
.psz_username
&& !( p_entry
->ppsz_values
[KEY_USER
] =
235 strdup( url
.psz_username
) ) )
237 if ( url
.psz_host
&& !( p_entry
->ppsz_values
[KEY_SERVER
] =
238 strdup( url
.psz_host
) ) )
240 if ( url
.i_port
&& asprintf( &p_entry
->ppsz_values
[KEY_PORT
],
241 "%d", url
.i_port
) == -1 )
243 if ( url
.psz_path
&& !( p_entry
->ppsz_values
[KEY_PATH
] =
244 strdup( url
.psz_path
) ) )
246 if ( url
.psz_option
)
250 for ( const char *psz_option
= strtok_r( url
.psz_option
, "&", &p_savetpr
);
252 psz_option
= strtok_r( NULL
, "&", &p_savetpr
) )
254 enum vlc_keystore_key key
;
255 const char *psz_value
;
257 if ( !strncmp( psz_option
, "realm=", strlen( "realm=" ) ) )
260 psz_value
= psz_option
+ strlen( "realm=" );
262 else if ( !strncmp( psz_option
, "authtype=", strlen( "authtype=" ) ) )
265 psz_value
= psz_option
+ strlen( "authtype=" );
270 if ( psz_value
!= NULL
)
272 p_entry
->ppsz_values
[key
] = vlc_b64_decode( psz_value
);
273 if ( !p_entry
->ppsz_values
[key
] )
282 vlc_UrlClean( &url
);
285 free( p_entry
->ppsz_values
[KEY_PROTOCOL
] );
286 free( p_entry
->ppsz_values
[KEY_USER
] );
287 free( p_entry
->ppsz_values
[KEY_SERVER
] );
288 free( p_entry
->ppsz_values
[KEY_PORT
] );
289 free( p_entry
->ppsz_values
[KEY_PATH
] );
290 free( p_entry
->ppsz_values
[KEY_REALM
] );
291 free ( p_entry
->ppsz_values
[KEY_AUTHTYPE
] );
297 vlc_dbus_new_method( vlc_keystore
* p_keystore
, const char* psz_method
)
299 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
302 msg
= dbus_message_new_method_call( ppsz_sAddr
[p_sys
->i_sid
],
303 ppsz_sPath
[p_sys
->i_sid
],
304 psz_kwallet_interface
,
308 msg_Err( p_keystore
, "vlc_dbus_new_method : Failed to create message" );
315 #define MAX_WATCHES 2
316 struct vlc_dbus_watch_data
318 struct pollfd pollfd
;
323 vlc_dbus_watch_get_poll_events( DBusWatch
*p_watch
)
325 unsigned int i_flags
= dbus_watch_get_flags( p_watch
);
328 if( i_flags
& DBUS_WATCH_READABLE
)
330 if( i_flags
& DBUS_WATCH_WRITABLE
)
335 static struct vlc_dbus_watch_data
*
336 vlc_dbus_watch_get_data( DBusWatch
*p_watch
,
337 struct vlc_dbus_watch_data
*p_ctx
)
339 for( unsigned i
= 0; i
< MAX_WATCHES
; ++i
)
341 if( p_ctx
[i
].p_watch
== NULL
|| p_ctx
[i
].p_watch
== p_watch
)
348 vlc_dbus_watch_add_function( DBusWatch
*p_watch
, void *p_data
)
350 struct vlc_dbus_watch_data
*p_ctx
= vlc_dbus_watch_get_data( p_watch
, p_data
);
355 short i_events
= POLLHUP
| POLLERR
;
357 i_events
|= vlc_dbus_watch_get_poll_events( p_watch
);
359 p_ctx
->pollfd
.fd
= dbus_watch_get_unix_fd( p_watch
);
360 p_ctx
->pollfd
.events
= i_events
;
361 p_ctx
->p_watch
= p_watch
;
366 vlc_dbus_watch_toggled_function( DBusWatch
*p_watch
, void *p_data
)
368 struct vlc_dbus_watch_data
*p_ctx
= vlc_dbus_watch_get_data( p_watch
, p_data
);
369 short i_events
= vlc_dbus_watch_get_poll_events( p_watch
);
371 if( dbus_watch_get_enabled( p_watch
) )
372 p_ctx
->pollfd
.events
|= i_events
;
374 p_ctx
->pollfd
.events
&= ~i_events
;
378 vlc_dbus_pending_call_notify( DBusPendingCall
*p_pending_call
, void *p_data
)
380 DBusMessage
**pp_repmsg
= p_data
;
381 *pp_repmsg
= dbus_pending_call_steal_reply( p_pending_call
);
385 vlc_dbus_send_message( vlc_keystore
* p_keystore
, DBusMessage
* p_msg
)
387 vlc_keystore_sys
*p_sys
= p_keystore
->p_sys
;
388 DBusMessage
*p_repmsg
= NULL
;
389 DBusPendingCall
*p_pending_call
= NULL
;
391 struct vlc_dbus_watch_data watch_ctx
[MAX_WATCHES
] = {};
393 for( unsigned i
= 0; i
< MAX_WATCHES
; ++i
)
394 watch_ctx
[i
].pollfd
.fd
= -1;
396 if( !dbus_connection_set_watch_functions( p_sys
->connection
,
397 vlc_dbus_watch_add_function
,
399 vlc_dbus_watch_toggled_function
,
403 if( !dbus_connection_send_with_reply( p_sys
->connection
, p_msg
,
405 DBUS_TIMEOUT_INFINITE
) )
408 if( !dbus_pending_call_set_notify( p_pending_call
,
409 vlc_dbus_pending_call_notify
,
413 while( p_repmsg
== NULL
)
416 struct pollfd pollfds
[MAX_WATCHES
];
418 for( unsigned i
= 0; i
< MAX_WATCHES
; ++i
)
420 if( watch_ctx
[i
].pollfd
.fd
== -1 )
422 pollfds
[i
].fd
= watch_ctx
[i
].pollfd
.fd
;
423 pollfds
[i
].events
= watch_ctx
[i
].pollfd
.events
;
424 pollfds
[i
].revents
= 0;
429 msg_Err( p_keystore
, "vlc_dbus_send_message: watch functions not called" );
432 if( vlc_poll_i11e( pollfds
, nfds
, -1 ) <= 0 )
435 msg_Dbg( p_keystore
, "vlc_dbus_send_message: poll was interrupted" );
437 msg_Err( p_keystore
, "vlc_dbus_send_message: poll failed" );
440 for( int i
= 0; i
< nfds
; ++ i
)
442 short i_events
= pollfds
[i
].revents
;
445 unsigned i_flags
= 0;
446 if( i_events
& POLLIN
)
447 i_flags
|= DBUS_WATCH_READABLE
;
448 if( i_events
& POLLOUT
)
449 i_flags
|= DBUS_WATCH_WRITABLE
;
450 if( i_events
& POLLHUP
)
451 i_flags
|= DBUS_WATCH_HANGUP
;
452 if( i_events
& POLLERR
)
453 i_flags
|= DBUS_WATCH_ERROR
;
454 if( !dbus_watch_handle( watch_ctx
[i
].p_watch
, i_flags
) )
458 DBusDispatchStatus status
;
459 while( ( status
= dbus_connection_dispatch( p_sys
->connection
) )
460 == DBUS_DISPATCH_DATA_REMAINS
);
461 if( status
== DBUS_DISPATCH_NEED_MEMORY
)
466 dbus_connection_set_watch_functions( p_sys
->connection
, NULL
, NULL
,
468 if( p_pending_call
!= NULL
)
470 if( p_repmsg
!= NULL
)
471 dbus_pending_call_cancel( p_pending_call
);
472 dbus_pending_call_unref( p_pending_call
);
479 kwallet_network_wallet( vlc_keystore
* p_keystore
)
481 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
482 DBusMessage
* msg
= NULL
;
483 DBusMessage
* repmsg
= NULL
;
486 int i_ret
= VLC_EGENERIC
;
489 msg
= vlc_dbus_new_method( p_keystore
, "networkWallet" );
492 msg_Err( p_keystore
, "kwallet_network_wallet : vlc_dbus_new_method failed" );
496 /* sending message */
497 repmsg
= vlc_dbus_send_message( p_keystore
, msg
);
500 msg_Err( p_keystore
, "kwallet_network_wallet : vlc_dbus_send_message failed" );
505 dbus_error_init( &error
);
506 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_STRING
,
507 &psz_reply
, DBUS_TYPE_INVALID
) )
509 msg_Err( p_keystore
, "kwallet_network_wallet : "
510 "dbus_message_get_args failed\n%s", error
.message
);
511 dbus_error_free( &error
);
515 p_sys
->psz_wallet
= strdup( psz_reply
);
516 if ( !p_sys
->psz_wallet
)
527 dbus_message_unref( msg
);
529 dbus_message_unref( repmsg
);
535 kwallet_is_enabled( vlc_keystore
* p_keystore
, int i_sid
, bool* b_is_enabled
)
537 VLC_UNUSED( p_keystore
);
538 DBusMessage
* msg
= NULL
;
539 DBusMessage
* repmsg
= NULL
;
540 DBusMessageIter args
;
543 int i_ret
= VLC_EGENERIC
;
546 msg
= dbus_message_new_method_call( "org.freedesktop.DBus",
548 "org.freedesktop.DBus",
552 msg_Err( p_keystore
, "vlc_dbus_new_method : Failed to create message" );
557 dbus_message_iter_init_append( msg
, &args
);
558 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &ppsz_sAddr
[i_sid
] ) )
561 /* sending message */
562 repmsg
= vlc_dbus_send_message( p_keystore
, msg
);
565 msg_Err( p_keystore
, "kwallet_is_enabled : vlc_dbus_send_message failed");
570 dbus_error_init( &error
);
571 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_BOOLEAN
,
572 &b_reply
, DBUS_TYPE_INVALID
) )
574 msg_Err( p_keystore
, "kwallet_is_enabled : "
575 "dbus_message_get_args failed\n%s", error
.message
);
576 dbus_error_free( &error
);
580 *b_is_enabled
= b_reply
;
587 dbus_message_unref( msg
);
589 dbus_message_unref( repmsg
);
595 vlc_dbus_init( vlc_keystore
* p_keystore
)
597 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
601 dbus_error_init( &error
);
603 /* DBus Connection */
604 p_sys
->connection
= dbus_bus_get_private( DBUS_BUS_SESSION
, &error
);
605 if ( dbus_error_is_set( &error
) )
607 msg_Dbg( p_keystore
, "vlc_dbus_init : "
608 "Connection error to session bus (%s)", error
.message
);
609 dbus_error_free( &error
);
611 if ( !p_sys
->connection
)
613 msg_Dbg( p_keystore
, "vlc_dbus_init : connection is NULL");
617 /* requesting name */
618 for( unsigned i
= 0; i
<= 99 && p_sys
->psz_app_id
== NULL
; ++i
)
620 char psz_dbus_name
[strlen( KWALLET_APP_ID
) + strlen( DBUS_INSTANCE_PREFIX
) + 5];
622 sprintf( psz_dbus_name
, "%s.%s_%02u", KWALLET_APP_ID
, DBUS_INSTANCE_PREFIX
, i
);
623 i_ret
= dbus_bus_request_name( p_sys
->connection
, psz_dbus_name
, 0,
625 if ( dbus_error_is_set( &error
) )
627 msg_Dbg( p_keystore
, "vlc_dbus_init : dbus_bus_request_name :"
628 " error (%s)", error
.message
);
629 dbus_error_free( &error
);
631 if ( i_ret
== DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
)
633 p_sys
->psz_app_id
= strdup( psz_dbus_name
);
634 if ( !p_sys
->psz_app_id
)
638 if ( p_sys
->psz_app_id
== NULL
)
640 msg_Dbg( p_keystore
, "vlc_dbus_init : Too many kwallet instances" );
644 /* check to see if any kwallet service is enabled */
646 for ( ; i
< SERVICE_MAX
; ++i
)
648 bool b_is_enabled
= false;
649 if ( kwallet_is_enabled( p_keystore
, i
, &b_is_enabled
) )
651 msg_Dbg( p_keystore
, "vlc_dbus_init : kwallet_is_enabled failed" );
654 if ( b_is_enabled
== true )
657 if ( i
== SERVICE_MAX
)
659 msg_Dbg( p_keystore
, "vlc_dbus_init : No kwallet service enabled" );
664 /* getting the name of the wallet assigned to network passwords */
665 if ( kwallet_network_wallet( p_keystore
) )
667 msg_Dbg(p_keystore
, "vlc_dbus_init : kwallet_network_wallet has failed");
674 FREENULL( p_sys
->psz_app_id
);
675 dbus_connection_close( p_sys
->connection
);
676 dbus_connection_unref( p_sys
->connection
);
681 kwallet_has_folder( vlc_keystore
* p_keystore
, const char* psz_folder_name
, bool *b_has_folder
)
683 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
684 DBusMessage
* msg
= NULL
;
685 DBusMessage
* repmsg
= NULL
;
687 DBusMessageIter args
;
689 int i_ret
= VLC_EGENERIC
;
692 msg
= vlc_dbus_new_method( p_keystore
, "hasFolder" );
695 msg_Err( p_keystore
, "kwallet_has_folder : vlc_dbus_new_method failed" );
700 dbus_message_iter_init_append( msg
, &args
);
701 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
702 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder_name
) ||
703 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
706 /* sending message */
707 repmsg
= vlc_dbus_send_message( p_keystore
, msg
);
710 msg_Err( p_keystore
, "kwallet_has_folder : vlc_dbus_send_message failed" );
716 dbus_error_init( &error
);
717 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_BOOLEAN
,
718 &b_reply
, DBUS_TYPE_INVALID
) )
720 msg_Err( p_keystore
, "kwallet_has_folder :"
721 " dbus_message_get_args failed\n%s", error
.message
);
722 dbus_error_free( &error
);
726 *b_has_folder
= b_reply
;
733 dbus_message_unref( msg
);
735 dbus_message_unref( repmsg
);
741 kwallet_create_folder( vlc_keystore
* p_keystore
, const char* psz_folder_name
)
743 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
744 DBusMessage
* msg
= NULL
;
745 DBusMessage
* repmsg
= NULL
;
747 DBusMessageIter args
;
749 int i_ret
= VLC_EGENERIC
;
752 msg
= vlc_dbus_new_method( p_keystore
, "createFolder" );
755 msg_Err( p_keystore
, "kwallet_create_folder : vlc_dbus_new_method failed" );
760 dbus_message_iter_init_append( msg
, &args
);
761 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
762 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder_name
) ||
763 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
766 /* sending message */
767 repmsg
= vlc_dbus_send_message( p_keystore
, msg
);
770 msg_Err( p_keystore
, "kwallet_create_folder : vlc_dbus_send_message failed" );
775 dbus_error_init( &error
);
776 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_BOOLEAN
,
777 &b_reply
, DBUS_TYPE_INVALID
) )
779 msg_Err( p_keystore
, "kwallet_create_folder :"
780 " dbus_message_get_args failed\n%s", error
.message
);
781 dbus_error_free( &error
);
787 msg_Err( p_keystore
, "kwallet_create_folder : Could not create folder" );
797 dbus_message_unref( msg
);
799 dbus_message_unref( repmsg
);
805 kwallet_open( vlc_keystore
* p_keystore
)
807 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
808 DBusMessage
* msg
= NULL
;
809 DBusMessage
* repmsg
= NULL
;
810 DBusMessageIter args
;
812 unsigned long long ull_win_id
= 0;
813 unsigned int ui_reply
= 1;
815 int i_ret
= VLC_EGENERIC
;
818 msg
= vlc_dbus_new_method( p_keystore
, "open" );
821 msg_Err( p_keystore
, "kwallet_open : vlc_dbus_new_method failed");
826 dbus_message_iter_init_append(msg
, &args
);
827 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_wallet
) ||
828 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT64
, &ull_win_id
) ||
829 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
832 /* sending message */
833 repmsg
= vlc_dbus_send_message( p_keystore
, msg
);
836 msg_Err( p_keystore
, "kwallet_open : vlc_dbus_send_message failed" );
840 /* reply arguments */
841 dbus_error_init( &error
);
842 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_INT32
,
843 &ui_reply
, DBUS_TYPE_INVALID
) )
845 msg_Err( p_keystore
, "kwallet_open :"
846 " dbus_message_get_args failed\n%s", error
.message
);
847 dbus_error_free( &error
);
850 p_sys
->i_handle
= ui_reply
;
852 /* opening the vlc password folder == VLC_KEYSTORE_NAME */
853 if ( kwallet_has_folder( p_keystore
, psz_folder
, &b_has_folder
) )
857 if ( kwallet_create_folder( p_keystore
, psz_folder
) )
859 msg_Err( p_keystore
, "kwallet_open : could not create folder %s",
870 dbus_message_unref( msg
);
872 dbus_message_unref( repmsg
);
878 kwallet_has_entry( vlc_keystore
* p_keystore
, char* psz_entry_name
, bool *b_has_entry
)
880 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
881 DBusMessage
* msg
= NULL
;
882 DBusMessage
* repmsg
= NULL
;
884 DBusMessageIter args
;
886 int i_ret
= VLC_EGENERIC
;
889 if ( !( msg
= vlc_dbus_new_method(p_keystore
, "hasEntry" ) ) )
891 msg_Err( p_keystore
, "kwallet_has_entry : vlc_dbus_new_method failed" );
896 dbus_message_iter_init_append( msg
, &args
);
897 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
898 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder
) ||
899 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_entry_name
) ||
900 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
903 /* sending message */
905 if ( !( repmsg
= vlc_dbus_send_message( p_keystore
, msg
) ) )
907 msg_Err( p_keystore
, "kwallet_has_entry : vlc_dbus_send_message failed" );
912 dbus_error_init( &error
);
913 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_BOOLEAN
,
914 &b_reply
, DBUS_TYPE_INVALID
) )
916 msg_Err( p_keystore
, "kwallet_has_entry :"
917 " dbus_message_get_args failed\n%s", error
.message
);
918 dbus_error_free( &error
);
921 *b_has_entry
= b_reply
;
928 dbus_message_unref( msg
);
930 dbus_message_unref( repmsg
);
936 kwallet_write_password( vlc_keystore
* p_keystore
, char* psz_entry_name
, const char* psz_secret
)
938 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
939 DBusMessage
* msg
= NULL
;
940 DBusMessage
* repmsg
= NULL
;
942 DBusMessageIter args
;
944 int i_ret
= VLC_EGENERIC
;
947 if ( !( msg
= vlc_dbus_new_method( p_keystore
, "writePassword" ) ) )
949 msg_Err( p_keystore
, "kwallet_write_password : vlc_dbus_new_method failed" );
954 dbus_message_iter_init_append( msg
, &args
);
955 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
956 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder
) ||
957 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_entry_name
) ||
958 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_secret
) ||
959 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
962 /* sending message */
963 if ( !( repmsg
= vlc_dbus_send_message( p_keystore
, msg
) ) )
965 msg_Err( p_keystore
, "kwallet_write_password : vlc_dbus_send_message failed" );
970 dbus_error_init( &error
);
971 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_INT32
,
972 &i_reply
, DBUS_TYPE_INVALID
) )
974 msg_Err( p_keystore
, "kwallet_write_password :"
975 " dbus_message_get_args failed\n%s", error
.message
);
976 dbus_error_free( &error
);
985 dbus_message_unref( msg
);
987 dbus_message_unref( repmsg
);
993 kwallet_remove_entry( vlc_keystore
* p_keystore
, char* psz_entry_name
)
995 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
996 DBusMessage
* msg
= NULL
;
997 DBusMessage
* repmsg
= NULL
;
999 DBusMessageIter args
;
1001 bool b_has_entry
= false;
1002 int i_ret
= VLC_EGENERIC
;
1004 if ( kwallet_has_entry( p_keystore
, psz_entry_name
, &b_has_entry
) )
1006 msg_Err( p_keystore
, "kwallet_remove_entry : kwallet_has_entry failed" );
1007 return VLC_EGENERIC
;
1011 msg_Err( p_keystore
, "kwallet_remove_entry : there is no such entry :"
1012 "%s", psz_entry_name
);
1013 return VLC_EGENERIC
;
1017 if ( !( msg
= vlc_dbus_new_method( p_keystore
, "removeEntry" ) ) )
1019 msg_Err( p_keystore
, "kwallet_remove_entry : vlc_dbus_new_method failed" );
1020 return VLC_EGENERIC
;
1024 dbus_message_iter_init_append( msg
, &args
);
1025 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
1026 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder
) ||
1027 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_entry_name
) ||
1028 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
1031 /* sending message */
1032 if ( !( repmsg
= vlc_dbus_send_message( p_keystore
, msg
) ) )
1034 msg_Err( p_keystore
, "kwallet_remove_entry : vlc_dbus_send_message failed" );
1038 /* handling reply */
1039 dbus_error_init( &error
);
1040 if ( !dbus_message_get_args( repmsg
, &error
, DBUS_TYPE_INT32
,
1041 &i_reply
, DBUS_TYPE_INVALID
) )
1043 msg_Err( p_keystore
, "kwallet_remove entry :"
1044 " dbus_message_get_args failed\n%s", error
.message
);
1045 dbus_error_free( &error
);
1049 i_ret
= VLC_SUCCESS
;
1054 dbus_message_unref( msg
);
1056 dbus_message_unref( repmsg
);
1061 static vlc_keystore_entry
*
1062 kwallet_read_password_list( vlc_keystore
* p_keystore
, char* psz_entry_name
,
1063 unsigned int* pi_count
)
1065 vlc_keystore_sys
* p_sys
= p_keystore
->p_sys
;
1066 DBusMessage
* msg
= NULL
;
1067 DBusMessage
* repmsg
= NULL
;
1068 DBusMessageIter args
;
1069 DBusMessageIter sub_iter
;
1070 DBusMessageIter dict_iter
;
1071 DBusMessageIter var_iter
;
1072 vlc_keystore_entry
* p_entries
= NULL
;
1074 uint8_t* p_secret_decoded
= NULL
;
1081 if ( !( msg
= vlc_dbus_new_method( p_keystore
, "readPasswordList" ) ) )
1083 msg_Err( p_keystore
, "kwallet_read_password_list : vlc_dbus_new_method failed" );
1088 dbus_message_iter_init_append( msg
, &args
);
1089 if ( !dbus_message_iter_append_basic( &args
, DBUS_TYPE_INT32
, &p_sys
->i_handle
) ||
1090 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_folder
) ||
1091 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &psz_entry_name
) ||
1092 !dbus_message_iter_append_basic( &args
, DBUS_TYPE_STRING
, &p_sys
->psz_app_id
) )
1095 /* sending message */
1096 if ( !( repmsg
= vlc_dbus_send_message( p_keystore
, msg
) ) )
1098 msg_Err( p_keystore
, "kwallet_read_password_list : vlc_dbus_send_message failed" );
1102 /* handling reply */
1103 if ( !dbus_message_iter_init( repmsg
, &args
) )
1105 msg_Err( p_keystore
, "kwallet_read_password_list : Message has no arguments" );
1108 else if ( dbus_message_iter_get_arg_type(&args
) != DBUS_TYPE_ARRAY
)
1110 msg_Err( p_keystore
, "kwallet_read_password_list : Wrong reply type" );
1115 /* calculating p_entries's size */
1116 dbus_message_iter_recurse( &args
, &sub_iter
);
1119 if ( dbus_message_iter_get_arg_type( &sub_iter
) != DBUS_TYPE_DICT_ENTRY
)
1121 dbus_message_iter_recurse( &sub_iter
, &dict_iter
);
1122 if ( dbus_message_iter_get_arg_type( &dict_iter
) != DBUS_TYPE_STRING
)
1124 dbus_message_iter_next(&dict_iter
);
1125 if ( dbus_message_iter_get_arg_type( &dict_iter
) != DBUS_TYPE_VARIANT
)
1128 } while ( dbus_message_iter_next( &sub_iter
) );
1130 if ( *pi_count
== 0 )
1132 if ( !( p_entries
= calloc( *pi_count
, sizeof( vlc_keystore_entry
) ) ) )
1135 dbus_message_iter_init( repmsg
, &args
);
1136 /* recurse into the reply array */
1137 dbus_message_iter_recurse( &args
, &sub_iter
);
1140 if ( dbus_message_iter_get_arg_type( &sub_iter
) != DBUS_TYPE_DICT_ENTRY
)
1142 msg_Err( p_keystore
, "Wrong type not DBUS_TYPE_DICT_ENTRY" );
1145 /* recurse into the dict-entry in the array */
1146 dbus_message_iter_recurse( &sub_iter
, &dict_iter
);
1147 if ( dbus_message_iter_get_arg_type( &dict_iter
) != DBUS_TYPE_STRING
)
1149 msg_Err( p_keystore
, "First type of Dict-Entry is not a string" );
1152 dbus_message_iter_get_basic( &dict_iter
, &p_reply
);
1153 dbus_message_iter_next(&dict_iter
);
1154 if ( dbus_message_iter_get_arg_type( &dict_iter
) != DBUS_TYPE_VARIANT
)
1156 msg_Err( p_keystore
, "Second type of Dict-Entry is not a variant" );
1159 /* recurse into the variant in the dict-entry */
1160 dbus_message_iter_recurse( &dict_iter
, &var_iter
);
1161 dbus_message_iter_get_basic( &var_iter
, &p_secret
);
1163 i_size
= vlc_b64_decode_binary( &p_secret_decoded
, p_secret
);
1164 if ( key2values( p_reply
, &p_entries
[i
] ) )
1166 if ( ( vlc_keystore_entry_set_secret( &p_entries
[i
],
1171 free(p_secret_decoded
);
1173 } while ( dbus_message_iter_next( &sub_iter
) );
1176 dbus_message_unref( msg
);
1177 dbus_message_unref( repmsg
);
1182 free( p_secret_decoded
);
1185 vlc_keystore_release_entries( p_entries
, i
);
1187 dbus_message_unref( msg
);
1189 dbus_message_unref( repmsg
);
1195 Store( vlc_keystore
* p_keystore
, const char *const ppsz_values
[KEY_MAX
],
1196 const uint8_t* p_secret
, size_t i_secret_len
, const char* psz_label
)
1199 char* psz_b64_secret
;
1203 psz_key
= values2key( ppsz_values
, false );
1207 psz_b64_secret
= vlc_b64_encode_binary( p_secret
, i_secret_len
);
1208 if ( !psz_b64_secret
)
1211 if ( kwallet_write_password( p_keystore
, psz_key
, psz_b64_secret
) )
1213 free( psz_b64_secret
);
1215 return VLC_EGENERIC
;
1218 free( psz_b64_secret
);
1225 Find( vlc_keystore
* p_keystore
, const char *const ppsz_values
[KEY_MAX
],
1226 vlc_keystore_entry
** pp_entries
)
1229 unsigned int i_count
= 0;
1231 psz_key
= values2key( ppsz_values
, true );
1234 *pp_entries
= kwallet_read_password_list( p_keystore
, psz_key
, &i_count
);
1247 Remove( vlc_keystore
* p_keystore
, const char* const ppsz_values
[KEY_MAX
] )
1250 vlc_keystore_entry
* p_entries
;
1251 unsigned i_count
= 0;
1253 psz_key
= values2key( ppsz_values
, true );
1257 p_entries
= kwallet_read_password_list( p_keystore
, psz_key
, &i_count
);
1266 for ( unsigned int i
= 0 ; i
< i_count
; ++i
)
1268 psz_key
= values2key( ( const char* const* )p_entries
[i
].ppsz_values
, false );
1271 vlc_keystore_release_entries( p_entries
, i_count
);
1275 if ( kwallet_remove_entry( p_keystore
, psz_key
) )
1277 vlc_keystore_release_entries( p_entries
, i_count
);
1281 for ( int inc
= 0 ; inc
< KEY_MAX
; ++inc
)
1282 free( p_entries
[i
].ppsz_values
[inc
] );
1283 free( p_entries
[i
].p_secret
);
1293 Close( vlc_object_t
* p_this
)
1295 vlc_keystore
*p_keystore
= ( vlc_keystore
* )p_this
;
1297 dbus_connection_close( p_keystore
->p_sys
->connection
);
1298 dbus_connection_unref( p_keystore
->p_sys
->connection
);
1299 free( p_keystore
->p_sys
->psz_app_id
);
1300 free( p_keystore
->p_sys
->psz_wallet
);
1301 free( p_keystore
->p_sys
);
1305 Open( vlc_object_t
* p_this
)
1307 vlc_keystore
*p_keystore
= ( vlc_keystore
* )p_this
;
1310 p_keystore
->p_sys
= calloc( 1, sizeof( vlc_keystore_sys
) );
1311 if ( !p_keystore
->p_sys
)
1314 i_ret
= vlc_dbus_init( p_keystore
);
1317 msg_Dbg( p_keystore
, "vlc_dbus_init failed" );
1321 i_ret
= kwallet_open( p_keystore
);
1324 msg_Dbg( p_keystore
, "kwallet_open failed" );
1328 p_keystore
->pf_store
= Store
;
1329 p_keystore
->pf_find
= Find
;
1330 p_keystore
->pf_remove
= Remove
;
1335 free( p_keystore
->p_sys
);