diff --git a/index.php b/index.php
index f7e479c53e..03b8075b5c 100755
--- a/index.php
+++ b/index.php
@@ -17,15 +17,6 @@
exit;
}
- $GLOBALS['sessionid'] = isset($_GET['sessionid']) ? $_GET['sessionid'] : @$_COOKIE['sessionid'];
- if(!$GLOBALS['sessionid'])
- {
- Header('Location: login.php'.
- (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']) ?
- '?phpgw_forward='.urlencode('/index.php?'.$_SERVER['QUERY_STRING']):''));
- exit;
- }
-
if(isset($_GET['hasupdates']) && $_GET['hasupdates'] == 'yes')
{
$hasupdates = True;
diff --git a/phpgwapi/inc/class.auth.inc.php b/phpgwapi/inc/class.auth.inc.php
index b68d05f60a..03e62a2ff1 100644
--- a/phpgwapi/inc/class.auth.inc.php
+++ b/phpgwapi/inc/class.auth.inc.php
@@ -11,10 +11,17 @@
* @version $Id$
*/
+// allow to set an application depending authentication type (eg. for syncml, groupdav, ...)
+if (isset($GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']]) &&
+ $GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']])
+{
+ $GLOBALS['egw_info']['server']['auth_type'] = $GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']];
+}
if(empty($GLOBALS['egw_info']['server']['auth_type']))
{
$GLOBALS['egw_info']['server']['auth_type'] = 'sql';
}
+//error_log('using auth_type='.$GLOBALS['egw_info']['server']['auth_type'].', currentapp='.$GLOBALS['egw_info']['flags']['currentapp']);
include(EGW_API_INC.'/class.auth_'.$GLOBALS['egw_info']['server']['auth_type'].'.inc.php');
/**
diff --git a/phpgwapi/inc/class.egw.inc.php b/phpgwapi/inc/class.egw.inc.php
index 42d0dd7119..a4b5fc0976 100644
--- a/phpgwapi/inc/class.egw.inc.php
+++ b/phpgwapi/inc/class.egw.inc.php
@@ -131,7 +131,6 @@ class egw extends egw_minimal
// setup the other subclasses
$this->translation = new translation();
$this->common = new common();
- $this->auth = new auth();
$this->accounts = accounts::getInstance();
$this->acl = new acl();
/* Do not create the session object if called by the sessions class. This way
@@ -277,7 +276,9 @@ class egw extends egw_minimal
}
// this removes the sessiondata if its saved in the URL
$query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']);
- Header('Location: '.$GLOBALS['egw_info']['server']['webserver_url'].'/login.php?cd=10&phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : '')));
+ $redirect = '/login.php?cd=10&';
+ if ($GLOBALS['egw_info']['server']['http_auth_types']) $redirect = '/phpgwapi/ntlm/index.php?';
+ Header('Location: '.$GLOBALS['egw_info']['server']['webserver_url'].$redirect.'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : '')));
exit;
}
}
diff --git a/phpgwapi/inc/class.sessions.inc.php b/phpgwapi/inc/class.sessions.inc.php
index 54cd1bfa93..053cf04d0a 100644
--- a/phpgwapi/inc/class.sessions.inc.php
+++ b/phpgwapi/inc/class.sessions.inc.php
@@ -560,9 +560,10 @@
* @param string $passwd user password
* @param string $passwd_type type of password being used, ie plaintext, md5, sha1
* @param boolean $no_session_needed=false dont create a real session, eg. for GroupDAV clients using only basic auth, no cookie support
+ * @param boolean $auth_check=true if false, the user is loged in without checking his password (eg. for single sign on), default = true
* @return string session id
*/
- function create($login,$passwd = '',$passwd_type = '',$no_session=false)
+ function create($login,$passwd = '',$passwd_type = '',$no_session=false,$auth_check=true)
{
if (is_array($login))
{
@@ -577,6 +578,7 @@
$this->passwd = $passwd;
$this->passwd_type = $passwd_type;
}
+ //error_log(__METHOD__."($this->login,$this->passwd,$this->passwd_type,$no_session,$auth_check)");
$this->clean_sessions();
$this->split_login_domain($login,$this->account_lid,$this->account_domain);
@@ -618,7 +620,7 @@
if (($blocked = $this->login_blocked($login,$user_ip)) || // too many unsuccessful attempts
$GLOBALS['egw_info']['server']['global_denied_users'][$this->account_lid] ||
- !$GLOBALS['egw']->auth->authenticate($this->account_lid, $this->passwd, $this->passwd_type) ||
+ $auth_check && !$GLOBALS['egw']->auth->authenticate($this->account_lid, $this->passwd, $this->passwd_type) ||
$this->account_id && $GLOBALS['egw']->accounts->get_type($this->account_id) == 'g')
{
$this->reason = $blocked ? 'blocked, too many attempts' : 'bad login or password';
diff --git a/phpgwapi/inc/horde/Horde/SyncML/State_egw.php b/phpgwapi/inc/horde/Horde/SyncML/State_egw.php
index 63c50bf5d0..8ddeedb1fd 100644
--- a/phpgwapi/inc/horde/Horde/SyncML/State_egw.php
+++ b/phpgwapi/inc/horde/Horde/SyncML/State_egw.php
@@ -244,51 +244,57 @@ class EGW_SyncML_State extends Horde_SyncML_State
}
- function isAuthorized()
- {
- if (!$this->_isAuthorized) {
-
- if(!isset($this->_locName) && !isset($this->_password))
+ function isAuthorized()
+ {
+ if (!$this->_isAuthorized)
{
- Horde::logMessage('SyncML: Authentication not yet possible currently. Username and password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return FALSE;
- }
-
- if(!isset($this->_password))
- {
- Horde::logMessage('SyncML: Authentication not yet possible currently. Password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return FALSE;
- }
-
- if(strpos($this->_locName,'@') === False)
- {
- $this->_locName .= '@'.$GLOBALS['egw_info']['server']['default_domain'];
- }
-
- #Horde::logMessage('SyncML: authenticate with username: ' . $this->_locName . ' and password: ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- if($GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($this->_locName,$this->_password,'text'))
- {
- $this->_isAuthorized = true;
- Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ if(!isset($this->_locName) && !isset($this->_password))
+ {
+ Horde::logMessage('SyncML: Authentication not yet possible currently. Username and password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ return FALSE;
+ }
+
+ if(!isset($this->_password))
+ {
+ Horde::logMessage('SyncML: Authentication not yet possible currently. Password not available' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ return FALSE;
+ }
+
+ if(strpos($this->_locName,'@') === False)
+ {
+ $this->_locName .= '@'.$GLOBALS['egw_info']['server']['default_domain'];
+ }
+
+ #Horde::logMessage('SyncML: authenticate with username: ' . $this->_locName . ' and password: ' . $this->_password, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+ if($GLOBALS['sessionid'] = $GLOBALS['egw']->session->create($this->_locName,$this->_password,'text'))
+ {
+ $this->_isAuthorized = true;
+ Horde::logMessage('SyncML_EGW: Authentication of ' . $this->_locName . '/' . $GLOBALS['sessionid'] . ' succeded' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ }
+ else
+ {
+ $this->_isAuthorized = false;
+ Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_INFO);
+ }
}
+ /*
+ * RalfBecker 2008-07-16: commented out, as return value is NOT used anyway
+ * It is not a security problem, as without a valid SyncML session
+ * one is created anyway. The horde SyncML codes handles that on it's own.
+ * Leaving it in gives problems with NTLM auth, as verify redirects there.
+ *
else
{
- $this->_isAuthorized = false;
- Horde::logMessage('SyncML: Authentication of ' . $this->_locName . ' failed' , __FILE__, __LINE__, PEAR_LOG_INFO);
- }
- }
- else
- {
- // store sessionID in a variable, because ->verify maybe resets that value
- $sessionID = session_id();
- if(!$GLOBALS['egw']->session->verify($sessionID, 'staticsyncmlkp3')) {
- Horde::logMessage('SyncML_EGW: egw session(' .$sessionID. ') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
- }
- }
+ // store sessionID in a variable, because ->verify maybe resets that value
+ $sessionID = session_id();
+ if(!$GLOBALS['egw']->session->verify($sessionID, 'staticsyncmlkp3')) {
+ Horde::logMessage('SyncML_EGW: egw session(' .$sessionID. ') not verified ' , __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ }
+ }*/
- return $this->_isAuthorized;
- }
+ return $this->_isAuthorized;
+ }
/**
* Removes all locid<->guid mappings for the given type.
diff --git a/phpgwapi/ntlm/README b/phpgwapi/ntlm/README
new file mode 100644
index 0000000000..4e304f04e9
--- /dev/null
+++ b/phpgwapi/ntlm/README
@@ -0,0 +1,40 @@
+Steps to set up NTLM Single Sign On for eGroupWare 1.6
+======================================================
+(Version: $Id$)
+
+NTLM SSO removes Windows users on a PC, which is a member of a Windows domain
+and who are logged into that domain, from the need to explicitly log into eGW.
+They simply point IE to the eGW URL (eg. http://domain.com/egroupware/) and
+start working. They can of cause explicitly log out and log in as an other user.
+
+As far as I tested, Firefox 3 only allows to enter user (including domain(!), eg. DOMAIN\user)
+and password in a popup, which then get's checked from apache via winbind.
+It does NOT automatically log you in, if you're logged into the domain on your PC!
+
+Here's in short what you need:
+-----------------------------
+1. eGW 1.6 running on Apache
+2. a fully working and configured winbind configuration (not described here)
+3. mod_ntlm_winbind (eg. for openSUSE from their package apache2-mod_auth_ntml_winbind)
+4. an Apache configuration with the egroupware.conf in this directory (expecting eGW
+ to be installed in it's default location /usr/share/egroupware) or port the necessary
+ settings to your Apache configuration.
+ --> You NEED to change the domain from "TEST" to your used domain name!
+5. Make the following changes in eGW's setup >> configuraition:
+ - HTTP auth types (comma-separated) to use without login-page, eg. "NTLM": NTLM
+ - Select which type of authentication you are using: ADS
+ This is not needed for NTLM authentication, but allows the users to use their windows
+ user and password to log into eGW, if they log in using an other browser or location.
+ - Host/IP Domain controler: ... <-- NEED to be filled out
+ - Domain name: ... <-- NEED to be filled out, same domain name as above
+6. If you use EMail, you have to explicitly specify user/pw to use for contacting the IMAP
+ (and SMTP) server, it's no longer available to eGW!
+
+Please note the DC has to be started before you start winbind!
+
+The eGW code should work with every Apache authentication, which sets REMOTE_USER and AUTH_TYPE.
+With slight modifications (different var names) it should work eg. with SSL client certificates.
+
+This feature was sponsored by Sponsored by Carl Knauber Holding GmbH und Co. KG.
+
+Ralf Becker
\ No newline at end of file
diff --git a/phpgwapi/ntlm/egroupware.conf b/phpgwapi/ntlm/egroupware.conf
new file mode 100644
index 0000000000..f9d3a20444
--- /dev/null
+++ b/phpgwapi/ntlm/egroupware.conf
@@ -0,0 +1,58 @@
+#
+# Apache and PHP configuration for eGroupWare using NTLM authentication
+#
+# Version: $Id$
+#
+
+Alias /egroupware /usr/share/egroupware
+
+
+ AuthName "NTLM eGroupWare Authentication"
+ NTLMAuth on
+ NegotiateAuth off
+ NTLMBasicRealm TEST
+ NTLMBasicAuth on
+ NTLMAuthHelper "/usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp"
+ NegotiateAuthHelper "/usr/bin/ntlm_auth --helper-protocol=gss-spnego"
+ PlaintextAuthHelper "/usr/bin/ntlm_auth --domain=TEST.LOCAL --helper-protocol=squid-2.5-basic"
+ NTLMBasicAuthoritative on
+ AuthType NTLM
+ require valid-user
+
+
+
+ Options FollowSymLinks ExecCGI
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+ DirectoryIndex index.html index.php
+ AddHandler cgi-script .cgi
+ AddDefaultCharset Off
+ php_flag file_uploads on
+ php_flag log_errors on
+ php_flag magic_quotes_gpc off
+ php_flag magic_quotes_runtime off
+ php_flag register_globals off
+ php_flag track_vars on
+ php_value error_reporting E_ALL
+ php_value max_execution_time 90
+ php_value mbstring.func_overload 7
+ php_value memory_limit 48M
+ php_value session.gc_maxlifetime 14400
+ php_value open_basedir /usr/share/egroupware:/var/lib/egroupware:/tmp:/var/lib/php5
+ php_value upload_max_filesize 16M
+
+ Order allow,deny
+ Deny from all
+
+
+
+
+ php_value open_basedir /
+
+
+
+ php_value mbstring.func_overload 0
+ Order allow,deny
+ Allow from all
+
diff --git a/phpgwapi/ntlm/index.php b/phpgwapi/ntlm/index.php
new file mode 100644
index 0000000000..27370a4aa6
--- /dev/null
+++ b/phpgwapi/ntlm/index.php
@@ -0,0 +1,61 @@
+
+ * @copyright (c) 2008 by Ralf Becker
+ * @version $Id$
+ */
+
+/**
+ * check if the given user has access
+ *
+ * Create a session or if the user has no account return authenticate header and 401 Unauthorized
+ *
+ * @param array &$account
+ * @return int session-id
+ */
+function check_access(&$account)
+{
+ //error_log("AUTH_TYPE={$_SERVER['AUTH_TYPE']}, REMOTE_USER={$_SERVER['REMOTE_USER']}, HTTP_USER_AGENT={$_SERVER['HTTP_USER_AGENT']}, http_auth_types={$GLOBALS['egw_info']['server']['http_auth_types']}");
+
+ if (isset($_SERVER['REMOTE_USER']) && $_SERVER['REMOTE_USER'] && isset($_SERVER['AUTH_TYPE']) &&
+ isset($GLOBALS['egw_info']['server']['http_auth_types']) && $GLOBALS['egw_info']['server']['http_auth_types'] &&
+ in_array(strtoupper($_SERVER['AUTH_TYPE']),explode(',',strtoupper($GLOBALS['egw_info']['server']['http_auth_types']))))
+ {
+ if (strpos($account=$_SERVER['REMOTE_USER'],'\\') !== false)
+ {
+ list(,$account) = explode('\\',$account,2);
+ }
+ $sessionid = $GLOBALS['egw']->session->create($account,null,'ntlm',false,false); // false=no auth check
+ //error_log("create('$account',null,'ntlm',false,false)=$sessionid ({$GLOBALS['egw']->session->reason})");
+ }
+ if (!$sessionid)
+ {
+ header('Location: ../../login.php'.(isset($_REQUEST['phpgw_forward']) ? '?'.$_REQUEST['phpgw_forward'] : ''));
+ exit;
+ }
+ return $sessionid;
+}
+
+$GLOBALS['egw_info']['flags'] = array(
+ 'noheader' => True,
+ 'currentapp' => 'home',
+ 'autocreate_session_callback' => 'check_access',
+);
+// if you move this file somewhere else, you need to adapt the path to the header!
+include(dirname(__FILE__).'/../../header.inc.php');
+
+if ($_REQUEST['phpgw_forward'])
+{
+ $forward = '../../'.(isset($_GET['phpgw_forward']) ? urldecode($_GET['phpgw_forward']) : @$_POST['phpgw_forward']);
+}
+else
+{
+ $forward = '../../index.php';
+}
+header('Location: '.$forward);
\ No newline at end of file
diff --git a/rpc.php b/rpc.php
index 52ec9a5181..39ebf340dd 100644
--- a/rpc.php
+++ b/rpc.php
@@ -24,6 +24,9 @@ $GLOBALS['egw_info'] = array(
);
include('./header.inc.php');
+// allow to use an authentication specific for SyncML
+$GLOBALS['egw_info']['flags']['currentapp'] = 'syncml';
+
$errors = array();
// SyncML works currently only with PHP sessions
diff --git a/setup/templates/default/config.tpl b/setup/templates/default/config.tpl
index 70c86c28d9..fc113af715 100644
--- a/setup/templates/default/config.tpl
+++ b/setup/templates/default/config.tpl
@@ -175,7 +175,7 @@