Disable update checking per default, re-enable with --enable-update-check

Add OpenPGP code, still unused as there is no download of binaries at the moment

We will need to define (and write) the files (and their location) we will use in the update system:

    * We will use a file per arch, which will be signed
    * ALL VideoLAN gpg public keys will be stored on http://download.videolan.org/pub/keys/XXXXXXXXXXXXXXXX.asc where XXXXXXXXXXXXXXXX is the long id of the key
    * Every downloadable file will be signed with gpg --sign --detach --armor
This commit is contained in:
Rafaël Carré 2007-12-14 17:53:27 +00:00
parent 2f06355e03
commit 48c2ac8c87
18 changed files with 958 additions and 11 deletions

View File

@ -5589,6 +5589,20 @@ then
fi
AM_CONDITIONAL([HAVE_LIBGCRYPT], [test "${have_libgcrypt}" = "yes"])
dnl
dnl update checking system
dnl
AC_ARG_ENABLE(update-check,
[ --enable-update-check update checking system (default disabled)])
if test "${enable_update_check}" = "yes"
then
if test "${have_libgcrypt}" != "yes"
then
AC_MSG_ERROR([libgcrypt is required for update checking system])
fi
VLC_ADD_LIBS([libvlc], [-lgcrypt])
AC_DEFINE([UPDATE_CHECK], [1], [Define if you want to use the VLC update mechanism])
fi
dnl
dnl Endianness check, AC_C_BIGENDIAN doesn't work if we are cross-compiling

View File

@ -15,6 +15,7 @@
· read all the commits and add important things to the NEWS file
· update the milestones info on https://trac.videolan.org/vlc
- Add a note about the matching contrib package in INSTALL.win32
- Make sure that the gpg key embedded in include/vlc_update.h is the last one
* Commit
@ -32,19 +33,20 @@
* BeOS Packages
Information on building: http://developers.videolan.org/vlc/beos-compile.html
Configure with --enable-update-check
Build in the "buildbeos" chroot on altair.
# add the .zip files to /opt/ftp/pub/videolan/testing/vlc-X.X.X/beos/
generate md5 hashes and gpg signature of these files
* Win32 Packages
make the packages using the nightly builds configure/options/...
make the packages using the nightly builds configure/options/... , don't forget --enable-update-check
don't forget to test the installer and uninstaller (the first 0.8.4 uninstaller was broken ...
kind of suxxs)
add the .zip and .exe files to /opt/ftp/pub/videolan/testing/vlc-X.X.X/win32/
generate md5 hashes and gpg signature of these files
* OS X packages
At the moment, only FK can do them (so they can be compatible with OS X 10.2)
Later: on the G5
configure with --enable-update-check
generate md5 hashes and gpg signature of these files
* Commit changes ... it never works the first time

View File

@ -1,10 +1,11 @@
/*****************************************************************************
* vlc_update.h: VLC update and plugins download
*****************************************************************************
* Copyright (C) 2005 the VideoLAN team
* Copyright © 2005-2007 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
* Rafaël Carré <funman@videolanorg>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,17 +26,226 @@
#error You are not libvlc or one of its plugins. You cannot include this file
#endif
#ifdef UPDATE_CHECK
#ifndef _VLC_UPDATE_H
#define _VLC_UPDATE_H
#include <vlc/vlc.h>
#include <vlc_stream.h> /* key & signature downloading */
#include <vlc_strings.h> /* b64 decoding */
#include <vlc_charset.h> /* utf8_fopen() */
#include <gcrypt.h> /* cryptography and digest algorithms */
/**
* \defgroup update Update
*
* @{
*/
enum /* Public key algorithms */
{
/* we will only use DSA public keys */
PUBLIC_KEY_ALGO_DSA = 0x11
};
enum /* Digest algorithms */
{
/* and DSA use SHA-1 digest */
DIGEST_ALGO_SHA1 = 0x02
};
enum /* Packet types */
{
SIGNATURE_PACKET = 0x02,
PUBLIC_KEY_PACKET = 0x06,
USER_ID_PACKET = 0x0d
};
enum /* Signature types */
{
BINARY_SIGNATURE = 0x00,
TEXT_SIGNATURE = 0x01,
/* Public keys signatures */
GENERIC_KEY_SIGNATURE = 0x10, /* No assumption of verification */
PERSONA_KEY_SIGNATURE = 0x11, /* No verification has been made */
CASUAL_KEY_SIGNATURE = 0x12, /* Some casual verification */
POSITIVE_KEY_SIGNATURE = 0x13 /* Substantial verification */
};
enum /* Signature subpacket types */
{
ISSUER_SUBPACKET = 0x10
};
struct public_key_packet_t
{ /* a public key packet (DSA/SHA-1) is 418 bytes */
uint8_t version; /* we use only version 4 */
uint8_t timestamp[4]; /* creation time of the key */
uint8_t algo; /* we only use DSA */
/* the multi precision integers, with their 2 bytes length header */
uint8_t p[2+128];
uint8_t q[2+20];
uint8_t g[2+128];
uint8_t y[2+128];
};
/* used for public key signatures */
struct signature_packet_v4_t
{ /* hashed_data or unhashed_data can be empty, so the signature packet is
* theorically at least 54 bytes long, but always more than that. */
uint8_t version;
uint8_t type;
uint8_t public_key_algo;
uint8_t digest_algo;
uint8_t hashed_data_len[2];
uint8_t *hashed_data;
uint8_t unhashed_data_len[2];
uint8_t *unhashed_data;
uint8_t hash_verification[2];
/* The part below is made of consecutive MPIs, their number and size being
* public-key-algorithm dependant.
* But since we use DSA signatures only, we fix it. */
uint8_t r[2+20];
uint8_t s[2+20];
};
/* Used for binary document signatures (to be compatible with older software)
* DSA/SHA-1 is always 65 bytes */
struct signature_packet_v3_t
{
uint8_t header[2];
uint8_t version; /* 3 */
uint8_t hashed_data_len; /* MUST be 5 */
uint8_t type;
uint8_t timestamp[4]; /* 4 bytes scalar number */
uint8_t issuer_longid[8]; /* The key which signed the document */
uint8_t public_key_algo; /* we only know about DSA */
uint8_t digest_algo; /* and his little sister SHA-1 */
uint8_t hash_verification[2];/* the 2 1st bytes of the SHA-1 hash */
/* The part below is made of consecutive MPIs, their number and size being
* public-key-algorithm dependant.
* But since we use DSA signatures only, we fix it. */
uint8_t r[2+20];
uint8_t s[2+20];
};
typedef struct public_key_packet_t public_key_packet_t;
typedef struct signature_packet_v4_t signature_packet_v4_t;
typedef struct signature_packet_v3_t signature_packet_v3_t;
struct public_key_t
{
uint8_t longid[8]; /* Long id */
uint8_t *psz_username; /* USER ID */
public_key_packet_t key; /* Public key packet */
signature_packet_v4_t sig; /* Signature packet, by the embedded key */
};
typedef struct public_key_t public_key_t;
/* We trust this public key, and by extension, also keys signed by it. */
//#define OLD 1 //Define OLD to use Videolan Key 2006, to test public key download
static uint8_t videolan_public_key_longid[8] = {
#ifdef OLD
0xC3, 0x67, 0xD8, 0xB9, 0x81, 0xCA, 0xCA, 0x84
#else
0x90, 0x28, 0x17, 0xE4, 0xAA, 0x5F, 0x4D, 0xE6
#endif
};
static uint8_t videolan_public_key[] = {
#ifdef OLD
"-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
"Version: GnuPG v2.0.4 (FreeBSD)\n"
"\n"
"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\n"
"=tVe2\n"
"-----END PGP PUBLIC KEY BLOCK-----\n"
#else
"-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
"Version: GnuPG v2.0.4 (FreeBSD)\n"
"\n"
"mQGiBEWbjf8RBAC+4m2yYYzuA0+D5JQatKmoxG4z3+bat08tMz0YvBUp1UU+95i4\n"
"cP9ndklv3yzhtZ4MIx5yy64FXtPi0/NQiikEVYPYn2KMO4LCfZCwYBEizVWzABya\n"
"LZcffCP/3VhoR90NUluWyi+zVAn9KNIRlnhnYpDDlI76fCrTTHDCtgpImwCg7VzB\n"
"4L6O0JpUJBCZOCAPJNYirUkD/3uCZe4vK4kLW+W3HB+grMCI1uFULmVSKMBQZc+p\n"
"dqDq++u3zYGqiMNaVrLg/J4GSH/P0ossXEtmTVjLHF4nJ7HXfIjqkqdkxq7g9odY\n"
"/dkA/aC7z4JBgcYfRnDMqfL12C+3b+KSwxQSzPcbvsFYm2KTgteLwG3mRlpL7Dh5\n"
"S70nBAC1PkIl7mP4OL7vpQk9dkdQCARJLgyn5pu/pZV7He4fDLHkUr/atnYaIHk1\n"
"15xl/ziHcBql2WmF0Uff9SuuNOi/hFCuWZSwPKsgtIhYZ5ut4FrBAVkqHV2CgxFp\n"
"aSiA7+FTG91++LDsg2xrHyTRW+fQnPdpf5a4H1fF15azo40h17QjVmlkZW9MQU4g\n"
"UmVsZWFzZSBTaWduaW5nIEtleSAoMjAwNymIRgQQEQIABgUCRZ41PgAKCRDDZ9i5\n"
"gcrKhPmUAJ49Krgt6ZPZZ2YkW7fWFwTvSgGongCePDjnFh1g4078f7lycT4wFk/c\n"
"vPiIRgQQEQIABgUCRZ71NQAKCRD9Ibw7rD4IebztAKCxuyWCjF2JPAe1hdZqNNbE\n"
"/gWDRACfaBw6mpHh3+jZuNnRk6NctFMbTzWIRgQTEQIABgUCRZuOiQAKCRDD7G2+\n"
"3W0SvRkEAJ9cCPrbfzoTHKUVlGLAKbx5pcoutQCdENlo4nwXbQHaREDqm+ISBU3p\n"
"iXeIZgQTEQIAJgUCRZuN/wIbAwUJAeEzgAYLCQgHAwIEFQIIAwQWAgMBAh4BAheA\n"
"AAoJEJAoF+SqX03m4ZQAoOSj3JzzUuY+n/oS0Y4/yZ4tThNNAJ4h+9FacWApQdNJ\n"
"+PcydRFEEm203LkCDQRFm44DEAgAlNLlnyIkLJ/Uyncsd5nB46LqQpJDLJ3AalfN\n"
"44Vy3aOG+aA7JsNL5T5r5WRGnAf41qSOFiuZHwjfrtKb4TWkcfWlpsi8t5uasII9\n"
"WAVX2aVIbiPMNWUnhQIn8rjCRLm2t/0Hch0HDbXaI/hvub5qhmSHfmqzlkuEUyVu\n"
"H+beivX8pQwxqpcWXrmwuNzhISR1DsWBn5u0WcOSqUDtFG5Me8AuPFR1oxdYTtvC\n"
"vqlVnw6ag3QuNqaAgWDU5Ug/U10ZxCZTn5TAcp+1ZDlM/dXIwh8wKXDjiKqHgYg1\n"
"VLQ4fOsscTJoUDOaobeaVwTcDaSB4yQ3bhB2q5fLKqj+bNrY9wADBQf/Rw92M9b/\n"
"JRs5IpX3fcrgHetVLHPiRuW8btD6EkmlgyRFOwOCzOSlSzFW6DKFrbOvd01EWkaP\n"
"4PWJNW7b7OZqzK+UWzlWTgtV/2iUJtHg3+euZRdc5V9gqW17+HIAxjJVE53Syn8u\n"
"kiJpk7HebtQo/v/pk3jtxdeJU3fY8ZAKJFl8V9aAj7ATFaAhYohzyKTRYc04F0n6\n"
"VJDtwQkobdhq2//+5hSVrJ9wXRRF6XFVxc32NinqDEYrJUvTVayYu28Ivg4CTlts\n"
"a+R7x92aDVT2KT+voPIGZxPYjALGa/I2hrlEYD9CiRFNBKAzRiNGAOo67SNI4hDu\n"
"rFWRmMNOONWpIIhPBBgRAgAPBQJFm44DAhsMBQkB4TOAAAoJEJAoF+SqX03m57kA\n"
"oMPb2o2D9gSwQFKXhamx2YdrykHOAKDqQ1tHH3ULY5cLLAKVaQtsNhVEtQ==\n"
"=qrc1\n"
"-----END PGP PUBLIC KEY BLOCK-----\n"
#endif
};
enum
{
UpdateReleaseStatusOlder,
@ -67,7 +277,6 @@ struct update_t
struct update_release_t release; ///< Release (version)
};
#define update_New( a ) __update_New( VLC_OBJECT( a ) )
VLC_EXPORT( update_t *, __update_New, ( vlc_object_t * ) );
@ -80,3 +289,5 @@ VLC_EXPORT( int, update_CompareReleaseToCurrent, ( update_t * ) );
*/
#endif
#endif

View File

@ -96,7 +96,9 @@ static int AudioConfig ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int Menu ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
#ifdef UPDATE_CHECK
static void checkUpdates( intf_thread_t *p_intf );
#endif
/* Status Callbacks */
static int TimeOffsetChanged( vlc_object_t *, char const *,
@ -750,10 +752,12 @@ static void Run( intf_thread_t *p_intf )
Help( p_intf, b_longhelp );
}
#ifdef UPDATE_CHECK
else if( !strcmp( psz_cmd, "check-updates" ) )
{
checkUpdates( p_intf );
}
#endif
else if( !strcmp( psz_cmd, "key" ) || !strcmp( psz_cmd, "hotkey" ) )
{
var_SetInteger( p_intf->p_libvlc, "key-pressed",
@ -922,9 +926,11 @@ static void Help( intf_thread_t *p_intf, vlc_bool_t b_longhelp)
msg_rc(_("| @name mosaic-cols #. . . . . . . . . . .number of cols"));
msg_rc(_("| @name mosaic-order id(,id)* . . . . order of pictures "));
msg_rc(_("| @name mosaic-keep-aspect-ratio {0,1} . . .aspect ratio"));
#ifdef UPDATE_CHECK
msg_rc( "| ");
msg_rc(_("| check-updates [newer] [equal] [older]\n"
"| [undef] [info] [source] [binary] [plugin]"));
#endif
msg_rc( "| ");
}
msg_rc(_("| help . . . . . . . . . . . . . . . this help message"));
@ -1634,7 +1640,7 @@ static int VideoConfig( vlc_object_t *p_this, char const *psz_cmd,
intf_thread_t *p_intf = (intf_thread_t*)p_this;
input_thread_t *p_input = NULL;
vout_thread_t * p_vout;
const char * psz_variable;
const char * psz_variable = NULL;
int i_error;
p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
@ -2105,6 +2111,7 @@ static input_item_t *parse_MRL( intf_thread_t *p_intf, char *psz_mrl )
/*****************************************************************************
* checkUpdates : check for updates
****************************************************************************/
#ifdef UPDATE_CHECK
static void checkUpdates( intf_thread_t *p_intf )
{
update_t *p_u = update_New( p_intf );
@ -2122,3 +2129,4 @@ static void checkUpdates( intf_thread_t *p_intf )
msg_rc( "\n+----Last version" );
update_Delete( p_u );
}
#endif

View File

@ -101,7 +101,9 @@ struct intf_sys_t
id o_embedded_list; /* VLCEmbeddedList*/
id o_interaction_list; /* VLCInteractionList*/
id o_sfilters; /* VLCsFilters */
#ifdef UPDATE_CHECK
id o_update; /* VLCUpdate */
#endif
id o_eyetv; /* VLCEyeTVController */
BOOL nib_main_loaded; /* main nibfile */
BOOL nib_open_loaded; /* open nibfile */

View File

@ -393,7 +393,9 @@ static VLCMain *_o_sharedMainInstance = nil;
o_embedded_list = [[VLCEmbeddedList alloc] init];
o_interaction_list = [[VLCInteractionList alloc] init];
o_sfilters = nil;
#ifdef UPDATE_CHECK
//FIXME o_update = [[VLCUpdate alloc] init];
#endif
i_lastShownVolume = -1;
@ -785,6 +787,7 @@ static VLCMain *_o_sharedMainInstance = nil;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
#ifdef UPDATE_CHECK
/* Check for update silently on startup */
if ( !nib_update_loaded )
nib_update_loaded = [NSBundle loadNibNamed:@"Update" owner:self];
@ -792,7 +795,8 @@ static VLCMain *_o_sharedMainInstance = nil;
// FIXME
//if([o_update shouldCheckForUpdate])
// [NSThread detachNewThreadSelector:@selector(checkForUpdate) toTarget:o_update withObject:NULL];
#endif
/* Handle sleep notification */
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:)
name:NSWorkspaceWillSleepNotification object:nil];
@ -1909,6 +1913,7 @@ static VLCMain *_o_sharedMainInstance = nil;
[o_prefs showPrefs];
}
#ifdef UPDATE_CHECK
- (IBAction)checkForUpdate:(id)sender
{/* FIXME
if( !nib_update_loaded )
@ -1916,6 +1921,7 @@ static VLCMain *_o_sharedMainInstance = nil;
[o_update showUpdateWindow];
*/}
#endif
- (IBAction)viewHelp:(id)sender
{

View File

@ -21,6 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifdef UPDATE_CHECK
#import <Cocoa/Cocoa.h>
#import <vlc_update.h>
@ -55,3 +56,4 @@
+ (VLCUpdate *)sharedInstance;
@end
#endif

View File

@ -27,6 +27,7 @@
* ../wxwidgets/dialogs/updatevlc.cpp, written by Antoine Cellerier.
*****************************************************************************/
#ifdef UPDATE_CHECK
/*****************************************************************************
* Preamble
@ -351,3 +352,5 @@ static VLCUpdate *_o_sharedInstance = nil;
}
@end
#endif

View File

@ -22,9 +22,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <vlc/vlc.h>
#include "dialogs/help.hpp"
#include <vlc_about.h>
#ifdef UPDATE_CHECK
#include <vlc_update.h>
#endif
#include "dialogs_provider.hpp"
@ -159,7 +164,7 @@ void AboutDialog::close()
this->toggleVisible();
}
#ifdef UPDATE_CHECK
UpdateDialog *UpdateDialog::instance = NULL;
UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
@ -217,3 +222,5 @@ void UpdateDialog::updateOrUpload()
<body><center>You have the latest version of VLC.</center></body></html>" );
}
}
#endif

View File

@ -24,7 +24,7 @@
#ifndef _HELP_DIALOG_H_
#define _HELP_DIALOG_H_
#include <vlc_update.h>
#include <vlc/vlc.h>
#include "util/qvlcframe.hpp"
@ -70,7 +70,7 @@ public slots:
void close();
};
#ifdef UPDATE_CHECK
class UpdateDialog : public QVLCFrame
{
Q_OBJECT;
@ -92,6 +92,6 @@ private slots:
void close();
void updateOrUpload();
};
#endif
#endif

View File

@ -172,10 +172,12 @@ void DialogsProvider::helpDialog()
HelpDialog::getInstance( p_intf )->toggleVisible();
}
#ifdef UPDATE_CHECK
void DialogsProvider::updateDialog()
{
UpdateDialog::getInstance( p_intf )->toggleVisible();
}
#endif
void DialogsProvider::aboutDialog()
{

View File

@ -146,7 +146,9 @@ public slots:
void messagesDialog();
void vlmDialog();
void helpDialog();
#ifdef UPDATE_CHECK
void updateDialog();
#endif
void aboutDialog();
void gotoTimeDialog();
void podcastConfigureDialog();

View File

@ -22,6 +22,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc_intf_strings.h>
#include "main_interface.hpp"
@ -457,7 +459,9 @@ QMenu *QVLCMenu::HelpMenu()
QMenu *menu = new QMenu();
addDPStaticEntry( menu, qtr( "Help..." ) , "",
":/pixmaps/menus_help_16px.png", SLOT( helpDialog() ), "F1" );
#ifdef UPDATE_CHECK
addDPStaticEntry( menu, qtr( "Update" ) , "", "", SLOT( updateDialog() ), "");
#endif
menu->addSeparator();
addDPStaticEntry( menu, qtr( I_MENU_ABOUT ), "", "", SLOT( aboutDialog() ),
"Ctrl+F1" );

View File

@ -63,7 +63,9 @@ private:
void Open( int i_access_method, int i_arg );
/* Event handlers (these functions should _not_ be virtual) */
#ifdef UPDATE_CHECK
void OnUpdateVLC( wxCommandEvent& event );
#endif
//void OnVLM( wxCommandEvent& event );
void OnInteraction( wxCommandEvent& event );
void OnExit( wxCommandEvent& event );
@ -108,7 +110,9 @@ public:
wxFrame *p_prefs_dialog;
wxFrame *p_bookmarks_dialog;
wxFileDialog *p_file_generic_dialog;
#ifdef UPDATE_CHECK
UpdateVLC *p_updatevlc_dialog;
#endif
//VLMFrame *p_vlm_dialog;
};
}
@ -156,8 +160,10 @@ BEGIN_EVENT_TABLE(DialogsProvider, wxFrame)
EVT_COMMAND(INTF_DIALOG_EXIT, wxEVT_DIALOG,
DialogsProvider::OnExitThread)
#ifdef UPDATE_CHECK
EVT_COMMAND(INTF_DIALOG_UPDATEVLC, wxEVT_DIALOG,
DialogsProvider::OnUpdateVLC)
#endif
#if 0
EVT_COMMAND(INTF_DIALOG_VLM, wxEVT_DIALOG,
DialogsProvider::OnVLM)
@ -549,6 +555,7 @@ void DialogsProvider::OnExitThread( wxCommandEvent& WXUNUSED(event) )
wxTheApp->ExitMainLoop();
}
#ifdef UPDATE_CHECK
void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
{
/* Show/hide the file info window */
@ -560,6 +567,7 @@ void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
p_updatevlc_dialog->Show( !p_updatevlc_dialog->IsShown() );
}
}
#endif
#if 0
void DialogsProvider::OnVLM( wxCommandEvent& WXUNUSED(event) )

View File

@ -21,6 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef UPDATE_CHECK
/*****************************************************************************
* Preamble
*****************************************************************************/
@ -120,3 +122,4 @@ void UpdateVLC::OnCheckForUpdate( wxCommandEvent& event )
SetSizerAndFit( main_sizer );
Layout();
}
#endif

View File

@ -21,6 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef UPDATE_CHECK
#ifndef _WXVLC_UPDATEVLC_H_
#define _WXVLC_UPDATEVLC_H_
@ -54,3 +56,5 @@ namespace wxvlc
};
#endif
#endif

View File

@ -300,7 +300,9 @@ enum
About_Event = wxID_ABOUT,
OnWebLink_Event,
OnWebHelp_Event,
#ifdef UPDATE_CHECK
UpdateVLC_Event,
#endif
//VLM_Event,
Iconize_Event,
@ -314,7 +316,9 @@ BEGIN_EVENT_TABLE(Interface, wxFrame)
EVT_MENU(About_Event, Interface::OnAbout)
EVT_MENU(OnWebLink_Event, Interface::OnWebLink)
EVT_MENU(OnWebHelp_Event, Interface::OnWebHelp)
#ifdef UPDATE_CHECK
EVT_MENU(UpdateVLC_Event, Interface::OnShowDialog)
#endif
//EVT_MENU(VLM_Event, Interface::OnShowDialog)
EVT_MENU(Playlist_Event, Interface::OnShowDialog)
@ -617,8 +621,10 @@ void Interface::CreateOurMenuBar()
help_menu->Append( OnWebHelp_Event, wxU(_("Online Help")) );
help_menu->AppendSeparator();
help_menu->Append( About_Event, wxU(_("About...")) );
#ifdef UPDATE_CHECK
help_menu->AppendSeparator();
help_menu->Append( UpdateVLC_Event, wxU(_("Check for Updates...")) );
#endif
/* Append the freshly created menus to the menu bar... */
wxMenuBar *menubar = new wxMenuBar();
@ -1024,9 +1030,11 @@ void Interface::OnShowDialog( wxCommandEvent& event )
case Bookmarks_Event:
i_id = INTF_DIALOG_BOOKMARKS;
break;
#ifdef UPDATE_CHECK
case UpdateVLC_Event:
i_id = INTF_DIALOG_UPDATEVLC;
break;
#endif
#if 0
case VLM_Event:
i_id = INTF_DIALOG_VLM;

View File

@ -26,12 +26,19 @@
* This file contains functions related to VLC and plugins update management
*/
/*
* TODO: * pgp verification of the update file
* binary download, and pgp verification
*/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#ifdef UPDATE_CHECK
#include <ctype.h> /* tolower() */
#include <assert.h>
@ -76,6 +83,658 @@ static int extracmp( char *psz_1, char *psz_2 );
static int CompareReleases( const struct update_release_t *p1,
const struct update_release_t *p2 );
/*****************************************************************************
* OpenPGP functions
*****************************************************************************/
#define packet_type( c ) ( ( c & 0x3c ) >> 2 ) /* 0x3C = 00111100 */
#define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
static inline int scalar_number( uint8_t *p, int header_len )
{
if( header_len == 1 )
return( p[0] );
else if( header_len == 2 )
return( (p[0] << 8) + p[1] );
else if( header_len == 4 )
return( (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3] );
else
abort();
}
/* number of data bytes in a MPI */
#define mpi_len( mpi ) ( ( scalar_number( mpi, 2 ) + 7 ) / 8 )
/*
* fill a public_key_packet_t structure from public key packet data
* verify that it is a version 4 public key packet, using DSA
*/
static int parse_public_key_packet( public_key_packet_t *p_key, uint8_t *p_buf,
size_t i_packet_len )
{
if( i_packet_len != 418 )
return VLC_EGENERIC;
p_key->version = *p_buf++;
if( p_key->version != 4 )
return VLC_EGENERIC;
/* warn when timestamp is > date ? */
memcpy( p_key->timestamp, p_buf, 4 ); p_buf += 4;
p_key->algo = *p_buf++;
if( p_key->algo != PUBLIC_KEY_ALGO_DSA )
return VLC_EGENERIC;
memcpy( p_key->p, p_buf, 2+128 ); p_buf += 2+128;
if( mpi_len( p_key->p ) != 128 )
return VLC_EGENERIC;
memcpy( p_key->q, p_buf, 2+20 ); p_buf += 2+20;
if( mpi_len( p_key->q ) != 20 )
return VLC_EGENERIC;
memcpy( p_key->g, p_buf, 2+128 ); p_buf += 2+128;
if( mpi_len( p_key->g ) != 128 )
return VLC_EGENERIC;
memcpy( p_key->y, p_buf, 2+128 ); p_buf += 2+128;
if( mpi_len( p_key->y ) != 128 )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
/*
* fill a signature_packet_v4_t from signature packet data
* verify that it was used with a DSA public key, using SHA-1 digest
*/
static int parse_signature_v4_packet( signature_packet_v4_t *p_sig,
uint8_t *p_buf, size_t i_sig_len )
{
if( i_sig_len < 54 )
return VLC_EGENERIC;
p_sig->version = *p_buf++;
if( p_sig->version != 4 )
return VLC_EGENERIC;
p_sig->type = *p_buf++;
if( p_sig->type < GENERIC_KEY_SIGNATURE ||
p_sig->type > POSITIVE_KEY_SIGNATURE )
return VLC_EGENERIC;
p_sig->public_key_algo = *p_buf++;
if( p_sig->public_key_algo != PUBLIC_KEY_ALGO_DSA )
return VLC_EGENERIC;
p_sig->digest_algo = *p_buf++;
if( p_sig->digest_algo != DIGEST_ALGO_SHA1 )
return VLC_EGENERIC;
memcpy( p_sig->hashed_data_len, p_buf, 2 ); p_buf += 2;
size_t i_pos = 6;
size_t i_hashed_data_len = scalar_number( p_sig->hashed_data_len, 2 );
i_pos += i_hashed_data_len;
if( i_pos > i_sig_len - 48 ) /* r & s are 44 bytes in total,
* + the unhashed data length (2 bytes)
* + the hash verification (2 bytes) */
return VLC_EGENERIC;
p_sig->hashed_data = (uint8_t*) malloc( i_hashed_data_len );
if( !p_sig->hashed_data )
return VLC_ENOMEM;
memcpy( p_sig->hashed_data, p_buf, i_hashed_data_len );
p_buf += i_hashed_data_len;
memcpy( p_sig->unhashed_data_len, p_buf, 2 ); p_buf += 2;
size_t i_unhashed_data_len = scalar_number( p_sig->unhashed_data_len, 2 );
i_pos += 2 + i_unhashed_data_len;
if( i_pos != i_sig_len - 46 )
{
free( p_sig->hashed_data );
return VLC_EGENERIC;
}
p_sig->unhashed_data = (uint8_t*) malloc( i_unhashed_data_len );
if( !p_sig->unhashed_data )
{
free( p_sig->hashed_data );
return VLC_ENOMEM;
}
memcpy( p_sig->unhashed_data, p_buf, i_unhashed_data_len );
p_buf += i_unhashed_data_len;
memcpy( p_sig->hash_verification, p_buf, 2 ); p_buf += 2;
memcpy( p_sig->r, p_buf, 22 ); p_buf += 22;
if( mpi_len( p_sig->r ) != 20 )
{
free( p_sig->hashed_data );
free( p_sig->unhashed_data );
return VLC_EGENERIC;
}
memcpy( p_sig->s, p_buf, 22 );
if( mpi_len( p_sig->s ) != 20 )
{
free( p_sig->hashed_data );
free( p_sig->unhashed_data );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
/*
* crc_octets() was lamely copied from rfc 2440
* Copyright (C) The Internet Society (1998). All Rights Reserved.
*/
#define CRC24_INIT 0xB704CEL
#define CRC24_POLY 0x1864CFBL
static long crc_octets( uint8_t *octets, size_t len )
{
long crc = CRC24_INIT;
int i;
while (len--)
{
crc ^= (*octets++) << 16;
for (i = 0; i < 8; i++)
{
crc <<= 1;
if (crc & 0x1000000)
crc ^= CRC24_POLY;
}
}
return crc & 0xFFFFFFL;
}
/*
* Transform an armored document in binary format
* Used on public keys and signatures
*/
static int pgp_unarmor( char *p_ibuf, size_t i_ibuf_len,
uint8_t *p_obuf, size_t i_obuf_len )
{
char *p_ipos = p_ibuf;
uint8_t *p_opos = p_obuf;
int i_end = 0;
int i_header_skipped = 0;
while( !i_end && p_ipos < p_ibuf + i_ibuf_len )
{
if( *p_ipos == '\r' || *p_ipos == '\n' )
{
p_ipos++;
continue;
}
size_t i_line_len = strcspn( p_ipos, "\r\n" );
if( i_line_len == 0 )
continue;
if( !i_header_skipped )
{
if( !strncmp( p_ipos, "-----BEGIN PGP", 14 ) )
i_header_skipped = 1;
p_ipos += i_line_len + 1;
continue;
}
if( !strncmp( p_ipos, "Version:", 8 ) )
{
p_ipos += i_line_len + 1;
continue;
}
if( p_ipos[i_line_len - 1] == '=' )
{
i_end = 1;
p_ipos[i_line_len - 1] = '\0';
}
else
p_ipos[i_line_len] = '\0';
p_opos += vlc_b64_decode_binary_to_buffer( p_opos,
p_obuf - p_opos + i_obuf_len,
p_ipos );
p_ipos += i_line_len + 1;
}
/* XXX: the CRC is OPTIONAL, really require it ? */
if( p_ipos + 5 > p_ibuf + i_ibuf_len || *p_ipos++ != '=' )
return 0;
uint8_t p_crc[3];
if( vlc_b64_decode_binary_to_buffer( p_crc, 3, p_ipos ) != 3 )
return 0;
long l_crc = crc_octets( p_obuf, p_opos - p_obuf );
long l_crc2 = ( 0 << 24 ) + ( p_crc[0] << 16 ) + ( p_crc[1] << 8 ) + p_crc[2];
return l_crc2 == l_crc ? p_opos - p_obuf : 0;
}
/*
* Download the signature associated to a document or a binary file.
* We're given the file's url, we just append ".asc" to it and download
*/
static int download_signature( vlc_object_t *p_this,
signature_packet_v3_t *p_sig, char *psz_url )
{
char *psz_sig = (char*) malloc( strlen( psz_url ) + 4 + 1 ); /* ".asc" + \0 */
if( !psz_sig )
return VLC_ENOMEM;
strcpy( psz_sig, psz_url );
strcat( psz_sig, ".asc" );
stream_t *p_stream = stream_UrlNew( p_this, psz_sig );
free( psz_sig );
if( !p_stream )
return VLC_ENOMEM;
int64_t i_size = stream_Size( p_stream );
if( i_size < 65 )
{
stream_Delete( p_stream );
return VLC_EGENERIC;
}
else if( i_size == 65 ) /* binary format signature */
{
int i_read = stream_Read( p_stream, p_sig, (int)i_size );
stream_Delete( p_stream );
if( i_read != i_size )
return VLC_EGENERIC;
else
return VLC_SUCCESS;
}
char *p_buf = (char*)malloc( i_size );
if( !p_buf )
{
stream_Delete( p_stream );
return VLC_ENOMEM;
}
int i_read = stream_Read( p_stream, p_buf, (int)i_size );
stream_Delete( p_stream );
if( i_read != i_size )
{
free( p_buf );
return VLC_EGENERIC;
}
int i_bytes = pgp_unarmor( p_buf, i_size, (uint8_t*)p_sig, 65 );
free( p_buf );
if( i_bytes != 65 )
return VLC_EGENERIC;
else
return VLC_SUCCESS;
}
/*
* Verify an OpenPGP signature made on some SHA-1 hash, with some DSA public key
*/
static int verify_signature( vlc_object_t *p_this, uint8_t *p_r, uint8_t *p_s,
public_key_packet_t *p_key, uint8_t *p_hash )
{
/* the data to be verified (a SHA-1 hash) */
const char *hash_sexp_s = "(data(flags raw)(value %m))";
/* the public key */
const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
/* the signature */
const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))";
size_t erroff;
gcry_mpi_t p, q, g, y, r, s, hash;
p = q = g = y = r = s = hash = NULL;
gcry_sexp_t key_sexp, hash_sexp, sig_sexp;
key_sexp = hash_sexp = sig_sexp = NULL;
if( gcry_mpi_scan( &p, GCRYMPI_FMT_USG, p_key->p + 2, 128, NULL ) ||
gcry_mpi_scan( &q, GCRYMPI_FMT_USG, p_key->q + 2, 20, NULL ) ||
gcry_mpi_scan( &g, GCRYMPI_FMT_USG, p_key->g + 2, 128, NULL ) ||
gcry_mpi_scan( &y, GCRYMPI_FMT_USG, p_key->y + 2, 128, NULL ) ||
gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, p, q, g, y ) )
goto problem;
if( gcry_mpi_scan( &r, GCRYMPI_FMT_USG, p_r + 2, 20, NULL ) ||
gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, 20, NULL ) ||
gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, r, s ) )
goto problem;
if( gcry_mpi_scan( &hash, GCRYMPI_FMT_USG, p_hash, 20, NULL ) ||
gcry_sexp_build( &hash_sexp, &erroff, hash_sexp_s, hash ) )
goto problem;
if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
goto problem;
return VLC_SUCCESS;
problem:
if( p ) gcry_mpi_release( p );
if( q ) gcry_mpi_release( q );
if( g ) gcry_mpi_release( g );
if( y ) gcry_mpi_release( y );
if( r ) gcry_mpi_release( r );
if( s ) gcry_mpi_release( s );
if( hash ) gcry_mpi_release( hash );
if( key_sexp ) gcry_sexp_release( key_sexp );
if( sig_sexp ) gcry_sexp_release( sig_sexp );
if( hash_sexp ) gcry_sexp_release( hash_sexp );
return VLC_EGENERIC;
}
/*
* Return the long id (8 bytes) of the public key used to generate a signature
*/
static uint8_t *get_issuer_from_signature_v4( signature_packet_v4_t *p_sig )
{
uint8_t *p = p_sig->unhashed_data;
uint8_t *max_pos = p + scalar_number( p_sig->unhashed_data_len, 2 );
while( p < max_pos )
{
int i_subpacket_len = *p < 192 ? *p++ :
*p < 255 ? ((*p++ - 192) << 8) + *p++ + 192 :
((*++p) << 24) + (*++p << 16) + (*++p << 8) + *++p;
if( p >= max_pos - 1 )
return NULL;
if( *p == ISSUER_SUBPACKET )
return p+1;
else
p += i_subpacket_len;
}
return NULL;
}
/*
* fill a public_key_t with public key data, including:
* * public key packet
* * signature packet issued by key which long id is p_sig_issuer
* * user id packet
*/
static int parse_public_key( const uint8_t *p_key_data, size_t i_key_len, public_key_t *p_key, const uint8_t *p_sig_issuer )
{
uint8_t *pos = (uint8_t*) p_key_data;
uint8_t *max_pos = pos + i_key_len;
int i_status = 0;
#define PUBLIC_KEY_FOUND 0x01
#define USER_ID_FOUND 0x02
#define SIGNATURE_FOUND 0X04
uint8_t *p_key_unarmored = NULL;
signature_packet_v4_t sig;
p_key->psz_username = NULL;
p_key->sig.hashed_data = p_key->sig.unhashed_data = NULL;
if( !( *pos & 0x80 ) )
{ /* first byte is ASCII, unarmoring */
p_key_unarmored = (uint8_t*)malloc( i_key_len );
if( !p_key_unarmored )
return VLC_ENOMEM;
int i_len = pgp_unarmor( (char*)p_key_data, i_key_len,
p_key_unarmored, i_key_len );
if( i_len == 0 )
goto error;
pos = p_key_unarmored;
max_pos = pos + i_len;
}
while( pos < max_pos )
{
if( !(*pos & 0x80) || *pos & 0x40 )
goto error;
int i_type = packet_type( *pos );
int i_header_len = packet_header_len( *pos++ );
if( pos + i_header_len > max_pos )
goto error;
int i_packet_len = scalar_number( pos, i_header_len );
pos += i_header_len;
if( pos + i_packet_len > max_pos )
goto error;
switch( i_type )
{
uint8_t *p_issuer;
case PUBLIC_KEY_PACKET:
i_status |= PUBLIC_KEY_FOUND;
if( parse_public_key_packet( &p_key->key, pos, i_packet_len ) != VLC_SUCCESS )
goto error;
break;
case SIGNATURE_PACKET:
if( !p_sig_issuer || i_status & SIGNATURE_FOUND ||
parse_signature_v4_packet( &sig, pos, i_packet_len ) != VLC_SUCCESS )
break;
p_issuer = get_issuer_from_signature_v4( &sig );
if( memcmp( p_issuer, p_sig_issuer, 8 ) == 0 )
{
memcpy( &p_key->sig, &sig, sizeof( signature_packet_v4_t ) );
i_status |= SIGNATURE_FOUND;
}
else
{
free( sig.hashed_data );
free( sig.unhashed_data );
}
break;
case USER_ID_PACKET:
if( p_key->psz_username ) /* save only the first User ID */
break;
i_status |= USER_ID_FOUND;
p_key->psz_username = (uint8_t*)malloc( i_packet_len + 1);
if( !p_key->psz_username )
goto error;
memcpy( p_key->psz_username, pos, i_packet_len );
p_key->psz_username[i_packet_len] = '\0';
break;
default:
break;
}
pos += i_packet_len;
}
free( p_key_unarmored );
if( !( i_status & ( PUBLIC_KEY_FOUND + USER_ID_FOUND ) ) )
return VLC_EGENERIC;
if( p_sig_issuer && !( i_status & SIGNATURE_FOUND ) )
return VLC_EGENERIC;
return VLC_SUCCESS;
error:
free( p_key->sig.hashed_data );
free( p_key->sig.unhashed_data );
free( p_key->psz_username );
free( p_key_unarmored );
return VLC_EGENERIC;
}
/*
* return a sha1 hash of a file
*/
static uint8_t *hash_sha1_from_file( const char *psz_file,
signature_packet_v3_t *p_sig )
{
FILE *f = utf8_fopen( psz_file, "r" );
if( !f )
return NULL;
uint8_t buffer[4096]; //FIXME
gcry_md_hd_t hd;
if( gcry_md_open( &hd, GCRY_MD_SHA1, 0 ) )
{
fclose( f );
return NULL;
}
size_t i_read;
while( ( i_read = fread( buffer, 1, sizeof(buffer), f ) ) > 0 )
gcry_md_write( hd, buffer, i_read );
gcry_md_putc( hd, p_sig->type );
gcry_md_write( hd, &p_sig->timestamp, 4 );
fclose( f );
gcry_md_final( hd );
return( (uint8_t*) gcry_md_read( hd, GCRY_MD_SHA1) );
}
/*
* download a public key (the last one) from videolan server, and parse it
*/
static public_key_t *download_key( vlc_object_t *p_this, const uint8_t *p_longid, const uint8_t *p_signature_issuer )
{
char *psz_url;
if( asprintf( &psz_url, "http://download.videolan.org/pub/keys/%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x.asc",
p_longid[0], p_longid[1],
p_longid[2], p_longid[3],
p_longid[4], p_longid[5],
p_longid[6], p_longid[7] ) == -1 )
return NULL;
stream_t *p_stream = stream_UrlNew( p_this, psz_url );
free( psz_url );
if( !p_stream )
return NULL;
int64_t i_size = stream_Size( p_stream );
if( i_size < 0 )
{
stream_Delete( p_stream );
return NULL;
}
uint8_t *p_buf = (uint8_t*)malloc( i_size );
if( !p_buf )
{
stream_Delete( p_stream );
return NULL;
}
int i_read = stream_Read( p_stream, p_buf, (int)i_size );
stream_Delete( p_stream );
if( i_read != (int)i_size )
{
free( p_buf );
return NULL;
}
public_key_t *p_pkey = (public_key_t*) malloc( sizeof( public_key_t ) );
if( !p_pkey )
{
free( p_buf );
return NULL;
}
int i_error = parse_public_key( p_buf, i_read, p_pkey, p_signature_issuer );
free( p_buf );
if( i_error != VLC_SUCCESS )
{
free( p_pkey );
return NULL;
}
return p_pkey;
}
/*
* Generate a SHA-1 hash on a public key, to verify a signature made on that hash
* Note that we need the signature to compute the hash
*/
static uint8_t *key_sign_hash( public_key_t *p_pkey )
{
gcry_error_t error = 0;
gcry_md_hd_t hd;
error = gcry_md_open( &hd, GCRY_MD_SHA1, 0 );
if( error )
return NULL;
gcry_md_putc( hd, 0x99 );
gcry_md_putc( hd, (418 >> 8) & 0xff );
gcry_md_putc( hd, 418 & 0xff );
gcry_md_write( hd, (uint8_t*)&p_pkey->key, 418 );
gcry_md_putc( hd, 0xb4 );
int i_len = strlen((char*)p_pkey->psz_username);
gcry_md_putc( hd, (i_len << 24) & 0xff );
gcry_md_putc( hd, (i_len << 16) & 0xff );
gcry_md_putc( hd, (i_len << 8) & 0xff );
gcry_md_putc( hd, (i_len) & 0xff );
gcry_md_write( hd, p_pkey->psz_username, i_len );
size_t i_hashed_data_len = scalar_number( p_pkey->sig.hashed_data_len, 2 );
gcry_md_putc( hd, p_pkey->sig.version );
gcry_md_putc( hd, p_pkey->sig.type );
gcry_md_putc( hd, p_pkey->sig.public_key_algo );
gcry_md_putc( hd, p_pkey->sig.digest_algo );
gcry_md_write( hd, p_pkey->sig.hashed_data_len, 2 );
gcry_md_write( hd, p_pkey->sig.hashed_data, i_hashed_data_len );
gcry_md_putc( hd, 0x04 );
gcry_md_putc( hd, 0xff );
i_hashed_data_len += 6; /* hashed data + 6 bytes header */
gcry_md_putc( hd, (i_hashed_data_len << 24) & 0xff);
gcry_md_putc( hd, (i_hashed_data_len << 16) &0xff );
gcry_md_putc( hd, (i_hashed_data_len << 8) & 0xff );
gcry_md_putc( hd, (i_hashed_data_len) & 0xff );
gcry_md_final( hd );
uint8_t *p_hash = gcry_md_read( hd, GCRY_MD_SHA1);
if( p_hash[0] != p_pkey->sig.hash_verification[0] ||
p_hash[1] != p_pkey->sig.hash_verification[1] )
{
free( p_hash );
return NULL;
}
return p_hash;
}
/*****************************************************************************
* Update_t functions
@ -325,3 +984,5 @@ int update_CompareReleaseToCurrent( update_t *p_update )
}
return i_result;
}
#endif