static int _save_header( const struct_opts * opts,const char * path,uid_t uid ) { int st = 4 ; const char * temp_path = _secure_file_path_1() ; zuluCryptSecurityGainElevatedPrivileges() ; if( zuluCryptVolumeIsLuks( opts->device ) ){ st = _save_luks_header( opts,temp_path,path,uid ) ; }else{ st = _save_truecrypt_header( opts,temp_path,path,uid ) ; } zuluCryptSecurityDropElevatedPrivileges() ; StringFree( temp_path ) ; return st ; }
/* * return values: * 5 - couldnt get key from the socket * 4 -permission denied * 1 invalid path * 2 insufficient memory to open file * 0 success */ int zuluCryptGetPassFromFile( const char * path,uid_t uid,string_t * st ) { /* * zuluCryptGetUserHomePath() is defined in ../lib/user_home_path.c */ string_t p = zuluCryptGetUserHomePath( uid ) ; const char * z = StringAppend( p,".zuluCrypt-socket" ) ; size_t s = StringLength( p ) ; int m = StringPrefixMatch( path,z,s ) ; StringDelete( &p ) ; zuluCryptSecurityDropElevatedPrivileges() ; if( m ){ /* * path that starts with $HOME/.zuluCrypt-socket is treated not as a path to key file but as path * to a local socket to get a passphrase */ /* * zuluCryptGetKeyFromSocket() is defined in ../pluginManager/zuluCryptPluginManager.c */ zuluCryptGetKeyFromSocket( path,st,uid ) ; return 0 ; }else{ /* * 8192000 bytes is the default cryptsetup maximum keyfile size */ m = StringGetFromFileMemoryLocked( st,path,0,8192000 ) ; switch( m ){ case 0 : return 0 ; case 1 : return 4 ; case 2 : return 2 ; } /* * not supposed to get here */ return -1 ; } }
void zuluCryptDeleteKeyFiles( stringList_t stl ) { StringListIterator it ; StringListIterator end ; StringListGetIterators( stl,&it,&end ) ; zuluCryptSecurityGainElevatedPrivileges() ; while( it != end ){ /* * zuluCryptDeleteFile_1() is defined in ../lib/file_path_security.c */ zuluCryptDeleteFile_1( *it ) ; it++ ; } zuluCryptSecurityDropElevatedPrivileges() ; }
char * zuluCryptEvaluateDeviceTags( const char * tag,const char * path ) { char * r ; zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptDeviceFromUUID() is defined in ../lib/blkid_evaluate_tag.c * zuluCryptDeviceFromLabel() is defined in ../lib/blkid_evaluate_tag.c */ if( StringsAreEqual( tag,"UUID" ) ){ r = zuluCryptDeviceFromUUID( path ) ; }else{ r = zuluCryptDeviceFromLabel( path ) ; } zuluCryptSecurityDropElevatedPrivileges() ; return r ; }
static string_t _create_path( uid_t uid,string_t path,int need_privileges ) { string_t st = StringVoid ; const char * m_point = StringContent( path ) ; if( m_point != NULL ){ if( need_privileges ){ zuluCryptSecurityGainElevatedPrivileges() ; st = _create_path_0( m_point,uid,path ) ; zuluCryptSecurityDropElevatedPrivileges() ; }else{ st = _create_path_0( m_point,uid,path ) ; } } return st ; }
static void _printResult( const char * device,const char * m_point ) { char * e ; zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptGetVolumeTypeFromMapperPath() is defined in ../lib/status.c */ e = zuluCryptGetVolumeTypeFromMapperPath( device ) ; zuluCryptSecurityDropElevatedPrivileges() ; if( StringHasComponent( e,"LUKS" ) ){ printf( gettext( "SUCCESS: %s volume opened successfully\n" ),"luks" ) ; }else if( StringHasComponent( e,"PLAIN" ) ){ printf( gettext( "SUCCESS: %s volume opened successfully\n" ),"plain" ) ; }else if( StringHasComponent( e,"TCRYPT" ) ){ printf( gettext( "SUCCESS: %s volume opened successfully\n" ),"tcrypt" ) ; }else if( StringHasComponent( e,"VCRYPT" ) ){ printf( gettext( "SUCCESS: %s volume opened successfully\n" ),"vcrypt" ) ; }else{ printf( gettext( "SUCCESS: volume opened successfully\n" ) ) ; } StringFree( e ) ; if( m_point != NULL ){ printf( gettext( "volume mounted at: %s\n" ),m_point ) ; } }
static char * _device_path( const char * device ) { char * path ; if( StringPrefixEqual( device,"/dev/loop" ) ){ zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptLoopDeviceAddress_1() is defined in ../zuluCrypt-cli/create_loop_device.c */ path = zuluCryptLoopDeviceAddress_1( device ) ; zuluCryptSecurityDropElevatedPrivileges() ; if( path == NULL ){ return StringCopy_2( device ) ; }else{ return path ; } }else{ return StringCopy_2( device ) ; } }
/* * Purpose of this function is to open a device and write random data to it as a way of hiding information on the disk. * * The above is accomplished by opening a plain mapper against the device and then write to the device through the mapper * */ int zuluCryptEXEWriteDeviceWithJunk( const struct_opts * opts,const char * mapping_name,uid_t uid ) { stringList_t stl = StringListInit() ; string_t * mapper = StringListAssign( stl ) ; string_t * confirm = StringListAssign( stl ); double size ; double size_written ; const char * device = opts->device ; char buffer[ SIZE ] ; int ratio ; int prev_ratio ; int k ; struct sigaction sigac; memset( &sigac,'\0',sizeof( struct sigaction ) ) ; sigac.sa_handler = &sigTERMhandler ; sigaction( SIGINT,&sigac,NULL ) ; sigaction( SIGTERM,&sigac,NULL ) ; sigaction( SIGHUP,&sigac,NULL ) ; __exit_as_requested = 0 ; if( ( k = open_plain_as_me_1( opts,mapping_name,uid,0 ) ) != 0 ){ return k ; } *mapper = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTshortMapperPath ) ; StringMultiplePrepend( *mapper,"/",crypt_get_dir(),NULL ) ; if( opts->ask_confirmation ){ printf( gettext( "\nWARNING, device \"%s\" will be overwritten with random data destroying all present data.\n" ),device ) ; printf( gettext( "Are you sure you want to proceed? Type \"YES\" and press enter if you are sure: " ) ) ; *confirm = StringGetFromTerminal_1( 3 ) ; if( *confirm == StringVoid ){ return zuluExit( stl,17 ) ; }else{ k = StringEqual( *confirm,gettext( "YES" ) ) ; if( k == 0 ){ if( zuluCryptSecurityGainElevatedPrivileges() ){ zuluCryptCloseMapper( StringContent( *mapper ) ) ; zuluCryptSecurityDropElevatedPrivileges() ; } return zuluExit( stl,5 ) ; } } } k = open( StringContent( *mapper ),O_WRONLY ) ; size = ( double ) blkid_get_dev_size( k ) ; memset( buffer,0,SIZE ) ; size_written = 0 ; prev_ratio = -1 ; while( write( k,buffer,SIZE ) > 0 ){ if( __exit_as_requested == 1 ){ break ; } size_written += SIZE ; ratio = ( int ) ( ( size_written / size ) * 100 ) ; if( ratio > prev_ratio ){ printf( "\r%s %d%%",gettext( "percentage complete: " ),ratio ) ; fflush( stdout ); prev_ratio = ratio ; } } close( k ) ; if( zuluCryptSecurityGainElevatedPrivileges() ){ zuluCryptCloseMapper( StringContent( *mapper ) ) ; zuluCryptSecurityDropElevatedPrivileges() ; } if( __exit_as_requested == 1 ){ return zuluExit( stl,15 ) ; }else{ return zuluExit( stl,3 ) ; } }
int zuluMountUMount( ARGS * args ) { const char * device = args->device ; uid_t uid = args->uid ; char * loop_device ; char * m_point = NULL ; int status ; string_t st = StringVoid ; const char * dev = NULL ; const char * errorMsg = gettext( "\ ERROR: You can not umount volumes out of \"%s\" since you are not root and do not belong to group \"zulumount\"\n" ) ; string_t xt ; if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress() is defined in ../zuluCrypt-cli/lib/create_loop_devices.c */ loop_device = zuluCryptLoopDeviceAddress( device ) ; if( loop_device == NULL ){ /* * the error msg is a lie,but its harmless since the user will most likely never see it as * this code path will not be passed. */ return _zuluExit( 100,StringVoid,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; }else{ st = StringInherit( &loop_device ) ; dev = StringContent( st ) ; /* * zuluCryptGetMountPointFromPath() is defined in defined in ../zuluCrypt-cli/lib/process_mountinfo.c */ m_point = zuluCryptGetMountPointFromPath( dev ) ; if( m_point == NULL ){ return _zuluExit( 100,st,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; } } }else{ /* * zuluCryptGetMountPointFromPath() is defined in defined in ../zuluCrypt-cli/lib/process_mountinfo.c */ m_point = zuluCryptGetMountPointFromPath( device ) ; if( m_point == NULL ){ return _zuluExit( 100,st,m_point,gettext( "ERROR: Device does not appear to be mounted" ) ) ; } } /* * zuluCryptMountPointPrefixMatch() is defined in ../zuluCrypt-cli/bin/create_mount_point.c */ if( zuluCryptMountPointPrefixMatch( m_point,uid,&xt ) ){ StringDelete( &xt ) ; }else{ /* * zuluCryptUserIsAMemberOfAGroup() is defined in ../zuluCrypt-cli/bin/security.c */ if( zuluCryptUserIsAMemberOfAGroup( uid,"zulumount" ) ){ StringDelete( &xt ) ; }else{ printf( errorMsg,StringContent( xt ) ) ; StringDelete( &xt ) ; return _zuluExit( 101,st,m_point,NULL ) ; } } StringFree( m_point ) ; m_point = NULL ; /* * zuluCryptBindUnmountVolume() is defined in ../zuluCrypt-cli/bin/bind.c */ switch( zuluCryptBindUnmountVolume( StringListVoid,device,uid ) ){ case 3 : return _zuluExit( 107,st,m_point,gettext( "ERROR: Shared mount point appear to be busy" ) ) ; case 4 : return _zuluExit( 108,st,m_point,gettext( "ERROR: Shared mount point appear to belong to a different user" ) ) ; case 5 : return _zuluExit( 109,st,m_point,gettext( "ERROR: Shared mount point appear to be in an ambiguous state,advice to unmount manually" ) ) ; default: ; } /* * zuluCryptSecurityGainElevatedPrivileges() is defined in ../zuluCrypt-cli/bin/security.c */ zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptUnmountVolume() is defined in ../zuluCrypt-cli/lib/unmount_volume.c */ status = zuluCryptUnmountVolume( device,&m_point ) ; /* * zuluCryptSecurityDropElevatedPrivileges() is defined in ../zuluCrypt-cli/bin/security.c */ zuluCryptSecurityDropElevatedPrivileges() ; if( status == 0 ){ if( m_point != NULL ){ /* * zuluCryptReuseMountPoint() is defined in ../zuluCrypt-cli/bin/create_mount_point.c */ if( !zuluCryptReuseMountPoint() ){ zuluCryptSecurityGainElevatedPrivileges() ; rmdir( m_point ) ; zuluCryptSecurityDropElevatedPrivileges() ; } } return _zuluExit( 0,st,m_point,gettext( "SUCCESS: umount complete successfully" ) ) ; }else{ switch( status ) { case 1 : return _zuluExit( 103,st,m_point,gettext( "ERROR: Device does not exist" ) ) ; case 2 : return _zuluExit( 104,st,m_point,gettext( "ERROR: Failed to unmount,the mount point and/or one or more files are in use" ) ) ; case 4 : return _zuluExit( 105,st,m_point,gettext( "ERROR: Failed to unmount,could not get a lock on /etc/mtab~" ) ) ; case 10: return _zuluExit( 107,st,m_point,gettext( "ERROR: Failed to unmount,multiple mount points for the volume detected" ) ) ; break ; default: return _zuluExit( 106,st,m_point,gettext( "ERROR: Failed to unmount the partition" ) ) ; } } }
/* * get_pass_from_file function is defined at get_pass_from_file.c * */ int zuluCryptEXEAddKey( const struct_opts * opts,uid_t uid ) { const char * device = opts->device ; const char * keyType1 = opts->existing_key_source ; const char * existingKey = opts->existing_key ; const char * keyType2 = opts->new_key_source ; const char * newKey = opts->new_key ; /* * Below is a form of memory management.All strings are collected in a stringlist object to easily delete them * when the function returns.This allows for the function to have multiple exit points without risks of leaking * memory from manually examining each exit point to make sure all strings are deleted or go with multiple goto * code deleting blocks to take into account different exit points. */ stringList_t stl ; string_t * stringArray = StringListArray( &stl,5 ) ; string_t * presentKey = &stringArray[ 0 ] ; string_t * newKey_1 = &stringArray[ 1 ] ; string_t * newKey_2 = &stringArray[ 2 ] ; string_t * ek = &stringArray[ 3 ] ; string_t * nk = &stringArray[ 4 ] ; const char * key1 = NULL ; const char * key2 = NULL ; size_t len1 = 0 ; size_t len2 = 0 ; int status = 0 ; tcrypt_opts tcrypt ; memset( &tcrypt,'\0',sizeof( tcrypt_opts ) ) ; /* * zuluCryptPartitionIsSystemPartition() is defined in ./partitions.c */ if( zuluCryptPartitionIsSystemPartition( device,uid ) ){ if( !zuluCryptUserIsAMemberOfAGroup( uid,"zulucrypt" ) ){ return zuluExit( 4,stl ) ; } } /* * zuluCryptSecurityDeviceIsWritable() is defined in path_access.c */ status = zuluCryptCanOpenPathForWriting( device,uid ) ; /* * 1-permissions denied * 2-invalid path * 3-shenanigans * 4-common error */ switch( status ){ case 0 : break ; case 1 : return zuluExit( 5,stl ) ; case 2 : return zuluExit( 5,stl ) ; case 3 : return zuluExit( 5,stl ) ; case 4 : return zuluExit( 5,stl ) ; default: return zuluExit( 5,stl ) ; } switch( _zuluCryptCheckEmptySlots( device ) ){ case 0 : return zuluExit( 6,stl ) ; case 1 : return zuluExit( 2,stl ) ; case 2 : /* no complains,continue */ ; } if( keyType1 == NULL && keyType2 == NULL ){ switch( zuluGetKeys( presentKey,newKey_1,newKey_2 ) ){ case 1 : return zuluExit( 7,stl ) ; case 2 : return zuluExit( 8,stl ) ; } if( StringEqualString( *newKey_1,*newKey_2 ) ){ key1 = StringContent( *presentKey ) ; len1 = StringLength ( *presentKey ) ; key2 = StringContent( *newKey_1 ) ; len2 = StringLength ( *newKey_1 ) ; }else{ return zuluExit( 9,stl ) ; } }else{ if( newKey == NULL || existingKey == NULL ){ return zuluExit( 10,stl ) ; } if( StringsAreEqual( keyType1,"-f" ) ){ /* * this function is defined at "path_access.c" */ switch( zuluCryptGetPassFromFile( existingKey,uid,ek ) ){ case 1 : return zuluExit( 11,stl ) ; case 4 : return zuluExit( 12,stl ) ; case 2 : return zuluExit( 13,stl ) ; case 5 : return zuluExit( 14,stl ) ; } key1 = StringContent( *ek ) ; len1 = StringLength( *ek ) ; if( StringHasNoComponent( existingKey,"/.zuluCrypt-socket" ) ){ tcrypt.existing_key_is_keyfile = 1 ; } } if( StringsAreEqual( keyType2,"-f" ) ){ /* * this function is defined at "path_access.c" */ switch( zuluCryptGetPassFromFile( newKey,uid,nk ) ){ case 1 : return zuluExit( 11,stl ) ; case 4 : return zuluExit( 12,stl ) ; case 2 : return zuluExit( 13,stl ) ; case 5 : return zuluExit( 14,stl ) ; } key2 = StringContent( *nk ) ; len2 = StringLength( *nk ) ; if( StringHasNoComponent( newKey,"/.zuluCrypt-socket" ) ){ tcrypt.new_key_is_keyfile = 1 ; } } if( StringsAreEqual( keyType1,"-f" ) && StringsAreEqual( keyType2,"-f" ) ){ ; }else if( StringsAreEqual( keyType1,"-p" ) && StringsAreEqual( keyType2,"-p" ) ){ key1 = existingKey ; len1 = StringSize( existingKey ) ; key2 = newKey ; len2 = StringSize( newKey ) ; }else if( StringsAreEqual( keyType1,"-p" ) && StringsAreEqual( keyType2,"-f" ) ){ key1 = existingKey ; len1 = StringSize( existingKey ) ; }else if( StringsAreEqual( keyType1,"-f" ) && StringsAreEqual( keyType2,"-p" ) ){ key2 = newKey ; len2 = StringSize( newKey ) ; }else{ return zuluExit( 10,stl ) ; } } zuluCryptSecurityLockMemory( stl ) ; zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptVolumeIsLuks() is defined in ../lib/is_luks.c */ if( zuluCryptVolumeIsLuks( device ) ){ /* * zuluCryptAddKey() is defined in ../lib/add_key.c */ status = zuluCryptAddKey( device,key1,len1,key2,len2 ) ; }else{ tcrypt.device = device ; tcrypt.existing_key = key1 ; tcrypt.existing_key_size = len1 ; tcrypt.new_key = key2 ; tcrypt.new_key_size = len2 ; status = _replace_truecrypt_key( &tcrypt ) ; } zuluCryptSecurityDropElevatedPrivileges() ; return zuluExit( status,stl ) ; }
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 ; }
int zuluCryptBindMountVolume( const char * device,string_t z_path,unsigned long flags ) { struct stat st ; string_t path ; string_t tmp ; ssize_t index = StringLastIndexOfChar( z_path,'/' ) ; const char * o_path = StringContent( z_path ) ; const char * m_path ; const char * e ; int xt ; stringList_t stl ; mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH ; if( index == -1 ){ return 1 ; } if( device ){;} zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptGetMoutedListFromMountInfo() is defined in ../lib/process_mountinfo.c */ stl = zuluCryptGetMoutedListFromMountInfo() ; path = String( "/run/media/public/" ) ; m_path = StringAppend( path,o_path + index + 1 ) ; #define path_does_not_exist( x ) stat( x,&st ) != 0 #define path_does_exist( x ) stat( x,&st ) == 0 if( path_does_not_exist( "/run" ) ){ mkdir( "/run",mode ) ; _chown( "/run",0,0 ) ; } if( path_does_not_exist( "/run/media" ) ){ mkdir( "/run/media",mode ) ; _chown( "/run/media",0,0 ) ; } if( path_does_not_exist( "/run/media/public" ) ){ mkdir( "/run/media/public",mode ) ; _chown( "/run/media/public",0,0 ) ; } if( path_does_exist( m_path ) ){ /* * bind mount point exists,this will happen if the mount point is already taken or a mount point folder * was not autodeleted for some reason */ tmp = StringCopy( path ) ; e = StringAppend( tmp," " ) ; if( StringListHasSequence( stl,e ) != -1 ){ /* * An attempt is made to bind mount on a path already bind mounted path,dont attempt to mount */ xt = 1 ; }else{ /* * the mount point folder is there for some reason but is not being used. */ xt = mount( o_path,m_path,"",flags|MS_BIND,"" ) ; } StringDelete( &tmp ) ; }else{ mkdir( m_path,S_IRWXU | S_IRWXG | S_IRWXG ) ; _chown( m_path,0,0 ) ; xt = mount( o_path,m_path,"",flags|MS_BIND,"" ) ; if( xt != 0 ){ rmdir( m_path ) ; } } StringListDelete( &stl ) ; StringDelete( &path ) ; zuluCryptSecurityDropElevatedPrivileges() ; return xt ; }
/* * 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 ){ ignore_result( write( fd_temp,buffer,len ) ) ; break ; }else{ ignore_result( write( fd_temp,buffer,len ) ) ; } } close( fd_source ) ; close( fd_temp ) ; zuluCryptSecurityDropElevatedPrivileges() ; *path = StringDeleteHandle( &st_path ) ; return 1 ; }
int zuluCryptEXECloseVolume( const char * dev,const char * mapping_name,uid_t uid ) { int st ; int i ; string_t p = StringVoid ; char * m_point = NULL ; struct stat xt ; const char * mapper ; /* * ZULUCRYPTlongMapperPath is set in ../constants.h * zuluCryptCreateMapperName() defined in ../lib/create_mapper_name.c */ p = zuluCryptCreateMapperName( dev,mapping_name,uid,ZULUCRYPTlongMapperPath ) ; mapper = StringContent( p ) ; if( stat( mapper,&xt ) != 0 ){ return zuluExit( 1,p ) ; } /* * zuluCryptBindUnmountVolume() is defined in ./bind.c */ switch( zuluCryptBindUnmountVolume( StringListVoid,mapper,uid ) ){ case 3 : return zuluExit( 7,p ) ; case 4 : return zuluExit( 8,p ) ; case 5 : return zuluExit( 9,p ) ; default: ; } zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptCloseVolume() is defined in ../lib/close_volume.c * * zuluCryptReuseMountPoint() is defined in create_mount_point.c */ if( zuluCryptReuseMountPoint() ){ st = zuluCryptCloseVolume( mapper,NULL ) ; }else{ st = zuluCryptCloseVolume( mapper,&m_point ) ; } if( st == 0 && m_point != NULL ){ for( i = 0 ; i < 2 ; i++ ){ if( rmdir( m_point ) == 0 ){ break ; }else{ sleep( 1 ) ; } } } StringFree( m_point ) ; zuluCryptSecurityDropElevatedPrivileges() ; return zuluExit( st,p ) ; }
static int open_plain_as_me_1(const struct_opts * opts,const char * mapping_name,uid_t uid,int op ) { /* * Below is a form of memory management.All strings are collected in a stringlist object to easily delete them * when the function returns.This allows for the function to have multiple exit points without risks of leaking * memory from manually examining each exit point to make sure all strings are deleted or go with multiple goto * code deleting blocks to take into account different exit points. */ stringList_t stl ; string_t * stringArray = StringListArray( &stl,5 ) ; string_t * mapper = &stringArray[ 0 ] ; string_t * passphrase = &stringArray[ 1 ] ; string_t * p = &stringArray[ 2 ] ; string_t * dev_st = &stringArray[ 3 ] ; string_t * dev_1 = &stringArray[ 4 ] ; size_t len = 0 ; const char * source = opts->key_source ; const char * pass = opts->key ; int k = opts->ask_confirmation ; const char * cpass = NULL ; char * d ; const char * device = opts->device ; const char * dev = opts->device ; int j ; int n ; const char * cmapper ; if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress() is defined in ../lib/create_loop_device.c */ d = zuluCryptLoopDeviceAddress( device ) ; *dev_st = StringInherit( &d ) ; dev = StringContent( *dev_st ) ; *dev_1 = StringCopy( *dev_st ) ; device = StringReplaceString( * dev_1,"\\040"," " ) ; } /* * zuluCryptPartitionIsSystemPartition() is defined in ./partition.c */ if( zuluCryptPartitionIsSystemPartition( device,uid ) ){ if( uid != 0 ){ return zuluExit( stl,8 ) ; } } /* * ZULUCRYPTlongMapperPath and ZULUCRYPTshortMapperPath are in ../constants.h * zuluCryptCreateMapperName() is defined at ../lib/create_mapper_name.c */ *mapper = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTshortMapperPath ) ; *p = zuluCryptCreateMapperName( device,mapping_name,uid,ZULUCRYPTlongMapperPath ) ; j = zuluCryptCheckOpenedMapper( StringContent( *p ) ) ; /* * zuluCryptPartitionIsMounted() is defined in ../lib/process_mountinfo.c */ n = zuluCryptPartitionIsMounted( dev ) ; if( j == 1 ){ return zuluExit( stl,13 ) ; } if( n == 1 ){ return zuluExit( stl,14 ) ; } if( k == 0 ){ *passphrase = StringRandomString( 64 ) ; cpass = StringContent( *passphrase ) ; len = StringLength( *passphrase ) ; }else if( source == NULL ){ printf( gettext( "Enter passphrase: " ) ) ; /* * ZULUCRYPT_KEY_MAX_SIZE is set in ../constants.h */ switch( StringSilentlyGetFromTerminal_1( passphrase,ZULUCRYPT_KEY_MAX_SIZE ) ){ case 1 : return zuluExit( stl,16 ) ; case 2 : return zuluExit( stl,17 ) ; } printf( "\n" ) ; cpass = StringContent( *passphrase ) ; len = StringLength( *passphrase ) ; }else{ if( strcmp( source,"-p" ) == 0 ){ *passphrase = String( pass ) ; cpass = StringContent( *passphrase ) ; len = StringLength( *passphrase ) ; }else if( strcmp( source,"-f" ) == 0 ){ /* * zuluCryptGetPassFromFile() is defined at "path_access.c" */ switch( zuluCryptGetPassFromFile( pass,uid,passphrase ) ){ case 1 : return zuluExit( stl,10 ) ; case 2 : return zuluExit( stl,11 ) ; case 4 : return zuluExit( stl,12 ) ; } cpass = StringContent( *passphrase ) ; len = StringLength( *passphrase ) ; } } if( zuluCryptSecurityGainElevatedPrivileges() ){ /* * zuluCryptOpenPlain() is defined in ../lib/open_plain.c */ if( zuluCryptOpenPlain( device,StringContent( *mapper ),"rw",cpass,len ) != 0 ){ zuluCryptSecurityDropElevatedPrivileges() ; return zuluExit( stl,1 ) ; } } zuluCryptSecurityDropElevatedPrivileges() ; /* * Create a mapper path(usually at /dev/mapper) associated with opened plain mapper above. */ cmapper = StringMultiplePrepend( *mapper,"/",crypt_get_dir(),NULL ) ; /* * mapper path is usually a soft link to /dev/dm-X * resolve the mapper path to its respective /dev/dm-X and set permission on it. * * We set permission of /dev/dm-X pointing to the device to "u+rw" because we want notmal user to be able * to write to the device through the mapper. * * Useful when a normal user want to delete content of the device by writing random data to it. */ d = zuluCryptRealPath( cmapper ) ; if( zuluCryptSecurityGainElevatedPrivileges() ){ if( d != NULL ){ _ignore_result( chown( d,uid,0 ) ) ; _ignore_result( chmod( d,S_IRWXU ) ) ; StringFree( d ) ; } zuluCryptSecurityDropElevatedPrivileges() ; }else{ return zuluExit( stl,1 ) ; } if( op == 1 ){ return zuluExit( stl,0 ) ; }else{ StringListClearDelete( &stl ) ; return 0 ; } }
int zuluCryptEXERemoveKey( const struct_opts * opts,uid_t uid ) { int ask_confirmation = opts->ask_confirmation ; const char * device = opts->device ; const char * keyType = opts->key_source ; const char * keytoremove = opts->key ; stringList_t stl = StringListInit() ; string_t * pass = StringListAssign( stl ) ; string_t * confirm = StringListAssign( stl ) ; int status = 0 ; const char * key ; size_t key_size ; /* * zuluCryptPartitionIsSystemPartition() is defined in ./partitions.c */ if( zuluCryptPartitionIsSystemPartition( device,uid ) ){ if( !zuluCryptUserIsAMemberOfAGroup( uid,"zulucrypt" ) ){ return zuluExit( 4,stl ) ; } } /* * zuluCryptCanOpenPathForWriting is defined in path_access.c */ status = zuluCryptCanOpenPathForWriting( device,uid ) ; /* * 1-permissions denied * 2-invalid path * 3-shenanigans * 4-common error */ switch( status ){ case 0 : break ; case 1 : return zuluExit( 5,stl ) ; case 2 : return zuluExit( 5,stl ) ; case 3 : return zuluExit( 5,stl ) ; case 4 : return zuluExit( 5,stl ) ; default: return zuluExit( 5,stl ) ; } if( _zuluCryptExECheckEmptySlots( device ) == 3 ){ if( ask_confirmation ){ printf( gettext( "WARNING: There is only one key in the volume and all data in it will be lost if you continue.\n" ) ) ; printf( gettext( "Do you still want to continue? Type \"YES\" if you do: " ) ) ; *confirm = StringGetFromTerminal_1( 3 ) ; if( *confirm == StringVoid ){ return zuluExit( 6,stl ) ; } if( !StringEqual( *confirm,gettext( "YES" ) ) ){ return zuluExit( 7,stl ) ; } } } if( keyType == NULL ){ printf( gettext( "Enter a key to be removed: " ) ) ; /* * ZULUCRYPT_KEY_MAX_SIZE is set in ../constants.h */ switch( StringSilentlyGetFromTerminal_1( pass,ZULUCRYPT_KEY_MAX_SIZE ) ){ case 1 : return zuluExit( 8,stl ) ; case 2 : return zuluExit( 9,stl ) ; } printf( "\n" ) ; key = StringContent( *pass ) ; key_size = StringLength( *pass ) ; zuluCryptSecurityLockMemory_1( *pass ) ; }else{ if( keyType == NULL || keytoremove == NULL ){ return zuluExit( 10,stl ) ; } if( StringsAreEqual( keyType,"-f" ) ){ /* * zuluCryptGetPassFromFile() is defined at path_access.c" */ switch( zuluCryptGetPassFromFile( keytoremove,uid,pass ) ){ case 1 : return zuluExit( 11,stl ) ; case 2 : return zuluExit( 12,stl ) ; case 4 : return zuluExit( 13,stl ) ; case 5 : return zuluExit( 14,stl ) ; } key = StringContent( *pass ) ; key_size = StringLength( *pass ) ; zuluCryptSecurityLockMemory_1( *pass ) ; }else if( StringsAreEqual( keyType, "-p" ) ){ key = keytoremove ; key_size = StringSize( keytoremove ) ; }else{ return zuluExit( 10,stl ) ; } } zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptRemoveKey() is defined in ../lib/remove_key.c */ status = zuluCryptRemoveKey( device,key,key_size ) ; zuluCryptSecurityDropElevatedPrivileges() ; if( status == 1 ){ status = zuluExit_1( status,device,stl ) ; }else{ status = zuluExit( status,stl ) ; } /* * zuluCryptCheckInvalidKey() is defined in check_invalid_key.c */ zuluCryptCheckInvalidKey( opts->device ) ; return status ; }
void zuluCryptPrintPartitionProperties( const char * device ) { #define SIZE 64 char buffer[ SIZE ] ; const char * e ; u_int64_t size ; blkid_probe blkid ; zuluCryptSecurityGainElevatedPrivileges() ; if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress_1() is defined in ../lib/create_loop_device.c */ e = zuluCryptLoopDeviceAddress_1( device ) ; if( e != NULL ){ printf( "%s\t",e ) ; StringFree( e ) ; }else{ printf( "%s\t",device ) ; } }else{ printf( "%s\t",device ) ; } size = zuluCryptGetVolumeSize( device ) ; blkid = blkid_new_probe_from_filename( device ) ; if( blkid == NULL ){ printf( "Nil\tNil\tNil\tNil\n" ) ; }else{ /* * zuluCryptFormatSize() is defined in ../lib/status.c */ zuluCryptFormatSize( size,buffer,SIZE ) ; printf( "%s\t",buffer ) ; blkid_do_probe( blkid ) ; if( blkid_probe_lookup_value( blkid,"LABEL",&e,NULL ) == 0 ){ printf( "%s\t",e ) ; }else{ printf( "Nil\t" ) ; } if( blkid_probe_lookup_value( blkid,"TYPE",&e,NULL ) == 0 ){ printf( "%s\t",e ) ; }else{ printf( "Nil\t" ) ; } if( blkid_probe_lookup_value( blkid,"UUID",&e,NULL ) == 0 ){ printf( "%s\n",e ) ; }else{ printf( "Nil\n" ) ; } blkid_free_probe( blkid ) ; } zuluCryptSecurityDropElevatedPrivileges() ; }
stringList_t zuluCryptPartitions( int option,uid_t uid ) { const char * device ; const char * e ; stringList_t non_system = StringListVoid ; stringList_t system = StringListVoid ; string_t st ; stringList_t p ; stringList_t stl = zuluCryptVolumeList() ; StringListIterator it ; StringListIterator end ; if( stl == StringListVoid ){ return StringListVoid ; } if( option == ZULUCRYPTallPartitions ){ return _remove_btfs_multiple_devices( stl ) ; } non_system = stl ; zuluCryptSecurityGainElevatedPrivileges() ; /* * zuluCryptGetFstabList() is defined in ../lib/parse_fstab.c */ stl = zuluCryptGetFstabList( uid ) ; zuluCryptSecurityDropElevatedPrivileges() ; StringListGetIterators( stl,&it,&end ) ; /* * gather an initial list of system and non system partitions by comparing entries in "/etc/fstab" and "/proc/partitions" * fstab entries makes an initial list of system partitions. * the difference btw list in "/proc/partitions" and "/etc/fstab" makes an initial list of non system partitions. */ while( it != end ){ st = *it ; it++ ; if( StringStartsWith( st,"/" ) ){ device = StringReplaceChar_1( st,0,' ','\0' ) ; system = StringListAppend( system,device ) ; StringListRemoveString( non_system,device ) ; } } StringListDelete( &stl ) ; /* * read entried from "crypttab" and then add them to "system" if absent in that list and remove them from "non system" if present * in that list */ p = zuluCryptGetPartitionFromCrypttab() ; if( p != StringListVoid ){ StringListGetIterators( p,&it,&end ) ; while( it != end ){ device = StringContent( *it ) ; it++ ; StringListAppendIfAbsent( system,device ) ; StringListRemoveIfPresent( non_system,device ) ; } StringListDelete( &p ) ; } /* * read entried from "zuluCrypt-system" and then add them to "system" if absent in that list and remove them from "non system" if present * in that list */ p = zuluCryptGetPartitionFromConfigFile( "/etc/zuluCrypt-system" ) ; if( p == StringListVoid ){ /* * This is the new path since zuluCrypt 4.6.9 */ p = zuluCryptGetPartitionFromConfigFile( "/etc/zuluCrypt/system_volumes.list" ) ; } if( p != StringListVoid ){ StringListGetIterators( p,&it,&end ) ; while( it != end ){ device = StringContent( *it ) ; it++ ; StringListAppendIfAbsent( system,device ) ; StringListRemoveIfPresent( non_system,device ) ; } StringListDelete( &p ) ; } /* * At this point: * "system" contains system devices gathered from fstab,zuluCrypt-system and crypttab * "non_system" contains non system devices gathered from /proc/partitions minus system partitions. */ StringListGetIterators( non_system,&it,&end ) ; /* * now we consult udev if enabled and we move partition in the "non system" list to "system" list if udev think they are system */ while( it != end ){ e = StringContent( *it ) ; if( _zuluCryptCheckSYSifDeviceIsSystem( e ) ){ StringListAppendIfAbsent( system,e ) ; StringListRemoveAt_1( non_system,it,&end ) ; }else{ it++ ; } } /* * Now we read from a config file that contains devices that are not to be considered system and remove them from * the system list if present in that list and add them to non system list if absent in that list */ p = zuluCryptGetPartitionFromConfigFile( "/etc/zuluCrypt-nonsystem" ) ; if( p == StringListVoid ){ /* * This is the new path since zuluCrypt 4.6.9 */ p = zuluCryptGetPartitionFromConfigFile( "/etc/zuluCrypt/nonsystem_volumes.list" ) ; } if( p != StringListVoid ){ StringListGetIterators( p,&it,&end ) ; while( it != end ){ device = StringContent( *it ) ; it++ ; StringListRemoveString( system,device ) ; StringListAppendIfAbsent( non_system,device ) ; } StringListDelete( &p ) ; } if( option == ZULUCRYPTsystemPartitions ){ StringListDelete( &non_system ) ; return _remove_btfs_multiple_devices( system ) ; }else{ StringListDelete( &system ) ; return _remove_btfs_multiple_devices( non_system ) ; } }
static stringList_t _zuluCryptVolumeList_0( int resolve_loop_devices ) { const char * device ; const char * e ; ssize_t index ; StringListIterator it ; StringListIterator end ; stringList_t stz = StringListVoid ; stringList_t stl = StringListVoid ; stringList_t stl_1 = StringListVoid ; string_t st = StringGetFromVirtualFile( "/proc/partitions" ) ; string_t st_1 = String( "/dev/" ) ; stl = StringListStringSplit( st,'\n' ) ; StringDelete( &st ) ; if( stl == StringListVoid ){ return StringListVoid ; } StringListGetIterators( stl,&it,&end ) ; /* * skip the first entry */ it++ ; zuluCryptSecurityGainElevatedPrivileges() ; while( it != end ){ st = *it ; it++ ; index = StringLastIndexOfChar( st,' ' ) ; if( index != -1 ){ e = StringContent( st ) + index + 1 ; device = StringAppendAt( st_1,5,e ) ; if( _supported_device( device ) ){ if( StringPrefixEqual( device,"/dev/loop" ) ){ /* * zuluCryptLoopDeviceAddress_1() id defined in ../lib/create_loop_device.c */ e = zuluCryptLoopDeviceAddress_1( device ) ; if( StringListHasNoEntry( stz,e ) ){ /* * Here we only keep one loop device if the volume file has * more than one loop device */ if( resolve_loop_devices ){ stl_1 = StringListAppend( stl_1,e ) ; }else{ stl_1 = StringListAppend( stl_1,device ) ; } stz = StringListAppend( stz,e ) ; } StringFree( e ) ; }else{ stl_1 = StringListAppendIfAbsent( stl_1,device ) ; } } } } zuluCryptSecurityDropElevatedPrivileges() ; StringListMultipleDelete( &stl,&stz,NULL ) ; StringDelete( &st_1 ) ; return _zuluCryptAddLVMVolumes( _zuluCryptAddMDRAIDVolumes( _remove_root_devices( stl_1 ) ) ) ; }
/* * It is possible for a btrfs volume to cover multiple volumes and this routine * keeps only the first one seen and removes the rest. */ static stringList_t _remove_btfs_multiple_devices( stringList_t stl ) { stringList_t stx = StringListVoid ; stringList_t stz = StringListVoid ; StringListIterator it ; StringListIterator end ; string_t st ; const char * e ; blkid_probe blkid ; StringListGetIterators( stl,&it,&end ) ; zuluCryptSecurityGainElevatedPrivileges() ; while( it != end ){ st = *it ; it++ ; blkid = blkid_new_probe_from_filename( StringContent( st ) ) ; if( blkid != NULL ){ e = NULL ; blkid_do_probe( blkid ) ; blkid_probe_lookup_value( blkid,"TYPE",&e,NULL ) ; if( StringsAreEqual( e,"btrfs" ) ){ e = NULL ; blkid_probe_lookup_value( blkid,"UUID",&e,NULL ) ; if( StringListHasNoEntry( stx,e ) ){ /* * we got a btrfs volume with UUID we do not know about, * This will be the only device with this btrfs UUID we support and * all device operations must happen through this device and this device only. */ stz = StringListAppendString( stz,st ) ; stx = StringListAppend( stx,e ) ; }else{ /* * we already know this UUID and this device is not supported.Any operation on this * device should fail. */ } }else{ /* * not a btrfs volume */ stz = StringListAppendString( stz,st ) ; } blkid_free_probe( blkid ) ; }else{ stz = StringListAppendString( stz,st ) ; } } zuluCryptSecurityDropElevatedPrivileges() ; StringListMultipleDelete( &stl,&stx,NULL ) ; return stz ; }