Solaris 9: libdvdread / libdvdcss needs root permission
Juergen Keil
jk at tools.de
Wed Oct 23 20:32:54 CEST 2002
> Just move the USCSICMD ioctls into a separate setuid-root process, and
> add code to libdvdcss's ioctl.c file to use that new setuid-root
> process to perform the USCSICMDs for drive authentication and title key
> access.
OK, I've implemented this one now. A patch against libdvdcss-1.2.3 is
appended and also available here:
<URL:http://www.tools.de/solaris/libdvdcss/libdvdcss-1.2.3-patch>
Apply it like this:
gunzip < libdvdcss-1.2.3.tar.gz | tar xf -
cd libdvdcss-1.2.3
patch -p1 < ../libdvdcss-1.2.3-patch
bootstrap
There are no ABI changes for libdvdcss.so.2, so it can be used as a direct
replacement for the official libdvdcss-1.2.3 on Solaris 9. I also tested it
on a Solaris 2.6 and several Solaris 8 boxes, the csstest program runs fine
on the older platform, too.
Linux and NetBSD builds are working, too.
-------------- next part --------------
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/ChangeLog libdvdcss-1.2.3-jk/ChangeLog
--- libdvdcss-1.2.3-orig/ChangeLog Sun Oct 13 01:01:13 2002
+++ libdvdcss-1.2.3-jk/ChangeLog Sun Oct 20 19:36:59 2002
@@ -2,6 +2,11 @@
# ChangeLog for libdvdcss #
#=========================#
+ * src/soldoor_*, src/ioctl.c: DVD ioctl support for non-root users
+ on Solaris 9 using a setuid root helper process. By J?rgen Keil
+ <jk at tools.de>.
+
+
1.2.3
Sun, 13 Oct 2002 01:01:03 +0200
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/configure.ac libdvdcss-1.2.3-jk/configure.ac
--- libdvdcss-1.2.3-orig/configure.ac Fri Oct 11 12:03:48 2002
+++ libdvdcss-1.2.3-jk/configure.ac Mon Oct 21 15:58:34 2002
@@ -99,10 +99,15 @@
])
dnl
dnl Solaris: sys/scsi/scsi_types.h, sys/scsi/impl/uscsi.h
+ dnl door.h for IPC setuid root uscsi server
dnl
AC_CHECK_HEADER(sys/scsi/scsi_types.h,[
AC_CHECK_HEADER(sys/scsi/impl/uscsi.h,[
AC_DEFINE(SOLARIS_USCSI, 1, Have userspace SCSI headers.)
+ AC_CHECK_HEADER(door.h,[
+ AC_DEFINE(SOLARIS_DOORS, 1, Have door IPC.)
+ SOL_DOOR_IPC=1
+ ])
])
])
dnl
@@ -141,6 +146,7 @@
AM_CONDITIONAL(SYS_BSDI, test "x$SYS_BSDI" = "x1")
AM_CONDITIONAL(SYS_MSVC, test "x$SYS_MSVC" = "x1")
+AM_CONDITIONAL(SOL_DOOR_IPC, test "x$SOL_DOOR_IPC" = "x1")
AC_OUTPUT([Makefile src/Makefile src/dvdcss/Makefile test/Makefile debian/Makefile doc/Makefile])
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/Makefile.am libdvdcss-1.2.3-jk/src/Makefile.am
--- libdvdcss-1.2.3-orig/src/Makefile.am Sat Oct 12 01:45:43 2002
+++ libdvdcss-1.2.3-jk/src/Makefile.am Mon Oct 21 16:01:50 2002
@@ -1,5 +1,7 @@
SUBDIRS = dvdcss
+AM_CPPFLAGS = -DEXEC_PREFIX=\"$(exec_prefix)\"
+
lib_LTLIBRARIES = libdvdcss.la
libdvdcss_la_SOURCES = \
@@ -9,12 +11,13 @@
ioctl.c ioctl.h \
error.c \
common.h \
- $(bsdi_sources)
+ $(bsdi_sources) \
+ $(soldoor_sources)
EXTRA_libdvdcss_la_SOURCES = \
$(bsdi_extras)
-libdvdcss_la_LIBADD = $(bsdi_libadd)
+libdvdcss_la_LIBADD = $(bsdi_libadd) $(soldoor_libadd)
libdvdcss_la_LDFLAGS = -version-info 2:3:0 $(libtool_flags)
bsdi_extras = bsdi_ioctl.c bsdi_dvd.h
@@ -29,3 +32,35 @@
libtool_flags = -no-undefined
endif
+if SOL_DOOR_IPC
+soldoor_sources = soldoor_ioctl.c
+soldoor_libadd = -ldoor
+
+libexec_PROGRAMS = dvdcss_door
+
+dvdcss_door_SOURCES = soldoor_server.c soldoor_uscsi.c
+dvdcss_door_LDADD = -ldoor -lpthread
+
+
+# Extra rule to set the correct permission of the setuid-root server program
+soldoor_install = soldoor-setuid-install
+soldoor-setuid-install:
+ @case `id` in \
+ uid=0*) set -x; \
+ chown root $(DESTDIR)$(libexecdir)/dvdcss_door; \
+ chmod 4755 $(DESTDIR)$(libexecdir)/dvdcss_door; \
+ ;; \
+ *) echo "=============================================="; \
+ echo "You must run 'make install' as user 'root' to "; \
+ echo "install the setuid dvdcss_door helper program."; \
+ echo; \
+ echo "Or run the following commands as user 'root':"; \
+ echo " chown root $(DESTDIR)$(libexecdir)/dvdcss_door";\
+ echo " chmod 4755 $(DESTDIR)$(libexecdir)/dvdcss_door";\
+ echo "=============================================="; \
+ ls -l $(DESTDIR)$(libexecdir)/dvdcss_door; \
+ ;; \
+ esac
+endif
+
+install-exec-hook: $(soldoor_install)
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/ioctl.c libdvdcss-1.2.3-jk/src/ioctl.c
--- libdvdcss-1.2.3-orig/src/ioctl.c Sun Oct 13 01:06:49 2002
+++ libdvdcss-1.2.3-jk/src/ioctl.c Sun Oct 20 23:49:50 2002
@@ -75,6 +75,12 @@
#ifdef HPUX_SCTL_IO
# include <sys/scsi.h>
#endif
+#ifdef SOLDOOR_COMPILE_USCSI
+# undef SOLARIS_DOORS
+#endif
+#ifdef SOLARIS_DOORS
+# include "soldoor_ioctl.h"
+#endif
#ifdef SOLARIS_USCSI
# include <unistd.h>
# include <stropts.h>
@@ -110,7 +116,7 @@
/*****************************************************************************
* Local prototypes, Solaris specific
*****************************************************************************/
-#if defined( SOLARIS_USCSI )
+#if defined( SOLARIS_USCSI ) && !defined( SOLARIS_DOORS )
static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type );
#endif
@@ -185,6 +191,8 @@
*pi_copyright = p_buffer[ 4 ];
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReadCopyright( i_fd, i_layer, pi_copyright );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 8 );
@@ -394,6 +402,8 @@
memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReadDiscKey( i_fd, pi_agid, p_key );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 );
@@ -553,6 +563,8 @@
memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReadTitleKey( i_fd, pi_agid, i_pos, p_key );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 12 );
@@ -709,6 +721,8 @@
*pi_agid = p_buffer[ 7 ] >> 6;
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReportAgid( i_fd, pi_agid );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 8 );
@@ -831,6 +845,8 @@
memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReportChallenge( i_fd, pi_agid, p_challenge );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 16 );
@@ -965,6 +981,8 @@
*pi_asf = p_buffer[ 7 ] & 1;
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReportASF( i_fd, pi_remove_me, pi_asf );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 8 );
@@ -1098,6 +1116,8 @@
memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReportKey1( i_fd, pi_agid, p_key );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 12 );
@@ -1219,6 +1239,8 @@
i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_InvalidateAgid( i_fd, pi_agid );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 0 );
@@ -1340,6 +1362,8 @@
return ioctl( i_fd, SIOC_IO, &sctl_io );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_SendChallenge( i_fd, pi_agid, p_challenge );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_SEND_KEY, 16 );
@@ -1477,6 +1501,8 @@
return ioctl( i_fd, SIOC_IO, &sctl_io );
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_SendKey2( i_fd, pi_agid, p_key );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_SEND_KEY, 12 );
@@ -1622,6 +1648,8 @@
*p_mask = p_buffer[ 5 ];
*p_scheme = p_buffer[ 6 ];
+#elif defined( SOLARIS_DOORS )
+ i_ret = door_ReportRPC( i_fd, p_type, p_mask, p_scheme );
#elif defined( SOLARIS_USCSI )
INIT_USCSI( GPCMD_REPORT_KEY, 8 );
@@ -1790,7 +1818,7 @@
}
#endif
-#if defined( SOLARIS_USCSI )
+#if defined( SOLARIS_USCSI ) && !defined( SOLARIS_DOORS )
/*****************************************************************************
* SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
*****************************************************************************
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/ioctl.h libdvdcss-1.2.3-jk/src/ioctl.h
--- libdvdcss-1.2.3-orig/src/ioctl.h Sun Oct 13 01:06:49 2002
+++ libdvdcss-1.2.3-jk/src/ioctl.h Sun Oct 20 23:51:45 2002
@@ -31,6 +31,7 @@
int ioctl_InvalidateAgid ( int, int * );
int ioctl_SendChallenge ( int, int *, u8 * );
int ioctl_SendKey2 ( int, int *, u8 * );
+int ioctl_ReportRPC ( int, int *, int *, int * );
#define DVD_KEY_SIZE 5
#define DVD_CHALLENGE_SIZE 10
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/soldoor_ioctl.c libdvdcss-1.2.3-jk/src/soldoor_ioctl.c
--- libdvdcss-1.2.3-orig/src/soldoor_ioctl.c Thu Jan 1 01:00:00 1970
+++ libdvdcss-1.2.3-jk/src/soldoor_ioctl.c Mon Oct 21 16:02:12 2002
@@ -0,0 +1,364 @@
+/*
+ * This file contains subroutines for the DVD ioctls, implemented as
+ * "door" procedure calls into a setuid-root server process
+ * ("dvdcss_door").
+ *
+ * Such a construct is needed, because Solaris 9 includes a security fix
+ * for the "vol" driver. A process without root credentials is not
+ * allowed any more to send USCSICMD ioctl to the DVD-ROM device via the
+ * "/vol/dev/aliases/cdrom" vol device.
+ *
+ * The dvdcss_door server runs with the necessary root permission, and
+ * we relay the open file descriptor and the arguments for the USCSICMD
+ * ioctl to the door server. The door server performs the USCSICMD and
+ * sends back the result parameters.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <door.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include "common.h"
+#include "ioctl.h"
+#include "soldoor_server.h"
+#include "soldoor_ioctl.h"
+
+
+/*
+ * Start the "door" server, and wait until it's ready to server requests.
+ */
+static int door_start_uscsi_server()
+{
+ pid_t pid, pid2;
+ int status;
+ int i;
+
+ pid = fork();
+ switch( pid ) {
+ case -1:
+ /* perror( "fork dvdcss_door server" ); */
+ return -1;
+ case 0:
+ /* do not pass random fds to the dvdcss_door daemon */
+ for(i = sysconf(_SC_OPEN_MAX); i >= 3; i--)
+ close(i);
+ execl( EXEC_PREFIX "/libexec/dvdcss_door", "(dvdcss helper)", 0 );
+ perror( EXEC_PREFIX "/libexec/dvdcss_door" );
+ _exit( 1 );
+ default:
+ while( (pid2 = waitpid( pid, &status, 0 )) < 0 && errno == EINTR )
+ ;
+ if( pid2 < 0 ) {
+ /* perror( "waitpid" ); */
+ return -1;
+ }
+
+ if( status )
+ return -1; /* exit status from dvdcss_door not OK */
+
+ /* exit status OK, dvdcss_door server should be up and runnnig */
+ return 0;
+ }
+}
+
+
+/*
+ * Pass an USCSICMD ioctl to the "door" server for execution with root
+ * credentials.
+ *
+ * The "door" USCSICMD server is automatically started, when we notice that
+ * it's not yet runing.
+ */
+static int door_uscsi_call( int i_fd,
+ void *args, int args_size,
+ void *rbuf, int rbuf_size )
+{
+ static int initialized;
+ static int door;
+ int i;
+ door_desc_t door_desc;
+ door_arg_t door_arg;
+
+ if( !initialized ) {
+ struct stat stb;
+ int start_server;
+ struct door_info di;
+
+ initialized = 1;
+
+ if( ( door = open( USCSI_DOOR, O_RDONLY ) ) < 0
+ || fstat( door, &stb ) < 0
+ || !S_ISDOOR( stb.st_mode)
+ || door_info( door, &di ) < 0
+ || di.di_target == -1 )
+ {
+ /* something is wrong with the "door" file entry, start server */
+ start_server = 1;
+ } else {
+ /* "door" file entry is there, test if server is up and running */
+ start_server = door_call( door, NULL ) < 0;
+ }
+
+ if( start_server ) {
+ if( door >= 0 )
+ close( door );
+
+ door_start_uscsi_server();
+
+ if( ( door = open( USCSI_DOOR, O_RDONLY ) ) < 0
+ || fstat( door, &stb ) < 0
+ || !S_ISDOOR( stb.st_mode)
+ || door_info( door, &di ) < 0
+ || di.di_target == -1 ) {
+
+ /* still not working after a sever start? give up... */
+ if( door >= 0 )
+ close( door );
+ door = -1;
+ }
+ }
+
+ }
+
+ if( door < 0 )
+ return -1;
+
+ door_desc.d_attributes = DOOR_DESCRIPTOR;
+ door_desc.d_data.d_desc.d_descriptor = i_fd;
+
+ door_arg.data_ptr = args;
+ door_arg.data_size = args_size;
+ door_arg.desc_ptr = &door_desc;
+ door_arg.desc_num = 1;
+ door_arg.rbuf = rbuf;
+ door_arg.rsize = rbuf_size;
+
+ /*
+ * According to the manual page, door_call() is not a restartable
+ * system call, so loop while we receive EINTR errors
+ */
+ while( ( i = door_call( door, &door_arg ) ) < 0 && errno == EINTR )
+ ;
+
+ if( i < 0 ) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * door_ReadCopyright: check whether the disc is encrypted or not
+ *****************************************************************************/
+int door_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
+{
+ struct uscsi_ReadCopyright_args arg;
+ struct uscsi_ReadCopyright_res res;
+
+ arg.command = DOOR_USCSI_READCOPYRIGHT;
+ arg.layer = i_layer;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ *pi_copyright = res.copyright;
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReadDiscKey: get the disc key
+ *****************************************************************************/
+int door_ReadDiscKey( int i_fd, int *pi_agid, unsigned char *p_key )
+{
+ struct uscsi_ReadDiscKey_args arg;
+ struct uscsi_ReadDiscKey_res res;
+
+ arg.command = DOOR_USCSI_REPORT_DISCKEY;
+ arg.agid = *pi_agid;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ memcpy( p_key, res.key, DVD_DISCKEY_SIZE );
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * ioctl_ReadTitleKey: get the title key
+ *****************************************************************************/
+int door_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, unsigned char *p_key )
+{
+ struct uscsi_ReadTitleKey_args arg;
+ struct uscsi_ReadTitleKey_res res;
+
+ arg.command = DOOR_USCSI_REPORT_TITLEKEY;
+ arg.agid = *pi_agid;
+ arg.pos = i_pos;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ memcpy( p_key, res.key, DVD_KEY_SIZE );
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReportAgid: get AGID from the drive
+ *****************************************************************************/
+int door_ReportAgid( int i_fd, int *pi_agid )
+{
+ struct uscsi_ReportAgid_args arg;
+ struct uscsi_ReportAgid_res res;
+
+ arg.command = DOOR_USCSI_REPORT_AGID;
+ arg.agid = *pi_agid;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ *pi_agid = res.agid;
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReportChallenge: get challenge from the drive
+ *****************************************************************************/
+int door_ReportChallenge( int i_fd, int *pi_agid, unsigned char *p_challenge )
+{
+ struct uscsi_ReportChallenge_args arg;
+ struct uscsi_ReportChallenge_res res;
+
+ arg.command = DOOR_USCSI_REPORT_CHALLENGE;
+ arg.agid = *pi_agid;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ memcpy( p_challenge, res.challenge, DVD_CHALLENGE_SIZE );
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReportASF: get ASF from the drive
+ *****************************************************************************/
+int door_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf )
+{
+ struct uscsi_ReportASF_args arg;
+ struct uscsi_ReportASF_res res;
+
+ arg.command = DOOR_USCSI_REPORT_ASF;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ *pi_asf = res.asf;
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReportKey1: get the first key from the drive
+ *****************************************************************************/
+int door_ReportKey1( int i_fd, int *pi_agid, unsigned char *p_key )
+{
+ struct uscsi_ReportKey1_args arg;
+ struct uscsi_ReportKey1_res res;
+
+ arg.command = DOOR_USCSI_REPORT_KEY1;
+ arg.agid = *pi_agid;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ memcpy( p_key, res.key, DVD_KEY_SIZE );
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_InvalidateAgid: invalidate the current AGID
+ *****************************************************************************/
+int door_InvalidateAgid( int i_fd, int *pi_agid )
+{
+ struct uscsi_InvalidateAgid_args arg;
+ struct uscsi_InvalidateAgid_res res;
+
+ arg.command = DOOR_USCSI_INVALIDATE_AGID;
+ arg.agid = *pi_agid;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ *pi_agid = res.agid;
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_SendChallenge: send challenge to the drive
+ *****************************************************************************/
+int door_SendChallenge( int i_fd, int *pi_agid, unsigned char *p_challenge )
+{
+ struct uscsi_SendChallenge_args arg;
+ struct uscsi_SendChallenge_res res;
+
+ arg.command = DOOR_USCSI_SEND_CHALLENGE;
+ arg.agid = *pi_agid;
+ memcpy( arg.challenge, p_challenge, DVD_CHALLENGE_SIZE );
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * ioctl_SendKey2: send the second key to the drive
+ *****************************************************************************/
+int door_SendKey2( int i_fd, int *pi_agid, unsigned char *p_key )
+{
+ struct uscsi_SendKey2_args arg;
+ struct uscsi_SendKey2_res res;
+
+ arg.command = DOOR_USCSI_SEND_KEY2;
+ arg.agid = *pi_agid;
+ memcpy( arg.key, p_key, DVD_KEY_SIZE );
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ return res.rval;
+}
+
+
+/*****************************************************************************
+ * door_ReportRPC: get RPC status for the drive
+ *****************************************************************************/
+int door_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme )
+{
+ struct uscsi_ReportRPC_args arg;
+ struct uscsi_ReportRPC_res res;
+
+ arg.command = DOOR_USCSI_REPORT_RPC;
+ if( door_uscsi_call( i_fd,
+ &arg, sizeof( arg ), &res, sizeof( res ) ) < 0 ) {
+ return -1;
+ }
+ *p_type = res.type;
+ *p_mask = res.mask;
+ *p_scheme = res.scheme;
+ return res.rval;
+}
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/soldoor_ioctl.h libdvdcss-1.2.3-jk/src/soldoor_ioctl.h
--- libdvdcss-1.2.3-orig/src/soldoor_ioctl.h Thu Jan 1 01:00:00 1970
+++ libdvdcss-1.2.3-jk/src/soldoor_ioctl.h Sun Oct 20 10:58:46 2002
@@ -0,0 +1,16 @@
+#ifndef soldoor_ioctl_h
+#define soldoor_ioctl_h
+
+int door_ReadCopyright( int i_fd, int i_layer, int *pi_copyright );
+int door_ReadDiscKey( int i_fd, int *pi_agid, unsigned char *p_key );
+int door_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, unsigned char *p_key );
+int door_ReportAgid( int i_fd, int *pi_agid );
+int door_ReportChallenge( int i_fd, int *pi_agid, unsigned char *p_challenge );
+int door_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf );
+int door_ReportKey1( int i_fd, int *pi_agid, unsigned char *p_key );
+int door_InvalidateAgid( int i_fd, int *pi_agid );
+int door_SendChallenge( int i_fd, int *pi_agid, unsigned char *p_challenge );
+int door_SendKey2( int i_fd, int *pi_agid, unsigned char *p_key );
+int door_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme );
+
+#endif
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/soldoor_server.c libdvdcss-1.2.3-jk/src/soldoor_server.c
--- libdvdcss-1.2.3-orig/src/soldoor_server.c Thu Jan 1 01:00:00 1970
+++ libdvdcss-1.2.3-jk/src/soldoor_server.c Mon Oct 21 17:20:59 2002
@@ -0,0 +1,395 @@
+/*
+ * This file contains a tiny server running setuid-root. It accepts
+ * solaris "door" calls (sent from soldoor_ioctl.c) for the DVD ioctls
+ * and executes them by sending USCSICMD ioctl to the dvd-rom's device
+ * driver.
+ */
+
+#define _REENTRANT
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <door.h>
+#include <sys/utsname.h>
+#include "common.h"
+#include "ioctl.h"
+#include "soldoor_server.h"
+
+
+/*
+ * Handle "door" calls
+ */
+static void
+uscsi_server_procedure (void *cookie,
+ char *argp, size_t arg_size,
+ door_desc_t *dp, uint_t n_desc)
+{
+ int command;
+ int fd = -1;
+
+ if (argp == DOOR_UNREF_DATA && dp == NULL) {
+ /*
+ * only a single reference to the door remains (the one we have open
+ * in this process). Time to shutdown, as noone is able to talk to
+ * us any more.
+ */
+ exit(0);
+ }
+
+ if (argp == NULL && dp == NULL) {
+ /* A no-op test call, without arguments */
+ if (door_return(NULL, 0, NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ return;
+ }
+
+ if (dp == NULL || n_desc != 1 || !(dp[0].d_attributes & DOOR_DESCRIPTOR)) {
+ syslog(LOG_INFO, "no fdesc arg");
+ goto error;
+ }
+ fd = dp[0].d_data.d_desc.d_descriptor;
+
+ if (argp == NULL || arg_size < sizeof(int)) {
+ syslog(LOG_ERR, "missing arg data");
+ goto error;
+ }
+ command = *(int *)argp;
+
+ switch (command) {
+ case DOOR_USCSI_READCOPYRIGHT:
+ if (arg_size == sizeof(struct uscsi_ReadCopyright_args)) {
+ struct uscsi_ReadCopyright_args *ap = (void*) argp;
+ struct uscsi_ReadCopyright_res res;
+
+ res.rval = ioctl_ReadCopyright(fd, ap->layer, &res.copyright);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_DISCKEY:
+ if (arg_size == sizeof(struct uscsi_ReadDiscKey_args)) {
+ struct uscsi_ReadDiscKey_args *ap = (void*) argp;
+ struct uscsi_ReadDiscKey_res res;
+
+ res.rval = ioctl_ReadDiscKey(fd, &ap->agid, res.key);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_TITLEKEY:
+ if (arg_size == sizeof(struct uscsi_ReadTitleKey_args)) {
+ struct uscsi_ReadTitleKey_args *ap = (void*) argp;
+ struct uscsi_ReadTitleKey_res res;
+
+ res.rval = ioctl_ReadTitleKey(fd, &ap->agid, ap->pos, res.key);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_AGID:
+ if (arg_size == sizeof(struct uscsi_ReportAgid_args)) {
+ struct uscsi_ReportAgid_args *ap = (void*) argp;
+ struct uscsi_ReportAgid_res res;
+
+ res.rval = ioctl_ReportAgid(fd, &ap->agid);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ res.agid = ap->agid;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_CHALLENGE:
+ if (arg_size == sizeof(struct uscsi_ReportChallenge_args)) {
+ struct uscsi_ReportChallenge_args *ap = (void*) argp;
+ struct uscsi_ReportChallenge_res res;
+
+ res.rval = ioctl_ReportChallenge(fd, &ap->agid, res.challenge);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_ASF:
+ if (arg_size == sizeof(struct uscsi_ReportASF_args)) {
+ struct uscsi_ReportASF_args *ap = (void*) argp;
+ struct uscsi_ReportASF_res res;
+
+ res.rval = ioctl_ReportASF(fd, &ap->remove_me, &res.asf);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_KEY1:
+ if (arg_size == sizeof(struct uscsi_ReportKey1_args)) {
+ struct uscsi_ReportKey1_args *ap = (void*) argp;
+ struct uscsi_ReportKey1_res res;
+
+ res.rval = ioctl_ReportKey1(fd, &ap->agid, res.key);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_INVALIDATE_AGID:
+ if (arg_size == sizeof(struct uscsi_InvalidateAgid_args)) {
+ struct uscsi_InvalidateAgid_args *ap = (void*) argp;
+ struct uscsi_InvalidateAgid_res res;
+
+ res.rval = ioctl_InvalidateAgid(fd, &ap->agid);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ res.agid = ap->agid;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_SEND_CHALLENGE:
+ if (arg_size == sizeof(struct uscsi_SendChallenge_args)) {
+ struct uscsi_SendChallenge_args *ap = (void*) argp;
+ struct uscsi_SendChallenge_res res;
+
+ res.rval = ioctl_SendChallenge(fd, &ap->agid, ap->challenge);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_SEND_KEY2:
+ if (arg_size == sizeof(struct uscsi_SendKey2_args)) {
+ struct uscsi_SendKey2_args *ap = (void*) argp;
+ struct uscsi_SendKey2_res res;
+
+ res.rval = ioctl_SendKey2(fd, &ap->agid, ap->key);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ case DOOR_USCSI_REPORT_RPC:
+ if (arg_size == sizeof(struct uscsi_ReportRPC_args)) {
+ struct uscsi_ReportRPC_res res;
+
+ res.rval = ioctl_ReportRPC(fd, &res.type, &res.mask, &res.scheme);
+ if (res.rval < 0)
+ res.sys_errno = errno;
+ close(fd);
+ if (door_return((void*) &res, sizeof(res), NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+ } else {
+ syslog(LOG_ERR, "invalid argument size");
+ goto error;
+ }
+ break;
+
+ default:
+ syslog(LOG_INFO, "unknown command %d", command);
+ goto error;
+ }
+ return;
+
+error:
+ if (fd >= 0)
+ close(fd);
+ if (door_return(NULL, 0, NULL, 0) < 0)
+ syslog(LOG_ERR, "door_return: %m");
+}
+
+
+static void
+usage()
+{
+ fprintf(stderr, "usage: dvdcss_door\n");
+ exit(1);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int debug = 0;
+ int c;
+ int door;
+ int fd;
+ int sync_pipe[2];
+ char ch;
+
+ while ((c = getopt(argc, argv, "d")) != -1) {
+ switch (c) {
+ case 'd':
+ debug = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ openlog("dvdcss_door", LOG_PID, LOG_DAEMON);
+
+ /*
+ * Not running as root?
+ * That's the whole purpose of the this deamon, to be able to send
+ * USCSICMDs to the DVD-ROM device with root credentials. Which is
+ * required for Solaris 9.
+ */
+ if (geteuid()) {
+ struct utsname unm;
+ int sunos5_9;
+ int major, minor;
+
+ /* are we running on Solaris 9 (aka SunOS 5.9) or later? */
+ uname(&unm);
+ sunos5_9 = sscanf(unm.release, "%d.%d", &major, &minor) == 2
+ && (major > 5 || (major == 5 && minor >= 9));
+
+ syslog(sunos5_9 ? LOG_ERR : LOG_INFO,
+ "server must run with root credentials");
+ }
+
+ setgid(0);
+ setuid(0);
+
+ if (!debug) {
+ chdir("/");
+
+ close(0);
+ close(1);
+ close(2);
+ if (open("/dev/null", O_RDWR) != 0 || dup(0) != 1 || dup(0) != 2)
+ exit(2);
+
+ pipe(sync_pipe);
+
+ /* we're a daemon process, automatically run in background */
+ switch (fork()) {
+ case -1:
+ syslog(LOG_ERR,
+ "unable to run as background daemon, fork failed: %m");
+ exit(1);
+ default:
+ /*
+ * real server continues in the child process,
+ * parent exits when server is ready
+ */
+ close(sync_pipe[1]);
+ ch = 0;
+ read(sync_pipe[0], &ch, 1);
+ exit(ch == '*' ? 0 : 3);
+ case 0:
+ /* child: continues to run as server */
+ close(sync_pipe[0]);
+ break;
+ }
+
+ setsid();
+ }
+
+ /* create the "door" */
+ door = door_create(uscsi_server_procedure, NULL, DOOR_UNREF);
+ if (door < 0) {
+ syslog(LOG_ERR, "door_create failed: %m");
+ exit(1);
+ }
+
+ /* an (empty) file is needed, so we can attach the "door" to it */
+ fd = open(USCSI_DOOR, O_WRONLY|O_TRUNC|O_CREAT, 0644);
+ if (fd < 0) {
+ syslog(LOG_ERR, "cannot create " USCSI_DOOR " file: %m");
+ exit(1);
+ }
+ close(fd);
+
+ /*
+ * clean up any old "door" attached to the file, just in case it was
+ * left lying around in case of a "door" server crash.
+ *
+ * And attach the "door" to the empty file.
+ */
+ fdetach(USCSI_DOOR);
+ if (fattach(door, USCSI_DOOR) < 0) {
+ syslog(LOG_ERR, "fattach " USCSI_DOOR " door: %m");
+ exit(1);
+ }
+
+ if (!debug) {
+ /*
+ * we're ready to serve requests, notify parent by sending a
+ * special token through the sync_pipe.
+ */
+ write(sync_pipe[1], "*", 1);
+ close(sync_pipe[1]);
+ }
+
+ while (1)
+ pause();
+
+ exit(0);
+}
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/soldoor_server.h libdvdcss-1.2.3-jk/src/soldoor_server.h
--- libdvdcss-1.2.3-orig/src/soldoor_server.h Thu Jan 1 01:00:00 1970
+++ libdvdcss-1.2.3-jk/src/soldoor_server.h Mon Oct 21 11:23:20 2002
@@ -0,0 +1,175 @@
+
+/*
+ * USCSI_DOOR: a fixed path name in the filesystem, clients can use it
+ * to connect to the DVD ioctl uscsi server.
+ *
+ * /var/run does not exist on old solaris releases, so use /tmp for now
+ * #define USCSI_DOOR "/var/run/dvdcss_door"
+ */
+#define USCSI_DOOR "/tmp/.dvdcss_door"
+
+enum door_uscsi_cmd {
+ DOOR_USCSI_READCOPYRIGHT = 1,
+ DOOR_USCSI_REPORT_DISCKEY,
+ DOOR_USCSI_REPORT_TITLEKEY,
+ DOOR_USCSI_REPORT_AGID,
+ DOOR_USCSI_REPORT_CHALLENGE,
+ DOOR_USCSI_REPORT_ASF,
+ DOOR_USCSI_REPORT_KEY1,
+ DOOR_USCSI_INVALIDATE_AGID,
+ DOOR_USCSI_SEND_CHALLENGE,
+ DOOR_USCSI_SEND_KEY2,
+ DOOR_USCSI_REPORT_RPC,
+};
+
+
+/*
+ * XXX_args and XXX_res structures, one for each request. XXX_args
+ * contains the request's input parameters, and XXX_res the result
+ * values.
+ */
+
+/* DOOR_USCSI_READCOPYRIGHT */
+struct uscsi_ReadCopyright_args {
+ enum door_uscsi_cmd command;
+ int layer;
+};
+
+struct uscsi_ReadCopyright_res {
+ int rval;
+ int sys_errno;
+ int copyright;
+};
+
+
+/* DOOR_USCSI_REPORT_DISCKEY */
+struct uscsi_ReadDiscKey_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_ReadDiscKey_res {
+ int rval;
+ int sys_errno;
+ unsigned char key[DVD_DISCKEY_SIZE];
+};
+
+
+/* DOOR_USCSI_REPORT_TITLEKEY */
+struct uscsi_ReadTitleKey_args {
+ enum door_uscsi_cmd command;
+ int agid;
+ int pos;
+};
+
+struct uscsi_ReadTitleKey_res {
+ int rval;
+ int sys_errno;
+ unsigned char key[DVD_KEY_SIZE];
+};
+
+
+/* DOOR_USCSI_REPORT_AGID */
+struct uscsi_ReportAgid_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_ReportAgid_res {
+ int rval;
+ int sys_errno;
+ int agid;
+};
+
+
+/* DOOR_USCSI_REPORT_CHALLENGE */
+struct uscsi_ReportChallenge_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_ReportChallenge_res {
+ int rval;
+ int sys_errno;
+ unsigned char challenge[DVD_CHALLENGE_SIZE];
+};
+
+
+/* DOOR_USCSI_REPORT_ASF */
+struct uscsi_ReportASF_args {
+ enum door_uscsi_cmd command;
+ int remove_me;
+};
+
+struct uscsi_ReportASF_res {
+ int rval;
+ int sys_errno;
+ int asf;
+};
+
+
+/* DOOR_USCSI_REPORT_KEY1 */
+struct uscsi_ReportKey1_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_ReportKey1_res {
+ int rval;
+ int sys_errno;
+ unsigned char key[DVD_KEY_SIZE];
+};
+
+
+/* DOOR_USCSI_INVALIDATE_AGID */
+struct uscsi_InvalidateAgid_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_InvalidateAgid_res {
+ int rval;
+ int sys_errno;
+ int agid;
+};
+
+
+/* DOOR_USCSI_SEND_CHALLENGE */
+struct uscsi_SendChallenge_args {
+ enum door_uscsi_cmd command;
+ int agid;
+ unsigned char challenge[DVD_CHALLENGE_SIZE];
+};
+
+struct uscsi_SendChallenge_res {
+ int rval;
+ int sys_errno;
+};
+
+
+/* DOOR_USCSI_SEND_KEY2 */
+struct uscsi_SendKey2_args {
+ enum door_uscsi_cmd command;
+ int agid;
+ unsigned char key[DVD_KEY_SIZE];
+};
+
+struct uscsi_SendKey2_res {
+ int rval;
+ int sys_errno;
+};
+
+
+/* DOOR_USCSI_REPORT_RPC */
+struct uscsi_ReportRPC_args {
+ enum door_uscsi_cmd command;
+ int agid;
+};
+
+struct uscsi_ReportRPC_res {
+ int rval;
+ int sys_errno;
+ int type;
+ int mask;
+ int scheme;
+};
diff -ru -N -x *.d -x mkinstalldirs -x missing -x ltmain.sh -x install-sh -x depcomp -x config.h.in -x configure -x aclocal.m4 -x Makefile.in libdvdcss-1.2.3-orig/src/soldoor_uscsi.c libdvdcss-1.2.3-jk/src/soldoor_uscsi.c
--- libdvdcss-1.2.3-orig/src/soldoor_uscsi.c Thu Jan 1 01:00:00 1970
+++ libdvdcss-1.2.3-jk/src/soldoor_uscsi.c Sun Oct 20 19:11:03 2002
@@ -0,0 +1,17 @@
+/*
+ * This file contains the real implementation of the Solaris DVD ioctls,
+ * implemented as USCSICMD ioctls passing SCSI commands from userland to
+ * the DVD-ROM driver.
+ *
+ * On Solaris 9 the USCSICMD ioctls will only work when the process using
+ * these subroutines has root credentials.
+ */
+
+#define _REENTRANT
+
+/*
+ * pull in the real solaris uscsi implementation of the DVD ioctls from the
+ * ioctl.c file, using some preprocessor magic
+ */
+#define SOLDOOR_COMPILE_USCSI 1
+#include "ioctl.c"
More information about the libdvdcss-devel
mailing list