-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide imap auth interface for plugins #9418
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,13 @@ class rcube | |
|
||
public const DEBUG_LINE_LENGTH = 4096; | ||
|
||
// Error codes | ||
public const ERROR_STORAGE = -2; | ||
public const ERROR_INVALID_REQUEST = 1; | ||
public const ERROR_INVALID_HOST = 2; | ||
public const ERROR_COOKIES_DISABLED = 3; | ||
public const ERROR_RATE_LIMIT = 4; | ||
|
||
/** @var rcube_config Stores instance of rcube_config */ | ||
public $config; | ||
|
||
|
@@ -1862,6 +1869,93 @@ public function deliver_message($message, $from, $mailto, &$error, | |
|
||
return $sent; | ||
} | ||
|
||
/** | ||
* Helper method to establish connection to an IMAP backend. | ||
* | ||
* @param rcube_storage $imap IMAP storage handler | ||
* @param string $host IMAP host | ||
* @param string $username IMAP username | ||
* @param string $password IMAP password | ||
* @param int $port IMAP port to connect to | ||
* @param string $ssl SSL schema or false if plain connection | ||
* @param array $imap_options Additional IMAP options | ||
* @param bool $just_connect Breaks after successful connect | ||
* | ||
* @return rcube_user|int|null Return user object on success, null or error code on failure | ||
*/ | ||
public function storage_connect($imap, $host, $username, $password, $port, $ssl, $imap_options = [], $just_connect = false) | ||
{ | ||
// user already registered -> overwrite username | ||
if ($user = rcube_user::query($username, $host)) { | ||
$username = $user->data['username']; | ||
|
||
// Brute-force prevention | ||
if ($user->is_locked()) { | ||
return self::ERROR_RATE_LIMIT; | ||
} | ||
} | ||
|
||
// enable proxy authentication | ||
if (!empty($imap_options)) { | ||
$imap->set_options($imap_options); | ||
} | ||
|
||
// try to log in | ||
if (!$imap->connect($host, $username, $password, $port, $ssl)) { | ||
if ($user) { | ||
$user->failed_login(); | ||
} | ||
|
||
// Wait a second to slow down brute-force attacks (#1490549) | ||
sleep(1); | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to never return null from this method. I.e. return error code or object, here it could be ERROR_STORAGE. That would mean we probably need other codes to cover the cases below. I'm not sure what to do with |
||
} | ||
|
||
// Only set user if just wanting to connect. | ||
// Note that for other scenarios user will also be set after successful login. | ||
if (!$just_connect) { | ||
// user already registered -> update user's record | ||
if (is_object($user)) { | ||
// update last login timestamp | ||
$user->touch(); | ||
} | ||
// create new system user | ||
elseif ($this->config->get('auto_create_user')) { | ||
// Temporarily set user email and password, so plugins can use it | ||
// this way until we set it in session later. This is required e.g. | ||
// by the user-specific LDAP operations from new_user_identity plugin. | ||
$domain = $this->config->mail_domain($host); | ||
$this->user_email = strpos($username, '@') ? $username : sprintf('%s@%s', $username, $domain); | ||
$this->password = $password; | ||
|
||
$user = rcube_user::create($username, $host); | ||
|
||
$this->user_email = null; | ||
$this->password = null; | ||
|
||
if (!$user) { | ||
self::raise_error([ | ||
'code' => 620, | ||
'message' => 'Failed to create a user record. Maybe aborted by a plugin?', | ||
], true, false); | ||
} | ||
} else { | ||
self::raise_error([ | ||
'code' => 621, | ||
'message' => "Access denied for new user {$username}. 'auto_create_user' is disabled", | ||
], true, false); | ||
} | ||
} | ||
|
||
if (is_object($user) && $user->ID) { | ||
// Configure environment | ||
$this->set_user($user); | ||
$this->set_storage_prop(); | ||
} | ||
|
||
return $user; | ||
} | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to not have the
$imap
argument. We can callget_storage()
in here. Then probably$imap_options
should be gone too. BTW, you miss$imap_options
in thestorage_connect()
call.