[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