Mercurial > mplayer.hg
view libmpdemux/dvdauth.c @ 9454:50ef22bcc0c3
optimize
author | michael |
---|---|
date | Tue, 18 Feb 2003 19:22:34 +0000 |
parents | 059746b0ecae |
children | a5785a0b9ee1 |
line wrap: on
line source
/* (C)2001,2002 by LGB (Gabor Lenart), based on example programs in libcss lgb@lgb.hu This source is part of MPlayer project. This source is copyrighted by the author according to rules declared in GNU/GPL license. 2001 Inital version (LGB) 2001 fibmap_mplayer to avoid uid=0 mplayer need (LGB) 2001 Support for libcss with the new API (by ???) 2002/Jan/04 Use dlopen to access libcss.so to avoid conflict with libdvdread [now with only libcss with old API (LGB) 2002/Sep/21 Fix a bug which caused segmentation fault when using -dvdkey option, since css.so was only loaded by -dvdauth. (LGB, reported and suggested by sbmpost <wortelsapje@hotmail.com>) Also some cosmetic fix with return value of dvd_css_descramble(). 2002/Sep/21 Try to load css syms with AND without underscore at their names, probably not only OpenBSD requires this so it's a better solution (LGB). TODO: support for libcss libraries with new API */ /* don't do anything with this source if css support was not requested */ #include "config.h" #ifdef HAVE_LIBCSS #warning FIXME: Dynamic loading of libcss.so with newer (ver>0.1) libcss API is not supported in this version! #include <stdio.h> #include <stdlib.h> //#include <string.h> // FIXME: conflicts with fs.h #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/wait.h> // #include <css.h> #if defined(__FreeBSD__) || defined(__NetBSD__) # include <sys/dvdio.h> #elif defined(__OpenBSD__) # include <sys/cdio.h> # define RTLD_NOW RTLD_LAZY #elif defined(__linux__) # include <linux/cdrom.h> #elif defined(__sun) # include <sun/dvdio.h> #elif defined(hpux) # include <sun/scsi.h> #elif defined(__bsdi__) # include <dvd.h> #else # error "Need the DVD ioctls" #endif #include <dlfcn.h> #include "dvdauth.h" // #if OLD_CSS_API /* * provide some backward compatibiliy macros to compile this * code using the old libcss-0.1 */ #define DVDHandle int #define DVDOpenFailed (-1) #define DVDAuth(hdl, s) ioctl(hdl, DVD_AUTH, s) #define DVDOpenDevice(path) open(path, O_RDONLY) #define DVDCloseDevice(hdl) close(hdl) // #define CSSDVDisEncrypted(hdl) CSSisEncrypted(hdl) // #define CSSDVDAuthDisc CSSAuthDisc char *dvd_auth_device=NULL; extern char *dvd_device; char *dvd_raw_device=NULL; char *css_so=NULL; unsigned char key_disc[2048]; unsigned char key_title[5]; unsigned char *dvdimportkey=NULL; int descrambling=0; static int css_so_is_loaded=0; static void *dlid; static int (*dl_CSSisEncrypted)(int); static int (*dl_CSSAuthDisc)(int,char *); static int (*dl_CSSAuthTitle)(int, char *,int); static int (*dl_CSSGetASF)(int); static int (*dl_CSSDecryptTitleKey)(char *, char *); static void (*dl_CSSDescramble)(u_char *, u_char *); void dvd_css_descramble ( u_char *sec , u_char *key ) { (*dl_CSSDescramble)(sec,key); } #ifdef __linux__ #include <linux/fs.h> #ifndef FIBMAP #define FIBMAP 1 #endif static int path_to_lba (char *path) { int lba = 0; char cmd[100]; FILE *fp; snprintf(cmd,sizeof(cmd),"fibmap_mplayer %s",path); fp=popen(cmd,"r"); if (fp) { int ret; memset(cmd,0,sizeof(cmd)); fgets(cmd,99,fp); // printf("DVD: cmd: %s\n",cmd); if ((ret=pclose(fp))) fprintf(stderr,"DVD: fibmap_mplayer: %s\n",*cmd?cmd:"no error info"); if (cmd[0]<'0'||cmd[0]>'9') fp=NULL; else { if(WIFEXITED(ret) && !WEXITSTATUS(ret)) { lba=atoi(cmd); printf("DVD: fibmap_mplayer is being used\n"); } else fp=NULL; } } if (!fp) { int fd; printf("DVD: fibmap_mplayer could not run, trying with ioctl() ...\n"); if ((fd = open(path, O_RDONLY)) == -1) { fprintf(stderr, "DVD: Cannot open file %s: %s", path ? path : "(NULL)", strerror(errno)); return -1; } if (ioctl(fd, FIBMAP, &lba) != 0) { perror("DVD: ioctl FIBMAP"); fprintf(stderr," Hint: run mplayer as root (or better to install fibmap_mplayer as suid root)!\n"); close(fd); return -1; } close(fd); } printf("DVD: LBA: %d\n",lba); return lba; } #else /*linux*/ static int path_to_lba (char *path) { #warning translating pathname to iso9660 LBA is not supported on this platform fprintf(stderr, "DVD: Translating pathname to iso9660 LBA is not supported on this platform\n"); return -1; } #endif /*linux*/ static int CSSDVDAuthTitlePath(DVDHandle hdl,unsigned char *key_title,char *path) { int lba=path_to_lba(path); if (lba==-1) return -1; return (*dl_CSSAuthTitle)(hdl,key_title,lba); } static void reset_agids ( DVDHandle dvd ) { #if !defined(DVD_AUTH) && defined(DVDIOCREPORTKEY) struct dvd_authinfo ai; int i; for (i = 0; i < 4; i++) { memset(&ai, 0, sizeof(ai)); ai.format = DVD_INVALIDATE_AGID; ai.agid = i; ioctl(dvd, DVDIOCREPORTKEY, &ai); } #else #if defined(__OpenBSD__) union #endif dvd_authinfo ai; int i; for (i = 0; i < 4; i++) { memset(&ai, 0, sizeof(ai)); ai.type = DVD_INVALIDATE_AGID; ai.lsa.agid = i; DVDAuth(dvd, &ai); } #endif } static int dvd_load_css_so ( void ) { if (css_so_is_loaded) { printf("DVD: warning: attempt to load css.so twice, ignoring.\n"); return 0; } if (!css_so) css_so=strdup("libcss.so"); printf("DVD: opening libcss.so as %s ...\n",css_so); dlid=dlopen(css_so,RTLD_NOW); if (!dlid) { printf("DVD: dlopen: %s\n",dlerror()); return 1; } printf("DVD: dlopen OK!\n"); /* #ifdef __OpenBSD__ #define CSS_DLSYM(v,s) if (!(v=dlsym(dlid,"_" s))) {\ fprintf(stderr,"DVD: %s\n Hint: use libcss version 0.1!\n",dlerror());\ return 1; } #else #define CSS_DLSYM(v,s) if (!(v=dlsym(dlid,s))) {\ fprintf(stderr,"DVD: %s\n Hint: use libcss version 0.1!\n",dlerror());\ return 1; } #endif */ #define CSS_DLSYM(v,s) \ if (!(v=dlsym(dlid,s))) {\ if (!(v=dlsym(dlid,"_" s))) {\ fprintf(stderr,"DVD: %s\n Hint: use libcss version 0.1!\n",dlerror());\ return 1;\ }\ } CSS_DLSYM(dl_CSSisEncrypted,"CSSisEncrypted"); CSS_DLSYM(dl_CSSAuthDisc,"CSSAuthDisc"); CSS_DLSYM(dl_CSSAuthTitle,"CSSAuthTitle"); CSS_DLSYM(dl_CSSGetASF,"CSSGetASF"); CSS_DLSYM(dl_CSSDecryptTitleKey,"CSSDecryptTitleKey"); CSS_DLSYM(dl_CSSDescramble,"CSSDescramble"); #undef CSS_DLSYM css_so_is_loaded=1; printf("DVD: shared object %s is loaded normally.\n",css_so); return 0; } int dvd_import_key ( unsigned char *hexkey ) { unsigned char *t=key_title; int digit=4,len; memset(key_title,0,sizeof(key_title)); // printf("DVD key: %s\n",hexkey); for (len=0;len<10;len++) { // printf("-> %c\n",*hexkey); if (!*hexkey) return 1; if (*hexkey>='A'&&*hexkey<='F') *t|=(*hexkey-'A'+10)<<digit; else if (*hexkey>='0'&&*hexkey<='9') *t|=(*hexkey-'0')<<digit; else return 1; if (digit) digit=0; else { digit=4; t++; } hexkey++; } if (*hexkey) return 1; printf("DVD: DVD key (requested): %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); if (dvd_load_css_so()) return 1; descrambling=1; return 0; } int dvd_auth ( char *dev , char *filename ) { DVDHandle dvd; /* DVD device handle */ if (dvd_load_css_so()) return 1; if ((dvd=DVDOpenDevice(dev)) == DVDOpenFailed) { fprintf(stderr,"DVD: cannot open DVD device \"%s\": %s.\n", dev, strerror(errno)); return 1; } if (!(*dl_CSSisEncrypted)(dvd)) { printf("DVD: DVD is unencrypted! Skipping authentication!\n(note: you should not use -dvd switch for unencrypted discs!)\n"); DVDCloseDevice(dvd); return 0; } else printf("DVD: DVD is encrypted, issuing authentication ...\n"); /* reset AGIDs */ reset_agids(dvd); /* authenticate disc */ if ((*dl_CSSAuthDisc)(dvd,key_disc)) { fprintf(stderr,"DVD: CSSDVDAuthDisc() failed.\n"); DVDCloseDevice(dvd); return 1; } if (CSSDVDAuthTitlePath(dvd,key_title,filename)) { fprintf(stderr,"DVD: CSSDVDAuthTitle() failed.\n"); DVDCloseDevice(dvd); return 1; } /* decrypting title */ if ((*dl_CSSDecryptTitleKey)(key_title, key_disc) < 0) { fprintf(stderr,"DVD: CSSDecryptTitleKey() failed.\n"); DVDCloseDevice(dvd); return 1; } DVDCloseDevice(dvd); printf("DVD: DVD title key is: %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); descrambling=1; return 0; } #endif