update.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:51k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * update.c: VLC update checking and downloading
  3.  *****************************************************************************
  4.  * Copyright © 2005-2008 the VideoLAN team
  5.  * $Id: e4e5d0161530771d5a09b3636eb87dab07794a27 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
  8.  *          Rémi Duraffort <ivoire at via.ecp.fr>
  9.             Rafaël Carré <funman@videolanorg>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either release 2 of the License, or
  14.  * (at your option) any later release.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25. /**
  26.  *   file
  27.  *   This file contains functions related to VLC update management
  28.  */
  29. /*****************************************************************************
  30.  * Preamble
  31.  *****************************************************************************/
  32. #ifdef HAVE_CONFIG_H
  33. # include "config.h"
  34. #endif
  35. #include <vlc_common.h>
  36. #include <vlc_update.h>
  37. #ifdef UPDATE_CHECK
  38. #include <assert.h>
  39. #include <vlc_pgpkey.h>
  40. #include <vlc_stream.h>
  41. #include <vlc_strings.h>
  42. #include <vlc_charset.h>
  43. #include <vlc_dialog.h>
  44. #include <gcrypt.h>
  45. #include <vlc_gcrypt.h>
  46. #include "update.h"
  47. #include "../libvlc.h"
  48. /*****************************************************************************
  49.  * Misc defines
  50.  *****************************************************************************/
  51. /*
  52.  * Here is the format of these "status files" :
  53.  * First line is the last version: "X.Y.Ze" where:
  54.  *      * X is the major number
  55.  *      * Y is the minor number
  56.  *      * Z is the revision number
  57.  *      * e is an OPTIONAL extra letter
  58.  *      * AKA "0.8.6d" or "0.9.0"
  59.  * Second line is an url of the binary for this last version
  60.  * Remaining text is a required description of the update
  61.  */
  62. #if defined( UNDER_CE )
  63. #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-ce"
  64. #elif defined( WIN32 )
  65. #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-win-x86"
  66. #elif defined( __APPLE__ )
  67. #   if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
  68. #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-ppc"
  69. #   else
  70. #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-x86"
  71. #   endif
  72. #elif defined( SYS_BEOS )
  73. #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-beos-x86"
  74. #else
  75. #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"
  76. #endif
  77. /*****************************************************************************
  78.  * OpenPGP functions
  79.  *****************************************************************************/
  80. #define packet_type( c ) ( ( c & 0x3c ) >> 2 )      /* 0x3C = 00111100 */
  81. #define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
  82. static inline int scalar_number( uint8_t *p, int header_len )
  83. {
  84.     assert( header_len == 1 || header_len == 2 || header_len == 4 );
  85.     if( header_len == 1 )
  86.         return( p[0] );
  87.     else if( header_len == 2 )
  88.         return( (p[0] << 8) + p[1] );
  89.     else if( header_len == 4 )
  90.         return( (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3] );
  91.     abort(); /* to shut up GCC warning */
  92. }
  93. /* number of data bytes in a MPI */
  94. #define mpi_len( mpi ) ( ( scalar_number( mpi, 2 ) + 7 ) / 8 )
  95. /*
  96.  * fill a public_key_packet_t structure from public key packet data
  97.  * verify that it is a version 4 public key packet, using DSA
  98.  */
  99. static int parse_public_key_packet( public_key_packet_t *p_key, uint8_t *p_buf,
  100.                                     size_t i_packet_len )
  101. {
  102.     if( i_packet_len > 418 || i_packet_len < 6 )
  103.         return VLC_EGENERIC;
  104.     size_t i_read = 0;
  105.     p_key->version   = *p_buf++; i_read++;
  106.     if( p_key->version != 4 )
  107.         return VLC_EGENERIC;
  108.     /* XXX: warn when timestamp is > date ? */
  109.     memcpy( p_key->timestamp, p_buf, 4 ); p_buf += 4; i_read += 4;
  110.     p_key->algo      = *p_buf++; i_read++;
  111.     if( p_key->algo != PUBLIC_KEY_ALGO_DSA )
  112.         return VLC_EGENERIC;
  113.     /* read p */
  114.     if( i_read + 2 > i_packet_len )
  115.         return VLC_EGENERIC;
  116.     int i_p_len = mpi_len( p_buf );
  117.     if( i_p_len > 128 || i_read + 2 + i_p_len > i_packet_len )
  118.         return VLC_EGENERIC;
  119.     memcpy( p_key->p, p_buf, 2+i_p_len );
  120.     p_buf += 2+i_p_len; i_read += 2+i_p_len;
  121.     /* read q */
  122.     if( i_read + 2 > i_packet_len )
  123.         return VLC_EGENERIC;
  124.     int i_q_len = mpi_len( p_buf );
  125.     if( i_q_len > 20 || i_read+2+i_q_len > i_packet_len )
  126.         return VLC_EGENERIC;
  127.     memcpy( p_key->q, p_buf, 2+i_q_len );
  128.     p_buf += 2+i_q_len; i_read += 2+i_q_len;
  129.     /* read g */
  130.     if( i_read + 2 > i_packet_len )
  131.         return VLC_EGENERIC;
  132.     int i_g_len = mpi_len( p_buf );
  133.     if( i_g_len > 128 || i_read+2+i_g_len > i_packet_len )
  134.         return VLC_EGENERIC;
  135.     memcpy( p_key->g, p_buf, 2+i_g_len );
  136.     p_buf += 2+i_g_len; i_read += 2+i_g_len;
  137.     /* read y */
  138.     if( i_read + 2 > i_packet_len )
  139.         return VLC_EGENERIC;
  140.     int i_y_len = mpi_len( p_buf );
  141.     if( i_y_len > 128 || i_read+2+i_y_len > i_packet_len )
  142.         return VLC_EGENERIC;
  143.     memcpy( p_key->y, p_buf, 2+i_y_len );
  144.     i_read += 2+i_y_len;
  145.     if( i_read != i_packet_len ) /* some extra data eh ? */
  146.         return VLC_EGENERIC;
  147.     return VLC_SUCCESS;
  148. }
  149. static size_t parse_signature_v3_packet( signature_packet_t *p_sig,
  150.                                       uint8_t *p_buf, size_t i_sig_len )
  151. {
  152.     size_t i_read = 1; /* we already read the version byte */
  153.     if( i_sig_len < 19 ) /* signature is at least 19 bytes + the 2 MPIs */
  154.         return 0;
  155.     p_sig->specific.v3.hashed_data_len = *p_buf++; i_read++;
  156.     if( p_sig->specific.v3.hashed_data_len != 5 )
  157.         return 0;
  158.     p_sig->type = *p_buf++; i_read++;
  159.     memcpy( p_sig->specific.v3.timestamp, p_buf, 4 );
  160.     p_buf += 4; i_read += 4;
  161.     memcpy( p_sig->issuer_longid, p_buf, 8 );
  162.     p_buf += 8; i_read += 8;
  163.     p_sig->public_key_algo = *p_buf++; i_read++;
  164.     p_sig->digest_algo = *p_buf++; i_read++;
  165.     p_sig->hash_verification[0] = *p_buf++; i_read++;
  166.     p_sig->hash_verification[1] = *p_buf++; i_read++;
  167.     assert( i_read == 19 );
  168.     return i_read;
  169. }
  170. /*
  171.  * fill a signature_packet_v4_t from signature packet data
  172.  * verify that it was used with a DSA public key, using SHA-1 digest
  173.  */
  174. static size_t parse_signature_v4_packet( signature_packet_t *p_sig,
  175.                                       uint8_t *p_buf, size_t i_sig_len )
  176. {
  177.     size_t i_read = 1; /* we already read the version byte */
  178.     if( i_sig_len < 10 ) /* signature is at least 10 bytes + the 2 MPIs */
  179.         return 0;
  180.     p_sig->type = *p_buf++; i_read++;
  181.     p_sig->public_key_algo = *p_buf++; i_read++;
  182.     p_sig->digest_algo = *p_buf++; i_read++;
  183.     memcpy( p_sig->specific.v4.hashed_data_len, p_buf, 2 );
  184.     p_buf += 2; i_read += 2;
  185.     size_t i_hashed_data_len =
  186.         scalar_number( p_sig->specific.v4.hashed_data_len, 2 );
  187.     i_read += i_hashed_data_len;
  188.     if( i_read + 4 > i_sig_len )
  189.         return 0;
  190.     p_sig->specific.v4.hashed_data = (uint8_t*) malloc( i_hashed_data_len );
  191.     if( !p_sig->specific.v4.hashed_data )
  192.         return 0;
  193.     memcpy( p_sig->specific.v4.hashed_data, p_buf, i_hashed_data_len );
  194.     p_buf += i_hashed_data_len;
  195.     memcpy( p_sig->specific.v4.unhashed_data_len, p_buf, 2 );
  196.     p_buf += 2; i_read += 2;
  197.     size_t i_unhashed_data_len =
  198.         scalar_number( p_sig->specific.v4.unhashed_data_len, 2 );
  199.     i_read += i_unhashed_data_len;
  200.     if( i_read + 2 > i_sig_len )
  201.         return 0;
  202.     p_sig->specific.v4.unhashed_data = (uint8_t*) malloc( i_unhashed_data_len );
  203.     if( !p_sig->specific.v4.unhashed_data )
  204.         return 0;
  205.     memcpy( p_sig->specific.v4.unhashed_data, p_buf, i_unhashed_data_len );
  206.     p_buf += i_unhashed_data_len;
  207.     memcpy( p_sig->hash_verification, p_buf, 2 );
  208.     p_buf += 2; i_read += 2;
  209.     uint8_t *p, *max_pos;
  210.     p = p_sig->specific.v4.unhashed_data;
  211.     max_pos = p + scalar_number( p_sig->specific.v4.unhashed_data_len, 2 );
  212.     for( ;; )
  213.     {
  214.         if( p > max_pos )
  215.             return 0;
  216.         size_t i_subpacket_len;
  217.         if( *p < 192 )
  218.         {
  219.             if( p + 1 > max_pos )
  220.                 return 0;
  221.             i_subpacket_len = *p++;
  222.         }
  223.         else if( *p < 255 )
  224.         {
  225.             if( p + 2 > max_pos )
  226.                 return 0;
  227.             i_subpacket_len = (*p++ - 192) << 8;
  228.             i_subpacket_len += *p++ + 192;
  229.         }
  230.         else
  231.         {
  232.             if( p + 4 > max_pos )
  233.                 return 0;
  234.             i_subpacket_len = *++p << 24;
  235.             i_subpacket_len += *++p << 16;
  236.             i_subpacket_len += *++p << 8;
  237.             i_subpacket_len += *++p;
  238.         }
  239.         if( *p == ISSUER_SUBPACKET )
  240.         {
  241.             if( p + 9 > max_pos )
  242.                 return 0;
  243.             memcpy( &p_sig->issuer_longid, p+1, 8 );
  244.             return i_read;
  245.         }
  246.         p += i_subpacket_len;
  247.     }
  248. }
  249. static int parse_signature_packet( signature_packet_t *p_sig,
  250.                                    uint8_t *p_buf, size_t i_sig_len )
  251. {
  252.     if( !i_sig_len ) /* 1st sanity check, we need at least the version */
  253.         return VLC_EGENERIC;
  254.     p_sig->version = *p_buf++;
  255.     size_t i_read;
  256.     switch( p_sig->version )
  257.     {
  258.         case 3:
  259.             i_read = parse_signature_v3_packet( p_sig, p_buf, i_sig_len );
  260.             break;
  261.         case 4:
  262.             p_sig->specific.v4.hashed_data = NULL;
  263.             p_sig->specific.v4.unhashed_data = NULL;
  264.             i_read = parse_signature_v4_packet( p_sig, p_buf, i_sig_len );
  265.             break;
  266.         default:
  267.             return VLC_EGENERIC;
  268.     }
  269.     if( i_read == 0 ) /* signature packet parsing has failed */
  270.         goto error;
  271.     if( p_sig->public_key_algo != PUBLIC_KEY_ALGO_DSA )
  272.         goto error;
  273.     if( p_sig->digest_algo != DIGEST_ALGO_SHA1 )
  274.         goto error;
  275.     switch( p_sig->type )
  276.     {
  277.         case BINARY_SIGNATURE:
  278.         case TEXT_SIGNATURE:
  279.         case GENERIC_KEY_SIGNATURE:
  280.         case PERSONA_KEY_SIGNATURE:
  281.         case CASUAL_KEY_SIGNATURE:
  282.         case POSITIVE_KEY_SIGNATURE:
  283.             break;
  284.         default:
  285.             goto error;
  286.     }
  287.     p_buf--; /* rewind to the version byte */
  288.     p_buf += i_read;
  289.     if( i_read + 2 > i_sig_len )
  290.         goto error;
  291.     size_t i_r_len = mpi_len( p_buf ); i_read += 2;
  292.     if( i_read + i_r_len > i_sig_len || i_r_len > 20 )
  293.         goto error;
  294.     memcpy( p_sig->r, p_buf, 2 + i_r_len );
  295.     p_buf += 2 + i_r_len;
  296.     i_read += i_r_len;
  297.     if( i_read + 2 > i_sig_len )
  298.         goto error;
  299.     size_t i_s_len = mpi_len( p_buf ); i_read += 2;
  300.     if( i_read + i_s_len > i_sig_len || i_s_len > 20 )
  301.         goto error;
  302.     memcpy( p_sig->s, p_buf, 2 + i_s_len );
  303.     p_buf += 2 + i_s_len;
  304.     i_read += i_s_len;
  305.     assert( i_read == i_sig_len );
  306.     if( i_read < i_sig_len ) /* some extra data, hm ? */
  307.         goto error;
  308.     return VLC_SUCCESS;
  309. error:
  310.     if( p_sig->version == 4 )
  311.     {
  312.         free( p_sig->specific.v4.hashed_data );
  313.         free( p_sig->specific.v4.unhashed_data );
  314.     }
  315.     return VLC_EGENERIC;
  316. }
  317. /*
  318.  * crc_octets() was lamely copied from rfc 2440
  319.  * Copyright (C) The Internet Society (1998).  All Rights Reserved.
  320.  */
  321. #define CRC24_INIT 0xB704CEL
  322. #define CRC24_POLY 0x1864CFBL
  323. static long crc_octets( uint8_t *octets, size_t len )
  324. {
  325.     long crc = CRC24_INIT;
  326.     int i;
  327.     while (len--)
  328.     {
  329.         crc ^= (*octets++) << 16;
  330.         for (i = 0; i < 8; i++)
  331.         {
  332.             crc <<= 1;
  333.             if (crc & 0x1000000)
  334.                 crc ^= CRC24_POLY;
  335.         }
  336.     }
  337.     return crc & 0xFFFFFFL;
  338. }
  339. /*
  340.  * Transform an armored document in binary format
  341.  * Used on public keys and signatures
  342.  */
  343. static int pgp_unarmor( char *p_ibuf, size_t i_ibuf_len,
  344.                         uint8_t *p_obuf, size_t i_obuf_len )
  345. {
  346.     char *p_ipos = p_ibuf;
  347.     uint8_t *p_opos = p_obuf;
  348.     int i_end = 0;
  349.     int i_header_skipped = 0;
  350.     while( !i_end && p_ipos < p_ibuf + i_ibuf_len && *p_ipos != '=' )
  351.     {
  352.         if( *p_ipos == 'r' || *p_ipos == 'n' )
  353.         {
  354.             p_ipos++;
  355.             continue;
  356.         }
  357.         size_t i_line_len = strcspn( p_ipos, "rn" );
  358.         if( i_line_len == 0 )
  359.             continue;
  360.         if( !i_header_skipped )
  361.         {
  362.             if( !strncmp( p_ipos, "-----BEGIN PGP", 14 ) )
  363.                 i_header_skipped = 1;
  364.             p_ipos += i_line_len + 1;
  365.             continue;
  366.         }
  367.         if( !strncmp( p_ipos, "Version:", 8 ) )
  368.         {
  369.             p_ipos += i_line_len + 1;
  370.             continue;
  371.         }
  372.         if( p_ipos[i_line_len - 1] == '=' )
  373.         {
  374.             i_end = 1;
  375.             p_ipos[i_line_len - 1] = '';
  376.         }
  377.         else
  378.             p_ipos[i_line_len] = '';
  379.         p_opos += vlc_b64_decode_binary_to_buffer(  p_opos,
  380.                         p_obuf - p_opos + i_obuf_len, p_ipos );
  381.         p_ipos += i_line_len + 1;
  382.     }
  383.     /* XXX: the CRC is OPTIONAL, really require it ? */
  384.     if( p_ipos + 5 > p_ibuf + i_ibuf_len || *p_ipos++ != '=' )
  385.         return 0;
  386.     uint8_t p_crc[3];
  387.     if( vlc_b64_decode_binary_to_buffer( p_crc, 3, p_ipos ) != 3 )
  388.         return 0;
  389.     long l_crc = crc_octets( p_obuf, p_opos - p_obuf );
  390.     long l_crc2 = ( 0 << 24 ) + ( p_crc[0] << 16 ) + ( p_crc[1] << 8 ) + p_crc[2];
  391.     return l_crc2 == l_crc ? p_opos - p_obuf : 0;
  392. }
  393. /*
  394.  * Download the signature associated to a document or a binary file.
  395.  * We're given the file's url, we just append ".asc" to it and download
  396.  */
  397. static int download_signature(  vlc_object_t *p_this,
  398.                                 signature_packet_t *p_sig,
  399.                                 const char *psz_url )
  400. {
  401.     char *psz_sig = (char*) malloc( strlen( psz_url ) + 4 + 1 ); /* ".asc" +  */
  402.     if( !psz_sig )
  403.         return VLC_ENOMEM;
  404.     strcpy( psz_sig, psz_url );
  405.     strcat( psz_sig, ".asc" );
  406.     stream_t *p_stream = stream_UrlNew( p_this, psz_sig );
  407.     free( psz_sig );
  408.     if( !p_stream )
  409.         return VLC_ENOMEM;
  410.     int64_t i_size = stream_Size( p_stream );
  411.     msg_Dbg( p_this, "Downloading signature (%"PRId64" bytes)", i_size );
  412.     uint8_t *p_buf = (uint8_t*)malloc( i_size );
  413.     if( !p_buf )
  414.     {
  415.         stream_Delete( p_stream );
  416.         return VLC_ENOMEM;
  417.     }
  418.     int i_read = stream_Read( p_stream, p_buf, (int)i_size );
  419.     stream_Delete( p_stream );
  420.     if( i_read != (int)i_size )
  421.     {
  422.         msg_Dbg( p_this,
  423.             "Couldn't download full signature (only %d bytes)", i_read );
  424.         free( p_buf );
  425.         return VLC_EGENERIC;
  426.     }
  427.     if( (uint8_t)*p_buf < 0x80 ) /* ASCII */
  428.     {
  429.         msg_Dbg( p_this, "Unarmoring signature" );
  430.         uint8_t* p_unarmored = (uint8_t*) malloc( ( i_size * 3 ) / 4 + 1 );
  431.         if( !p_unarmored )
  432.         {
  433.             free( p_buf );
  434.             return VLC_EGENERIC;
  435.         }
  436.         int i_bytes = pgp_unarmor( (char*)p_buf, i_size, p_unarmored, i_size );
  437.         free( p_buf );
  438.         p_buf = p_unarmored;
  439.         i_size = i_bytes;
  440.         if( i_bytes < 2 )
  441.         {
  442.             free( p_buf );
  443.             msg_Dbg( p_this, "Unarmoring failed : corrupted signature ?" );
  444.             return VLC_EGENERIC;
  445.         }
  446.     }
  447.     if( packet_type( *p_buf ) != SIGNATURE_PACKET )
  448.     {
  449.         free( p_buf );
  450.         msg_Dbg( p_this, "Not a signature: %d", *p_buf );
  451.         return VLC_EGENERIC;
  452.     }
  453.     size_t i_header_len = packet_header_len( *p_buf );
  454.     if( ( i_header_len != 1 && i_header_len != 2 && i_header_len != 4 ) ||
  455.         i_header_len + 1 > (size_t)i_size )
  456.     {
  457.         free( p_buf );
  458.         msg_Dbg( p_this, "Invalid signature packet header" );
  459.         return VLC_EGENERIC;
  460.     }
  461.     size_t i_len = scalar_number( p_buf+1, i_header_len );
  462.     if( i_len + i_header_len + 1 != (size_t)i_size )
  463.     {
  464.         free( p_buf );
  465.         msg_Dbg( p_this, "Invalid signature packet" );
  466.         return VLC_EGENERIC;
  467.     }
  468.     int i_ret = parse_signature_packet( p_sig, p_buf+1+i_header_len, i_len );
  469.     free( p_buf );
  470.     if( i_ret != VLC_SUCCESS )
  471.     {
  472.         msg_Dbg( p_this, "Couldn't parse signature" );
  473.         return i_ret;
  474.     }
  475.     if( p_sig->type != BINARY_SIGNATURE && p_sig->type != TEXT_SIGNATURE )
  476.     {
  477.         msg_Dbg( p_this, "Invalid signature type: %d", p_sig->type );
  478.         if( p_sig->version == 4 )
  479.         {
  480.             free( p_sig->specific.v4.hashed_data );
  481.             free( p_sig->specific.v4.unhashed_data );
  482.         }
  483.         return VLC_EGENERIC;
  484.     }
  485.     return VLC_SUCCESS;
  486. }
  487. /*
  488.  * Verify an OpenPGP signature made on some SHA-1 hash, with some DSA public key
  489.  */
  490. static int verify_signature( uint8_t *p_r, uint8_t *p_s,
  491.         public_key_packet_t *p_key, uint8_t *p_hash )
  492. {
  493.     /* the data to be verified (a SHA-1 hash) */
  494.     const char *hash_sexp_s = "(data(flags raw)(value %m))";
  495.     /* the public key */
  496.     const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
  497.     /* the signature */
  498.     const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))";
  499.     size_t erroff;
  500.     gcry_mpi_t p, q, g, y, r, s, hash;
  501.     p = q = g = y = r = s = hash = NULL;
  502.     gcry_sexp_t key_sexp, hash_sexp, sig_sexp;
  503.     key_sexp = hash_sexp = sig_sexp = NULL;
  504.     int i_p_len = mpi_len( p_key->p );
  505.     int i_q_len = mpi_len( p_key->q );
  506.     int i_g_len = mpi_len( p_key->g );
  507.     int i_y_len = mpi_len( p_key->y );
  508.     if( gcry_mpi_scan( &p, GCRYMPI_FMT_USG, p_key->p + 2, i_p_len, NULL ) ||
  509.         gcry_mpi_scan( &q, GCRYMPI_FMT_USG, p_key->q + 2, i_q_len, NULL ) ||
  510.         gcry_mpi_scan( &g, GCRYMPI_FMT_USG, p_key->g + 2, i_g_len, NULL ) ||
  511.         gcry_mpi_scan( &y, GCRYMPI_FMT_USG, p_key->y + 2, i_y_len, NULL ) ||
  512.         gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, p, q, g, y ) )
  513.         goto problem;
  514.     int i_r_len = mpi_len( p_r );
  515.     int i_s_len = mpi_len( p_s );
  516.     if( gcry_mpi_scan( &r, GCRYMPI_FMT_USG, p_r + 2, i_r_len, NULL ) ||
  517.         gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, i_s_len, NULL ) ||
  518.         gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, r, s ) )
  519.         goto problem;
  520.     int i_hash_len = 20;
  521.     if( gcry_mpi_scan( &hash, GCRYMPI_FMT_USG, p_hash, i_hash_len, NULL ) ||
  522.         gcry_sexp_build( &hash_sexp, &erroff, hash_sexp_s, hash ) )
  523.         goto problem;
  524.     if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
  525.         goto problem;
  526.     return VLC_SUCCESS;
  527. problem:
  528.     if( p ) gcry_mpi_release( p );
  529.     if( q ) gcry_mpi_release( q );
  530.     if( g ) gcry_mpi_release( g );
  531.     if( y ) gcry_mpi_release( y );
  532.     if( r ) gcry_mpi_release( r );
  533.     if( s ) gcry_mpi_release( s );
  534.     if( hash ) gcry_mpi_release( hash );
  535.     if( key_sexp ) gcry_sexp_release( key_sexp );
  536.     if( sig_sexp ) gcry_sexp_release( sig_sexp );
  537.     if( hash_sexp ) gcry_sexp_release( hash_sexp );
  538.     return VLC_EGENERIC;
  539. }
  540. /*
  541.  * fill a public_key_t with public key data, including:
  542.  *   * public key packet
  543.  *   * signature packet issued by key which long id is p_sig_issuer
  544.  *   * user id packet
  545.  */
  546. static int parse_public_key( const uint8_t *p_key_data, size_t i_key_len,
  547.                              public_key_t *p_key, const uint8_t *p_sig_issuer )
  548. {
  549.     uint8_t *pos = (uint8_t*) p_key_data;
  550.     uint8_t *max_pos = pos + i_key_len;
  551.     int i_status = 0;
  552. #define PUBLIC_KEY_FOUND    0x01
  553. #define USER_ID_FOUND       0x02
  554. #define SIGNATURE_FOUND     0X04
  555.     uint8_t *p_key_unarmored = NULL;
  556.     p_key->psz_username = NULL;
  557.     p_key->sig.specific.v4.hashed_data = NULL;
  558.     p_key->sig.specific.v4.unhashed_data = NULL;
  559.     if( !( *pos & 0x80 ) )
  560.     {   /* first byte is ASCII, unarmoring */
  561.         p_key_unarmored = (uint8_t*)malloc( i_key_len );
  562.         if( !p_key_unarmored )
  563.             return VLC_ENOMEM;
  564.         int i_len = pgp_unarmor( (char*)p_key_data, i_key_len,
  565.                                  p_key_unarmored, i_key_len );
  566.         if( i_len == 0 )
  567.             goto error;
  568.         pos = p_key_unarmored;
  569.         max_pos = pos + i_len;
  570.     }
  571.     while( pos < max_pos )
  572.     {
  573.         if( !(*pos & 0x80) || *pos & 0x40 )
  574.             goto error;
  575.         int i_type = packet_type( *pos );
  576.         int i_header_len = packet_header_len( *pos++ );
  577.         if( pos + i_header_len > max_pos ||
  578.             ( i_header_len != 1 && i_header_len != 2 && i_header_len != 4 ) )
  579.             goto error;
  580.         int i_packet_len = scalar_number( pos, i_header_len );
  581.         pos += i_header_len;
  582.         if( pos + i_packet_len > max_pos )
  583.             goto error;
  584.         switch( i_type )
  585.         {
  586.             case PUBLIC_KEY_PACKET:
  587.                 i_status |= PUBLIC_KEY_FOUND;
  588.                 if( parse_public_key_packet( &p_key->key, pos, i_packet_len ) != VLC_SUCCESS )
  589.                     goto error;
  590.                 break;
  591.             case SIGNATURE_PACKET: /* we accept only v4 signatures here */
  592.                 if( i_status & SIGNATURE_FOUND || !p_sig_issuer )
  593.                     break;
  594.                 int i_ret = parse_signature_packet( &p_key->sig, pos,
  595.                                                     i_packet_len );
  596.                 if( i_ret == VLC_SUCCESS )
  597.                 {
  598.                     if( p_key->sig.version != 4 )
  599.                         break;
  600.                     if( memcmp( p_key->sig.issuer_longid, p_sig_issuer, 8 ) )
  601.                     {
  602.                         free( p_key->sig.specific.v4.hashed_data );
  603.                         free( p_key->sig.specific.v4.unhashed_data );
  604.                         p_key->sig.specific.v4.hashed_data = NULL;
  605.                         p_key->sig.specific.v4.unhashed_data = NULL;
  606.                         break;
  607.                     }
  608.                     i_status |= SIGNATURE_FOUND;
  609.                 }
  610.                 break;
  611.             case USER_ID_PACKET:
  612.                 if( p_key->psz_username ) /* save only the first User ID */
  613.                     break;
  614.                 i_status |= USER_ID_FOUND;
  615.                 p_key->psz_username = (uint8_t*)malloc( i_packet_len + 1);
  616.                 if( !p_key->psz_username )
  617.                     goto error;
  618.                 memcpy( p_key->psz_username, pos, i_packet_len );
  619.                 p_key->psz_username[i_packet_len] = '';
  620.                 break;
  621.             default:
  622.                 break;
  623.         }
  624.         pos += i_packet_len;
  625.     }
  626.     free( p_key_unarmored );
  627.     if( !( i_status & ( PUBLIC_KEY_FOUND | USER_ID_FOUND ) ) )
  628.         return VLC_EGENERIC;
  629.     if( p_sig_issuer && !( i_status & SIGNATURE_FOUND ) )
  630.         return VLC_EGENERIC;
  631.     return VLC_SUCCESS;
  632. error:
  633.     if( p_key->sig.version == 4 )
  634.     {
  635.         free( p_key->sig.specific.v4.hashed_data );
  636.         free( p_key->sig.specific.v4.unhashed_data );
  637.     }
  638.     free( p_key->psz_username );
  639.     free( p_key_unarmored );
  640.     return VLC_EGENERIC;
  641. }
  642. /*
  643.  * return a sha1 hash of a file
  644.  */
  645. static uint8_t *hash_sha1_from_file( const char *psz_file,
  646.                             signature_packet_t *p_sig )
  647. {
  648.     if( p_sig->type != BINARY_SIGNATURE && p_sig->type != TEXT_SIGNATURE )
  649.         return NULL;
  650.     FILE *f = utf8_fopen( psz_file, "r" );
  651.     if( !f )
  652.         return NULL;
  653.     uint8_t buffer[4096];
  654.     gcry_md_hd_t hd;
  655.     if( gcry_md_open( &hd, GCRY_MD_SHA1, 0 ) )
  656.     {
  657.         fclose( f );
  658.         return NULL;
  659.     }
  660.     size_t i_read;
  661.     while( ( i_read = fread( buffer, 1, sizeof(buffer), f ) ) > 0 )
  662.         gcry_md_write( hd, buffer, i_read );
  663.     if( p_sig->version == 3 )
  664.     {
  665.         gcry_md_putc( hd, p_sig->type );
  666.         gcry_md_write( hd, &p_sig->specific.v3.timestamp, 4 );
  667.     }
  668.     else if( p_sig->version == 4 )
  669.     {
  670.         gcry_md_putc( hd, p_sig->version );
  671.         gcry_md_putc( hd, p_sig->type );
  672.         gcry_md_putc( hd, p_sig->public_key_algo );
  673.         gcry_md_putc( hd, p_sig->digest_algo );
  674.         gcry_md_write( hd, p_sig->specific.v4.hashed_data_len, 2 );
  675.         size_t i_len = scalar_number( p_sig->specific.v4.hashed_data_len, 2 );
  676.         gcry_md_write( hd, p_sig->specific.v4.hashed_data, i_len );
  677.         gcry_md_putc( hd, 0x04 );
  678.         gcry_md_putc( hd, 0xFF );
  679.         i_len += 6; /* hashed data + 6 bytes header */
  680.         gcry_md_putc( hd, (i_len >> 24) & 0xff );
  681.         gcry_md_putc( hd, (i_len >> 16) & 0xff );
  682.         gcry_md_putc( hd, (i_len >> 8) & 0xff );
  683.         gcry_md_putc( hd, (i_len) & 0xff );
  684.     }
  685.     else
  686.     {   /* RFC 4880 only tells about versions 3 and 4 */
  687.         gcry_md_close( hd );
  688.         return NULL;
  689.     }
  690.     fclose( f );
  691.     gcry_md_final( hd );
  692.     uint8_t *p_tmp = (uint8_t*) gcry_md_read( hd, GCRY_MD_SHA1);
  693.     uint8_t *p_hash = malloc( 20 );
  694.     if( p_hash )
  695.         memcpy( p_hash, p_tmp, 20 );
  696.     gcry_md_close( hd );
  697.     return p_hash;
  698. }
  699. /*
  700.  * download a public key (the last one) from videolan server, and parse it
  701.  */
  702. static public_key_t *download_key( vlc_object_t *p_this,
  703.                     const uint8_t *p_longid, const uint8_t *p_signature_issuer )
  704. {
  705.     char *psz_url;
  706.     if( asprintf( &psz_url, "http://download.videolan.org/pub/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc",
  707.                     p_longid[0], p_longid[1], p_longid[2], p_longid[3],
  708.                     p_longid[4], p_longid[5], p_longid[6], p_longid[7] ) == -1 )
  709.         return NULL;
  710.     stream_t *p_stream = stream_UrlNew( p_this, psz_url );
  711.     free( psz_url );
  712.     if( !p_stream )
  713.         return NULL;
  714.     int64_t i_size = stream_Size( p_stream );
  715.     if( i_size < 0 )
  716.     {
  717.         stream_Delete( p_stream );
  718.         return NULL;
  719.     }
  720.     uint8_t *p_buf = (uint8_t*)malloc( i_size );
  721.     if( !p_buf )
  722.     {
  723.         stream_Delete( p_stream );
  724.         return NULL;
  725.     }
  726.     int i_read = stream_Read( p_stream, p_buf, (int)i_size );
  727.     stream_Delete( p_stream );
  728.     if( i_read != (int)i_size )
  729.     {
  730.         msg_Dbg( p_this, "Couldn't read full GPG key" );
  731.         free( p_buf );
  732.         return NULL;
  733.     }
  734.     public_key_t *p_pkey = (public_key_t*) malloc( sizeof( public_key_t ) );
  735.     if( !p_pkey )
  736.     {
  737.         free( p_buf );
  738.         return NULL;
  739.     }
  740.     memcpy( p_pkey->longid, p_longid, 8 );
  741.     int i_error = parse_public_key( p_buf, i_read, p_pkey, p_signature_issuer );
  742.     free( p_buf );
  743.     if( i_error != VLC_SUCCESS )
  744.     {
  745.         msg_Dbg( p_this, "Couldn't parse GPG key" );
  746.         free( p_pkey );
  747.         return NULL;
  748.     }
  749.     return p_pkey;
  750. }
  751. /*
  752.  * Generate a SHA1 hash on a public key, to verify a signature made on that hash
  753.  * Note that we need the signature (v4) to compute the hash
  754.  */
  755. static uint8_t *key_sign_hash( public_key_t *p_pkey )
  756. {
  757.     if( p_pkey->sig.version != 4 )
  758.         return NULL;
  759.     if( p_pkey->sig.type < GENERIC_KEY_SIGNATURE ||
  760.         p_pkey->sig.type > POSITIVE_KEY_SIGNATURE )
  761.         return NULL;
  762.     gcry_error_t error = 0;
  763.     gcry_md_hd_t hd;
  764.     error = gcry_md_open( &hd, GCRY_MD_SHA1, 0 );
  765.     if( error )
  766.         return NULL;
  767.     gcry_md_putc( hd, 0x99 );
  768.     size_t i_p_len = mpi_len( p_pkey->key.p );
  769.     size_t i_g_len = mpi_len( p_pkey->key.g );
  770.     size_t i_q_len = mpi_len( p_pkey->key.q );
  771.     size_t i_y_len = mpi_len( p_pkey->key.y );
  772.     size_t i_size = 6 + 2*4 + i_p_len + i_g_len + i_q_len + i_y_len;
  773.     gcry_md_putc( hd, (i_size >> 8) & 0xff );
  774.     gcry_md_putc( hd, i_size & 0xff );
  775.     gcry_md_putc( hd, p_pkey->key.version );
  776.     gcry_md_write( hd, p_pkey->key.timestamp, 4 );
  777.     gcry_md_putc( hd, p_pkey->key.algo );
  778.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.p, 2 );
  779.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.p + 2, i_p_len );
  780.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.q, 2 );
  781.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.q + 2, i_q_len );
  782.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.g, 2 );
  783.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.g + 2, i_g_len );
  784.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.y, 2 );
  785.     gcry_md_write( hd, (uint8_t*)&p_pkey->key.y + 2, i_y_len );
  786.     gcry_md_putc( hd, 0xb4 );
  787.     size_t i_len = strlen((char*)p_pkey->psz_username);
  788.     gcry_md_putc( hd, (i_len >> 24) & 0xff );
  789.     gcry_md_putc( hd, (i_len >> 16) & 0xff );
  790.     gcry_md_putc( hd, (i_len >> 8) & 0xff );
  791.     gcry_md_putc( hd, (i_len) & 0xff );
  792.     gcry_md_write( hd, p_pkey->psz_username, i_len );
  793.     size_t i_hashed_data_len =
  794.         scalar_number( p_pkey->sig.specific.v4.hashed_data_len, 2 );
  795.     gcry_md_putc( hd, p_pkey->sig.version );
  796.     gcry_md_putc( hd, p_pkey->sig.type );
  797.     gcry_md_putc( hd, p_pkey->sig.public_key_algo );
  798.     gcry_md_putc( hd, p_pkey->sig.digest_algo );
  799.     gcry_md_write( hd, p_pkey->sig.specific.v4.hashed_data_len, 2 );
  800.     gcry_md_write( hd, p_pkey->sig.specific.v4.hashed_data, i_hashed_data_len );
  801.     gcry_md_putc( hd, 0x04 );
  802.     gcry_md_putc( hd, 0xff );
  803.     i_hashed_data_len += 6; /* hashed data + 6 bytes header */
  804.     gcry_md_putc( hd, (i_hashed_data_len >> 24) & 0xff );
  805.     gcry_md_putc( hd, (i_hashed_data_len >> 16) & 0xff );
  806.     gcry_md_putc( hd, (i_hashed_data_len >> 8) & 0xff );
  807.     gcry_md_putc( hd, (i_hashed_data_len) & 0xff );
  808.     gcry_md_final( hd );
  809.     uint8_t *p_tmp = gcry_md_read( hd, GCRY_MD_SHA1 );
  810.     if( !p_tmp ||
  811.         p_tmp[0] != p_pkey->sig.hash_verification[0] ||
  812.         p_tmp[1] != p_pkey->sig.hash_verification[1] )
  813.     {
  814.         gcry_md_close( hd );
  815.         return NULL;
  816.     }
  817.     uint8_t *p_hash = malloc( 20 );
  818.     if( p_hash )
  819.         memcpy( p_hash, p_tmp, 20 );
  820.     gcry_md_close( hd );
  821.     return p_hash;
  822. }
  823. /*****************************************************************************
  824.  * Update_t functions
  825.  *****************************************************************************/
  826. /**
  827.  * Create a new update VLC struct
  828.  *
  829.  * param p_this the calling vlc_object
  830.  * return pointer to new update_t or NULL
  831.  */
  832. update_t *__update_New( vlc_object_t *p_this )
  833. {
  834.     update_t *p_update;
  835.     assert( p_this );
  836.     p_update = (update_t *)malloc( sizeof( update_t ) );
  837.     if( !p_update ) return NULL;
  838.     vlc_mutex_init( &p_update->lock );
  839.     p_update->p_libvlc = p_this->p_libvlc;
  840.     p_update->release.psz_url = NULL;
  841.     p_update->release.psz_desc = NULL;
  842.     p_update->p_download = NULL;
  843.     p_update->p_check = NULL;
  844.     p_update->p_pkey = NULL;
  845.     vlc_gcrypt_init();
  846.     return p_update;
  847. }
  848. /**
  849.  * Delete an update_t struct
  850.  *
  851.  * param p_update update_t* pointer
  852.  * return nothing
  853.  */
  854. void update_Delete( update_t *p_update )
  855. {
  856.     assert( p_update );
  857.     if( p_update->p_check )
  858.     {
  859.         vlc_object_kill( p_update->p_check );
  860.         vlc_thread_join( p_update->p_check );
  861.         vlc_object_release( p_update->p_check );
  862.     }
  863.     if( p_update->p_download )
  864.     {
  865.         vlc_object_kill( p_update->p_download );
  866.         vlc_thread_join( p_update->p_download );
  867.         vlc_object_release( p_update->p_download );
  868.     }
  869.     vlc_mutex_destroy( &p_update->lock );
  870.     free( p_update->release.psz_url );
  871.     free( p_update->release.psz_desc );
  872.     free( p_update->p_pkey );
  873.     free( p_update );
  874. }
  875. /**
  876.  * Empty the release struct
  877.  *
  878.  * param p_update update_t* pointer
  879.  * return nothing
  880.  */
  881. static void EmptyRelease( update_t *p_update )
  882. {
  883.     p_update->release.i_major = 0;
  884.     p_update->release.i_minor = 0;
  885.     p_update->release.i_revision = 0;
  886.     FREENULL( p_update->release.psz_url );
  887.     FREENULL( p_update->release.psz_desc );
  888. }
  889. /**
  890.  * Get the update file and parse it
  891.  * p_update has to be locked when calling this function
  892.  *
  893.  * param p_update pointer to update struct
  894.  * return true if the update is valid and authenticated
  895.  */
  896. static bool GetUpdateFile( update_t *p_update )
  897. {
  898.     stream_t *p_stream = NULL;
  899.     int i_major = 0;
  900.     int i_minor = 0;
  901.     int i_revision = 0;
  902.     unsigned char extra;
  903.     char *psz_version_line = NULL;
  904.     p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL );
  905.     if( !p_stream )
  906.     {
  907.         msg_Err( p_update->p_libvlc, "Failed to open %s for reading",
  908.                  UPDATE_VLC_STATUS_URL );
  909.         goto error;
  910.     }
  911.     /* Start reading the status file */
  912.     if( !( psz_version_line = stream_ReadLine( p_stream ) ) )
  913.     {
  914.         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : missing version",
  915.                  UPDATE_VLC_STATUS_URL );
  916.         goto error;
  917.     }
  918.     /* first line : version number */
  919.     p_update->release.extra = 0;
  920.     switch( sscanf( psz_version_line, "%i.%i.%i%c",
  921.                     &i_major, &i_minor, &i_revision, &extra ) )
  922.     {
  923.         case 4:
  924.             p_update->release.extra = extra;
  925.         case 3:
  926.             p_update->release.i_major = i_major;
  927.             p_update->release.i_minor = i_minor;
  928.             p_update->release.i_revision = i_revision;
  929.             break;
  930.         default:
  931.             msg_Err( p_update->p_libvlc, "Update version false formated" );
  932.             goto error;
  933.     }
  934.     /* second line : URL */
  935.     if( !( p_update->release.psz_url = stream_ReadLine( p_stream ) ) )
  936.     {
  937.         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : URL missing",
  938.                  UPDATE_VLC_STATUS_URL );
  939.         goto error;
  940.     }
  941.     /* Remaining data : description */
  942.     int i_read = stream_Size( p_stream ) - stream_Tell( p_stream );
  943.     if( i_read <= 0 )
  944.     {
  945.         msg_Err( p_update->p_libvlc,
  946.                 "Update file %s is corrupted: description missing",
  947.                 UPDATE_VLC_STATUS_URL );
  948.         goto error;
  949.     }
  950.     p_update->release.psz_desc = (char*) malloc( i_read + 1 );
  951.     if( !p_update->release.psz_desc )
  952.         goto error;
  953.     if( stream_Read( p_stream, p_update->release.psz_desc, i_read ) != i_read )
  954.     {
  955.         msg_Err( p_update->p_libvlc, "Couldn't download update file %s",
  956.                 UPDATE_VLC_STATUS_URL );
  957.         goto error;
  958.     }
  959.     p_update->release.psz_desc[i_read] = '';
  960.     stream_Delete( p_stream );
  961.     p_stream = NULL;
  962.     /* Now that we know the status is valid, we must download its signature
  963.      * to authenticate it */
  964.     signature_packet_t sign;
  965.     if( download_signature( VLC_OBJECT( p_update->p_libvlc ), &sign,
  966.             UPDATE_VLC_STATUS_URL ) != VLC_SUCCESS )
  967.     {
  968.         msg_Err( p_update->p_libvlc, "Couldn't download signature of status file" );
  969.         goto error;
  970.     }
  971.     if( sign.type != BINARY_SIGNATURE && sign.type != TEXT_SIGNATURE )
  972.     {
  973.         msg_Err( p_update->p_libvlc, "Invalid signature type" );
  974.         goto error;
  975.     }
  976.     p_update->p_pkey = (public_key_t*)malloc( sizeof( public_key_t ) );
  977.     if( !p_update->p_pkey )
  978.         goto error;
  979.     if( parse_public_key( videolan_public_key, sizeof( videolan_public_key ),
  980.                         p_update->p_pkey, NULL ) != VLC_SUCCESS )
  981.     {
  982.         msg_Err( p_update->p_libvlc, "Couldn't parse embedded public key, something went really wrong..." );
  983.         FREENULL( p_update->p_pkey );
  984.         goto error;
  985.     }
  986.     memcpy( p_update->p_pkey->longid, videolan_public_key_longid, 8 );
  987.     if( memcmp( sign.issuer_longid, p_update->p_pkey->longid , 8 ) != 0 )
  988.     {
  989.         msg_Dbg( p_update->p_libvlc, "Need to download the GPG key" );
  990.         public_key_t *p_new_pkey = download_key(
  991.                 VLC_OBJECT(p_update->p_libvlc),
  992.                 sign.issuer_longid, videolan_public_key_longid );
  993.         if( !p_new_pkey )
  994.         {
  995.             msg_Err( p_update->p_libvlc, "Couldn't download GPG key" );
  996.             FREENULL( p_update->p_pkey );
  997.             goto error;
  998.         }
  999.         uint8_t *p_hash = key_sign_hash( p_new_pkey );
  1000.         if( !p_hash )
  1001.         {
  1002.             msg_Err( p_update->p_libvlc, "Failed to hash signature" );
  1003.             free( p_new_pkey );
  1004.             FREENULL( p_update->p_pkey );
  1005.             goto error;
  1006.         }
  1007.         if( verify_signature( p_new_pkey->sig.r, p_new_pkey->sig.s,
  1008.                     &p_update->p_pkey->key, p_hash ) == VLC_SUCCESS )
  1009.         {
  1010.             free( p_hash );
  1011.             msg_Info( p_update->p_libvlc, "Key authenticated" );
  1012.             free( p_update->p_pkey );
  1013.             p_update->p_pkey = p_new_pkey;
  1014.         }
  1015.         else
  1016.         {
  1017.             free( p_hash );
  1018.             msg_Err( p_update->p_libvlc, "Key signature invalid !n" );
  1019.             goto error;
  1020.         }
  1021.     }
  1022.     gcry_md_hd_t hd;
  1023.     if( gcry_md_open( &hd, GCRY_MD_SHA1, 0 ) )
  1024.         goto error_hd;
  1025.     gcry_md_write( hd, psz_version_line, strlen( psz_version_line ) );
  1026.     FREENULL( psz_version_line );
  1027.     if( sign.type == TEXT_SIGNATURE )
  1028.         gcry_md_putc( hd, 'r' );
  1029.     gcry_md_putc( hd, 'n' );
  1030.     gcry_md_write( hd, p_update->release.psz_url,
  1031.                         strlen( p_update->release.psz_url ) );
  1032.     if( sign.type == TEXT_SIGNATURE )
  1033.         gcry_md_putc( hd, 'r' );
  1034.     gcry_md_putc( hd, 'n' );
  1035.     char *psz_desc = p_update->release.psz_desc;
  1036.     while( *psz_desc )
  1037.     {
  1038.         size_t i_len = strcspn( psz_desc, "rn" );
  1039.         if( !i_len )
  1040.             break;
  1041.         gcry_md_write( hd, psz_desc, i_len );
  1042.         if( sign.type == TEXT_SIGNATURE )
  1043.             gcry_md_putc( hd, 'r' );
  1044.         gcry_md_putc( hd, 'n' );
  1045.         psz_desc += i_len;
  1046.         while( *psz_desc == 'r' || *psz_desc == 'n' )
  1047.             psz_desc++;
  1048.     }
  1049.     if( sign.version == 3 )
  1050.     {
  1051.         gcry_md_putc( hd, sign.type );
  1052.         gcry_md_write( hd, &sign.specific.v3.timestamp, 4 );
  1053.     }
  1054.     else if( sign.version == 4 )
  1055.     {
  1056.         gcry_md_putc( hd, sign.version );
  1057.         gcry_md_putc( hd, sign.type );
  1058.         gcry_md_putc( hd, sign.public_key_algo );
  1059.         gcry_md_putc( hd, sign.digest_algo );
  1060.         gcry_md_write( hd, sign.specific.v4.hashed_data_len, 2 );
  1061.         size_t i_len = scalar_number( sign.specific.v4.hashed_data_len, 2 );
  1062.         gcry_md_write( hd, sign.specific.v4.hashed_data, i_len );
  1063.         gcry_md_putc( hd, 0x04 );
  1064.         gcry_md_putc( hd, 0xFF );
  1065.         i_len += 6; /* hashed data + 6 bytes header */
  1066.         gcry_md_putc( hd, (i_len >> 24) & 0xff );
  1067.         gcry_md_putc( hd, (i_len >> 16) & 0xff );
  1068.         gcry_md_putc( hd, (i_len >> 8) & 0xff );
  1069.         gcry_md_putc( hd, (i_len) & 0xff );
  1070.     }
  1071.     else
  1072.     {   /* RFC 4880 only tells about versions 3 and 4 */
  1073.         msg_Warn( p_update->p_libvlc, "Invalid signature version %d",
  1074.                 sign.version);
  1075.         goto error_hd;
  1076.     }
  1077.     gcry_md_final( hd );
  1078.     uint8_t *p_hash = gcry_md_read( hd, GCRY_MD_SHA1 );
  1079.     if( p_hash[0] != sign.hash_verification[0] ||
  1080.         p_hash[1] != sign.hash_verification[1] )
  1081.     {
  1082.         msg_Warn( p_update->p_libvlc, "Bad SHA1 hash for status file" );
  1083.         goto error_hd;
  1084.     }
  1085.     if( verify_signature( sign.r, sign.s, &p_update->p_pkey->key, p_hash )
  1086.             != VLC_SUCCESS )
  1087.     {
  1088.         msg_Err( p_update->p_libvlc, "BAD SIGNATURE for status file" );
  1089.         goto error_hd;
  1090.     }
  1091.     else
  1092.     {
  1093.         msg_Info( p_update->p_libvlc, "Status file authenticated" );
  1094.         gcry_md_close( hd );
  1095.         return true;
  1096.     }
  1097. error_hd:
  1098.     gcry_md_close( hd );
  1099. error:
  1100.     if( p_stream )
  1101.         stream_Delete( p_stream );
  1102.     free( psz_version_line );
  1103.     return false;
  1104. }
  1105. static void* update_CheckReal( vlc_object_t *p_this );
  1106. /**
  1107.  * Check for updates
  1108.  *
  1109.  * param p_update pointer to update struct
  1110.  * param pf_callback pointer to a function to call when the update_check is finished
  1111.  * param p_data pointer to some datas to give to the callback
  1112.  * returns nothing
  1113.  */
  1114. void update_Check( update_t *p_update, void (*pf_callback)( void*, bool ), void *p_data )
  1115. {
  1116.     assert( p_update );
  1117.     // If the object already exist, destroy it
  1118.     if( p_update->p_check )
  1119.     {
  1120.         vlc_object_kill( p_update->p_check );
  1121.         vlc_thread_join( p_update->p_check );
  1122.         vlc_object_release( p_update->p_check );
  1123.     }
  1124.     update_check_thread_t *p_uct =
  1125.         vlc_custom_create( p_update->p_libvlc, sizeof( *p_uct ),
  1126.                            VLC_OBJECT_GENERIC, "update check" );
  1127.     if( !p_uct ) return;
  1128.     p_uct->p_update = p_update;
  1129.     p_update->p_check = p_uct;
  1130.     p_uct->pf_callback = pf_callback;
  1131.     p_uct->p_data = p_data;
  1132.     vlc_thread_create( p_uct, "check for update", update_CheckReal,
  1133.                        VLC_THREAD_PRIORITY_LOW );
  1134. }
  1135. void* update_CheckReal( vlc_object_t* p_this )
  1136. {
  1137.     update_check_thread_t *p_uct = (update_check_thread_t *)p_this;
  1138.     bool b_ret;
  1139.     int canc;
  1140.     canc = vlc_savecancel ();
  1141.     vlc_mutex_lock( &p_uct->p_update->lock );
  1142.     EmptyRelease( p_uct->p_update );
  1143.     b_ret = GetUpdateFile( p_uct->p_update );
  1144.     vlc_mutex_unlock( &p_uct->p_update->lock );
  1145.     if( p_uct->pf_callback )
  1146.         (p_uct->pf_callback)( p_uct->p_data, b_ret );
  1147.     vlc_restorecancel (canc);
  1148.     return NULL;
  1149. }
  1150. /**
  1151.  * Compare a given release's version number to the current VLC's one
  1152.  *
  1153.  * param p_update structure
  1154.  * return true if we have to upgrade to the given version to be up to date
  1155.  */
  1156. static bool is_strictly_greater( int * a, int * b, int n)
  1157. {
  1158.     if( n <= 0 ) return false;
  1159.     if(a[0] > b[0] ) return true;
  1160.     if(a[0] == b[0] ) return is_strictly_greater( a+1, b+1, n-1 );
  1161.     /* a[0] < b[0] */ return false;
  1162. }
  1163. bool update_NeedUpgrade( update_t *p_update )
  1164. {
  1165.     assert( p_update );
  1166.     int current_version[] = {
  1167.         *PACKAGE_VERSION_MAJOR - '0',
  1168.         *PACKAGE_VERSION_MINOR - '0',
  1169.         *PACKAGE_VERSION_REVISION - '0',
  1170.         /* extra string of development versions is "-git", "-rc" ..
  1171.          * so make sure version a.b.c is newer than a.b.c-XXX */
  1172.         (*PACKAGE_VERSION_EXTRA == '-') ? -1 : *PACKAGE_VERSION_EXTRA
  1173.     };
  1174.     int latest_version[] = {
  1175.         p_update->release.i_major,
  1176.         p_update->release.i_minor,
  1177.         p_update->release.i_revision,
  1178.         p_update->release.extra
  1179.     };
  1180.     return is_strictly_greater( latest_version, current_version, 4 );
  1181. }
  1182. /**
  1183.  * Convert a long int size in bytes to a string
  1184.  *
  1185.  * param l_size the size in bytes
  1186.  * return the size as a string
  1187.  */
  1188. static char *size_str( long int l_size )
  1189. {
  1190.     char *psz_tmp = NULL;
  1191.     int i_retval = 0;
  1192.     if( l_size >> 30 )
  1193.         i_retval = asprintf( &psz_tmp, _("%.1f GB"), (float)l_size/(1<<30) );
  1194.     else if( l_size >> 20 )
  1195.         i_retval = asprintf( &psz_tmp, _("%.1f MB"), (float)l_size/(1<<20) );
  1196.     else if( l_size >> 10 )
  1197.         i_retval = asprintf( &psz_tmp, _("%.1f kB"), (float)l_size/(1<<10) );
  1198.     else
  1199.         i_retval = asprintf( &psz_tmp, _("%ld B"), l_size );
  1200.     return i_retval == -1 ? NULL : psz_tmp;
  1201. }
  1202. void update_WaitDownload( update_t *p_update )
  1203. {
  1204.     if( p_update->p_download )
  1205.     {
  1206.         vlc_thread_join( p_update->p_download );
  1207.         vlc_object_release( p_update->p_download );
  1208.         p_update->p_download = NULL;
  1209.     }
  1210. }
  1211. static void* update_DownloadReal( vlc_object_t *p_this );
  1212. /**
  1213.  * Download the file given in the update_t
  1214.  *
  1215.  * param p_update structure
  1216.  * param dir to store the download file
  1217.  * return nothing
  1218.  */
  1219. void update_Download( update_t *p_update, const char *psz_destdir )
  1220. {
  1221.     assert( p_update );
  1222.     // If the object already exist, destroy it
  1223.     if( p_update->p_download )
  1224.     {
  1225.         vlc_object_kill( p_update->p_download );
  1226.         vlc_thread_join( p_update->p_download );
  1227.         vlc_object_release( p_update->p_download );
  1228.     }
  1229.     update_download_thread_t *p_udt =
  1230.         vlc_custom_create( p_update->p_libvlc, sizeof( *p_udt ),
  1231.                            VLC_OBJECT_GENERIC, "update download" );
  1232.     if( !p_udt )
  1233.         return;
  1234.     p_udt->p_update = p_update;
  1235.     p_update->p_download = p_udt;
  1236.     p_udt->psz_destdir = psz_destdir ? strdup( psz_destdir ) : NULL;
  1237.     vlc_thread_create( p_udt, "download update", update_DownloadReal,
  1238.                        VLC_THREAD_PRIORITY_LOW );
  1239. }
  1240. static void* update_DownloadReal( vlc_object_t *p_this )
  1241. {
  1242.     update_download_thread_t *p_udt = (update_download_thread_t *)p_this;
  1243.     dialog_progress_bar_t *p_progress = NULL;
  1244.     long int l_size;
  1245.     long int l_downloaded = 0;
  1246.     float f_progress;
  1247.     char *psz_status = NULL;
  1248.     char *psz_downloaded = NULL;
  1249.     char *psz_size = NULL;
  1250.     char *psz_destfile = NULL;
  1251.     char *psz_tmpdestfile = NULL;
  1252.     FILE *p_file = NULL;
  1253.     stream_t *p_stream = NULL;
  1254.     void* p_buffer = NULL;
  1255.     int i_read;
  1256.     int canc;
  1257.     update_t *p_update = p_udt->p_update;
  1258.     char *psz_destdir = p_udt->psz_destdir;
  1259.     msg_Dbg( p_udt, "Opening Stream '%s'", p_update->release.psz_url );
  1260.     canc = vlc_savecancel ();
  1261.     /* Open the stream */
  1262.     p_stream = stream_UrlNew( p_udt, p_update->release.psz_url );
  1263.     if( !p_stream )
  1264.     {
  1265.         msg_Err( p_udt, "Failed to open %s for reading", p_update->release.psz_url );
  1266.         goto end;
  1267.     }
  1268.     /* Get the stream size */
  1269.     l_size = stream_Size( p_stream );
  1270.     /* Get the file name and open it*/
  1271.     psz_tmpdestfile = strrchr( p_update->release.psz_url, '/' );
  1272.     if( !psz_tmpdestfile )
  1273.     {
  1274.         msg_Err( p_udt, "The URL %s is badly formated",
  1275.                  p_update->release.psz_url );
  1276.         goto end;
  1277.     }
  1278.     psz_tmpdestfile++;
  1279.     if( asprintf( &psz_destfile, "%s%s", psz_destdir, psz_tmpdestfile ) == -1 )
  1280.         goto end;
  1281.     p_file = utf8_fopen( psz_destfile, "w" );
  1282.     if( !p_file )
  1283.     {
  1284.         msg_Err( p_udt, "Failed to open %s for writing", psz_destfile );
  1285.         dialog_FatalWait( p_udt, _("Saving file failed"),
  1286.             _("Failed to open "%s" for writing"),
  1287.              psz_destfile );
  1288.         goto end;
  1289.     }
  1290.     /* Create a buffer and fill it with the downloaded file */
  1291.     p_buffer = (void *)malloc( 1 << 10 );
  1292.     if( !p_buffer )
  1293.     {
  1294.         msg_Err( p_udt, "Can't malloc (1 << 10) bytes! download cancelled." );
  1295.         goto end;
  1296.     }
  1297.     msg_Dbg( p_udt, "Downloading Stream '%s'", p_update->release.psz_url );
  1298.     psz_size = size_str( l_size );
  1299.     if( asprintf( &psz_status, _("%snDownloading... %s/%s %.1f%% done"),
  1300.         p_update->release.psz_url, "0.0", psz_size, 0.0 ) != -1 )
  1301.     {
  1302.         p_progress = dialog_ProgressCreate( p_udt, _( "Downloading ..."),
  1303.                                             psz_status, _("Cancel") );
  1304.         free( psz_status );
  1305.     }
  1306.     while( vlc_object_alive( p_udt ) &&
  1307.            ( i_read = stream_Read( p_stream, p_buffer, 1 << 10 ) ) &&
  1308.            !dialog_ProgressCancelled( p_progress ) )
  1309.     {
  1310.         if( fwrite( p_buffer, i_read, 1, p_file ) < 1 )
  1311.         {
  1312.             msg_Err( p_udt, "Failed to write into %s", psz_destfile );
  1313.             break;
  1314.         }
  1315.         l_downloaded += i_read;
  1316.         psz_downloaded = size_str( l_downloaded );
  1317.         f_progress = (float)l_downloaded/(float)l_size;
  1318.         if( asprintf( &psz_status, _( "%snDownloading... %s/%s - %.1f%% done" ),
  1319.                       p_update->release.psz_url, psz_downloaded, psz_size,
  1320.                       f_progress*100 ) != -1 )
  1321.         {
  1322.             dialog_ProgressSet( p_progress, psz_status, f_progress );
  1323.             free( psz_status );
  1324.         }
  1325.         free( psz_downloaded );
  1326.     }
  1327.     /* Finish the progress bar or delete the file if the user had canceled */
  1328.     fclose( p_file );
  1329.     p_file = NULL;
  1330.     if( vlc_object_alive( p_udt ) &&
  1331.         !dialog_ProgressCancelled( p_progress ) )
  1332.     {
  1333.         if( asprintf( &psz_status, _("%snDone %s (100.0%%)"),
  1334.             p_update->release.psz_url, psz_size ) != -1 )
  1335.         {
  1336.             dialog_ProgressDestroy( p_progress );
  1337.             p_progress = NULL;
  1338.             free( psz_status );
  1339.         }
  1340.     }
  1341.     else
  1342.     {
  1343.         utf8_unlink( psz_destfile );
  1344.         goto end;
  1345.     }
  1346.     signature_packet_t sign;
  1347.     if( download_signature( VLC_OBJECT( p_udt ), &sign,
  1348.             p_update->release.psz_url ) != VLC_SUCCESS )
  1349.     {
  1350.         utf8_unlink( psz_destfile );
  1351.         dialog_FatalWait( p_udt, _("File could not be verified"),
  1352.             _("It was not possible to download a cryptographic signature for "
  1353.               "the downloaded file "%s". Thus, it was deleted."),
  1354.             psz_destfile );
  1355.         msg_Err( p_udt, "Couldn't download signature of downloaded file" );
  1356.         goto end;
  1357.     }
  1358.     if( memcmp( sign.issuer_longid, p_update->p_pkey->longid, 8 ) )
  1359.     {
  1360.         utf8_unlink( psz_destfile );
  1361.         msg_Err( p_udt, "Invalid signature issuer" );
  1362.         dialog_FatalWait( p_udt, _("Invalid signature"),
  1363.             _("The cryptographic signature for the downloaded file "%s" was "
  1364.               "invalid and could not be used to securely verify it. Thus, the "
  1365.               "file was deleted."),
  1366.             psz_destfile );
  1367.         goto end;
  1368.     }
  1369.     if( sign.type != BINARY_SIGNATURE )
  1370.     {
  1371.         utf8_unlink( psz_destfile );
  1372.         msg_Err( p_udt, "Invalid signature type" );
  1373.         dialog_FatalWait( p_udt, _("Invalid signature"),
  1374.             _("The cryptographic signature for the downloaded file "%s" was "
  1375.               "invalid and could not be used to securely verify it. Thus, the "
  1376.               "file was deleted."),
  1377.             psz_destfile );
  1378.         goto end;
  1379.     }
  1380.     uint8_t *p_hash = hash_sha1_from_file( psz_destfile, &sign );
  1381.     if( !p_hash )
  1382.     {
  1383.         msg_Err( p_udt, "Unable to hash %s", psz_destfile );
  1384.         utf8_unlink( psz_destfile );
  1385.         dialog_FatalWait( p_udt, _("File not verifiable"),
  1386.             _("It was not possible to securely verify the downloaded file"
  1387.               " "%s". Thus, it was deleted."),
  1388.             psz_destfile );
  1389.         goto end;
  1390.     }
  1391.     if( p_hash[0] != sign.hash_verification[0] ||
  1392.         p_hash[1] != sign.hash_verification[1] )
  1393.     {
  1394.         utf8_unlink( psz_destfile );
  1395.         dialog_FatalWait( p_udt, _("File corrupted"),
  1396.             _("Downloaded file "%s" was corrupted. Thus, it was deleted."),
  1397.              psz_destfile );
  1398.         msg_Err( p_udt, "Bad SHA1 hash for %s", psz_destfile );
  1399.         free( p_hash );
  1400.         goto end;
  1401.     }
  1402.     if( verify_signature( sign.r, sign.s, &p_update->p_pkey->key, p_hash )
  1403.             != VLC_SUCCESS )
  1404.     {
  1405.         utf8_unlink( psz_destfile );
  1406.         dialog_FatalWait( p_udt, _("File corrupted"),
  1407.             _("Downloaded file "%s" was corrupted. Thus, it was deleted."),
  1408.              psz_destfile );
  1409.         msg_Err( p_udt, "BAD SIGNATURE for %s", psz_destfile );
  1410.         free( p_hash );
  1411.         goto end;
  1412.     }
  1413.     msg_Info( p_udt, "%s authenticated", psz_destfile );
  1414.     free( p_hash );
  1415. end:
  1416.     if( p_progress )
  1417.         dialog_ProgressDestroy( p_progress );
  1418.     if( p_stream )
  1419.         stream_Delete( p_stream );
  1420.     if( p_file )
  1421.         fclose( p_file );
  1422.     free( psz_destdir );
  1423.     free( psz_destfile );
  1424.     free( p_buffer );
  1425.     free( psz_size );
  1426.     vlc_restorecancel( canc );
  1427.     return NULL;
  1428. }
  1429. update_release_t *update_GetRelease( update_t *p_update )
  1430. {
  1431.     return &p_update->release;
  1432. }
  1433. #else
  1434. update_t *__update_New( vlc_object_t *p_this )
  1435. {
  1436.     (void)p_this;
  1437.     return NULL;
  1438. }
  1439. void update_Delete( update_t *p_update )
  1440. {
  1441.     (void)p_update;
  1442. }
  1443. void update_Check( update_t *p_update, void (*pf_callback)( void*, bool ),
  1444.                    void *p_data )
  1445. {
  1446.     (void)p_update; (void)pf_callback; (void)p_data;
  1447. }
  1448. bool update_NeedUpgrade( update_t *p_update )
  1449. {
  1450.     (void)p_update;
  1451.     return false;
  1452. }
  1453. void update_WaitDownload( update_t *p_update )
  1454. {
  1455.     (void)p_update;
  1456. }
  1457. void update_Download( update_t *p_update, const char *psz_destdir )
  1458. {
  1459.     (void)p_update; (void)psz_destdir;
  1460. }
  1461. update_release_t *update_GetRelease( update_t *p_update )
  1462. {
  1463.     (void)p_update;
  1464.     return NULL;
  1465. }
  1466. #endif