Fix: dol_check_secure_access_document is also used by viewimage. This

also solve bug of not found supplier doc and solve some security holes.
This commit is contained in:
Laurent Destailleur 2013-04-25 10:06:54 +02:00
parent cce857d6ee
commit 86ea79c860
4 changed files with 544 additions and 578 deletions

View File

@ -1229,25 +1229,189 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('\.meta$
} }
/** /**
* Security check when accessing to a document (used in document.php and webservices) * Security check when accessing to a document (used by document.php, viewimage.php and webservices)
* @param string $modulepart module of document *
* @param string $original_file relative path with filename * @param string $modulepart Module of document
* @return mixed Array with access information : accessallowed & sqlprotectagainstexternals * @param string $original_file Relative path with filename
* @return mixed Array with access information : accessallowed & sqlprotectagainstexternals & original_file (as full path name)
*/ */
function dol_check_secure_access_document($modulepart,&$original_file) function dol_check_secure_access_document($modulepart,$original_file)
{ {
global $user, $conf; global $user, $conf;
if (empty($modulepart)) return 'ErrorBadParameter';
// We define $accessallowed and $sqlprotectagainstexternals
$accessallowed=0; $accessallowed=0;
$sqlprotectagainstexternals=''; $sqlprotectagainstexternals='';
$ret=array(); $ret=array();
if ($modulepart) // Wrapping for some images
if ($modulepart == 'companylogo')
{ {
// On fait une verification des droits et on definit le repertoire concerne $accessallowed=1;
$original_file=$conf->mycompany->dir_output.'/logos/'.$original_file;
}
// Wrapping for users photos
elseif ($modulepart == 'userphoto')
{
$accessallowed=1;
$original_file=$conf->user->dir_output.'/'.$original_file;
}
// Wrapping for members photos
elseif ($modulepart == 'memberphoto')
{
$accessallowed=1;
$original_file=$conf->adherent->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu factures
elseif ($modulepart == 'apercufacture')
{
if ($user->rights->facture->lire) $accessallowed=1;
$original_file=$conf->facture->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu propal
elseif ($modulepart == 'apercupropal')
{
if ($user->rights->propale->lire) $accessallowed=1;
$original_file=$conf->propal->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu commande
elseif ($modulepart == 'apercucommande')
{
if ($user->rights->commande->lire) $accessallowed=1;
$original_file=$conf->commande->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu intervention
elseif ($modulepart == 'apercufichinter')
{
if ($user->rights->ficheinter->lire) $accessallowed=1;
$original_file=$conf->ficheinter->dir_output.'/'.$original_file;
}
// Wrapping pour les images des stats propales
elseif ($modulepart == 'propalstats')
{
if ($user->rights->propale->lire) $accessallowed=1;
$original_file=$conf->propal->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats commandes
elseif ($modulepart == 'orderstats')
{
if ($user->rights->commande->lire) $accessallowed=1;
$original_file=$conf->commande->dir_temp.'/'.$original_file;
}
elseif ($modulepart == 'orderstatssupplier')
{
if ($user->rights->fournisseur->commande->lire) $accessallowed=1;
$original_file=$conf->fournisseur->dir_output.'/commande/temp/'.$original_file;
}
// Wrapping pour les images des stats factures
elseif ($modulepart == 'billstats')
{
if ($user->rights->facture->lire) $accessallowed=1;
$original_file=$conf->facture->dir_temp.'/'.$original_file;
}
elseif ($modulepart == 'billstatssupplier')
{
if ($user->rights->fournisseur->facture->lire) $accessallowed=1;
$original_file=$conf->fournisseur->dir_output.'/facture/temp/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'expeditionstats')
{
if ($user->rights->expedition->lire) $accessallowed=1;
$original_file=$conf->expedition->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'tripsexpensesstats')
{
if ($user->rights->deplacement->lire) $accessallowed=1;
$original_file=$conf->deplacement->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'memberstats')
{
if ($user->rights->adherent->lire) $accessallowed=1;
$original_file=$conf->adherent->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats produits
elseif (preg_match('/^productstats_/i',$modulepart))
{
if ($user->rights->produit->lire || $user->rights->service->lire) $accessallowed=1;
$original_file=(!empty($conf->product->multidir_temp[$entity])?$conf->product->multidir_temp[$entity]:$conf->service->multidir_temp[$entity]).'/'.$original_file;
}
// Wrapping for products or services
elseif ($modulepart == 'tax')
{
if ($user->rights->tax->charges->lire) $accessallowed=1;
$original_file=$conf->tax->dir_output.'/'.$original_file;
}
// Wrapping for products or services
elseif ($modulepart == 'actions')
{
if ($user->rights->agenda->myactions->read) $accessallowed=1;
$original_file=$conf->agenda->dir_output.'/'.$original_file;
}
// Wrapping for categories
elseif ($modulepart == 'category')
{
if ($user->rights->categorie->lire) $accessallowed=1;
$original_file=$conf->categorie->multidir_output[$entity].'/'.$original_file;
}
// Wrapping pour les prelevements
elseif ($modulepart == 'prelevement')
{
if ($user->rights->prelevement->bons->lire) $accessallowed=1;
$original_file=$conf->prelevement->dir_output.'/receipts/'.$original_file;
}
// Wrapping pour les graph energie
elseif ($modulepart == 'graph_stock')
{
$accessallowed=1;
$original_file=$conf->stock->dir_temp.'/'.$original_file;
}
// Wrapping pour les graph fournisseurs
elseif ($modulepart == 'graph_fourn')
{
$accessallowed=1;
$original_file=$conf->fournisseur->dir_temp.'/'.$original_file;
}
// Wrapping pour les graph des produits
elseif ($modulepart == 'graph_product')
{
$accessallowed=1;
$original_file=$conf->product->multidir_temp[$entity].'/'.$original_file;
}
// Wrapping pour les code barre
elseif ($modulepart == 'barcode')
{
$accessallowed=1;
// If viewimage is called for barcode, we try to output an image on the fly,
// with not build of file on disk.
//$original_file=$conf->barcode->dir_temp.'/'.$original_file;
$original_file='';
}
// Wrapping pour les icones de background des mailings
elseif ($modulepart == 'iconmailing')
{
$accessallowed=1;
$original_file=$conf->mailing->dir_temp.'/'.$original_file;
}
// Wrapping pour les icones de background des mailings
elseif ($modulepart == 'scanner_user_temp')
{
$accessallowed=1;
$original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file;
}
// Wrapping pour les images fckeditor
elseif ($modulepart == 'fckeditor')
{
$accessallowed=1;
$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
}
// Wrapping for third parties // Wrapping for third parties
if ($modulepart == 'company' || $modulepart == 'societe') else if ($modulepart == 'company' || $modulepart == 'societe')
{ {
if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file)) if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file))
{ {
@ -1427,7 +1591,7 @@ function dol_check_secure_access_document($modulepart,&$original_file)
} }
// Wrapping pour les produits et services // Wrapping pour les produits et services
else if ($modulepart == 'produit' || $modulepart == 'service') else if ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service')
{ {
if (($user->rights->produit->lire || $user->rights->service->lire) || preg_match('/^specimen/i',$original_file)) if (($user->rights->produit->lire || $user->rights->service->lire) || preg_match('/^specimen/i',$original_file))
{ {
@ -1539,19 +1703,46 @@ function dol_check_secure_access_document($modulepart,&$original_file)
$original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file; $original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file;
} }
// Generic wrapping // GENERIC Wrapping
// If modulepart=module_user_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp/iduser
// If modulepart=module_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp
// If modulepart=module_user Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/iduser
// If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
else else
{ {
// For dir temp
$dir_temp=false;
if (preg_match('/\_temp$/i', $modulepart)) {
$modulepart = str_replace('_temp', '', $modulepart);
$dir_temp=true;
}
// Define $accessallowed // Define $accessallowed
if (($user->rights->$modulepart->lire) || ($user->rights->$modulepart->read) || ($user->rights->$modulepart->download)) $accessallowed=1; // No subpermission, we have checked on main permission if (preg_match('/^([a-z]+)_user_temp$/i',$modulepart,$reg))
elseif (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a specimen {
elseif ($user->admin) $accessallowed=1; // If user is admin if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read || ($user->rights->$reg[1]->download)) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_temp.'/'.$user->id.'/'.$original_file;
}
else if (preg_match('/^([a-z]+)_temp$/i',$modulepart,$reg))
{
if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read || ($user->rights->$reg[1]->download)) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_temp.'/'.$original_file;
}
else if (preg_match('/^([a-z]+)_user$/i',$modulepart,$reg))
{
if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read || ($user->rights->$reg[1]->download)) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_output.'/'.$user->id.'/'.$original_file;
}
else
{
$perm=GETPOST('perm');
$subperm=GETPOST('subperm');
if ($perm || $subperm)
{
if (($perm && ! $subperm && $user->rights->$modulepart->$perm) || ($perm && $subperm && $user->rights->$modulepart->$perm->$subperm)) $accessallowed=1;
$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
}
else
{
if ($user->rights->$modulepart->lire || $user->rights->$modulepart->read) $accessallowed=1;
$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
}
}
if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a specimen
if ($user->admin) $accessallowed=1; // If user is admin
// For modules who wants to manage different levels of permissions for documents // For modules who wants to manage different levels of permissions for documents
$subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS'; $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS';
@ -1564,11 +1755,6 @@ function dol_check_secure_access_document($modulepart,&$original_file)
} }
} }
// Define $original_file
$dir = $conf->$modulepart->dir_output;
if ($dir_temp) $dir = $conf->$modulepart->dir_temp;
$original_file = $dir.'/'.$original_file;
// Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query. // Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query.
$sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS'; $sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS';
if (! empty($conf->global->$sqlProtectConstName)) // If module want to define its own $sqlprotectagainstexternals if (! empty($conf->global->$sqlProtectConstName)) // If module want to define its own $sqlprotectagainstexternals
@ -1580,10 +1766,10 @@ function dol_check_secure_access_document($modulepart,&$original_file)
$ret = array( $ret = array(
'accessallowed' => $accessallowed, 'accessallowed' => $accessallowed,
'sqlprotectagainstexternals'=>$sqlprotectagainstexternals 'sqlprotectagainstexternals'=>$sqlprotectagainstexternals,
'original_file'=>$original_file
); );
}
return $ret; return $ret;
} }
?> ?>

View File

@ -95,10 +95,11 @@ $original_file = str_replace("../","/", $original_file);
$refname=basename(dirname($original_file)."/"); $refname=basename(dirname($original_file)."/");
// Security check // Security check
$accessallowed=0; if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart');
$check_access = dol_check_secure_access_document($modulepart,$original_file); $check_access = dol_check_secure_access_document($modulepart,$original_file);
$accessallowed=$check_access['accessallowed']; $accessallowed = $check_access['accessallowed'];
$sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals']; $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
$original_file = $check_access['original_file'];
// Basic protection (against external users only) // Basic protection (against external users only)
if ($user->societe_id > 0) if ($user->societe_id > 0)

View File

@ -203,7 +203,8 @@ if ($object->id > 0)
// List of document // List of document
$param='&facid='.$object->id; $param='&facid='.$object->id;
$formfile->list_of_documents($filearray,$object,'facture_fournisseur',$param,0,get_exdir($object->id,2,0).$object->id.'/'); $ref=dol_sanitizeFileName($object->ref);
$formfile->list_of_documents($filearray,$object,'facture_fournisseur',$param,0,get_exdir($object->id,2,0).$ref.'/');
} }
else else

View File

@ -98,234 +98,12 @@ else $type=dol_mimetype($original_file);
// Suppression de la chaine de caractere ../ dans $original_file // Suppression de la chaine de caractere ../ dans $original_file
$original_file = str_replace("../","/", $original_file); $original_file = str_replace("../","/", $original_file);
// Security checks // Security check
if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart'); if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart');
$accessallowed=0; $check_access = dol_check_secure_access_document($modulepart,$original_file);
if ($modulepart) $accessallowed = $check_access['accessallowed'];
{ $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
// Check permissions and define directory $original_file = $check_access['original_file'];
// Wrapping for company logo
if ($modulepart == 'companylogo')
{
$accessallowed=1;
$original_file=$conf->mycompany->dir_output.'/logos/'.$original_file;
}
// Wrapping for users photos
elseif ($modulepart == 'userphoto')
{
$accessallowed=1;
$original_file=$conf->user->dir_output.'/'.$original_file;
}
// Wrapping for members photos
elseif ($modulepart == 'memberphoto')
{
$accessallowed=1;
$original_file=$conf->adherent->dir_output.'/'.$original_file;
}
// Wrapping for members photos
elseif ($modulepart == 'member')
{
$accessallowed=1;
$original_file=$conf->adherent->dir_output.'/'.$original_file;
}
// Wrapping pour les images des societes
elseif ($modulepart == 'societe')
{
$accessallowed=1;
$original_file=$conf->societe->multidir_output[$entity].'/'.$original_file;
}
// Wrapping pour les apercu factures
elseif ($modulepart == 'apercufacture')
{
if ($user->rights->facture->lire) $accessallowed=1;
$original_file=$conf->facture->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu propal
elseif ($modulepart == 'apercupropal')
{
if ($user->rights->propale->lire) $accessallowed=1;
$original_file=$conf->propal->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu commande
elseif ($modulepart == 'apercucommande')
{
if ($user->rights->commande->lire) $accessallowed=1;
$original_file=$conf->commande->dir_output.'/'.$original_file;
}
// Wrapping pour les apercu intervention
elseif ($modulepart == 'apercufichinter')
{
if ($user->rights->ficheinter->lire) $accessallowed=1;
$original_file=$conf->ficheinter->dir_output.'/'.$original_file;
}
// Wrapping pour les images des stats propales
elseif ($modulepart == 'propalstats')
{
if ($user->rights->propale->lire) $accessallowed=1;
$original_file=$conf->propal->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats commandes
elseif ($modulepart == 'orderstats')
{
if ($user->rights->commande->lire) $accessallowed=1;
$original_file=$conf->commande->dir_temp.'/'.$original_file;
}
elseif ($modulepart == 'orderstatssupplier')
{
if ($user->rights->fournisseur->commande->lire) $accessallowed=1;
$original_file=$conf->fournisseur->dir_output.'/commande/temp/'.$original_file;
}
// Wrapping pour les images des stats factures
elseif ($modulepart == 'billstats')
{
if ($user->rights->facture->lire) $accessallowed=1;
$original_file=$conf->facture->dir_temp.'/'.$original_file;
}
elseif ($modulepart == 'billstatssupplier')
{
if ($user->rights->fournisseur->facture->lire) $accessallowed=1;
$original_file=$conf->fournisseur->dir_output.'/facture/temp/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'expeditionstats')
{
if ($user->rights->expedition->lire) $accessallowed=1;
$original_file=$conf->expedition->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'tripsexpensesstats')
{
if ($user->rights->deplacement->lire) $accessallowed=1;
$original_file=$conf->deplacement->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats expeditions
elseif ($modulepart == 'memberstats')
{
if ($user->rights->adherent->lire) $accessallowed=1;
$original_file=$conf->adherent->dir_temp.'/'.$original_file;
}
// Wrapping pour les images des stats produits
elseif (preg_match('/^productstats_/i',$modulepart))
{
if ($user->rights->produit->lire || $user->rights->service->lire) $accessallowed=1;
$original_file=(!empty($conf->product->multidir_temp[$entity])?$conf->product->multidir_temp[$entity]:$conf->service->multidir_temp[$entity]).'/'.$original_file;
}
// Wrapping for products or services
elseif ($modulepart == 'product')
{
if ($user->rights->produit->lire || $user->rights->service->lire) $accessallowed=1;
$original_file=(! empty($conf->product->multidir_output[$entity])?$conf->product->multidir_output[$entity]:$conf->service->multidir_output[$entity]).'/'.$original_file;
}
// Wrapping for products or services
elseif ($modulepart == 'tax')
{
if ($user->rights->tax->charges->lire) $accessallowed=1;
$original_file=$conf->tax->dir_output.'/'.$original_file;
}
// Wrapping for products or services
elseif ($modulepart == 'actions')
{
if ($user->rights->agenda->myactions->read) $accessallowed=1;
$original_file=$conf->agenda->dir_output.'/'.$original_file;
}
// Wrapping for categories
elseif ($modulepart == 'category')
{
if ($user->rights->categorie->lire) $accessallowed=1;
$original_file=$conf->categorie->multidir_output[$entity].'/'.$original_file;
}
// Wrapping pour les prelevements
elseif ($modulepart == 'prelevement')
{
if ($user->rights->prelevement->bons->lire) $accessallowed=1;
$original_file=$conf->prelevement->dir_output.'/receipts/'.$original_file;
}
// Wrapping pour les graph energie
elseif ($modulepart == 'graph_stock')
{
$accessallowed=1;
$original_file=$conf->stock->dir_temp.'/'.$original_file;
}
// Wrapping pour les graph fournisseurs
elseif ($modulepart == 'graph_fourn')
{
$accessallowed=1;
$original_file=$conf->fournisseur->dir_temp.'/'.$original_file;
}
// Wrapping pour les graph des produits
elseif ($modulepart == 'graph_product')
{
$accessallowed=1;
$original_file=$conf->product->multidir_temp[$entity].'/'.$original_file;
}
// Wrapping pour les code barre
elseif ($modulepart == 'barcode')
{
$accessallowed=1;
// If viewimage is called for barcode, we try to output an image on the fly,
// with not build of file on disk.
//$original_file=$conf->barcode->dir_temp.'/'.$original_file;
$original_file='';
}
// Wrapping pour les icones de background des mailings
elseif ($modulepart == 'iconmailing')
{
$accessallowed=1;
$original_file=$conf->mailing->dir_temp.'/'.$original_file;
}
// Wrapping pour les icones de background des mailings
elseif ($modulepart == 'scanner_user_temp')
{
$accessallowed=1;
$original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file;
}
// Wrapping pour les images fckeditor
elseif ($modulepart == 'fckeditor')
{
$accessallowed=1;
$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
}
// GENERIC Wrapping
// If modulepart=module_user_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp/iduser
// If modulepart=module_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp
// If modulepart=module_user Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/iduser
// If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
else
{
if (preg_match('/^([a-z]+)_user_temp$/i',$modulepart,$reg))
{
if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_temp.'/'.$user->id.'/'.$original_file;
}
else if (preg_match('/^([a-z]+)_temp$/i',$modulepart,$reg))
{
if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_temp.'/'.$original_file;
}
else if (preg_match('/^([a-z]+)_user$/i',$modulepart,$reg))
{
if ($user->rights->$reg[1]->lire || $user->rights->$reg[1]->read) $accessallowed=1;
$original_file=$conf->$reg[1]->dir_output.'/'.$user->id.'/'.$original_file;
}
else
{
$perm=GETPOST('perm');
$subperm=GETPOST('subperm');
if ($perm || $subperm)
{
if (($perm && ! $subperm && $user->rights->$modulepart->$perm) || ($perm && $subperm && $user->rights->$modulepart->$perm->$subperm)) $accessallowed=1;
$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
}
else
{
if ($user->rights->$modulepart->lire || $user->rights->$modulepart->read) $accessallowed=1;
$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
}
}
}
}
// Security: // Security:
// Limit access if permissions are wrong // Limit access if permissions are wrong