Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
0473ca29
Commit
0473ca29
authored
Nov 24, 2015
by
Thomas Guillem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
keystore: add libsecret module
parent
cb4130bf
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
363 additions
and
0 deletions
+363
-0
configure.ac
configure.ac
+5
-0
modules/MODULES_LIST
modules/MODULES_LIST
+1
-0
modules/keystore/Makefile.am
modules/keystore/Makefile.am
+11
-0
modules/keystore/secret.c
modules/keystore/secret.c
+346
-0
No files found.
configure.ac
View file @
0473ca29
...
...
@@ -4082,6 +4082,11 @@ AS_IF([test "${enable_taglib}" != "no"], [
AC_MSG_WARN([${TAGLIB_PKG_ERRORS}.])])
])
dnl
dnl libsecret
dnl
PKG_ENABLE_MODULES_VLC([SECRET], [], [libsecret-1], [use libsecret for keystore], [auto])
dnl
dnl Developers helper modules (should be hidden from configure help)
dnl
...
...
modules/MODULES_LIST
View file @
0473ca29
...
...
@@ -202,6 +202,7 @@ $Id$
* karaoke: simple karaoke audio filter
* kate: kate text bitstream decoder
* keystore_plaintext: store secrets in a plaintext file (insecure)
* keystore_secret: store secrets via Gnome libsecret
* kva: OS/2 video output
* libass: Subtitle renderers using libass
* libbluray: Library to access Blu-Ray drives
...
...
modules/keystore/Makefile.am
View file @
0473ca29
...
...
@@ -2,3 +2,14 @@ keystoredir = $(pluginsdir)/keystore
libplaintext_keystore_plugin_la_SOURCES
=
keystore/plaintext.c
keystore_LTLIBRARIES
=
libplaintext_keystore_plugin.la
libsecret_plugin_la_SOURCES
=
keystore/secret.c
libsecret_plugin_la_CPPFLAGS
=
$(AM_CPPFLAGS)
$(SECRET_CFLAGS)
libsecret_plugin_la_LDFLAGS
=
$(AM_LDFLAGS)
-rpath
'
$(keystoredir)
'
libsecret_plugin_la_LIBADD
=
$(SECRET_LIBS)
keystore_LTLIBRARIES
+=
\
$(LTLIBsecret)
EXTRA_LTLIBRARIES
+=
\
libsecret_plugin.la
modules/keystore/secret.c
0 → 100644
View file @
0473ca29
/*****************************************************************************
* secret.c: libsecret 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_plugin.h>
#include <vlc_keystore.h>
#include <vlc_interrupt.h>
#include <assert.h>
#include <libsecret/secret.h>
#include <gio/gdbusnamewatching.h>
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_shortname
(
N_
(
"libsecret keystore"
))
set_description
(
N_
(
"secrets are stored via libsecret"
))
set_category
(
CAT_ADVANCED
)
set_subcategory
(
SUBCAT_ADVANCED_MISC
)
set_capability
(
"keystore"
,
100
)
set_callbacks
(
Open
,
Close
)
/* Since we can't destroy gdbus_shared_thread_func */
cannot_unload_broken_library
()
vlc_module_end
()
static
const
char
*
const
ppsz_keys
[]
=
{
"protocol"
,
"user"
,
"server"
,
"path"
,
"port"
,
"realm"
,
"authtype"
,
};
static_assert
(
sizeof
(
ppsz_keys
)
/
sizeof
(
*
ppsz_keys
)
==
KEY_MAX
,
"key mismatch"
);
static
int
str2key
(
const
char
*
psz_key
)
{
for
(
unsigned
int
i
=
0
;
i
<
KEY_MAX
;
++
i
)
{
if
(
strcmp
(
ppsz_keys
[
i
],
psz_key
)
==
0
)
return
i
;
}
return
-
1
;
}
static
void
cancellable_interrupted
(
void
*
p_data
)
{
GCancellable
*
p_canc
=
p_data
;
g_cancellable_cancel
(
p_canc
);
}
static
GCancellable
*
cancellable_register
()
{
GCancellable
*
p_canc
=
g_cancellable_new
();
if
(
!
p_canc
)
return
NULL
;
vlc_interrupt_register
(
cancellable_interrupted
,
p_canc
);
return
p_canc
;
}
static
void
cancellable_unregister
(
GCancellable
*
p_canc
)
{
if
(
p_canc
!=
NULL
)
{
vlc_interrupt_unregister
();
g_object_unref
(
p_canc
);
}
}
static
GHashTable
*
values_to_ghashtable
(
const
char
*
const
ppsz_values
[
KEY_MAX
])
{
GHashTable
*
p_hash
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
NULL
,
NULL
);
if
(
!
p_hash
)
return
NULL
;
for
(
unsigned
int
i
=
0
;
i
<
KEY_MAX
;
++
i
)
{
if
(
ppsz_values
[
i
])
g_hash_table_insert
(
p_hash
,
(
gpointer
)
ppsz_keys
[
i
],
(
gpointer
)
ppsz_values
[
i
]);
}
return
p_hash
;
}
static
void
ghash_to_value
(
gpointer
key
,
gpointer
value
,
gpointer
user_data
)
{
const
char
**
ppsz_values
=
user_data
;
const
char
*
psz_key
=
key
;
int
i_key
=
str2key
(
psz_key
);
if
(
i_key
==
-
1
||
i_key
>=
KEY_MAX
)
return
;
ppsz_values
[
i_key
]
=
strdup
((
const
char
*
)
value
);
}
static
int
ghashtable_to_values
(
GHashTable
*
g_hash
,
const
char
*
ppsz_values
[
KEY_MAX
])
{
g_hash_table_foreach
(
g_hash
,
ghash_to_value
,
ppsz_values
);
return
VLC_SUCCESS
;
}
static
void
ghashtable_insert_vlc_id
(
GHashTable
*
g_hash
)
{
g_hash_table_insert
(
g_hash
,
(
gpointer
)
".created_by"
,
(
gpointer
)
VLC_KEYSTORE_NAME
);
}
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
)
{
SecretService
*
p_ss
=
(
SecretService
*
)
p_keystore
->
p_sys
;
GHashTable
*
p_hash
=
values_to_ghashtable
(
ppsz_values
);
if
(
!
p_hash
)
return
VLC_EGENERIC
;
ghashtable_insert_vlc_id
(
p_hash
);
SecretValue
*
p_sv
=
secret_value_new
((
const
gchar
*
)
p_secret
,
i_secret_len
,
"text/plain"
);
if
(
!
p_sv
)
{
g_hash_table_unref
(
p_hash
);
return
VLC_EGENERIC
;
}
GCancellable
*
p_canc
=
cancellable_register
();
gboolean
b_ret
=
secret_service_store_sync
(
p_ss
,
NULL
,
p_hash
,
SECRET_COLLECTION_DEFAULT
,
psz_label
,
p_sv
,
p_canc
,
NULL
);
cancellable_unregister
(
p_canc
);
secret_value_unref
(
p_sv
);
g_hash_table_unref
(
p_hash
);
return
b_ret
?
VLC_SUCCESS
:
VLC_EGENERIC
;
}
static
GList
*
items_search
(
SecretService
*
p_ss
,
const
char
*
const
ppsz_values
[
KEY_MAX
],
bool
b_safe
)
{
GHashTable
*
p_hash
=
values_to_ghashtable
(
ppsz_values
);
if
(
!
p_hash
)
return
0
;
/* If true, do not allow to remove non VLC entries */
if
(
b_safe
)
ghashtable_insert_vlc_id
(
p_hash
);
GCancellable
*
p_canc
=
cancellable_register
();
GList
*
p_list
=
secret_service_search_sync
(
p_ss
,
NULL
,
p_hash
,
SECRET_SEARCH_ALL
|
SECRET_SEARCH_UNLOCK
|
SECRET_SEARCH_LOAD_SECRETS
,
p_canc
,
NULL
);
cancellable_unregister
(
p_canc
);
g_hash_table_unref
(
p_hash
);
return
p_list
;
}
static
unsigned
int
Find
(
vlc_keystore
*
p_keystore
,
const
char
*
const
ppsz_values
[
KEY_MAX
],
vlc_keystore_entry
**
pp_entries
)
{
SecretService
*
p_ss
=
(
SecretService
*
)
p_keystore
->
p_sys
;
GList
*
p_list
=
items_search
(
p_ss
,
ppsz_values
,
false
);
if
(
!
p_list
)
return
0
;
unsigned
int
i_found_count
=
g_list_length
(
p_list
);
unsigned
int
i_entry_count
=
0
;
vlc_keystore_entry
*
p_entries
=
calloc
(
i_found_count
,
sizeof
(
vlc_keystore_entry
));
if
(
!
p_entries
)
goto
error
;
for
(
GList
*
l
=
p_list
;
l
!=
NULL
;
l
=
l
->
next
)
{
SecretItem
*
p_item
=
(
SecretItem
*
)
l
->
data
;
GHashTable
*
p_attrs
=
secret_item_get_attributes
(
p_item
);
vlc_keystore_entry
*
p_entry
=
&
p_entries
[
i_entry_count
++
];
/* fill ppsz_values */
if
(
ghashtable_to_values
(
p_attrs
,
(
const
char
**
)
p_entry
->
ppsz_values
))
{
g_hash_table_unref
(
p_attrs
);
goto
error
;
}
g_hash_table_unref
(
p_attrs
);
/* fill secret */
SecretValue
*
p_secret_value
=
secret_item_get_secret
(
p_item
);
gsize
i_len
;
const
gchar
*
psz_value
=
secret_value_get
(
p_secret_value
,
&
i_len
);
if
(
i_len
>
0
)
{
if
(
vlc_keystore_entry_set_secret
(
p_entry
,
(
const
uint8_t
*
)
psz_value
,
i_len
))
{
secret_value_unref
(
p_secret_value
);
goto
error
;
}
}
secret_value_unref
(
p_secret_value
);
}
g_list_free_full
(
p_list
,
g_object_unref
);
*
pp_entries
=
p_entries
;
return
i_entry_count
;
error:
g_list_free_full
(
p_list
,
g_object_unref
);
if
(
i_entry_count
>
0
)
vlc_keystore_release_entries
(
p_entries
,
i_entry_count
);
return
0
;
}
static
unsigned
int
Remove
(
vlc_keystore
*
p_keystore
,
const
char
*
const
ppsz_values
[
KEY_MAX
])
{
SecretService
*
p_ss
=
(
SecretService
*
)
p_keystore
->
p_sys
;
GList
*
p_list
=
items_search
(
p_ss
,
ppsz_values
,
true
);
if
(
!
p_list
)
return
0
;
unsigned
int
i_entry_count
=
0
;
for
(
GList
*
l
=
p_list
;
l
!=
NULL
;
l
=
l
->
next
)
{
SecretItem
*
p_item
=
(
SecretItem
*
)
l
->
data
;
secret_item_delete
(
p_item
,
NULL
,
NULL
,
NULL
);
i_entry_count
++
;
}
g_list_free_full
(
p_list
,
g_object_unref
);
return
i_entry_count
;
}
struct
secrets_watch_data
{
vlc_sem_t
sem
;
bool
b_running
;
};
static
void
dbus_appeared_cb
(
GDBusConnection
*
connection
,
const
gchar
*
name
,
const
gchar
*
name_owner
,
gpointer
user_data
)
{
(
void
)
connection
;
(
void
)
name
;
(
void
)
name_owner
;
struct
secrets_watch_data
*
p_watch_data
=
user_data
;
p_watch_data
->
b_running
=
true
;
vlc_sem_post
(
&
p_watch_data
->
sem
);
}
static
void
dbus_vanished_cb
(
GDBusConnection
*
connection
,
const
gchar
*
name
,
gpointer
user_data
)
{
(
void
)
connection
;
(
void
)
name
;
struct
secrets_watch_data
*
p_watch_data
=
user_data
;
p_watch_data
->
b_running
=
false
;
vlc_sem_post
(
&
p_watch_data
->
sem
);
}
static
int
Open
(
vlc_object_t
*
p_this
)
{
if
(
!
p_this
->
b_force
)
{
/* First, check if secrets service is running using g_bus_watch_name().
* Indeed, secret_service_get_sync will spawn a service if it's not
* running, even on non Gnome environments */
struct
secrets_watch_data
watch_data
;
watch_data
.
b_running
=
false
;
vlc_sem_init
(
&
watch_data
.
sem
,
0
);
guint
i_id
=
g_bus_watch_name
(
G_BUS_TYPE_SESSION
,
"org.freedesktop.secrets"
,
G_BUS_NAME_WATCHER_FLAGS_NONE
,
dbus_appeared_cb
,
dbus_vanished_cb
,
&
watch_data
,
NULL
);
/* We are guaranteed that one of the callbacks will be invoked after
* calling g_bus_watch_name */
vlc_sem_wait_i11e
(
&
watch_data
.
sem
);
g_bus_unwatch_name
(
i_id
);
vlc_sem_destroy
(
&
watch_data
.
sem
);
if
(
!
watch_data
.
b_running
)
return
VLC_EGENERIC
;
}
GCancellable
*
p_canc
=
cancellable_register
();
SecretService
*
p_ss
=
secret_service_get_sync
(
SECRET_SERVICE_NONE
,
p_canc
,
NULL
);
cancellable_unregister
(
p_canc
);
if
(
!
p_ss
)
return
VLC_EGENERIC
;
vlc_keystore
*
p_keystore
=
(
vlc_keystore
*
)
p_this
;
p_keystore
->
p_sys
=
(
vlc_keystore_sys
*
)
p_ss
;
p_keystore
->
pf_store
=
Store
;
p_keystore
->
pf_find
=
Find
;
p_keystore
->
pf_remove
=
Remove
;
return
VLC_SUCCESS
;
}
static
void
Close
(
vlc_object_t
*
p_this
)
{
vlc_keystore
*
p_keystore
=
(
vlc_keystore
*
)
p_this
;
SecretService
*
p_ss
=
(
SecretService
*
)
p_keystore
->
p_sys
;
g_object_unref
(
p_ss
);
secret_service_disconnect
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment