📄 update.c
字号:
/***************************************************************************** * update.c: VLC update checking and downloading ***************************************************************************** * Copyright © 2005-2008 the VideoLAN team * $Id: 96a3948992f7fdfe5aed37b0fe3d8565272d2237 $ * * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org> * Rémi Duraffort <ivoire at via.ecp.fr> 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 * the Free Software Foundation; either release 2 of the License, or * (at your option) any later release. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//** * \file * This file contains functions related to VLC update management *//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_update.h>#ifdef UPDATE_CHECK#include <assert.h>#include <vlc_pgpkey.h>#include <vlc_stream.h>#include <vlc_strings.h>#include <vlc_charset.h>#include <vlc_interface.h>#include <gcrypt.h>#include <vlc_gcrypt.h>#include "update.h"#include "../libvlc.h"/***************************************************************************** * Misc defines *****************************************************************************//* * Here is the format of these "status files" : * First line is the last version: "X.Y.Ze" where: * * X is the major number * * Y is the minor number * * Z is the revision number * * e is an OPTIONAL extra letter * * AKA "0.8.6d" or "0.9.0" * Second line is an url of the binary for this last version * Remaining text is a required description of the update */#if defined( UNDER_CE )# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-ce"#elif defined( WIN32 )# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-win-x86"#elif defined( __APPLE__ )# if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-ppc"# else# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-x86"# endif#elif defined( SYS_BEOS )# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-beos-x86"#else# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"#endif/***************************************************************************** * Local Prototypes *****************************************************************************/static void EmptyRelease( update_t *p_update );static bool GetUpdateFile( update_t *p_update );static char * size_str( long int l_size );/***************************************************************************** * 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 ){ assert( header_len == 1 || header_len == 2 || header_len == 4 ); 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] ); abort(); /* to shut up GCC warning */}/* 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 || i_packet_len < 6 ) return VLC_EGENERIC; size_t i_read = 0; p_key->version = *p_buf++; i_read++; if( p_key->version != 4 ) return VLC_EGENERIC; /* XXX: warn when timestamp is > date ? */ memcpy( p_key->timestamp, p_buf, 4 ); p_buf += 4; i_read += 4; p_key->algo = *p_buf++; i_read++; if( p_key->algo != PUBLIC_KEY_ALGO_DSA ) return VLC_EGENERIC; /* read p */ if( i_read + 2 > i_packet_len ) return VLC_EGENERIC; int i_p_len = mpi_len( p_buf ); if( i_p_len > 128 || i_read + 2 + i_p_len > i_packet_len ) return VLC_EGENERIC; memcpy( p_key->p, p_buf, 2+i_p_len ); p_buf += 2+i_p_len; i_read += 2+i_p_len; /* read q */ if( i_read + 2 > i_packet_len ) return VLC_EGENERIC; int i_q_len = mpi_len( p_buf ); if( i_q_len > 20 || i_read+2+i_q_len > i_packet_len ) return VLC_EGENERIC; memcpy( p_key->q, p_buf, 2+i_q_len ); p_buf += 2+i_q_len; i_read += 2+i_q_len; /* read g */ if( i_read + 2 > i_packet_len ) return VLC_EGENERIC; int i_g_len = mpi_len( p_buf ); if( i_g_len > 128 || i_read+2+i_g_len > i_packet_len ) return VLC_EGENERIC; memcpy( p_key->g, p_buf, 2+i_g_len ); p_buf += 2+i_g_len; i_read += 2+i_g_len; /* read y */ if( i_read + 2 > i_packet_len ) return VLC_EGENERIC; int i_y_len = mpi_len( p_buf ); if( i_y_len > 128 || i_read+2+i_y_len > i_packet_len ) return VLC_EGENERIC; memcpy( p_key->y, p_buf, 2+i_y_len ); i_read += 2+i_y_len; if( i_read != i_packet_len ) /* some extra data eh ? */ return VLC_EGENERIC; return VLC_SUCCESS;}static size_t parse_signature_v3_packet( signature_packet_t *p_sig, uint8_t *p_buf, size_t i_sig_len ){ size_t i_read = 1; /* we already read the version byte */ if( i_sig_len < 19 ) /* signature is at least 19 bytes + the 2 MPIs */ return 0; p_sig->specific.v3.hashed_data_len = *p_buf++; i_read++; if( p_sig->specific.v3.hashed_data_len != 5 ) return 0; p_sig->type = *p_buf++; i_read++; memcpy( p_sig->specific.v3.timestamp, p_buf, 4 ); p_buf += 4; i_read += 4; memcpy( p_sig->issuer_longid, p_buf, 8 ); p_buf += 8; i_read += 8; p_sig->public_key_algo = *p_buf++; i_read++; p_sig->digest_algo = *p_buf++; i_read++; p_sig->hash_verification[0] = *p_buf++; i_read++; p_sig->hash_verification[1] = *p_buf++; i_read++; assert( i_read == 19 ); return i_read;}/* * 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 size_t parse_signature_v4_packet( signature_packet_t *p_sig, uint8_t *p_buf, size_t i_sig_len ){ size_t i_read = 1; /* we already read the version byte */ if( i_sig_len < 10 ) /* signature is at least 10 bytes + the 2 MPIs */ return 0; p_sig->type = *p_buf++; i_read++; p_sig->public_key_algo = *p_buf++; i_read++; p_sig->digest_algo = *p_buf++; i_read++; memcpy( p_sig->specific.v4.hashed_data_len, p_buf, 2 ); p_buf += 2; i_read += 2; size_t i_hashed_data_len = scalar_number( p_sig->specific.v4.hashed_data_len, 2 ); i_read += i_hashed_data_len; if( i_read + 4 > i_sig_len ) return 0; p_sig->specific.v4.hashed_data = (uint8_t*) malloc( i_hashed_data_len ); if( !p_sig->specific.v4.hashed_data ) return 0; memcpy( p_sig->specific.v4.hashed_data, p_buf, i_hashed_data_len ); p_buf += i_hashed_data_len; memcpy( p_sig->specific.v4.unhashed_data_len, p_buf, 2 ); p_buf += 2; i_read += 2; size_t i_unhashed_data_len = scalar_number( p_sig->specific.v4.unhashed_data_len, 2 ); i_read += i_unhashed_data_len; if( i_read + 2 > i_sig_len ) return 0; p_sig->specific.v4.unhashed_data = (uint8_t*) malloc( i_unhashed_data_len ); if( !p_sig->specific.v4.unhashed_data ) return 0; memcpy( p_sig->specific.v4.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; i_read += 2; uint8_t *p, *max_pos; p = p_sig->specific.v4.unhashed_data; max_pos = p + scalar_number( p_sig->specific.v4.unhashed_data_len, 2 ); for( ;; ) { if( p > max_pos ) return 0; size_t i_subpacket_len; if( *p < 192 ) { if( p + 1 > max_pos ) return 0; i_subpacket_len = *p++; } else if( *p < 255 ) { if( p + 2 > max_pos ) return 0; i_subpacket_len = (*p++ - 192) << 8; i_subpacket_len += *p++ + 192; } else { if( p + 4 > max_pos ) return 0; i_subpacket_len = *++p << 24; i_subpacket_len += *++p << 16; i_subpacket_len += *++p << 8; i_subpacket_len += *++p; } if( *p == ISSUER_SUBPACKET ) { if( p + 9 > max_pos ) return 0; memcpy( &p_sig->issuer_longid, p+1, 8 ); return i_read; } p += i_subpacket_len; }}static int parse_signature_packet( signature_packet_t *p_sig, uint8_t *p_buf, size_t i_sig_len ){ if( !i_sig_len ) /* 1st sanity check, we need at least the version */ return VLC_EGENERIC; p_sig->version = *p_buf++; size_t i_read; switch( p_sig->version ) { case 3: i_read = parse_signature_v3_packet( p_sig, p_buf, i_sig_len ); break; case 4: p_sig->specific.v4.hashed_data = NULL; p_sig->specific.v4.unhashed_data = NULL; i_read = parse_signature_v4_packet( p_sig, p_buf, i_sig_len ); break; default: return VLC_EGENERIC; } if( i_read == 0 ) /* signature packet parsing has failed */ goto error; if( p_sig->public_key_algo != PUBLIC_KEY_ALGO_DSA ) goto error; if( p_sig->digest_algo != DIGEST_ALGO_SHA1 ) goto error; switch( p_sig->type ) { case BINARY_SIGNATURE: case TEXT_SIGNATURE: case GENERIC_KEY_SIGNATURE: case PERSONA_KEY_SIGNATURE: case CASUAL_KEY_SIGNATURE: case POSITIVE_KEY_SIGNATURE: break; default: goto error; } p_buf--; /* rewind to the version byte */ p_buf += i_read; if( i_read + 2 > i_sig_len ) goto error; size_t i_r_len = mpi_len( p_buf ); i_read += 2; if( i_read + i_r_len > i_sig_len || i_r_len > 20 ) goto error; memcpy( p_sig->r, p_buf, 2 + i_r_len ); p_buf += 2 + i_r_len; i_read += i_r_len; if( i_read + 2 > i_sig_len ) goto error; size_t i_s_len = mpi_len( p_buf ); i_read += 2; if( i_read + i_s_len > i_sig_len || i_s_len > 20 ) goto error; memcpy( p_sig->s, p_buf, 2 + i_s_len ); p_buf += 2 + i_s_len; i_read += i_s_len; assert( i_read == i_sig_len ); if( i_read < i_sig_len ) /* some extra data, hm ? */ goto error; return VLC_SUCCESS;error: if( p_sig->version == 4 ) { free( p_sig->specific.v4.hashed_data ); free( p_sig->specific.v4.unhashed_data ); } return VLC_EGENERIC;}/* * crc_octets() was lamely copied from rfc 2440 * Copyright (C) The Internet Society (1998). All Rights Reserved. */#define CRC24_INIT 0xB704CEL#define CRC24_POLY 0x1864CFBLstatic 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -