aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2010-04-19 20:57:24 +1000
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2010-04-19 20:57:24 +1000
commitc2362db03db36962e93532cd7132976b3f79e81d (patch)
tree5532275e5e787cda579f6c73d0cdba5df52df87a /src
parentLDAP extensible match support (EJAB-722) (diff)
allow inband password change (EJAB-199)
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_auth_ldap.erl10
-rw-r--r--src/eldap/ELDAPv3.asn10
-rw-r--r--src/eldap/eldap.erl34
-rw-r--r--src/eldap/eldap_pool.erl6
4 files changed, 55 insertions, 5 deletions
diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl
index 8be61f65b..9c490bb93 100644
--- a/src/ejabberd_auth_ldap.erl
+++ b/src/ejabberd_auth_ldap.erl
@@ -153,8 +153,14 @@ check_password(User, Server, Password) ->
check_password(User, Server, Password, _Digest, _DigestGen) ->
check_password(User, Server, Password).
-set_password(_User, _Server, _Password) ->
- {error, not_allowed}.
+set_password(User, Server, Password) ->
+ {ok, State} = eldap_utils:get_state(Server, ?MODULE),
+ case find_user_dn(User, State) of
+ false ->
+ {error, user_not_found};
+ DN ->
+ eldap_pool:modify_passwd(State#state.eldap_id, DN, Password)
+ end.
%% @spec (User, Server, Password) -> {error, not_allowed}
try_register(_User, _Server, _Password) ->
diff --git a/src/eldap/ELDAPv3.asn b/src/eldap/ELDAPv3.asn
index 0cfac48c3..1fec35cd8 100644
--- a/src/eldap/ELDAPv3.asn
+++ b/src/eldap/ELDAPv3.asn
@@ -286,6 +286,16 @@ ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
responseName [10] LDAPOID OPTIONAL,
response [11] OCTET STRING OPTIONAL }
+passwdModifyOID LDAPOID ::= "1.3.6.1.4.1.4203.1.11.1"
+
+PasswdModifyRequestValue ::= SEQUENCE {
+ userIdentity [0] OCTET STRING OPTIONAL,
+ oldPasswd [1] OCTET STRING OPTIONAL,
+ newPasswd [2] OCTET STRING OPTIONAL }
+
+PasswdModifyResponseValue ::= SEQUENCE {
+ genPasswd [0] OCTET STRING OPTIONAL }
+
END
diff --git a/src/eldap/eldap.erl b/src/eldap/eldap.erl
index 1c7331768..5bc0c425a 100644
--- a/src/eldap/eldap.erl
+++ b/src/eldap/eldap.erl
@@ -33,9 +33,11 @@
%%% Modified by Alexey Shchepin <alexey@sevcom.net>
-%%% Modified by Evgeniy Khramtsov <xram@jabber.ru>
+%%% Modified by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Implemented queue for bind() requests to prevent pending binds.
%%% Implemented extensibleMatch/2 function.
+%%% Implemented LDAP Extended Operations (currently only Password Modify
+%%% is supported - RFC 3062).
%%% Modified by Christophe Romain <christophe.romain@process-one.net>
%%% Improve error case handling
@@ -74,7 +76,7 @@
equalityMatch/2,greaterOrEqual/2,lessOrEqual/2,
approxMatch/2,search/2,substrings/2,present/1,extensibleMatch/2,
'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2,
- mod_replace/2, add/3, delete/2, modify_dn/5, bind/3]).
+ mod_replace/2, add/3, delete/2, modify_dn/5, modify_passwd/3, bind/3]).
-export([get_status/1]).
%% gen_fsm callbacks
@@ -240,6 +242,10 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup)
{modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)},
?CALL_TIMEOUT).
+modify_passwd(Handle, DN, Passwd) when is_list(DN), is_list(Passwd) ->
+ Handle1 = get_handle(Handle),
+ gen_fsm:sync_send_event(
+ Handle1, {modify_passwd, DN, Passwd}, ?CALL_TIMEOUT).
%%% --------------------------------------------------------------------
%%% Bind.
@@ -695,6 +701,16 @@ gen_req({modify_dn, Entry, NewRDN, DelOldRDN, NewSup}) ->
deleteoldrdn = DelOldRDN,
newSuperior = NewSup}};
+gen_req({modify_passwd, DN, Passwd}) ->
+ {ok, ReqVal} = asn1rt:encode(
+ 'ELDAPv3', 'PasswdModifyRequestValue',
+ #'PasswdModifyRequestValue'{
+ userIdentity = DN,
+ newPasswd = Passwd}),
+ {extendedReq,
+ #'ExtendedRequest'{requestName = ?passwdModifyOID,
+ requestValue = list_to_binary(ReqVal)}};
+
gen_req({bind, RootDN, Passwd}) ->
{bindRequest,
#'BindRequest'{version = ?LDAP_VERSION,
@@ -769,6 +785,11 @@ recvd_packet(Pkt, S) ->
cancel_timer(Timer),
Reply = check_bind_reply(Result, From),
{reply, Reply, From, S#eldap{dict = New_dict}};
+ {extendedReq, {extendedResp, Result}} ->
+ New_dict = dict:erase(Id, Dict),
+ cancel_timer(Timer),
+ Reply = check_extended_reply(Result, From),
+ {reply, Reply, From, S#eldap{dict = New_dict}};
{OtherName, OtherResult} ->
New_dict = dict:erase(Id, Dict),
cancel_timer(Timer),
@@ -793,6 +814,15 @@ check_bind_reply(#'BindResponse'{resultCode = Reason}, _From) ->
check_bind_reply(Other, _From) ->
{error, Other}.
+%% TODO: process reply depending on requestName:
+%% this requires BER-decoding of #'ExtendedResponse'.response
+check_extended_reply(#'ExtendedResponse'{resultCode = success}, _From) ->
+ ok;
+check_extended_reply(#'ExtendedResponse'{resultCode = Reason}, _From) ->
+ {error, Reason};
+check_extended_reply(Other, _From) ->
+ {error, Other}.
+
get_op_rec(Id, Dict) ->
case dict:find(Id, Dict) of
{ok, [{Timer, _Command, From, Name}|Res]} ->
diff --git a/src/eldap/eldap_pool.erl b/src/eldap/eldap_pool.erl
index f6cb721d1..2331b2c05 100644
--- a/src/eldap/eldap_pool.erl
+++ b/src/eldap/eldap_pool.erl
@@ -31,7 +31,8 @@
-export([
start_link/7,
bind/3,
- search/2
+ search/2,
+ modify_passwd/3
]).
-include("ejabberd.hrl").
@@ -45,6 +46,9 @@ bind(PoolName, DN, Passwd) ->
search(PoolName, Opts) ->
do_request(PoolName, {search, [Opts]}).
+modify_passwd(PoolName, DN, Passwd) ->
+ do_request(PoolName, {modify_passwd, [DN, Passwd]}).
+
start_link(Name, Hosts, Backups, Port, Rootdn, Passwd, Encrypt) ->
PoolName = make_id(Name),
pg2:create(PoolName),