changeset 31100:45159a4b8815

libdvdcss: Fix potential format string crash; check RPC status on disc access. This merges upstream revisions 223 and 224 + 225.
author diego
date Tue, 11 May 2010 11:10:28 +0000
parents f43e87f69590
children bb98a3561775
files libdvdcss/css.c libdvdcss/libdvdcss.c
diffstat 2 files changed, 62 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/libdvdcss/css.c	Tue May 11 10:58:50 2010 +0000
+++ b/libdvdcss/css.c	Tue May 11 11:10:28 2010 +0000
@@ -89,10 +89,19 @@
 
 /*****************************************************************************
  * _dvdcss_test: check if the disc is encrypted or not
+ *****************************************************************************
+ * Return values:
+ *   1: DVD is scrambled but can be read
+ *   0: DVD is not scrambled and can be read
+ *  -1: could not get "copyright" information
+ *  -2: could not get RPC information (reading the disc might be possible)
+ *  -3: drive is RPC-II, region is not set, and DVD is scrambled: the RPC
+ *      scheme will prevent us from reading the scrambled data
  *****************************************************************************/
 int _dvdcss_test( dvdcss_t dvdcss )
 {
-    int i_ret, i_copyright;
+    char const *psz_type, *psz_rpc;
+    int i_ret, i_copyright, i_type, i_mask, i_rpc;
 
     i_ret = ioctl_ReadCopyright( dvdcss->i_fd, 0 /* i_layer */, &i_copyright );
 
@@ -115,14 +124,51 @@
     if( i_ret < 0 )
     {
         /* Since it's the first ioctl we try to issue, we add a notice */
-        print_error( dvdcss, "css error: ioctl_ReadCopyright failed, "
-                     "make sure there is a DVD in the drive, and that "
-                     "you have used the correct device node." );
+        print_error( dvdcss, "css error: could not get \"copyright\""
+                     " information, make sure there is a DVD in the drive,"
+                     " and that you have used the correct device node." );
+
+        return -1;
+    }
 
-        return i_ret;
+    print_debug( dvdcss, "disc reports copyright information 0x%x",
+                         i_copyright );
+
+    i_ret = ioctl_ReportRPC( dvdcss->i_fd, &i_type, &i_mask, &i_rpc);
+
+    if( i_ret < 0 )
+    {
+        print_error( dvdcss, "css error: could not get RPC status" );
+        return -2;
     }
 
-    return i_copyright;
+    switch( i_rpc )
+    {
+        case 0: psz_rpc = "RPC-I"; break;
+        case 1: psz_rpc = "RPC-II"; break;
+        default: psz_rpc = "unknown RPC scheme"; break;
+    }
+
+    switch( i_type )
+    {
+        case 0: psz_type = "no region code set"; break;
+        case 1: psz_type = "region code set"; break;
+        case 2: psz_type = "one region change remaining"; break;
+        case 3: psz_type = "region code set permanently"; break;
+        default: psz_type = "unknown status"; break;
+    }
+
+    print_debug( dvdcss, "drive region mask %x, %s, %s",
+                         i_mask, psz_rpc, psz_type );
+
+    if( i_copyright && i_rpc == 1 && i_type == 0 )
+    {
+        print_error( dvdcss, "css error: drive will prevent access to "
+                             "scrambled data" );
+        return -3;
+    }
+
+    return i_copyright ? 1 : 0;
 }
 
 /*****************************************************************************
--- a/libdvdcss/libdvdcss.c	Tue May 11 10:58:50 2010 +0000
+++ b/libdvdcss/libdvdcss.c	Tue May 11 11:10:28 2010 +0000
@@ -367,7 +367,14 @@
     if( dvdcss->b_ioctls )
     {
         i_ret = _dvdcss_test( dvdcss );
-        if( i_ret < 0 )
+        if( i_ret == -2 )
+        {
+            /* Scrambled disk, RPC-II drive, no region set: bail out */
+            free( dvdcss->psz_device );
+            free( dvdcss );
+            return NULL;
+        }
+        else if( i_ret < 0 )
         {
             /* Disable the CSS ioctls and hope that it works? */
             print_debug( dvdcss,
@@ -420,7 +427,6 @@
     if( psz_cache )
     {
         uint8_t p_sector[DVDCSS_BLOCK_SIZE];
-        char psz_debug[PATH_MAX + 30];
         char psz_key[1 + KEY_SIZE * 2 + 1];
         char *psz_title;
         uint8_t *psz_serial;
@@ -548,9 +554,8 @@
         /* Pointer to the filename we will use. */
         dvdcss->psz_block = dvdcss->psz_cachefile + i;
 
-        sprintf( psz_debug, "using CSS key cache dir: %s",
-                            dvdcss->psz_cachefile );
-        print_debug( dvdcss, psz_debug );
+        print_debug( dvdcss, "using CSS key cache dir: %s",
+                             dvdcss->psz_cachefile );
     }
     nocache: