summaryrefslogblamecommitdiffstats
path: root/modules-available/sysconfig/addmodule_adauth.inc.php
blob: 421871718432e1acd2977127e0eb9c8c4270e607 (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                                                                         



                                                                                                            
                                         



                                           
                                                                                                                                                                                
                                
                                           


                                                                                 

                                            
                 
                                                                



                                                        
                                                                                                                   

                                                  
                                                                                                                                             

                                                                          
                                                         
                                          
                                                                                                                  
                                                                                                                        



         
                                                   
 
 
                          
                        
 



                            

                                               

                                                                                                 
                                                        

                                                            






                                                                                                            


                                                                                                            
                                                                                                      
                                                                                


                                                                                                            
                                                                             
                                                
                                                
                                                                                                                               
                                 
                                                       
                        
                                                       

                                                                        


                                                                         


                                                                                                            




                                           
                                                                   
                              
                                                        
                                                          
                                                  

                                                          


                                                            
                                                            
                                                                          
                                                          
                                                                                
                  
                                               
                                                                                                        
                                                            
                                                         
                                                               


                                                                  
                                                                                                                                       



         
                                              

 
                         
                                
 

                                               
                                         
                                                              
                                                  
                                                            
                                                            
                                                                            


                                                                                                            

                                                                               
                                           

                                                 
                                                                                          
                                                       
                        
                                                      
                 

                                                                                

                                         
                                         
                                                        
                                            
                  
                                                                                   
                                                                                

                                                                                      
                                                        

                                                                                                              
                                                     



                                                                                  
                                                                                                        



                                                                                 

                                                                                                            


                                                                           








                                                                                                            
                                                                   
                              








                                                                    
                                                            


                                                                          
                                                                                

                                                
                                                   



                                                                  
                                                                                                                     











                                                            
                                                 
                                                              


                                                            
                                                                            


                                                                                                            






                                                                                                                    





                                                        
                                                                                
                                                               


                                         
                                                        













                                                                                                            
                                                                                                                                                        







                                                                            
                                                                       
                                                                    



                                                                                    
                                                                                                                       

                                                                   












                                                    
                                                 
                                                              


                                                            
                                                                            


                                                                                                            






                                                                                                                    
                 




                                                        
                 
                                                                      


                                                    

                                                                              
                   
                                                
                                                                                                            


                                       
                                                        
                  
         
 

                                           
                                                                                                                                                                   








                                                                                                  
                                                                    


                                                                                    
                                                                                                                       

                                                          





                          
                                           

 

                            
 

                                               


                                                                
                                                                                
                                                                                                        
                                                                                 
                                                                                                   


                                                                                                   
                                                                            
                                           
                                                                                           
                                                                                                   
                         
                                                                   
                                                                              

                                         
                                                                             


                                                                 
                                                                         
                                                   
                                                                                                           

                                 
                 













                                                                
                                                            


                                                                            
                                                                                                               


                                                 
                                           




                                                                                 
                                                                         



                                                                                                                  
                                                                                                    
                        

                                                                                                                                                          





                                                    
                                                                                                          




                                                                                                                               
                                                     
         

                                                                                                                      










                                               


                                                                  
                                           
                                                                      
                        
                                              
                 
                                                            
                                                                                                                                


                                                                                             
                                              
                                                                                      










                                                                   



                                                                                          
                 
                                         
                                                       


                                                       
                                                                              

                                     
                                                                       

                                     
                                                                                                            


                                       
                                            
                  
 
                                           
                                                                                   

                 
         
 

                                           
                                                                                                                                  


         
<?php

/*
 * Wizard for setting up active directory integration for authentication.
 */

define('AD_SHORT_REGEX', '#^([^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+)[/\\\\]([^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+)$#');
define('AD_BOTH_REGEX', '#^[^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+[/\\\\@][^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+$#');
define('AD_AT_REGEX', '#^([^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+)@([^\[\]\:;\|\=\+\?\<\>\*"/\\\\,]+)$#');

class AdAuth_Start extends AddModule_Base
{

	protected function renderInternal()
	{
		$ADAUTH_COMMON_FIELDS = array('title', 'server', 'searchbase', 'binddn', 'bindpw', 'home', 'homeattr', 'ssl', 'genuid', 'certificate', 'mapping', 'nohomewarn');
		$data = array();
		if ($this->edit !== null) {
			moduleToArray($this->edit, $data, $ADAUTH_COMMON_FIELDS);
			$data['title'] = $this->edit->title();
			$data['edit'] = $this->edit->id();
		} else {
			$data['ssl'] = true;
		}
		postToArray($data, $ADAUTH_COMMON_FIELDS, true);
		$obdn = Request::post('originalbinddn');
		if (!empty($obdn)) {
			$data['binddn'] = $obdn;
		}
		if (isset($data['server']) && preg_match('/^(.*)\:(636|3269|389|3268)$/', $data['server'], $out)) {
			$data['server'] = $out[1];
		}
		if (isset($data['homeattr']) && !isset($data['mapping']['homemount']) && strtolower($data['homeattr']) !== 'homedirectory') {
			$data['mapping']['homemount'] = $data['homeattr'];
		}
		$data['step'] = 'AdAuth_CheckConnection';
		$data['map_empty'] = true;
		$data['mapping'] = ConfigModuleBaseLdap::getMapping($data['mapping'] ?? null, $data['map_empty']);
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-start', $data);
	}

}

class AdAuth_CheckConnection extends AddModule_Base
{

	private $scanTask;
	private $server;

	private $searchBase;

	private $bindDn;

	protected function preprocessInternal()
	{
		$this->bindDn = Ldap::normalizeDn(Request::post('binddn', '', 'string'));
		$this->searchBase = Ldap::normalizeDn(Request::post('searchbase', '', 'string'));
		$this->server = Request::post('server');
		$binddn = Request::post('binddn');
		$ssl = Request::post('ssl', 'off') === 'on';
		if (empty($this->server)) {
			Message::addError('main.parameter-empty', 'server');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		if (empty($binddn)) {
			Message::addError('main.parameter-empty', 'binddn');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		if ((preg_match(AD_AT_REGEX, $this->bindDn) > 0) && (strlen($this->searchBase) < 2)) {
			Message::addError('main.parameter-empty', 'searchBase');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		if (preg_match('/^([^\:]+)\:(\d+)$/', $this->server, $out)) {
			$ports = array($out[2]);
			$this->server = $out[1];
			// Test the default ports twice since the other one might not return all required data (home directory)
		} elseif ($ssl) {
			$ports = array(636, 3269, 636);
		} else {
			$ports = array(389, 3268, 389);
		}
		$this->scanTask = Taskmanager::submit('PortScan', array(
			'host' => $this->server,
			'ports' => $ports,
			'certificate' => Request::post('certificate', '')
		));
		if (!isset($this->scanTask['id'])) {
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
		}
	}

	protected function renderInternal()
	{
		$mapping = Request::post('mapping', null, 'array');
		$data = array(
			'edit' => Request::post('edit'),
			'title' => Request::post('title'),
			'server' => $this->server,
			'searchbase' => $this->searchBase,
			'binddn' => $this->bindDn,
			'bindpw' => Request::post('bindpw'),
			'home' => Request::post('home'),
			'ssl' => Request::post('ssl'),
			'genuid' => Request::post('genuid'),
			'certificate' => Request::post('certificate', ''),
			'taskid' => $this->scanTask['id'],
			'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
		);
		$data['prev'] = 'AdAuth_Start';
		if ((preg_match(AD_BOTH_REGEX, $this->bindDn) > 0) || (strlen($this->searchBase) < 2)) {
			$data['next'] = 'AdAuth_SelfSearch';
		} elseif (empty($mapping['homemount'])) {
			$data['next'] = 'AdAuth_HomeAttrCheck';
		} else {
			$data['next'] = 'AdAuth_CheckCredentials';
		}
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad_ldap-checkconnection', $data);
	}

}

class AdAuth_SelfSearch extends AddModule_Base
{

	private $taskIds;
	private $originalBindDn;

	protected function preprocessInternal()
	{
		$server = $binddn = null;
		$searchbase = Request::post('searchbase', '');
		$bindpw = Request::post('bindpw');
		$ssl = Request::post('ssl', 'off') === 'on';
		if ($ssl && !Request::post('fingerprint')) {
			Message::addError('main.error-read', 'fingerprint');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$server = Request::post('server', Request::REQUIRED, 'string');
		$binddn = Request::post('binddn', Request::REQUIRED, 'string');
		$this->originalBindDn = '';
		// Fix bindDN if short name given
		//
		if ($ssl) { // Use the specific AD ports so the domain\username bind works
			$uri = "ldaps://$server:3269/";
		} else {
			$uri = "ldap://$server:3268/";
		}

		$selfSearchBase = Ldap::getSelfSearchBase($binddn, $searchbase);
		// Set up selfSearch task
		$taskData = array(
			'server' => $uri,
			'searchbase' => $selfSearchBase,
			'bindpw' => $bindpw,
		);
		if (preg_match(AD_SHORT_REGEX, $binddn, $out) && !empty($out[2])) {
			$this->originalBindDn = str_replace('/', '\\', $binddn);
			$taskData['filter'] = 'sAMAccountName=' . $out[2];
		} elseif (preg_match(AD_AT_REGEX, $binddn, $out) && !empty($out[1])) {
			$this->originalBindDn = $binddn;
			$taskData['filter'] = 'userPrincipalName=' . $binddn;
		} elseif (preg_match('/^cn\=([^\=]+),.*?dc\=([^\=]+),/i', Ldap::normalizeDn($binddn), $out)) {
			if (empty($selfSearchBase)) {
				$this->originalBindDn = $out[2] . '\\' . $out[1];
				$taskData['filter'] = 'sAMAccountName=' . $out[1];
			} else {
				$this->originalBindDn = $binddn;
				$taskData['filter'] = 'distinguishedName=' . Ldap::normalizeDn($binddn);
			}
		} else {
			Message::addError('could-not-determine-binddn', $binddn);
			$this->originalBindDn = $binddn;
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$taskData['binddn'] = $this->originalBindDn;
		$selfSearch = Taskmanager::submit('LdapSearch', $taskData);
		if (!isset($selfSearch['id'])) {
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$this->taskIds['self-search'] = $selfSearch['id'];
	}

	protected function renderInternal()
	{
		$mapping = Request::post('mapping', null, 'array');
		$data = array(
			'edit' => Request::post('edit'),
			'title' => Request::post('title'),
			'server' => Request::post('server'),
			'port' => Request::post('port'),
			'searchbase' => Request::post('searchbase'),
			'binddn' => Request::post('binddn'),
			'bindpw' => Request::post('bindpw'),
			'home' => Request::post('home'),
			'ssl' => Request::post('ssl') === 'on',
			'genuid' => Request::post('genuid'),
			'fingerprint' => Request::post('fingerprint'),
			'certificate' => Request::post('certificate', ''),
			'originalbinddn' => $this->originalBindDn,
			'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
			'prev' => 'AdAuth_Start'
		);
		if (empty($mapping['homemount'])) {
			$data['next'] = 'AdAuth_HomeAttrCheck';
		} else {
			$data['next'] = 'AdAuth_CheckCredentials';
		}
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-selfsearch',
			array_merge($this->taskIds, $data));
	}

}

class AdAuth_HomeAttrCheck extends AddModule_Base
{

	private $taskIds;

	protected function preprocessInternal()
	{
		$server = $binddn = $port = null;
		$searchbase = Request::post('searchbase', '');
		$bindpw = Request::post('bindpw');
		$ssl = Request::post('ssl', 'off') === 'on';
		if ($ssl && !Request::post('fingerprint')) {
			Message::addError('main.error-read', 'fingerprint');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		foreach (['server', 'binddn', 'port'] as $var) {
			$$var = Request::post($var, null);
			if (empty($$var)) {
				Message::addError('main.parameter-empty', $var);
				AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
				return;
			}
		}
		if ($ssl) {
			$uri = "ldaps://$server:$port/";
		} else {
			$uri = "ldap://$server:$port/";
		}
		$selfSearchBase = Ldap::getSelfSearchBase($binddn, $searchbase);
		preg_match('#^(\w+\=[^\=]+),#', $binddn, $out);
		$filter = $out[1];
		$data = array(
			'server' => $uri,
			'searchbase' => $selfSearchBase,
			'binddn' => $binddn,
			'bindpw' => $bindpw,
			'filter' => $filter
		);
		$selfSearch = Taskmanager::submit('LdapSearch', $data);
		if (!isset($selfSearch['id'])) {
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$this->taskIds['self-search'] = $selfSearch['id'];
	}

	protected function renderInternal()
	{
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-selfsearch', array_merge($this->taskIds, array(
				'edit' => Request::post('edit'),
				'title' => Request::post('title'),
				'server' => Request::post('server'),
				'port' => Request::post('port'),
				'searchbase' => Request::post('searchbase'),
				'binddn' => Request::post('binddn'),
				'bindpw' => Request::post('bindpw'),
				'home' => Request::post('home'),
				'ssl' => Request::post('ssl') === 'on',
				'genuid' => Request::post('genuid'),
				'fingerprint' => Request::post('fingerprint'),
				'certificate' => Request::post('certificate', ''),
				'originalbinddn' => Request::post('originalbinddn'),
				'tryHomeAttr' => true,
				'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
				'prev' => 'AdAuth_Start',
				'next' => 'AdAuth_CheckCredentials'
			))
		);
	}

}

class AdAuth_CheckCredentials extends AddModule_Base
{

	private $taskIds;

	protected function preprocessInternal()
	{
		$server = $binddn = $port = null;
		$searchbase = Request::post('searchbase', '');
		$bindpw = Request::post('bindpw');
		$ssl = Request::post('ssl', 'off') === 'on';
		if ($ssl && !Request::post('fingerprint')) {
			Message::addError('main.error-read', 'fingerprint');
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		foreach (['server', 'binddn', 'port'] as $var) {
			$$var = Request::post($var, null);
			if (empty($$var)) {
				Message::addError('main.parameter-empty', $var);
				AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
				return;
			}
		}
		// Test query 4 users
		if ($ssl) {
			$uri = "ldaps://$server:$port/";
		} else {
			$uri = "ldap://$server:$port/";
		}
		$ldapSearch = Taskmanager::submit('LdapSearch', array(
			'server' => $uri,
			'searchbase' => $searchbase,
			'binddn' => $binddn,
			'bindpw' => $bindpw,
			'mapping' => Request::post('mapping', false, 'array'),
		));
		if (!isset($ldapSearch['id'])) {
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$this->taskIds = array(
			'tm-search' => $ldapSearch['id']
		);
	}

	protected function renderInternal()
	{
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad_ldap-checkcredentials', array_merge($this->taskIds, array(
				'edit' => Request::post('edit'),
				'title' => Request::post('title'),
				'server' => Request::post('server') . ':' . Request::post('port'),
				'searchbase' => Request::post('searchbase'),
				'binddn' => Request::post('binddn'),
				'bindpw' => Request::post('bindpw'),
				'home' => Request::post('home'),
				'homeattr' => Request::post('homeattr'),
				'ssl' => Request::post('ssl') === 'on',
				'genuid' => Request::post('genuid'),
				'fingerprint' => Request::post('fingerprint'),
				'certificate' => Request::post('certificate', ''),
				'originalbinddn' => Request::post('originalbinddn'),
				'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
				'prev' => 'AdAuth_Start',
				'next' => 'AdAuth_HomeDir'
			))
		);
	}

}

class AdAuth_HomeDir extends AddModule_Base
{

	private $searchbase;
	private $binddn;

	protected function preprocessInternal()
	{
		$this->binddn = Request::post('binddn');
		$this->searchbase = Request::post('searchbase');
		if (empty($this->searchbase)) {
			// If no search base was given, determine it from the dn
			$originalBindDn = str_replace('\\', '/', trim(Request::post('originalbinddn')));
			if (!preg_match(AD_SHORT_REGEX, $originalBindDn, $out)) {
				Message::addError('main.value-invalid', 'binddn', $originalBindDn);
				Util::redirect('?do=SysConfig&action=addmodule&step=AdAuth_Start');
			} // $out[1] is the domain
			// Find the domain in the dn
			$i = mb_stripos($this->binddn, '=' . $out[1] . ',');
			if ($i === false) {
				Message::addError('main.value-invalid', 'binddn', $out[1]);
				Util::redirect('?do=SysConfig&action=addmodule&step=AdAuth_Start');
			}
			// Now find ',' before it so we get the key
			$i = mb_strrpos(mb_substr($this->binddn, 0, $i), ',');
			if ($i === false)
				$i = -1;
			$this->searchbase = mb_substr($this->binddn, $i + 1);
		} else {
			$somedn = Request::post('somedn', false);
			if (!empty($somedn)) {
				$i = stripos($somedn, $this->searchbase);
				if ($i !== false) {
					$this->searchbase = substr($somedn, $i, strlen($this->searchbase));
				}
			}
		}
	}

	protected function renderInternal()
	{
		$data = array(
			'edit' => Request::post('edit'),
			'title' => Request::post('title'),
			'server' => Request::post('server'),
			'searchbase' => $this->searchbase,
			'binddn' => $this->binddn,
			'bindpw' => Request::post('bindpw'),
			'home' => Request::post('home'),
			'homeattr' => Request::post('homeattr'),
			'ssl' => Request::post('ssl') === 'on',
			'genuid' => Request::post('genuid'),
			'fingerprint' => Request::post('fingerprint'),
			'certificate' => Request::post('certificate', ''),
			'originalbinddn' => Request::post('originalbinddn'),
			'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
			'prev' => 'AdAuth_Start',
			'next' => 'AdAuth_Finish'
		);
		if ($this->edit !== null) {
			foreach (self::getAttributes() as $key) {
				if ($this->edit->getData($key)) {
					$data[$key . '_c'] = 'checked="checked"';
				}
			}
			$letter = $this->edit->getData('shareHomeDrive');
			$data['shareRemapMode_' . $this->edit->getData('shareRemapMode')] = 'selected="selected"';
			foreach (['shareDomain', 'shareHomeMountOpts', 'ldapAttrMountOpts'] as $key) {
				$data[$key] = $this->edit->getData($key);
			}
			$data['nohomewarn_' . (int)$this->edit->getData('nohomewarn')] = 'selected';
		} else {
			$data['shareDownloads_c'] = $data['shareMedia_c'] = $data['shareDocuments_c'] = $data['shareRemapCreate_c'] = 'checked="checked"';
			$data['shareRemapMode_1'] = 'selected="selected"';
			$letter = 'H:';
		}
		$data['drives'] = array();
		foreach (range('D', 'Z') as $l) {
			$data['drives'][] = array(
				'drive' => $l . ':',
				'selected' => (strtoupper($letter[0]) === $l) ? 'selected="selected"' : ''
			);
		}
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad_ldap-homedir', $data);
	}

	public static function getAttributes(): array
	{
		return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop',
			'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
	}

}

class AdAuth_Finish extends AddModule_Base
{

	private $taskIds;

	protected function preprocessInternal()
	{
		$title = Request::post('title');
		if (empty($title))
			$title = 'AD: ' . Request::post('server');
		if ($this->edit === null) {
			$module = ConfigModule::getInstance('AdAuth');
		} else {
			$module = $this->edit;
		}
		$ssl = Request::post('ssl', 'off') === 'on';
		foreach (['searchbase', 'binddn', 'server', 'bindpw', 'home', 'nohomewarn', 'homeattr', 'certificate', 'genuid',
					'ldapAttrMountOpts', 'shareHomeMountOpts'] as $key) {
			$module->setData($key, Request::post($key, '', 'string'));
		}
		$module->setData('ssl', $ssl);
		$module->setData('mapping', Request::post('mapping', false, 'array'));
		foreach (AdAuth_HomeDir::getAttributes() as $key) {
			$value = Request::post($key);
			if (is_numeric($value)) {
				settype($value, 'integer');
			} elseif ($value === 'on') {
				$value = 1;
			} elseif ($value === false) {
				$value = 0;
			}
			$module->setData($key, $value);
		}
		if ($ssl) {
			$module->setData('fingerprint', Request::post('fingerprint', ''));
		} else {
			$module->setData('fingerprint', '');
		}
		if ($this->edit !== null)
			$ret = $module->update($title);
		else
			$ret = $module->insert($title);
		if (!$ret) {
			Message::addError('main.value-invalid', 'any', 'any');
			$tgz = false;
		} else {
			$tgz = $module->generate($this->edit === null);
		}
		if ($tgz === false) {
			AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
			return;
		}
		$this->taskIds = array(
			'tm-config' => $tgz,
		);

		if ($this->edit === null) {
			AddModule_Base::setStep('AddModule_Assign', $module->id());
		}

	}

	protected function renderInternal()
	{
		Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-finish', $this->taskIds);
	}

}