char * zuluCryptLoopDeviceAddress_1( const char * device ) { int fd ; char * path ; struct loop_info64 l_info ; string_t st = String_1( "/sys/block/",device + 5,"/loop/backing_file",NULL ) ; string_t xt = _StringGetFromVirtualFile( &st ) ; if( xt == StringVoid ){ memset( &l_info,'\0',sizeof( struct loop_info64 ) ) ; fd = open( device,O_RDONLY ) ; ioctl( fd,LOOP_GET_STATUS64,&l_info ) ; path = zuluCryptRealPath( ( char * ) l_info.lo_file_name ) ; close( fd ) ; st = String( path ) ; StringFree( path ) ; _clean_loop_path( st ) ; return StringDeleteHandle( &st ) ; ; }else{ _clean_loop_path( xt ) ; return StringDeleteHandle( &xt ) ; } }
/* * this function return a secured file path to be used to create a file at the path */ static const char * _secure_file_path_1( void ) { string_t st_path = _create_work_directory() ; StringAppend( st_path,"1-" ) ; StringAppendInt( st_path,syscall( SYS_gettid ) ) ; return StringDeleteHandle( &st_path ) ; }
/* * Below function copies a file owned and managed by a user to a secured location so that it can be accessed securely. */ static int _secure_file_path( const char ** path,const char * source ) { int fd_source ; int fd_temp ; char buffer[ SIZE ] ; size_t len ; const char * temp_path ; struct stat ststr ; string_t st_path = _create_work_directory() ; StringAppend( st_path,"0-" ) ; temp_path = StringAppendInt( st_path,syscall( SYS_gettid ) ) ; zuluCryptSecurityDropElevatedPrivileges() ; fd_source = open( source,O_RDONLY ) ; if( fd_source == -1 ){ StringDelete( &st_path ) ; return 0 ; } fstat( fd_source,&ststr ) ; if( ststr.st_size >= 3145728 ){ /* * headers are less than 3MB so we obvious have a wrong file */ StringDelete( &st_path ) ; return 0 ; } zuluCryptSecurityGainElevatedPrivileges() ; fd_temp = open( temp_path,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH ) ; if( fd_temp == -1 ){ close( fd_source ) ; StringDelete( &st_path ) ; return 0 ; } while( 1 ){ len = read( fd_source,buffer,SIZE ) ; if( len < SIZE ){ write( fd_temp,buffer,len ) ; break ; }else{ write( fd_temp,buffer,len ) ; } } close( fd_source ) ; close( fd_temp ) ; zuluCryptSecurityDropElevatedPrivileges() ; *path = StringDeleteHandle( &st_path ) ; return 1 ; }
char * zuluCryptVolumeStatus( const char * mapper ) { char * path ; string_t p ; if( zuluCryptTrueCryptOrVeraCryptVolume( mapper ) ){ p = _get_crypto_info_from_tcplay( mapper ) ; }else{ p = _get_crypto_info_from_cryptsetup( mapper ) ; } if( p == StringVoid ){ return NULL ; }else{ /* * zuluCryptGetMountPointFromPath() is defined in ./process_mountinfo.c */ path = zuluCryptGetMountPointFromPath( mapper ) ; if( path != NULL ){ zuluCryptFileSystemProperties( p,mapper,path ) ; StringFree( path ) ; } return StringDeleteHandle( &p ) ; } }
char * zuluCryptGetALoopDeviceAssociatedWithAnImageFile( const char * path ) { int i ; string_t st = String( "" ) ; const char * e ; char * f ; for( i = 0 ; i < 255 ; i++ ){ StringReplace( st,"/dev/loop" ) ; e = StringAppendInt( st,i ) ; f = zuluCryptLoopDeviceAddress_1( e ) ; if( StringsAreEqual( path,f ) ){ StringFree( f ) ; return StringDeleteHandle( &st ) ; }else{ StringFree( f ) ; } } StringDelete( &st ) ; return NULL ; }
char * zuluCryptGetLoopDeviceAddress( const char * device ) { char * z = NULL ; const char * e ; string_t st = StringVoid ; string_t xt = StringVoid ; int i ; int r ; z = zuluCryptLoopDeviceAddress_1( device ) ; if( z == NULL ){ return NULL ; }else{ st = String( "" ) ; for( i = 0 ; i < 255 ; i++ ){ StringReplace( st,"/sys/block/loop" ) ; StringAppendInt( st,i ) ; xt = StringGetFromVirtualFile( StringAppend( st,"/loop/backing_file" ) ) ; e = StringRemoveRight( xt,1 ) ; r = StringsAreEqual( e,z ) ; StringDelete( &xt ) ; if( r ){ StringReplace( st,"/dev/loop" ) ; e = StringAppendInt( st,i ) ; if( StringsAreNotEqual( device,e ) ){ break ; } }else{ StringReset( st ) ; } } StringFree( z ) ; if( StringIsEmpty( st ) ){ StringDelete( &st ) ; return NULL ; }else{ return StringDeleteHandle( &st ) ; } } }
static char * _get_type_from_udev( const char * mapper ) { string_t st = _get_mapper_property_from_udev( mapper,"dm-uuid-CRYPT-",TYPE ) ; if( st == StringVoid ){ return StringCopy_2( "Nil" ) ; }else{ StringPrepend( st,"crypto_" ) ; return StringDeleteHandle( &st ) ; } }
static char * _empty_slots( const char * device,const resolve_path_t * opts ) { struct crypt_device * cd; int j ; int k ; const char * type ; string_t p ; if( opts ){;} if( crypt_init( &cd,device ) != 0 ){ return zuluExit( NULL,NULL ) ; } if( crypt_load( cd,NULL,NULL ) != 0 ){ return zuluExit( NULL,cd ) ; } type = crypt_get_type( cd ) ; if( type == NULL ){ return zuluExit( NULL,cd ) ; } k = crypt_keyslot_max( type ) ; if( k < 0 ){ return zuluExit( NULL,cd ) ; } p = StringEmpty() ; for( j = 0 ; j < k ; j++ ){ switch( crypt_keyslot_status( cd,j ) ){ case CRYPT_SLOT_INACTIVE : StringAppend( p,"0" ) ; break ; case CRYPT_SLOT_ACTIVE : StringAppend( p,"1" ) ; break ; case CRYPT_SLOT_INVALID : StringAppend( p,"2" ) ; break ; case CRYPT_SLOT_ACTIVE_LAST: StringAppend( p,"3" ) ; break ; default : ; } } return zuluExit( StringDeleteHandle( &p ),cd ) ; }
char * zuluCryptGetUUIDFromMapper( const char * mapper ) { string_t uuid ; struct crypt_device * cd ; const char * id ; const char * e = " UUID: \t\"Nil\"" ; char * f ; if( crypt_init_by_name( &cd,mapper ) < 0 ){ uuid = String( e ) ; }else{ id = crypt_get_uuid( cd ) ; if( id == NULL ){ /* * Either not a LUKS volume or a LUKS volume but with a detached header. * consult udev to see if it can sort this volume out. */ f = _get_uuid_from_udev( mapper ) ; if( f == NULL ){ uuid = String( e ) ; }else{ uuid = String_1( " UUID: \t\"",f,"\"",NULL ) ; StringFree( f ) ; } }else{ uuid = String_1( " UUID: \t\"",id,"\"",NULL ) ; } crypt_free( cd ) ; } return StringDeleteHandle( &uuid ) ; }
char * zuluCryptGetMountPointFromPath( const char * path ) { string_t st = zuluCryptGetMountEntry( path ) ; stringList_t stl ; if( st == StringVoid ) { return NULL ; } else { stl = StringListStringSplit( st,' ' ) ; StringDelete( &st ) ; if( stl == StringListVoid ) { return NULL ; } else { st = StringListCopyStringAtSecondPlace( stl ) ; StringListDelete( &stl ) ; zuluCryptDecodeMountEntry( st ) ; return StringDeleteHandle( &st ) ; } } }
char * zuluCryptGetVolumeTypeFromMapperPath( const char * mapper ) { struct crypt_device * cd ; const char * type ; char * r ; string_t st ; if( StringPrefixNotEqual( mapper,crypt_get_dir() ) ){ return StringCopy_2( "Nil" ) ; } if( crypt_init_by_name( &cd,mapper ) < 0 ){ return StringCopy_2( "Nil" ) ; } type = crypt_get_type( cd ) ; if( type == NULL ){ if( StringHasComponent( mapper,"veracrypt" ) ){ r = StringCopy_2( "crypto_VCRYPT" ) ; }else if( StringHasComponent( mapper,"truecrypt" ) ){ r = StringCopy_2( "crypto_TCRYPT" ) ; }else{ r = _get_type_from_udev( mapper ) ; } }else{ st = String_1( "crypto_",type,NULL ) ; r = StringDeleteHandle( &st ) ; } crypt_free( cd ) ; return r ; }
static char * _convert_if_path_is_lvm( const char * path ) { string_t st = zuluCryptConvertIfPathIsLVM( path ) ; return StringDeleteHandle( &st ) ; }
char * zuluCryptResolveMDPath( const char * path ) { string_t st = zuluCryptResolveMDPath_1( path ) ; return StringDeleteHandle( &st ) ; }
static char * _get_uuid_from_udev( const char * mapper ) { string_t st = _get_mapper_property_from_udev( mapper,"dm-uuid-CRYPT-LUKS",UUID ) ; return StringDeleteHandle( &st ) ; }
int zuluCryptGetDeviceFileProperties( const char * file,int * fd_path,int * fd_loop,char ** dev,uid_t uid ) { int st = 100 ; int xt = 0 ; int lfd ; const char * dev_1 = NULL ; string_t st_dev = StringVoid ; struct stat stat_st ; struct stat stat_st_1 ; /* * try to open the device with user privileges */ seteuid( uid ) ; *dev = NULL ; *fd_path = open( file,O_RDONLY ) ; if( *fd_path != -1 ){ fstat( *fd_path,&stat_st ) ; fcntl( *fd_path,F_SETFD,FD_CLOEXEC ) ; /* * A user has access to the device.They should get here only with paths to files they have access to. * Allow access to files only */ if( S_ISREG( stat_st.st_mode ) ){ /* * we can open file in read mode,let see if we can in write mode too */ lfd = open( file,O_RDWR ) ; if( lfd != -1 ){ /* * we can open the file in read write mode */ fstat( lfd,&stat_st_1 ) ; fcntl( lfd,F_SETFD,FD_CLOEXEC ) ; /* * check to make sure the file we got earlier is the same one we got now. * ie check to make sure the file wasnt changed btw calls. */ if( stat_st.st_dev == stat_st_1.st_dev && stat_st.st_ino == stat_st_1.st_ino ){ close( *fd_path ) ; *fd_path = lfd ; seteuid( 0 ) ; /* * zuluCryptAttachLoopDeviceToFileUsingFileDescriptor() is defined in ./create_loop_device.c */ xt = zuluCryptAttachLoopDeviceToFileUsingFileDescriptor( *fd_path,fd_loop,O_RDWR,&st_dev ) ; seteuid( uid ) ; *dev = StringDeleteHandle( &st_dev ) ; } }else{ /* * we can not open the file in write mode,continue with read only access */ seteuid( 0 ) ; /* * zuluCryptAttachLoopDeviceToFileUsingFileDescriptor() is defined in ./create_loop_device.c */ xt = zuluCryptAttachLoopDeviceToFileUsingFileDescriptor( *fd_path,fd_loop,O_RDONLY,&st_dev ) ; seteuid( uid ) ; *dev = StringDeleteHandle( &st_dev ) ; } if( xt != 1 ){ st = 100 ; close( *fd_path ) ; *fd_path = -1 ; }else{ dev_1 = zuluCryptGetFileNameFromFileDescriptor( *fd_path ) ; if( StringPrefixEqual( dev_1,"/dev/shm/" ) ){ st =1 ; close( *fd_path ) ; *fd_path = -1 ; }else{ st = 0 ; } StringFree( dev_1 ) ; } }else{ if( S_ISBLK( stat_st.st_mode ) ){ if( uid == 0 ) { /* * we got a block device and we are root,accept it */ *dev = zuluCryptGetFileNameFromFileDescriptor( *fd_path ) ; st = 0 ; }else{ /* * odd,normal user has access to a block device,allow it only if the * device is in "/dev/" but not in "/dev/shm" */ *dev = zuluCryptGetFileNameFromFileDescriptor( *fd_path ) ; if( StringPrefixEqual( *dev,"/dev/shm/" ) ){ st = 1 ; }else if( StringPrefixEqual( *dev,"/dev/" ) ){ st = 0 ; } } }else if( S_ISDIR( stat_st.st_mode ) ){ st = 2 ; }else{ /* * whatever it is,it cant be good,reject it */ st = 100 ; } close( *fd_path ) ; *fd_path = -1 ; } }else{ /* * failed to open above with users privileges,try to open the device with root's privileges. * We should only accept block devices in "/dev/" but not in "/dev/shm". */ seteuid( 0 ) ; *fd_path = open( file,O_RDONLY ) ; if( *fd_path != -1 ){ fstat( *fd_path,&stat_st ) ; /* * zuluCryptGetFileNameFromFileDescriptor() is defined in ./create_loop_device.c */ *dev = zuluCryptGetFileNameFromFileDescriptor( *fd_path ) ; if( S_ISBLK( stat_st.st_mode ) ){ if( StringPrefixEqual( *dev,"/dev/shm/" ) ){ /* * we do not support this path */ st = 1 ; }else if( StringPrefixEqual( *dev,"/dev/" ) ){ /* * got a block device,accept it */ st = 0 ; }else{ /* * reject others */ st = 100 ; } }else{ /* * whatever it is,it cant be good,reject it */ st = 100 ; } /* * We are closing the file because we dont need to hold on to it as paths in "/dev/" can not be moved under us by * normal users. */ close( *fd_path ) ; *fd_path = -1 ; }else{ /* * invalid path or something i dont know,reject */ st = 100 ; } seteuid( uid ) ; } return _check_if_device_is_supported( st,uid,dev ) ; }
char * zuluCryptLoopDeviceAddress( const char * device ) { string_t st = zuluCryptLoopDeviceAddress_2( device ) ; return StringDeleteHandle( &st ) ; }
int zuluCryptBindUnmountVolume( stringList_t stx,const char * device,uid_t uid ) { stringList_t stl ; string_t xt ; string_t st ; string_t zt ; ssize_t index = -1 ; const char * f ; const char * g ; char * h = NULL ; int r = 1 ; int k ; int delete_stx = 0 ; /* * zuluCryptUserIsAMemberOfAGroup() is defined in security.c */ /* * root user is a member of all groups and hence is allowed */ int allowedUser = zuluCryptUserIsAMemberOfAGroup( uid,"zulumount" ) ; zuluCryptSecurityGainElevatedPrivileges() ; if( stx == StringListVoid ){ /* * zuluCryptGetMoutedListFromMountInfo() is defined in ../lib/process_mountinfo.c */ stx = zuluCryptGetMoutedListFromMountInfo() ; delete_stx = 1 ; } if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress_2() is defined in ../lib/create_loop_device.c */ st = zuluCryptLoopDeviceAddress_2( device ) ; /* * Add a space at the end of the device name to make sure we check the full device name to avoid possible collisions * that may exist if one device is named "/home/abc" and another "/home/abcdef" */ zt = StringListHasStartSequence_1( stx,StringAppend( st," " ) ) ; StringRemoveRight( st,1 ) ; device = h = StringDeleteHandle( &st ) ; }else{ /* * Add a space at the end of the device name to make sure we check the full device name to avoid possible collisions * that may exist if one device is named "/dev/sdc1" and another "/dev/sdc12" */ st = String( device ) ; zt = StringListHasStartSequence_1( stx,StringAppend( st," " ) ) ; StringDelete( &st ) ; } if( zt == StringVoid ){ /* * The volume does not appear to be mounted */ r = 1 ; }else{ stl = StringListStringSplit( zt,' ' ) ; xt = StringListCopyStringAtSecondPlace( stl ) ; StringListDelete( &stl ) ; st = StringCopy( xt ) ; /* * zuluCryptDecodeMountEntry() is defined in ../lib/mount_volume.c * g will contain something like "/run/media/private/$USER/sdc1" */ g = zuluCryptDecodeMountEntry( st ) ; if( allowedUser ){ /* * a privileged user is attempting to unmount a shared mount point,allow them */ k = 1 ; }else{ /* * a non privileged user is attempting to unmount a shared mount point,allow them only if * they are the one that created it */ /* * zuluCryptSecurityMountPointPrefixMatch() is defined in ./security.c */ k = zuluCryptMountPointPrefixMatch( g,uid,NULL ) ; } StringDelete( &st ) ; if( k != 1 ){ /* * One none privileged user is attempting to unmount a bind mount from another use,disallow it */ r = 4 ; }else{ index = StringLastIndexOfChar( xt,'/' ) + 1 ; StringRemoveLeft( xt,index ) ; StringPrepend( xt,"/run/media/public/" ) ; /* * f will now contain something like "/run/media/public/sdc1" * space character is added before checking to avoid possible collisions * as explained in above comments */ f = StringAppend( xt," " ) ; zt = StringListHasSequence_1( stx,f ) ; f = StringRemoveRight( xt,1 ) ; if( zt == StringVoid ){ /* * volume is not shared */ }else{ /* * volume is shared,try to unmount it * a volume is assumed to be shared if its device path in mountinfo has two mount points,one * in /run/media/private/$USER and the other in /run/media/public/ */ if( StringStartsWith( zt,device ) ){ f = zuluCryptDecodeMountEntry( xt ) ; /* * good,the device associated with the shared mount is the same as that of the * private mount,try to unmount it. */ r = 3 ; for( k = 0 ; k < 3 ; k++ ){ /* * try to unmount 3 times before giving up */ if( umount( f ) == 0 ){ rmdir( f ) ; r = 0 ; break ; }else{ sleep( 1 ) ; } } }else{ /* * i dont see how we will get here,we shouldnt */ r = 0 ; } } } StringDelete( &xt ) ; } if( delete_stx ){ StringListDelete( &stx ) ; } StringFree( h ) ; zuluCryptSecurityDropElevatedPrivileges() ; return r ; }