diff -ur -x config.log ../ejabberd-1.1.2.orig/src/cyrsasl_anonymous.erl ./src/cyrsasl_anonymous.erl --- ../ejabberd-1.1.2.orig/src/cyrsasl_anonymous.erl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/cyrsasl_anonymous.erl 2007-06-06 16:22:48.000000000 +0200 @@ -9,12 +9,13 @@ %% See http://www.ietf.org/internet-drafts/draft-ietf-sasl-anon-05.txt -module(cyrsasl_anonymous). --vsn('$Revision: 528 $'). +-vsn('$Revision: 528 $ '). --export([start/1, stop/0, mech_new/3, mech_step/2]). +-export([start/1, stop/0, mech_new/1, mech_step/2]). -behaviour(cyrsasl). +-include("ejabberd.hrl"). -record(state, {server}). start(_Opts) -> @@ -24,7 +25,7 @@ stop() -> ok. -mech_new(Host, _GetPassword, _CheckPassword) -> +mech_new(#sasl_ctx{host=Host}) -> {ok, #state{server = Host}}. mech_step(State, _ClientIn) -> diff -ur -x config.log ../ejabberd-1.1.2.orig/src/cyrsasl_digest.erl ./src/cyrsasl_digest.erl --- ../ejabberd-1.1.2.orig/src/cyrsasl_digest.erl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/cyrsasl_digest.erl 2007-06-06 11:19:23.000000000 +0200 @@ -12,11 +12,12 @@ -export([start/1, stop/0, - mech_new/3, + mech_new/1, mech_step/2]). -behaviour(cyrsasl). +-include("ejabberd.hrl"). -record(state, {step, nonce, username, authzid, get_password}). start(_Opts) -> @@ -25,7 +26,7 @@ stop() -> ok. -mech_new(_Host, GetPassword, _CheckPassword) -> +mech_new(#sasl_ctx{get_password=GetPassword}) -> {ok, #state{step = 1, nonce = randoms:get_string(), get_password = GetPassword}}. diff -ur -x config.log ../ejabberd-1.1.2.orig/src/cyrsasl.erl ./src/cyrsasl.erl --- ../ejabberd-1.1.2.orig/src/cyrsasl.erl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/cyrsasl.erl 2007-06-06 16:46:39.000000000 +0200 @@ -13,19 +13,18 @@ -export([start/0, register_mechanism/3, listmech/1, - server_new/6, + server_new/7, server_start/3, server_step/2]). -record(sasl_mechanism, {mechanism, module, require_plain_password}). --record(sasl_state, {service, myname, realm, - get_password, check_password, - mech_mod, mech_state}). +-record(sasl_state, {service, myname, + mech_mod, mech_state, ctx}). -export([behaviour_info/1]). behaviour_info(callbacks) -> - [{mech_new, 3}, {mech_step, 2}]; + [{mech_new, 1}, {mech_step, 2}]; behaviour_info(Other) -> undefined. @@ -33,6 +32,7 @@ ets:new(sasl_mechanism, [named_table, public, {keypos, #sasl_mechanism.mechanism}]), + cyrsasl_gssapi:start([]), cyrsasl_plain:start([]), cyrsasl_digest:start([]), cyrsasl_anonymous:start([]), @@ -96,22 +96,25 @@ filter_anonymous(Host, Mechs). server_new(Service, ServerFQDN, UserRealm, SecFlags, - GetPassword, CheckPassword) -> + GetPassword, CheckPassword, FQDN) -> + Ctx = #sasl_ctx{ + host = ServerFQDN, + realm = UserRealm, + get_password = GetPassword, + check_password = CheckPassword, + fqdn = FQDN + }, + #sasl_state{service = Service, myname = ServerFQDN, - realm = UserRealm, - get_password = GetPassword, - check_password = CheckPassword}. + ctx = Ctx}. server_start(State, Mech, ClientIn) -> case lists:member(Mech, listmech(State#sasl_state.myname)) of true -> case ets:lookup(sasl_mechanism, Mech) of [#sasl_mechanism{module = Module}] -> - {ok, MechState} = Module:mech_new( - State#sasl_state.myname, - State#sasl_state.get_password, - State#sasl_state.check_password), + {ok, MechState} = Module:mech_new(State#sasl_state.ctx), server_step(State#sasl_state{mech_mod = Module, mech_state = MechState}, ClientIn); diff -ur -x config.log ../ejabberd-1.1.2.orig/src/cyrsasl_plain.erl ./src/cyrsasl_plain.erl --- ../ejabberd-1.1.2.orig/src/cyrsasl_plain.erl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/cyrsasl_plain.erl 2007-06-06 16:22:55.000000000 +0200 @@ -10,10 +10,11 @@ -author('alexey@sevcom.net'). -vsn('$Revision: 527 $ '). --export([start/1, stop/0, mech_new/3, mech_step/2, parse/1]). +-export([start/1, stop/0, mech_new/1, mech_step/2, parse/1]). -behaviour(cyrsasl). +-include("ejabberd.hrl"). -record(state, {check_password}). start(_Opts) -> @@ -23,7 +24,7 @@ stop() -> ok. -mech_new(_Host, _GetPassword, CheckPassword) -> +mech_new(#sasl_ctx{check_password=CheckPassword}) -> {ok, #state{check_password = CheckPassword}}. mech_step(State, ClientIn) -> diff -ur -x config.log ../ejabberd-1.1.2.orig/src/ejabberd_c2s.erl ./src/ejabberd_c2s.erl --- ../ejabberd-1.1.2.orig/src/ejabberd_c2s.erl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/ejabberd_c2s.erl 2007-06-06 11:34:16.000000000 +0200 @@ -42,6 +42,7 @@ -record(state, {socket, receiver, sockmod, + fqdn, streamid, sasl_state, access, @@ -152,8 +153,10 @@ Socket, SockMod, none, MaxStanzaSize), {SockMod, Socket, RecPid} end, + {ok, FQDN} = ejabberd_net:gethostname(Socket), {ok, wait_for_stream, #state{socket = Socket1, sockmod = SockMod1, + fqdn = FQDN, receiver = ReceiverPid, zlib = Zlib, tls = TLS, @@ -195,6 +198,8 @@ send_text(StateData, Header), case StateData#state.authenticated of false -> + FQDN = StateData#state.fqdn, + ?INFO_MSG("FQDN: ~p~n", [FQDN]), SASLState = cyrsasl:server_new( "jabber", Server, "", [], @@ -205,7 +210,8 @@ fun(U, P) -> ejabberd_auth:check_password( U, Server, P) - end), + end, + FQDN), Mechs = lists:map( fun(S) -> {xmlelement, "mechanism", [], diff -ur -x config.log ../ejabberd-1.1.2.orig/src/ejabberd.hrl ./src/ejabberd.hrl --- ../ejabberd-1.1.2.orig/src/ejabberd.hrl 2006-09-27 22:49:59.000000000 +0200 +++ ./src/ejabberd.hrl 2007-06-06 17:10:44.000000000 +0200 @@ -39,3 +39,9 @@ -define(PRIVACY_SUPPORT, true). +-record(sasl_ctx, { + host, + realm, + get_password, + check_password, + fqdn}). --- /dev/null 2003-05-28 19:37:54.000000000 +0200 +++ src/cyrsasl_gssapi.erl 2007-06-06 16:00:01.000000000 +0200 @@ -0,0 +1,143 @@ +%%%---------------------------------------------------------------------- +%%% File : cyrsasl_gssapi.erl +%%% Author : Mikael Magnusson +%%% Purpose : GSSAPI SASL mechanism +%%% Created : 1 June 2007 by Mikael Magnusson +%%% Id : $Id: $ +%%%---------------------------------------------------------------------- +%%% +%%% Copyright (C) 2007 Mikael Magnusson +%%% +%%% Permission is hereby granted, free of charge, to any person +%%% obtaining a copy of this software and associated documentation +%%% files (the "Software"), to deal in the Software without +%%% restriction, including without limitation the rights to use, copy, +%%% modify, merge, publish, distribute, sublicense, and/or sell copies +%%% of the Software, and to permit persons to whom the Software is +%%% furnished to do so, subject to the following conditions: +%%% +%%% The above copyright notice and this permission notice shall be +%%% included in all copies or substantial portions of the Software. +%%% +%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +%%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +%%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +%%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +%%% SOFTWARE. +%%% + +%%% +%%% configuration options: +%%% {sasl_realm, ""}. +%%% +%%% environment variables: +%%% KRB5_KTNAME +%%% + +-module(cyrsasl_gssapi). +-author('mikma@users.sourceforge.net'). +-vsn('$Revision: $ '). + +-include("ejabberd.hrl"). + +-export([start/1, + stop/0, + mech_new/1, + mech_step/2]). + +-behaviour(cyrsasl). + +-define(SERVER, cyrsasl_gssapi). +-define(MSG, ?DEBUG). + +-record(state, {sasl, + needsmore=true, + step=0, + host, + authid, + authzid, + authrealm}). + +start(_Opts) -> + ChildSpec = + {?SERVER, + {esasl, start_link, [{local, ?SERVER}]}, + transient, + 1000, + worker, + [esasl]}, + + {ok, _Pid} = supervisor:start_child(ejabberd_sup, ChildSpec), + + cyrsasl:register_mechanism("GSSAPI", ?MODULE, false). + +stop() -> + esasl:stop(?SERVER), + supervisor:terminate_child(ejabberd_sup, ?SERVER), + supervisor:delete_child(ejabberd_sup, ?SERVER). + +mech_new(#sasl_ctx{host=Host, fqdn=FQDN}) -> + ?MSG("mech_new ~p ~p~n", [Host, FQDN]), + {ok, Sasl} = esasl:server_start(?SERVER, "GSSAPI", "xmpp", FQDN), + {ok, #state{sasl=Sasl,host=Host}}. + +mech_step(State, ClientIn) when is_list(ClientIn) -> + catch do_step(State, ClientIn). + +do_step(#state{needsmore=false}=State, _) -> + check_user(State); +do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) -> + ?MSG("mech_step~n", []), + case esasl:step(Sasl, list_to_binary(ClientIn)) of + {ok, RspAuth} -> + ?MSG("ok~n", []), + {ok, Display_name} = esasl:property_get(Sasl, gssapi_display_name), + {ok, Authzid} = esasl:property_get(Sasl, authzid), + {Authid, [$@ | Auth_realm]} = + lists:splitwith(fun(E)->E =/= $@ end, Display_name), + State1 = State#state{authid=Authid, + authzid=Authzid, + authrealm=Auth_realm}, + handle_step_ok(State1, binary_to_list(RspAuth)); + {needsmore, RspAuth} -> + ?MSG("needsmore~n", []), + if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) -> + {error, "not-authorized"}; + true -> + {continue, binary_to_list(RspAuth), + State#state{step=Step+1}} + end; + {error, _} -> + {error, "not-authorized"} + end. + +handle_step_ok(State, []) -> + check_user(State); +handle_step_ok(#state{step=Step}=State, RspAuth) -> + ?MSG("continue~n", []), + {continue, RspAuth, State#state{needsmore=false,step=Step+1}}. + +check_user(#state{authid=Authid,authzid=Authzid, + authrealm=Auth_realm,host=Host}) -> + Realm = ejabberd_config:get_local_option({sasl_realm, Host}), + + if Realm =/= Auth_realm -> + ?MSG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]), + throw({error, "not-authorized"}); + true -> + ok + end, + + case ejabberd_auth:is_user_exists(Authid, Host) of + false -> + ?MSG("bad user ~p~n",[Authid]), + throw({error, "not-authorized"}); + true -> + ok + end, + + ?MSG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]), + {ok, [{username, Authid}, {authzid, Authzid}]}. --- /dev/null 2003-05-28 19:37:54.000000000 +0200 +++ src/ejabberd_net.erl 2007-06-06 10:14:41.000000000 +0200 @@ -0,0 +1,31 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_net.erl +%%% Author : Mikael Magnusson +%%% Purpose : Serve C2S connection +%%% Created : 6 June 2007 by Mikael Magnusson +%%% Id : $Id: $ +%%%---------------------------------------------------------------------- + +-module(ejabberd_net). +-author('mikma@users.sourceforge.net'). +%% -update_info({update, 0}). + +-export([gethostname/1]). + +-include("ejabberd.hrl"). +-include_lib("kernel/include/inet.hrl"). + +%% +%% gethostname(Socket) +%% +gethostname(Socket) -> + ?INFO_MSG("gethostname ~p~n", [Socket]), +%% {ok, "skinner.hem.za.org"}. + + {ok, {Addr, Port}} = inet:sockname(Socket), + case inet:gethostbyaddr(Addr) of + {ok, HostEnt} when is_record(HostEnt, hostent) -> + {ok, HostEnt#hostent.h_name}; + {error, What} -> + error + end.