You've already forked Mailu
mirror of
https://github.com/Mailu/Mailu.git
synced 2025-11-23 22:04:47 +02:00
Make rainloop use internal auth
This commit is contained in:
@@ -7,7 +7,6 @@ import ipaddress
|
|||||||
import socket
|
import socket
|
||||||
import tenacity
|
import tenacity
|
||||||
|
|
||||||
|
|
||||||
SUPPORTED_AUTH_METHODS = ["none", "plain"]
|
SUPPORTED_AUTH_METHODS = ["none", "plain"]
|
||||||
|
|
||||||
|
|
||||||
@@ -49,11 +48,19 @@ def handle_authentication(headers):
|
|||||||
user = models.User.query.get(user_email)
|
user = models.User.query.get(user_email)
|
||||||
status = False
|
status = False
|
||||||
if user:
|
if user:
|
||||||
for token in user.tokens:
|
# webmails
|
||||||
if (token.check_password(password) and
|
if len(password) == 64 and ip == app.config['WEBMAIL_ADDRESS']:
|
||||||
(not token.ip or token.ip == ip)):
|
if user.verify_temp_token(password):
|
||||||
status = True
|
status = True
|
||||||
if user.check_password(password):
|
|
||||||
|
# All tokens are 32 characters hex lowercase
|
||||||
|
if len(password) == 32:
|
||||||
|
for token in user.tokens:
|
||||||
|
if (token.check_password(password) and
|
||||||
|
(not token.ip or token.ip == ip)):
|
||||||
|
status = True
|
||||||
|
break
|
||||||
|
if not status and user.check_password(password):
|
||||||
status = True
|
status = True
|
||||||
if status:
|
if status:
|
||||||
if protocol == "imap" and not user.enable_imap:
|
if protocol == "imap" and not user.enable_imap:
|
||||||
|
|||||||
@@ -43,6 +43,18 @@ def admin_authentication():
|
|||||||
return ""
|
return ""
|
||||||
return flask.abort(403)
|
return flask.abort(403)
|
||||||
|
|
||||||
|
@internal.route("/auth/user")
|
||||||
|
def user_authentication():
|
||||||
|
""" Fails if the user is not authenticated.
|
||||||
|
"""
|
||||||
|
if (not flask_login.current_user.is_anonymous
|
||||||
|
and flask_login.current_user.enabled):
|
||||||
|
response = flask.Response()
|
||||||
|
response.headers["X-User"] = flask_login.current_user.get_id()
|
||||||
|
response.headers["X-User-Token"] = models.User.get_temp_token(flask_login.current_user.get_id())
|
||||||
|
return response
|
||||||
|
return flask.abort(403)
|
||||||
|
|
||||||
|
|
||||||
@internal.route("/auth/basic")
|
@internal.route("/auth/basic")
|
||||||
def basic_authentication():
|
def basic_authentication():
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import re
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
import hmac
|
||||||
import smtplib
|
import smtplib
|
||||||
import idna
|
import idna
|
||||||
import dns
|
import dns
|
||||||
@@ -425,6 +426,15 @@ class User(Base, Email):
|
|||||||
user = cls.query.get(email)
|
user = cls.query.get(email)
|
||||||
return user if (user and user.enabled and user.check_password(password)) else None
|
return user if (user and user.enabled and user.check_password(password)) else None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_temp_token(cls, email):
|
||||||
|
user = cls.query.get(email)
|
||||||
|
return hmac.new(bytearray(app.secret_key,'utf-8'), bytearray("{}|{}".format(datetime.utcnow().strftime("%Y%m%d"), email), 'utf-8'), 'sha256').hexdigest() if (user and user.enabled) else None
|
||||||
|
|
||||||
|
def verify_temp_token(self, token):
|
||||||
|
return hmac.compare_digest(b''.fromhex(self.get_temp_token(self.email)), b''.fromhex(token))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Alias(Base, Email):
|
class Alias(Base, Email):
|
||||||
""" An alias is an email address that redirects to some destination.
|
""" An alias is an email address that redirects to some destination.
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ def announcement():
|
|||||||
flask.flash('Your announcement was sent', 'success')
|
flask.flash('Your announcement was sent', 'success')
|
||||||
return flask.render_template('announcement.html', form=form)
|
return flask.render_template('announcement.html', form=form)
|
||||||
|
|
||||||
|
@ui.route('/webmail', methods=['GET'])
|
||||||
|
def webmail():
|
||||||
|
return flask.redirect(app.config['WEB_WEBMAIL'])
|
||||||
|
|
||||||
@ui.route('/client', methods=['GET'])
|
@ui.route('/client', methods=['GET'])
|
||||||
def client():
|
def client():
|
||||||
|
|||||||
@@ -133,7 +133,27 @@ http {
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
include /etc/nginx/proxy.conf;
|
include /etc/nginx/proxy.conf;
|
||||||
client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
|
client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
|
||||||
|
auth_request /internal/auth/user;
|
||||||
proxy_pass http://$webmail;
|
proxy_pass http://$webmail;
|
||||||
|
error_page 403 @webmail_login;
|
||||||
|
}
|
||||||
|
location {{ WEB_WEBMAIL }}/sso.php {
|
||||||
|
{% if WEB_WEBMAIL != '/' %}
|
||||||
|
rewrite ^({{ WEB_WEBMAIL }})$ $1/ permanent;
|
||||||
|
rewrite ^{{ WEB_WEBMAIL }}/(.*) /$1 break;
|
||||||
|
{% endif %}
|
||||||
|
include /etc/nginx/proxy.conf;
|
||||||
|
client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
|
||||||
|
auth_request /internal/auth/user;
|
||||||
|
auth_request_set $user $upstream_http_x_user;
|
||||||
|
auth_request_set $token $upstream_http_x_user_token;
|
||||||
|
proxy_set_header X-Remote-User $user;
|
||||||
|
proxy_set_header X-Remote-User-Token $token;
|
||||||
|
proxy_pass http://$webmail;
|
||||||
|
error_page 403 @webmail_login;
|
||||||
|
}
|
||||||
|
location @webmail_login {
|
||||||
|
return 302 {{ WEB_ADMIN }}/ui/login?next=ui.webmail;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ RUN apt-get update && apt-get install -y \
|
|||||||
&& rm -rf /var/lib/apt/lists
|
&& rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
COPY include.php /var/www/html/include.php
|
COPY include.php /var/www/html/include.php
|
||||||
|
COPY sso.php /var/www/html/sso.php
|
||||||
COPY php.ini /php.ini
|
COPY php.ini /php.ini
|
||||||
|
|
||||||
COPY application.ini /application.ini
|
COPY application.ini /application.ini
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ attachment_size_limit = {{ MAX_FILESIZE }}
|
|||||||
allow_admin_panel = Off
|
allow_admin_panel = Off
|
||||||
|
|
||||||
[labs]
|
[labs]
|
||||||
|
custom_login_link='sso.php'
|
||||||
|
custom_logout_link='{{ WEB_ADMIN }}/ui/logout'
|
||||||
allow_gravatar = Off
|
allow_gravatar = Off
|
||||||
|
|
||||||
[contacts]
|
[contacts]
|
||||||
|
|||||||
31
webmails/rainloop/sso.php
Normal file
31
webmails/rainloop/sso.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$_ENV['RAINLOOP_INCLUDE_AS_API'] = true;
|
||||||
|
if (!defined('APP_VERSION')) {
|
||||||
|
$version = file_get_contents('/data/VERSION');
|
||||||
|
if ($version) {
|
||||||
|
define('APP_VERSION', $version);
|
||||||
|
define('APP_INDEX_ROOT_FILE', __FILE__);
|
||||||
|
define('APP_INDEX_ROOT_PATH', str_replace('\\', '/', rtrim(dirname(__FILE__), '\\/').'/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php')) {
|
||||||
|
include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php';
|
||||||
|
} else {
|
||||||
|
echo '[105] Missing version directory';
|
||||||
|
exit(105);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve email and password
|
||||||
|
if (in_array('HTTP_X_REMOTE_USER', $_SERVER) && in_array('HTTP_X_REMOTE_USER_TOKEN', $_SERVER)) {
|
||||||
|
$email = $_SERVER['HTTP_X_REMOTE_USER'];
|
||||||
|
$password = $_SERVER['HTTP_X_REMOTE_USER_TOKEN'];
|
||||||
|
$ssoHash = \RainLoop\Api::GetUserSsoHash($email, $password);
|
||||||
|
|
||||||
|
// redirect to webmail sso url
|
||||||
|
header('Location: index.php?sso&hash='.$ssoHash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header('HTTP/1.0 403 Forbidden');
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ conf.jinja("/application.ini", os.environ, "/data/_data_/_default_/configs/appli
|
|||||||
conf.jinja("/php.ini", os.environ, "/usr/local/etc/php/conf.d/rainloop.ini")
|
conf.jinja("/php.ini", os.environ, "/usr/local/etc/php/conf.d/rainloop.ini")
|
||||||
|
|
||||||
os.system("chown -R www-data:www-data /data")
|
os.system("chown -R www-data:www-data /data")
|
||||||
|
os.system("chmod -R a+rX /var/www/html/")
|
||||||
|
|
||||||
os.execv("/usr/local/bin/apache2-foreground", ["apache2-foreground"])
|
os.execv("/usr/local/bin/apache2-foreground", ["apache2-foreground"])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user