⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 update.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 )    {        msg_Dbg( p_this, "Couldn't read full GPG key" );        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;    }    memcpy( p_pkey->longid, p_longid, 8 );    int i_error = parse_public_key( p_buf, i_read, p_pkey, p_signature_issuer );    free( p_buf );    if( i_error != VLC_SUCCESS )    {        msg_Dbg( p_this, "Couldn't parse GPG key" );        free( p_pkey );        return NULL;    }    return p_pkey;}/* * Generate a SHA1 hash on a public key, to verify a signature made on that hash * Note that we need the signature (v4) to compute the hash */static uint8_t *key_sign_hash( public_key_t *p_pkey ){    if( p_pkey->sig.version != 4 )        return NULL;    if( p_pkey->sig.type < GENERIC_KEY_SIGNATURE ||        p_pkey->sig.type > POSITIVE_KEY_SIGNATURE )        return NULL;    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 );    size_t i_p_len = mpi_len( p_pkey->key.p );    size_t i_g_len = mpi_len( p_pkey->key.g );    size_t i_q_len = mpi_len( p_pkey->key.q );    size_t i_y_len = mpi_len( p_pkey->key.y );    size_t i_size = 6 + 2*4 + i_p_len + i_g_len + i_q_len + i_y_len;    gcry_md_putc( hd, (i_size >> 8) & 0xff );    gcry_md_putc( hd, i_size & 0xff );    gcry_md_putc( hd, p_pkey->key.version );    gcry_md_write( hd, p_pkey->key.timestamp, 4 );    gcry_md_putc( hd, p_pkey->key.algo );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.p, 2 );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.p + 2, i_p_len );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.q, 2 );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.q + 2, i_q_len );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.g, 2 );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.g + 2, i_g_len );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.y, 2 );    gcry_md_write( hd, (uint8_t*)&p_pkey->key.y + 2, i_y_len );    gcry_md_putc( hd, 0xb4 );    size_t 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.specific.v4.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.specific.v4.hashed_data_len, 2 );    gcry_md_write( hd, p_pkey->sig.specific.v4.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_tmp = gcry_md_read( hd, GCRY_MD_SHA1);    if( !p_tmp ||        p_tmp[0] != p_pkey->sig.hash_verification[0] ||        p_tmp[1] != p_pkey->sig.hash_verification[1] )    {        gcry_md_close( hd );        return NULL;    }    uint8_t *p_hash = malloc( 20 );    if( p_hash )        memcpy( p_hash, p_tmp, 20 );    gcry_md_close( hd );    return p_hash;}/***************************************************************************** * Update_t functions *****************************************************************************//** * Create a new update VLC struct * * \param p_this the calling vlc_object * \return pointer to new update_t or NULL */update_t *__update_New( vlc_object_t *p_this ){    update_t *p_update;    assert( p_this );    p_update = (update_t *)malloc( sizeof( update_t ) );    if( !p_update ) return NULL;    vlc_mutex_init( &p_update->lock );    p_update->p_libvlc = p_this->p_libvlc;    p_update->release.psz_url = NULL;    p_update->release.psz_desc = NULL;    p_update->p_download = NULL;    p_update->p_check = NULL;    p_update->p_pkey = NULL;    vlc_gcrypt_init();    return p_update;}/** * Delete an update_t struct * * \param p_update update_t* pointer * \return nothing */void update_Delete( update_t *p_update ){    assert( p_update );    if( p_update->p_check )    {        assert( !p_update->p_download );        vlc_object_kill( p_update->p_check );        vlc_thread_join( p_update->p_check );    }    else if( p_update->p_download )    {        vlc_object_kill( p_update->p_download );        vlc_thread_join( p_update->p_download );        vlc_object_release( p_update->p_download );    }    vlc_mutex_destroy( &p_update->lock );    free( p_update->release.psz_url );    free( p_update->release.psz_desc );    free( p_update->p_pkey );    free( p_update );}/** * Empty the release struct * * \param p_update update_t* pointer * \return nothing */static void EmptyRelease( update_t *p_update ){    p_update->release.i_major = 0;    p_update->release.i_minor = 0;    p_update->release.i_revision = 0;    FREENULL( p_update->release.psz_url );    FREENULL( p_update->release.psz_desc );}/** * Get the update file and parse it * p_update has to be locked when calling this function * * \param p_update pointer to update struct * \return true if the update is valid and authenticated */static bool GetUpdateFile( update_t *p_update ){    stream_t *p_stream = NULL;    int i_major = 0;    int i_minor = 0;    int i_revision = 0;    unsigned char extra;    char *psz_version_line = NULL;    p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL );    if( !p_stream )    {        msg_Err( p_update->p_libvlc, "Failed to open %s for reading",                 UPDATE_VLC_STATUS_URL );        goto error;    }    /* Start reading the status file */    if( !( psz_version_line = stream_ReadLine( p_stream ) ) )    {        msg_Err( p_update->p_libvlc, "Update file %s is corrupted : missing version",                 UPDATE_VLC_STATUS_URL );        goto error;    }    /* first line : version number */    p_update->release.extra = 0;    switch( sscanf( psz_version_line, "%i.%i.%i%c",                    &i_major, &i_minor, &i_revision, &extra ) )    {        case 4:            p_update->release.extra = extra;        case 3:            p_update->release.i_major = i_major;            p_update->release.i_minor = i_minor;            p_update->release.i_revision = i_revision;            break;        default:            msg_Err( p_update->p_libvlc, "Update version false formated" );            goto error;    }    /* second line : URL */    if( !( p_update->release.psz_url = stream_ReadLine( p_stream ) ) )    {        msg_Err( p_update->p_libvlc, "Update file %s is corrupted : URL missing",                 UPDATE_VLC_STATUS_URL );        goto error;    }    /* Remaining data : description */    int i_read = stream_Size( p_stream ) - stream_Tell( p_stream );    if( i_read <= 0 )    {        msg_Err( p_update->p_libvlc,                "Update file %s is corrupted: description missing",                UPDATE_VLC_STATUS_URL );        goto error;    }    p_update->release.psz_desc = (char*) malloc( i_read + 1 );    if( !p_update->release.psz_desc )        goto error;    if( stream_Read( p_stream, p_update->release.psz_desc, i_read ) != i_read )    {        msg_Err( p_update->p_libvlc, "Couldn't download update file %s",                UPDATE_VLC_STATUS_URL );        goto error;    }    p_update->release.psz_desc[i_read] = '\0';    stream_Delete( p_stream );    p_stream = NULL;    /* Now that we know the status is valid, we must download its signature     * to authenticate it */    signature_packet_t sign;    if( download_signature( VLC_OBJECT( p_update->p_libvlc ), &sign,            UPDATE_VLC_STATUS_URL ) != VLC_SUCCESS )    {        msg_Err( p_update->p_libvlc, "Couldn't download signature of status file" );        goto error;    }    if( sign.type != BINARY_SIGNATURE && sign.type != TEXT_SIGNATURE )    {        msg_Err( p_update->p_libvlc, "Invalid signature type" );        goto error;    }    p_update->p_pkey = (public_key_t*)malloc( sizeof( public_key_t ) );    if( !p_update->p_pkey )        goto error;    if( parse_public_key( videolan_public_key, sizeof( videolan_public_key ),                        p_update->p_pkey, NULL ) != VLC_SUCCESS )    {        msg_Err( p_update->p_libvlc, "Couldn't parse embedded public key, something went really wrong..." );        FREENULL( p_update->p_pkey );        goto error;    }    memcpy( p_update->p_pkey->longid, videolan_public_key_longid, 8 );    if( memcmp( sign.issuer_longid, p_update->p_pkey->longid , 8 ) != 0 )    {        msg_Dbg( p_update->p_libvlc, "Need to download the GPG key" );        public_key_t *p_new_pkey = download_key(                VLC_OBJECT(p_update->p_libvlc),                sign.issuer_longid, videolan_public_key_longid );        if( !p_new_pkey )        {            msg_Err( p_update->p_libvlc, "Couldn't download GPG key" );            FREENULL( p_update->p_pkey );            goto error;        }        uint8_t *p_hash = key_sign_hash( p_new_pkey );        if( !p_hash )        {            msg_Err( p_update->p_libvlc, "Failed to hash signature" );            free( p_new_pkey );            FREENULL( p_update->p_pkey );            goto error;        }        if( verify_signature( p_new_pkey->sig.r, p_new_pkey->sig.s,                    &p_update->p_pkey->key, p_hash ) == VLC_SUCCESS )        {            free( p_hash );            msg_Info( p_update->p_libvlc, "Key authenticated" );            free( p_update->p_pkey );            p_update->p_pkey = p_new_pkey;        }        else        {            free( p_hash );            msg_Err( p_update->p_libvlc, "Key signature invalid !\n" );            goto error;        }    }    gcry_md_hd_t hd;    if( gcry_md_open( &hd, GCRY_MD_SHA1, 0 ) )        goto error_hd;    gcry_md_write( hd, psz_version_line, strlen( psz_version_line ) );    FREENULL( psz_version_line );    if( sign.type == TEXT_SIGNATURE )        gcry_md_putc( hd, '\r' );    gcry_md_putc( hd, '\n' );    gcry_md_write( hd, p_update->release.psz_url,                        strlen( p_update->release.psz_url ) );    if( sign.type == TEXT_SIGNATURE )        gcry_md_putc( hd, '\r' );    gcry_md_putc( hd, '\n' );    char *psz_desc = p_update->release.psz_desc;    while( *psz_desc )    {        size_t i_len = strcspn( psz_desc, "\r\n" );        if( !i_len )            break;        gcry_md_write( hd, psz_desc, i_len );        if( sign.type == TEXT_SIGNATURE )            gcry_md_putc( hd, '\r' );        gcry_md_putc( hd, '\n' );        psz_desc += i_len;        while( *psz_desc == '\r' || *psz_desc == '\n' )            psz_desc++;    }    if( sign.version == 3 )    {        gcry_md_putc( hd, sign.type );        gcry_md_write( hd, &sign.specific.v3.timestamp, 4 );    }    else if( sign.version == 4 )    {        gcry_md_putc( hd, sign.version );        gcry_md_putc( hd, sign.type );        gcry_md_putc( hd, sign.public_key_algo );        gcry_md_putc( hd, sign.digest_algo );        gcry_md_write( hd, sign.specific.v4.hashed_data_len, 2 );        size_t i_len = scalar_number( sign.specific.v4.hashed_data_len, 2 );        gcry_md_write( hd, sign.specific.v4.hashed_data, i_len );        gcry_md_putc( hd, 0x04 );        gcry_md_putc( hd, 0xFF );        i_len += 6; /* hashed data + 6 bytes header */        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 );    }    else    {   /* RFC 4880 only tells about versions 3 and 4 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -