Skip to content

Commit 7e7a684

Browse files
committed
portal-api: improve handling of ldap interfaces
1 parent 2be1dcc commit 7e7a684

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

src/portal.py

+23-23
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424

2525
import ldap
2626
from moulinette.utils.filesystem import read_json
27-
from yunohost.authenticators.ldap_ynhuser import URI, USERDN, Authenticator as Auth, user_is_allowed_on_domain
27+
from yunohost.authenticators.ldap_ynhuser import Authenticator as Auth, user_is_allowed_on_domain
2828
from yunohost.user import _hash_user_password
2929
from yunohost.utils.error import YunohostError, YunohostValidationError
30-
from yunohost.utils.ldap import LDAPInterface, _ldap_path_extract
30+
from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract, LDAPInterface
3131
from yunohost.utils.password import (
3232
assert_password_is_compatible,
3333
assert_password_is_strong_enough,
@@ -41,15 +41,14 @@
4141

4242
def _get_user_infos(
4343
user_attrs: list[str],
44-
) -> tuple[str, str, dict[str, Any], LDAPInterface]:
45-
auth = Auth().get_session_cookie(decrypt_pwd=True)
44+
) -> tuple[str, str, dict[str, Any]]:
45+
auth = Auth().get_session_cookie()
4646
username = auth["user"]
47-
ldap_interface = LDAPInterface(username, auth["pwd"])
48-
result = ldap_interface.search("ou=users", f"uid={username}", user_attrs)
47+
result = _get_ldap_interface().search("ou=users", f"uid={username}", user_attrs)
4948
if not result:
5049
raise YunohostValidationError("user_unknown", user=username)
5150

52-
return username, auth["host"], result[0], ldap_interface
51+
return username, auth["host"], result[0]
5352

5453

5554
def _get_portal_settings(
@@ -123,7 +122,7 @@ def portal_me():
123122
"""
124123
Get user informations
125124
"""
126-
username, domain, user, _ = _get_user_infos(
125+
username, domain, user = _get_user_infos(
127126
["cn", "mail", "maildrop", "mailuserquota", "memberOf", "permission"]
128127
)
129128

@@ -163,7 +162,7 @@ def portal_update(
163162
from yunohost.domain import domain_list
164163

165164
domains = domain_list()["domains"]
166-
username, domain, current_user, ldap_interface = _get_user_infos(
165+
username, domain, current_user = _get_user_infos(
167166
["givenName", "sn", "cn", "mail", "maildrop", "memberOf"]
168167
)
169168
new_attr_dict = {}
@@ -198,7 +197,7 @@ def portal_update(
198197
)
199198

200199
try:
201-
ldap_interface.validate_uniqueness({"mail": mail})
200+
_get_ldap_interface().validate_uniqueness({"mail": mail})
202201
except YunohostError:
203202
raise YunohostValidationError(
204203
"mail_already_exists", mail=mail, path=f"mailalias[{index}]"
@@ -221,19 +220,6 @@ def portal_update(
221220
]
222221

223222
if newpassword:
224-
# FIXME: this ldap stuff should be handled in utils/ldap.py imho ?
225-
226-
# Check that current password is valid
227-
try:
228-
con = ldap.ldapobject.ReconnectLDAPObject(URI, retry_max=0)
229-
con.simple_bind_s(USERDN.format(username=username), currentpassword)
230-
except ldap.INVALID_CREDENTIALS:
231-
raise YunohostValidationError("invalid_password", path="currentpassword")
232-
finally:
233-
# Free the connection, we don't really need it to keep it open as the point is only to check authentication...
234-
if con:
235-
con.unbind_s()
236-
237223
# Ensure compatibility and sufficiently complex password
238224
try:
239225
assert_password_is_compatible(newpassword)
@@ -248,10 +234,24 @@ def portal_update(
248234

249235
new_attr_dict["userPassword"] = [_hash_user_password(newpassword)]
250236

237+
# Check that current password is valid
238+
# To be able to edit the user info, an authenticated ldap session is needed
239+
if newpassword:
240+
# When setting the password, check the user provided the valid current password
241+
try:
242+
ldap_interface = LDAPInterface(username, currentpassword)
243+
except ldap.INVALID_CREDENTIALS:
244+
raise YunohostValidationError("invalid_password", path="currentpassword")
245+
else:
246+
# Otherwise we use the encrypted password stored in the cookie
247+
ldap_interface = LDAPInterface(username, Auth().get_session_cookie(decrypt_pwd=True)["pwd"])
248+
251249
try:
252250
ldap_interface.update(f"uid={username},ou=users", new_attr_dict)
253251
except Exception as e:
254252
raise YunohostError("user_update_failed", user=username, error=e)
253+
finally:
254+
del ldap_interface
255255

256256
if "userPassword" in new_attr_dict:
257257
Auth.invalidate_all_sessions_for_user(username)

0 commit comments

Comments
 (0)