[vlc-devel] [PATCH 2/2] keystore: Add kwallet keystore
Denis Charmet
typx at dinauz.org
Thu Jun 16 15:52:47 CEST 2016
Hi,
On 2016-06-15 18:44, Duncan McNAMARA wrote:
> diff --git a/modules/keystore/kwallet.c b/modules/keystore/kwallet.c
> new file mode 100644
> index 0000000..d2435da
> --- /dev/null
> +++ b/modules/keystore/kwallet.c
> @@ -0,0 +1,1216 @@
> +/*****************************************************************************
> + * kwallet.c: KWallet keystore module
> +
> *****************************************************************************
> + * Copyright © 2015-2016 VLC authors, VideoLAN and VideoLabs
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU Lesser General Public License as
> published by
> + * the Free Software Foundation; either version 2.1 of the License,
> or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> License
> + * along with this program; if not, write to the Free Software
> Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> +
> *****************************************************************************/
> +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +
> +#include <vlc_common.h>
> +#include <vlc_keystore.h>
> +#include <dbus/dbus.h>
> +#include <string.h>
> +#include <vlc_url.h>
> +#include <vlc_plugin.h>
> +#include <vlc_strings.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +
> +static int Open( vlc_object_t* p_this);
> +static void Close( vlc_object_t * p_this);
> +
> +vlc_module_begin()
> + set_shortname(N_("KWallet keystore"))
> + set_description(N_("secrets are stored via KWallet"))
> + set_category(CAT_ADVANCED)
> + set_subcategory(SUBCAT_ADVANCED_MISC)
> + set_capability("keystore", 100)
> + set_callbacks(Open, Close)
> +vlc_module_end ()
> +
> +/* kwallet is the kde keyring. *
> + * There are several entry categories, *
> + * but we only use the "Password" category. *
> + * It is juste a simple Entry name ( or key ) *
> + * associated with a secret. *
> + * Keys are urls formated with : *
> + * _ Protocol *
> + * _ User ( optional ) *
> + * _ Server *
> + * _ Port ( optional ) *
> + * _ Path ( optional ) *
> + * _ Realm ( binary encrypted ) ( optional ) *
> + * _ Authtype ( binary encrypted ) ( optional ) *
> + * Secrets are binary encrypted strings */
> +
> +#define KWALLET_APP_NAME "org.videolan.kwallet"
> +#define KWALLET_INTERFACE "org.kde.KWallet"
> +
> +static const char* psz_app_id = KWALLET_APP_NAME;
Why not drop the define if you have your const?
> +
> +/*
> + * There are two kwallet services :
> + * kwallet and kwallet5 */
> +
> +/* These services have the same interfaces and methods *
> + * but not the same addresses and paths */
> +
> +enum serviceId
> +{
> + KWALLET = 0,
> + KWALLET5,
> + SERVICE_MAX
> +};
> +
> +static const char *ppsz_sAddr[SERVICE_MAX] = {
> + "org.kde.kwalletd",
> + "org.kde.kwalletd5"
> +};
> +
> +static const char *ppsz_sPath[SERVICE_MAX] = {
> + "/modules/kwalletd",
> + "/modules/kwalletd5"
> +};
> +
> +typedef struct vlc_keystore_sys
> +{
> + DBusConnection* connection;
> + int i_sid; /* service ID */
> + char* psz_wallet;
> + char* psz_folder;
I might have missed it but since it's a strdup of a constant defined
string I don't really see the point to keep it in a sys struct.
> + int i_handle;
> +} vlc_keystore_sys;
> +
> +/* takes all values in the values of vlc_keystore_entry *
> + * and formats them in a url key */
> +static char*
> +values2key( const char* const* ppsz_values, bool b_search )
> +{
> + const char* psz_protocol = "";
> + const char* psz_user = "";
> + const char* psz_sep_user = "";
> + const char* psz_server = "";
> + const char* psz_port = "";
> + const char* psz_sep_port = "";
> + const char* psz_path = "";
> + const char* psz_sep_path = "";
> + const char* psz_sep_option = "";
> + const char* psz_sep_realm_auth = "";
> + const char* psz_realm = "";
> + const char* psz_auth = "";
> + char* psz_b64_realm = NULL;
> + char* psz_b64_auth = NULL;
> + char* psz_key = NULL;
> +
> + if ( ( !ppsz_values[KEY_PROTOCOL] || !ppsz_values[KEY_SERVER] )
> + && !b_search )
> + return NULL;
> +
> + /* Protocol section */
> + if ( ppsz_values[KEY_PROTOCOL] )
> + psz_protocol = ppsz_values[KEY_PROTOCOL];
> + else if ( b_search )
> + psz_protocol = "*";
> +
> + /* User section */
> + if ( ppsz_values[KEY_USER] )
> + {
> + psz_user = ppsz_values[KEY_USER];
> + psz_sep_user = "@";
> + }
> + else if ( b_search )
> + psz_user = "*";
> +
> + /* Server section */
> + if ( ppsz_values[KEY_SERVER] )
> + psz_server = ppsz_values[KEY_SERVER];
> + else if ( b_search )
> + psz_server = "*";
> +
> + /* Port section */
> + if ( ppsz_values[KEY_PORT] )
> + {
> + psz_sep_port = ":";
> + psz_port = ppsz_values[KEY_PORT];
> + }
> + else if ( b_search )
> + psz_port = "*";
> +
> + /* Path section */
> + if ( ppsz_values[KEY_PATH] )
> + {
> + psz_path = ppsz_values[KEY_PATH];
> + if ( ppsz_values[KEY_PATH][0] != '/' )
> + psz_sep_path = "/";
> + }
> + else if ( b_search )
> + psz_path = "*";
> +
> + /* Realm and authtype section */
> + if ( ppsz_values[KEY_REALM] || ppsz_values[KEY_AUTHTYPE] ||
> b_search )
> + {
> + psz_sep_option = "?";
> +
> + /* Realm section */
> + if ( ppsz_values[KEY_REALM] || b_search )
> + {
> + if ( ppsz_values[KEY_REALM] )
> + {
> + psz_realm = "realm=";
> + if ( !( psz_b64_realm =
> + vlc_b64_encode_binary( ( uint8_t*
> )ppsz_values[KEY_REALM],
> +
> strlen(ppsz_values[KEY_REALM] ) ) ) )
> + goto end;
> + }
> + else
> + psz_realm = "*";
> +
> + if ( ppsz_values[KEY_AUTHTYPE] )
> + psz_sep_realm_auth = "&";
> + }
> +
> + /* Authtype section */
> + if ( ppsz_values[KEY_AUTHTYPE] || b_search )
> + {
> +
> + if ( ppsz_values[KEY_AUTHTYPE] )
> + {
> + psz_auth = "authtype=";
> + if ( !( psz_b64_auth =
> + vlc_b64_encode_binary( ( uint8_t*
> )ppsz_values[KEY_AUTHTYPE],
> +
> strlen(ppsz_values[KEY_AUTHTYPE] ) ) ) )
> + goto end;
> + }
> + else
> + psz_auth = "*";
> + }
> +
> + }
> +
> + if ( asprintf( &psz_key, "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s",
> psz_protocol,
> + psz_user, psz_sep_user,
> + psz_server,
> + psz_sep_port, psz_port,
> + psz_sep_path, psz_path,
> + psz_sep_option,
> + psz_realm, psz_b64_realm ? psz_b64_realm : "",
> + psz_sep_realm_auth,
> + psz_auth, psz_b64_auth ? psz_b64_realm : "" ) ==
> -1 )
> + goto end;
> +
> +end:
> + free( psz_b64_realm );
> + free( psz_b64_auth );
> + return psz_key;
> +}
> +
> +/* Take an url key and splits it into vlc_keystore_entry values */
> +static int
> +key2values( char* psz_key, vlc_keystore_entry* p_entry )
> +{
> + vlc_url_t url;
> + char* psz_b64_realm = NULL;
> + char* psz_b64_authtype = NULL;
> + int i_offset = 0;
> + int i = 0;
> + int i_ret = VLC_ENOMEM;
> +
> + for ( int inc = 0 ; inc < KEY_MAX ; ++inc )
> + p_entry->ppsz_values[inc] = NULL;
> +
> + vlc_UrlParse( &url, psz_key );
> +
> + if ( url.psz_protocol && !( p_entry->ppsz_values[KEY_PROTOCOL] =
> + strdup( url.psz_protocol ) ) )
> + goto end;
> + if ( url.psz_username && !( p_entry->ppsz_values[KEY_USER] =
> + strdup( url.psz_username ) ) )
> + goto end;
> + if ( url.psz_host && !( p_entry->ppsz_values[KEY_SERVER] =
> + strdup( url.psz_host ) ) )
> + goto end;
> + if ( url.i_port && asprintf( &p_entry->ppsz_values[KEY_PORT],
> + "%d", url.i_port) == -1 )
> + goto end;
> + if ( url.psz_path && !( p_entry->ppsz_values[KEY_PATH] =
> + strdup( url.psz_path ) ) )
> + goto end;
> + if ( url.psz_option )
> + {
> + if ( !strncmp( url.psz_option, "realm=", strlen("realm=" ) )
> )
> + {
> + i = i_offset = strlen( "realm=" );
> + while ( url.psz_option[i] != '&' && url.psz_option[i] !=
> 0 )
> + ++i;
> + if ( !( psz_b64_realm = strndup( url.psz_option +
> i_offset,
> + i - i_offset ) ) )
> + goto end;
You could skip the whole strdup part by just doing something like
if ( url.psz_option[i] == '&')
url.psz_option[i++] = '\0';
p_entry->ppsz_values[KEY_REALM] = vlc_b64_decode( url.psz_option +
i_offset );
> + p_entry->ppsz_values[KEY_REALM] = vlc_b64_decode(
> psz_b64_realm );
> + free( psz_b64_realm );
> + if ( !p_entry->ppsz_values[KEY_REALM] )
> + goto end;
> + if ( url.psz_option[i] == '&' )
> + ++i;
> + }
> + else if ( !strncmp( url.psz_option + i, "authtype=", strlen(
> "authtype=" ) ) )
> + {
> + i = i_offset = i + strlen( "authtype=" );
> + while ( url.psz_option[i] != 0 )
I suppose that it has to be in the order realm=foo&authtype=bar and
never authtype=bar&realm=foo because this second case apparently will
not work if I'm not mistaken.
> + ++i;
> + if ( !( psz_b64_authtype = strndup( url.psz_option +
> i_offset, i - i_offset ) ) )
> + goto end;
like above you could skip the strdup.
> + p_entry->ppsz_values[KEY_AUTHTYPE] = vlc_b64_decode(
> psz_b64_authtype );
> + free( psz_b64_authtype );
> + if ( !p_entry->ppsz_values[KEY_AUTHTYPE] )
> + goto end;
> + }
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> + vlc_UrlClean( &url );
> + if ( i_ret )
> + {
> + free( p_entry->ppsz_values[KEY_PROTOCOL] );
> + free( p_entry->ppsz_values[KEY_USER] );
> + free( p_entry->ppsz_values[KEY_SERVER] );
> + free( p_entry->ppsz_values[KEY_PORT] );
> + free( p_entry->ppsz_values[KEY_PATH] );
> + free( p_entry->ppsz_values[KEY_REALM] );
> + free ( p_entry->ppsz_values[KEY_AUTHTYPE] );
> + }
> + return i_ret;
> +}
> +
> +static DBusMessage*
> +vlc_dbus_new_method( vlc_keystore* p_keystore, const char* psz_method
> )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg;
> +
> + msg = dbus_message_new_method_call( ppsz_sAddr[p_sys->i_sid],
> + ppsz_sPath[p_sys->i_sid],
> + KWALLET_INTERFACE,
> + psz_method );
> + if ( !msg )
> + {
> + msg_Err( p_keystore, "vlc_dbus_new_method : Failed to create
> message" );
> + return NULL;
> + }
> +
> + return msg;
> +}
> +
> +static DBusMessage*
> +vlc_dbus_send_message( vlc_keystore* p_keystore, DBusMessage* msg )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* repmsg;
> + DBusError error;
> +
> + dbus_error_init( &error );
> +
> + if ( !( repmsg = dbus_connection_send_with_reply_and_block(
> p_sys->connection,
> + msg,
> -1,
> +
> &error)))
> + {
> + msg_Err( p_keystore, "vlc_dbus_send_message : "
> + "Failed dbus_connection_send_with_reply_and_block"
> );
> + return NULL;
> + }
> + if ( dbus_error_is_set( &error ) )
> + {
> + msg_Err( p_keystore, "vlc_dbus_send_message : "
> + "dbus_connection_send_with_reply_and_block has error
> set" );
> + return NULL;
> + }
> +
> + return repmsg;
> +}
> +
> +static int
> +kwallet_network_wallet( vlc_keystore* p_keystore )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + char* psz_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "networkWallet" )
> ) )
> + {
> + msg_Err( p_keystore, "kwallet_network_wallet :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_network_wallet :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_network_wallet : Message has
> no arguments\n" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_STRING )
> + {
> + msg_Err( p_keystore, "kwallet_network_wallet : Wrong reply
> type" );
> + goto end;
> + }
> + else
> + {
> + dbus_message_iter_get_basic( &args, &psz_reply );
> + p_sys->psz_wallet = strdup( psz_reply );
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_is_enabled( vlc_keystore* p_keystore, int i_sid, bool*
> b_is_enabled )
> +{
> + vlc_keystore_sys *p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + bool b_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + msg = dbus_message_new_method_call( ppsz_sAddr[i_sid],
> + ppsz_sPath[i_sid],
> + KWALLET_INTERFACE,
> + "isEnabled" );
> + if ( !msg )
> + {
> + msg_Err( p_keystore, "vlc_dbus_new_method : Failed to create
> message" );
> + goto end;
> + }
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_is_enabled :
> vlc_dbus_send_message failed");
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_is_enabled : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_BOOLEAN )
> + {
> + msg_Err( p_keystore, "kwallet_is_enabled : wrong reply type"
> );
> + goto end;
> + }
> + else
> + {
> + dbus_message_iter_get_basic( &args, &b_reply );
> + *b_is_enabled = b_reply;
> + }
> +
> + if ( !( p_sys->psz_folder = strdup( VLC_KEYSTORE_NAME ) ) )
As stated previously is this useful?
> + {
> + msg_Err( p_keystore, "kwallet_is_enabled : psz_folder
> allocation failed" );
In any case, imho, it's usually a bad practice to call msg_Xxx when
your allocation failed since vfprintf might rely on malloc too.
> + goto end;
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +vlc_dbus_init( vlc_keystore* p_keystore )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + int i_ret;
> + DBusError error;
> +
> + dbus_error_init( &error );
> +
> + p_sys->connection = dbus_bus_get_private( DBUS_BUS_SESSION,
> &error );
> + if ( dbus_error_is_set( &error ) )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : "
> + "Connection error to session bus (%s)",
> error.message );
> + dbus_error_free( &error );
> + }
> + if ( !p_sys->connection )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : connection is NULL");
> + return VLC_EGENERIC;
> + }
> + i_ret = dbus_bus_request_name( p_sys->connection,
> KWALLET_APP_NAME,
> + DBUS_NAME_FLAG_REPLACE_EXISTING |
> + DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
> + &error );
> + if ( dbus_error_is_set( &error ) )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : dbus_bus_request_name
> :"
> + " error (%s)", error.message );
> + dbus_error_free( &error );
> + }
> + if ( i_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : not primary owner");
> + return VLC_EGENERIC;
> + }
> +
> + /* check to see if any kwallet service is enabled */
> + int i = 0;
> + for ( ; i < SERVICE_MAX ; ++i )
> + {
> + bool b_is_enabled = false;
> + if ( kwallet_is_enabled( p_keystore, i, &b_is_enabled ) )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : kwallet_is_enabled
> failed" );
> + goto error;
> + }
> + if ( b_is_enabled == true )
> + break;
> + }
> + if ( i == SERVICE_MAX )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init : No kwallet service
> enabled" );
> + goto error;
> + }
> + p_sys->i_sid = i;
> +
> + /* getting the name of the wallet assigned to network passwords
> */
> + if ( kwallet_network_wallet( p_keystore ) )
> + {
> + msg_Err(p_keystore, "vlc_dbus_init : kwallet_network_wallet
> has failed");
> + goto error;
> + }
> +
> + return VLC_SUCCESS;
> +
> +error:
> + dbus_connection_close( p_sys->connection );
> + return VLC_EGENERIC;
> +}
> +
> +static int
> +kwallet_has_folder( vlc_keystore* p_keystore, const char*
> psz_folder_name, bool *b_has_folder )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + bool b_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "hasFolder" ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_folder :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_folder_name ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_folder :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_folder : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_BOOLEAN )
> + {
> + msg_Err( p_keystore, "kwallet_has_folder : Wrong reply type"
> );
> + goto end;
> + }
> + else
> + {
> + dbus_message_iter_get_basic( &args, &b_reply );
> + *b_has_folder = b_reply;
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg);
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_create_folder( vlc_keystore* p_keystore, const char*
> psz_folder_name )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + bool b_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "createFolder" ) )
> )
> + {
> + msg_Err( p_keystore, "kwallet_create_folder :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_folder_name ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_create_folder :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_create_folder : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_BOOLEAN )
> + {
> + msg_Err( p_keystore, "kwallet_create_folder : Wrong reply
> type" );
> + goto end;
> + }
> + else
> + dbus_message_iter_get_basic( &args, &b_reply );
> +
> + if ( b_reply == false )
> + {
> + msg_Err( p_keystore, "kwallet_create_folder : Could not
> create folder" );
> + goto end;
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_open( vlc_keystore* p_keystore )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + unsigned long long ull_win_id = 0;
> + unsigned int ui_reply = 1;
> + bool b_has_folder;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "open" ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_open : vlc_dbus_new_method
> failed");
> + return VLC_EGENERIC;
> + }
> +
> + /* Init args */
> + dbus_message_iter_init_append(msg, &args);
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &p_sys->psz_wallet ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT64,
> &ull_win_id ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_open : vlc_dbus_send_message
> failed" );
> + goto end;
> + }
> +
> + /* reply arguments */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_open : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_INT32 )
> + {
> + msg_Err( p_keystore, "kwallet_open : Wrong reply type" );
> + goto end;
> + }
> + else
> + {
> + dbus_message_iter_get_basic( &args, &ui_reply );
> + p_sys->i_handle = ui_reply;
> + }
> +
> + /* opening the vlc password folder == VLC_KEYSTORE_NAME */
> + if ( kwallet_has_folder( p_keystore, VLC_KEYSTORE_NAME,
> &b_has_folder ) )
> + goto end;
> + if ( !b_has_folder )
> + {
> + if ( kwallet_create_folder( p_keystore, VLC_KEYSTORE_NAME ) )
> + {
> + msg_Err( p_keystore, "kwallet_open : could not create
> folder %s",
> + VLC_KEYSTORE_NAME );
> + goto end;
> + }
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_has_entry( vlc_keystore* p_keystore, char* psz_entry_name,
> bool *b_has_entry )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + bool b_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method(p_keystore, "hasEntry" ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_entry :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &p_sys->psz_folder ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_entry_name ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> +
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_entry :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_has_entry : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_BOOLEAN )
> + {
> + msg_Err(p_keystore, "kwallet_has_entry : Wrong reply type");
> + goto end;
> + }
> + else
> + {
> + dbus_message_iter_get_basic( &args, &b_reply );
> + *b_has_entry = b_reply;
> + }
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_write_password( vlc_keystore* p_keystore, char*
> psz_entry_name, const char* psz_secret )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + int i_reply;
> + int i_ret = VLC_EGENERIC;
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "writePassword" )
> ) )
> + {
> + msg_Err( p_keystore, "kwallet_write_password :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &p_sys->psz_folder ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_entry_name ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_secret ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_write_password :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_write_password : Message has
> no arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_INT32 )
> + {
> + msg_Err( p_keystore, "kwallet_write_password : Wrong reply
> type" );
> + goto end;
> + }
> + else
> + dbus_message_iter_get_basic( &args, &i_reply );
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static int
> +kwallet_remove_entry( vlc_keystore* p_keystore, char* psz_entry_name
> )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + int i_reply;
> + bool b_has_entry = false;
> + int i_ret = VLC_EGENERIC;
> +
> + if ( kwallet_has_entry( p_keystore, psz_entry_name, &b_has_entry
> ) )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry :
> kwallet_has_entry failed" );
> + return VLC_EGENERIC;
> + }
> + if ( !b_has_entry )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry : there is no such
> entry :"
> + "%s", psz_entry_name );
> + return VLC_EGENERIC;
> + }
> +
> + /* init */
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "removeEntry" ) )
> )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry :
> vlc_dbus_new_method failed" );
> + return VLC_EGENERIC;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &p_sys->psz_folder ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_entry_name ) )
> + goto end;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto end;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry :
> vlc_dbus_send_message failed" );
> + goto end;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry : Message has no
> arguments" );
> + goto end;
> + }
> + else if ( dbus_message_iter_get_arg_type( &args ) !=
> DBUS_TYPE_INT32 )
> + {
> + msg_Err( p_keystore, "kwallet_remove_entry : Wrong reply
> type" );
> + goto end;
> + }
> + else
> + dbus_message_iter_get_basic( &args, &i_reply );
> +
> + i_ret = VLC_SUCCESS;
> +
> +end:
> +
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> +
> + return i_ret;
> +}
> +
> +static vlc_keystore_entry*
> +kwallet_read_password_list( vlc_keystore* p_keystore, char*
> psz_entry_name,
> + unsigned int* pi_count )
> +{
> + vlc_keystore_sys* p_sys = p_keystore->p_sys;
> + DBusMessage* msg = NULL;
> + DBusMessage* repmsg = NULL;
> + DBusMessageIter args;
> + DBusMessageIter sub_iter;
> + DBusMessageIter dict_iter;
> + DBusMessageIter var_iter;
> + vlc_keystore_entry* p_entries = NULL;
> + size_t i_size;
> + uint8_t* p_secret_decoded;
> + char* p_reply;
> + char* p_secret;
> + int i = 0;
> +
> + /* init */
> + *pi_count = 0;
> + if ( !( msg = vlc_dbus_new_method( p_keystore, "readPasswordList"
> ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_read_password_list :
> vlc_dbus_new_method failed" );
> + goto error;
> + }
> +
> + /* argument init */
> + dbus_message_iter_init_append( msg, &args );
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_INT32,
> &p_sys->i_handle ) )
> + goto error;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &p_sys->psz_folder ) )
> + goto error;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_entry_name ) )
> + goto error;
> + if ( !dbus_message_iter_append_basic( &args, DBUS_TYPE_STRING,
> &psz_app_id ) )
> + goto error;
> +
> + /* sending message */
> + if ( !( repmsg = vlc_dbus_send_message( p_keystore, msg ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_read_password_list :
> vlc_dbus_send_message failed" );
> + goto error;
> + }
> +
> + /* handling reply */
> + if ( !dbus_message_iter_init( repmsg, &args ) )
> + {
> + msg_Err( p_keystore, "kwallet_read_password_list : Message
> has no arguments" );
> + goto error;
> + }
> + else if ( dbus_message_iter_get_arg_type(&args) !=
> DBUS_TYPE_ARRAY )
> + {
> + msg_Err( p_keystore, "kwallet_read_password_list : Wrong
> reply type" );
> + goto error;
> + }
> + else
> + {
> + /* calculating p_entries's size */
> + dbus_message_iter_recurse( &args, &sub_iter );
> + do
> + {
> + if ( dbus_message_iter_get_arg_type( &sub_iter ) !=
> DBUS_TYPE_DICT_ENTRY )
> + continue;
> + dbus_message_iter_recurse( &sub_iter, &dict_iter );
> + if ( dbus_message_iter_get_arg_type( &dict_iter ) !=
> DBUS_TYPE_STRING )
> + continue;
> + dbus_message_iter_next(&dict_iter);
> + if ( dbus_message_iter_get_arg_type( &dict_iter ) !=
> DBUS_TYPE_VARIANT )
> + continue;
> + ++( *pi_count );
> + } while ( dbus_message_iter_next( &sub_iter ) );
> +
> + if ( *pi_count == 0 )
> + goto error;
> + if ( !( p_entries = calloc( *pi_count, sizeof(
> vlc_keystore_entry ) ) ) )
> + goto error;
> +
> + dbus_message_iter_init( repmsg, &args );
> + /* recurse into the reply array */
> + dbus_message_iter_recurse( &args, &sub_iter );
> + do
> + {
> + if ( dbus_message_iter_get_arg_type( &sub_iter ) !=
> DBUS_TYPE_DICT_ENTRY )
> + {
> + msg_Err( p_keystore, "Wrong type not
> DBUS_TYPE_DICT_ENTRY" );
> + continue;
> + }
> + /* recurse into the dict-entry in the array */
> + dbus_message_iter_recurse( &sub_iter, &dict_iter );
> + if ( dbus_message_iter_get_arg_type( &dict_iter ) !=
> DBUS_TYPE_STRING )
> + {
> + msg_Err( p_keystore, "First type of Dict-Entry is
> not a string" );
> + continue;
> + }
> + dbus_message_iter_get_basic( &dict_iter, &p_reply );
> + dbus_message_iter_next(&dict_iter);
> + if ( dbus_message_iter_get_arg_type( &dict_iter ) !=
> DBUS_TYPE_VARIANT )
> + {
> + msg_Err( p_keystore, "Second type of Dict-Entry is
> not a variant" );
> + continue;
> + }
> + /* recurse into the variant in the dict-entry */
> + dbus_message_iter_recurse( &dict_iter, &var_iter );
> + dbus_message_iter_get_basic( &var_iter, &p_secret );
> +
> + i_size = vlc_b64_decode_binary( &p_secret_decoded,
> p_secret);
> + if ( key2values( p_reply, &p_entries[i] ) )
> + goto error;
> + if ( ( vlc_keystore_entry_set_secret( &p_entries[i],
> + p_secret_decoded,
> + i_size ) ) )
> + goto error;
> +
> + free(p_secret_decoded);
> + i += 1;
> + } while ( dbus_message_iter_next( &sub_iter ) );
> + }
> +
> + dbus_message_unref( msg );
> + dbus_message_unref( repmsg );
> +
> + return p_entries;
> +
> +error:
> + *pi_count = 0;
> + vlc_keystore_release_entries( p_entries, i );
> + if ( msg )
> + dbus_message_unref( msg );
> + if ( repmsg )
> + dbus_message_unref( repmsg );
> + return NULL;
> +}
> +
> +
> +static int
> +Store( vlc_keystore* p_keystore, const char *const
> ppsz_values[KEY_MAX],
> + const uint8_t* p_secret, size_t i_secret_len, const char*
> psz_label )
> +{
> + char* psz_key;
> + char* psz_b64_secret;
> +
> + (void)psz_label;
> +
> + if ( !( psz_key = values2key( ppsz_values, false ) ) )
> + return VLC_ENOMEM;
> +
> + if ( !( psz_b64_secret = vlc_b64_encode_binary( p_secret,
> i_secret_len ) ) )
> + return VLC_ENOMEM;
> +
> + if ( kwallet_write_password( p_keystore, psz_key, psz_b64_secret
> ) )
> + {
> + free( psz_b64_secret );
> + free( psz_key );
> + return VLC_EGENERIC;
> + }
> +
> + free( psz_b64_secret );
> + free( psz_key );
> +
> + return VLC_SUCCESS;
> +}
> +
> +static unsigned int
> +Find( vlc_keystore* p_keystore, const char *const
> ppsz_values[KEY_MAX],
> + vlc_keystore_entry** pp_entries )
> +{
> + char* psz_key;
> + unsigned int i_count = 0;
> +
> + if ( !( psz_key = values2key( ppsz_values, true ) ) )
> + return i_count;
> +
> + if ( !( *pp_entries = kwallet_read_password_list( p_keystore,
> + psz_key,
> &i_count ) ) )
> + {
> + free( psz_key );
> + return i_count;
> + }
> +
> + free( psz_key );
> +
> + return i_count;
> +}
> +
> +static unsigned int
> +Remove( vlc_keystore* p_keystore, const char* const
> ppsz_values[KEY_MAX] )
> +{
> + char* psz_key;
> + vlc_keystore_entry* p_entries;
> + unsigned i_count = 0;
> +
> + if ( !( psz_key = values2key( ppsz_values, true ) ) )
> + return 0;
> +
> + if ( !( p_entries = kwallet_read_password_list( p_keystore,
> + psz_key, &i_count
> ) ) )
> + {
> + free( psz_key );
> + return 0;
> + }
> +
> + free( psz_key );
> +
> + for ( unsigned int i = 0 ; i < i_count ; ++i )
> + {
> + if ( !( psz_key = values2key( ( const char* const*
> )p_entries[i].ppsz_values,
> + false ) ) )
> + {
> + vlc_keystore_release_entries( p_entries, i_count );
> + return i;
> + }
> +
> + if ( kwallet_remove_entry( p_keystore, psz_key ) )
> + {
> + vlc_keystore_release_entries( p_entries, i_count );
> + free( psz_key );
> + return i;
> + }
> + for ( int inc = 0 ; inc < KEY_MAX ; ++inc )
> + if ( p_entries[i].ppsz_values[inc] )
> + free( p_entries[i].ppsz_values[inc] );
useless if.
> + free( p_entries[i].p_secret );
> + free( psz_key );
> + }
> +
> + free( p_entries );
> +
> + return i_count;
> +}
> +
> +static void
> +Close( vlc_object_t* p_this )
> +{
> + vlc_keystore *p_keystore = ( vlc_keystore* )p_this;
> +
> + dbus_connection_close( p_keystore->p_sys->connection );
> + free( p_keystore->p_sys->psz_wallet );
> + free( p_keystore->p_sys->psz_folder );
> + free( p_keystore->p_sys );
> +}
> +
> +static int
> +Open( vlc_object_t* p_this )
> +{
> + vlc_keystore *p_keystore = ( vlc_keystore* )p_this;
> + int i_ret;
> +
> + if ( !( p_keystore->p_sys = malloc( sizeof( vlc_keystore_sys ) )
> ) )
> + {
> + msg_Err( p_keystore, "vlc_keystore_sys allocation failed" );
> + return VLC_ENOMEM;
> + }
> +
> + if ( ( i_ret = vlc_dbus_init( p_keystore ) ) )
> + {
> + msg_Err( p_keystore, "vlc_dbus_init failed" );
> + goto error;
> + }
> + if ( ( i_ret = kwallet_open( p_keystore ) ) )
> + {
> + msg_Err( p_keystore, "kwallet_open failed" );
> + goto error;
> + }
> +
> + p_keystore->pf_store = Store;
> + p_keystore->pf_find = Find;
> + p_keystore->pf_remove = Remove;
> +
> + return i_ret;
> +
> +error:
> + free( p_keystore->p_sys );
> + return i_ret;
> +}
> diff --git a/test/modules/keystore/test.c
> b/test/modules/keystore/test.c
> index 956c014..a75451e 100644
> --- a/test/modules/keystore/test.c
> +++ b/test/modules/keystore/test.c
> @@ -54,7 +54,7 @@ static const struct
> /* Following keystores are tested only when asked explicitly by
> the tester
> * (with "-a" argv) */
> { "secret", false, true },
> - { "kwallet", false, true },
> + { "kwallet", true, true },
> { "keychain", false, true }
> };
>
> @@ -331,11 +331,6 @@ main(int i_argc, char *ppsz_argv[])
> "--keystore-file=%s", psz_tmp_path) != -1);
> i_vlc_argc++;
> }
> - else if (strcmp(psz_module, "kwallet") == 0)
> - {
> - /* See TODO in kwallet.cpp, VLCKWallet::connect() */
> -
> assert(libvlc_InternalAddIntf(p_libvlc->p_libvlc_int, "qt") ==
> VLC_SUCCESS);
> - }
>
> test_module(psz_module, b_test_all,
> keystore_args[i].b_persistent,
> i_vlc_argc, (const char * const
> *)ppsz_vlc_argv);
Regards,
--
Denis Charmet - TypX
Le mauvais esprit est un art de vivre
More information about the vlc-devel
mailing list