Skip to content
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

SASL EXTERNAL implementation #1735

Merged
merged 14 commits into from
Mar 7, 2018
Merged

Conversation

DenysGonchar
Copy link
Collaborator

Initial implementation of SASL EXTERNAL

@@ -27,12 +27,13 @@
tls_required = false :: boolean(),
tls_enabled = false :: boolean(),
tls_options = [],
verify :: verify_none | verify_peer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sasl_verify or something more self-describing good to have.
Should we replace this record with a map eventually?

At least with my client we have everything else field with a map for any extra stuff.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify_none & verify_peer are the standard atoms in erlang's ssl and fast_tls. so let it stay standard,
if we want to change record to map - let's do it in another CR. this one is already too big

Copy link
Contributor

@arcusfelis arcusfelis Feb 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was talking about #state.verify field name.
Values are fine. But field name is very confusing.

Can be

sasl_verify    :: verify_none | verify_peer

or

sasl_ssl_verify :: verify_none | verify_peer

or

sasl_tls_verify :: verify_none | verify_peer

Also, there should be info, that this field is initialized based on listener settings.

@@ -0,0 +1,86 @@
-module(cert_utils).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module description comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E.g. what certificates, what is the primary user of this module...

#'AttributeTypeAndValue'{type = ?'id-at-commonName', value = V} <- AtributesList],
CN
catch
_:_ -> error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

report error here, we are loosing stacktrace info.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not gonna log here anything, it's normal when certificate is missing some of the fields, generally it's not an error. if you want to log something - do it in the proper place, it's a duty of the caller

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not about logging but returning a meaningful error, so the caller will actually know what went wrong.

XmppAddr
end || {otherName, #'AnotherName'{'type-id' = ?'id-on-xmppAddr', value = V}} <- SANs]
catch
_:_ -> []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

report an error here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not gonna log here anything, it's normal when certificate is missing some of the fields, generally it's not an error. if you want to log something - do it in the proper place, it's a duty of the caller

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Than this code can be rewritten without try ... catch.
Just by expecting missing fields.
There also should be at least two tests: one with missing field, one with not.

.... ideally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It deserves a separate error return, when a field expected to have a valid XMPP address, does not actually have one. If fields are missing at all, then I think it's OK to return [].

@DenysGonchar DenysGonchar force-pushed the SASL_EXTERNAL_implementation branch 2 times, most recently from 5d72381 to a350408 Compare February 21, 2018 14:49
{ok, SANs} = 'OTP-PUB-KEY':decode('SubjectAltName', BinVal),
[DNS || {dNSName, DNS} <- SANs]
catch
_:_ -> []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, catching everything is usually bad practice.
I should be used with care and should report errors and stacktrace.
Otherwise we would ignore some invisible errors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not gonna log here anything, it's normal when certificate is missing some of the fields, generally it's not an error. if you want to log something - do it in the proper place, it's a duty of the caller

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try ... catch _:_ construction should not used in code, because it hides all the errors.
Both expected and not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there was a typo in SubjectAltName, for example SubjectAltnaen we would never find this out.

I am fine with

case decode(....) of
    {ok, SANs} ->
....
{error, _} ->
[]
end

On microbenchmarking side: going inside catch construction is slower than just case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Michael, this module will be covered with the tests. that will be done in the next PR because we need to change our SSL certs generation suit, and that is big chunk of work. generally i did manual tests for this code so it's ok to archive it. this code provides only ASN1 parsing, it is ok to to use try/catch here. i'm not gonna change it. period. this comment is related to all the parsing functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not about doing a typo in a code or tests but lack of any meaningful error return here will make it more difficult to debug problems with real-world certificates. I'd even prefer a lack of try..catch rather than hiding errors.

end.


-spec get_cert_domains(certificate()) -> [any()].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more specific type than any().

end.


-spec get_xmpp_addresses(certificate()) -> [any()].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more specific type.

Addresses = get_xmpp_addresses(Cert),
Domains = get_dns_addresses(Cert),
lists:flatten(get_lserver_from_addr(CN,false) ++
[get_lserver_from_addr(Addr,true) || Addr <- Addresses, is_binary(Addr)] ++
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespaces , .

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is nothing in dev-handbook about whitespaces, but generally we use them.

Val.


get_lserver_from_addr(V, UTF8) when is_binary(V); is_list(V) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can be two functions, UTF8 argument is not needed.
Also, it returns list if failed to parse - should be in a comment.

returns a list of binaries. The length of the list is one or zero.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it really requires a comment. Spec would be useful on the other hand.

CN = get_common_name(Cert),
Addresses = get_xmpp_addresses(Cert),
Domains = get_dns_addresses(Cert),
lists:flatten(get_lserver_from_addr(CN,false) ++
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while lists:flatten works here, lists:append is more fitting, because we don't have nested lists.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually it is [bitstring] ++ [[bitstring],...] ++ [[bitstring],...]

@@ -122,9 +122,9 @@ listmech(Host) ->
{'EXIT', {undef, [{Module, store_type, []} | _]}} ->
?WARNING_MSG("~p doesn't implement the function store_type/0",
[Module]),
[];
[{'/=','$2', cert}];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love to see a comment like: "we don't need any type of password for cert mechanism".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wat? It's more like "we don't want to offer cert mechanism if store type is unknown... but why exactly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct, we want to offer external mechanism only if store type is scram. it's done with thought regarding future extension of DB based auth backends. we can extend them with certificates support only if password is scrammed, other-way we can't distinguish values between passwords and certs

@@ -0,0 +1,61 @@
-module(cyrsasl_external).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header, what is while for, how works.
What's the difference between this and cyrsasl_plain.


-behaviour(cyrsasl).

-record(state, {creds}).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saslext_state would be a better name.
Because sometimes we do load records definitions into shell, and it works better, if each record have a unique name.

But maybe consider to use maps.
creds should be typed and commented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use state for record name in so many places, that I think it should be a coordinated refactoring effort (if we would like to do it at all).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But 👍 for typed creds.

Creds :: mongoose_credentials:t()) -> {ok, tuple()}.
mech_new(_Host, Creds) ->
case mongoose_credentials:get(Creds,client_cert,undefined) of
undefined -> {ok, #state{creds = invalid_cert}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line?

DerCert = public_key:pkix_encode('Certificate', Cert, plain),
PemCert = public_key:pem_encode([{'Certificate', DerCert, not_encrypted}]),
ExtraFields = get_common_name(Cert) ++ get_xmpp_addresses(Cert),
{ok, #state{creds = mongoose_credentials:extend(Creds, [ {pem_cert, PemCert},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ {pem_cert, ..... can go into a separate variable. ExtraFields2 or something.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is dedicated variable ExtraFields, because it can be [ ], or list of definitions. and that is not the case for DerCert and PemCert.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

ExtraFields = get_common_name(Cert) ++ get_xmpp_addresses(Cert),
AllFields = [{pem_cert, PemCert}, {der_cert, DerCert} | ExtraFields],
mongoose_credentials:extend(Creds, AllFields)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to know that the second argument of extend is fields just by looking at the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is fine as it is now and looks clear. :)

-spec mech_new(Host :: ejabberd:server(),
Creds :: mongoose_credentials:t()) -> {ok, tuple()}.
mech_new(_Host, Creds) ->
case mongoose_credentials:get(Creds,client_cert,undefined) of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespaces , .

-spec mech_new(Host :: ejabberd:server(),
Creds :: mongoose_credentials:t()) -> {ok, tuple()}.
mech_new(_Host, Creds) ->
case mongoose_credentials:get(Creds,client_cert,undefined) of
Copy link
Contributor

@arcusfelis arcusfelis Feb 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to know on which step we add client_cert when reading the code.
And if the client_cert is missing, the client is considered unauthorized.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if client cert is missing, client can try another SASL mechanisms, it's not proposed to use SASL EXTERNAL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for a client to reach cyrsasl_external:new without certificate present anyway?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arcusfelis
It's pretty intuitive that the certificate is provided by c2s. And line 36 is not that far and it explains everything.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, it's not possible, see ejabberd_c2s, it filters out external mechanism if clients certificate is not provided.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which part of the XEP covers a case when the EXTERNAL mechanism is offered but client hasn't provided any certificate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, you right, it's not XEP178, it's RFC6120. see 6.3.4. Mechanism Offers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, the receiving entity MAY offer the SASL EXTERNAL mechanism under other circumstances, as well.

But we do not offer it under other circumstances, right? Currently it's an unreachable code that confuses the reader. YAGNI.

Copy link
Collaborator Author

@DenysGonchar DenysGonchar Feb 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's quite fun to so YAGNI reference in a context of 1 extra code line.

any way, SASL mechanism filtering is not mandatory, and it simply was added later than cyrsasl_external module. so this code was triggered in initial implementation, and it was required to close client's session gracefully

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it important that filtering was added by this PR? The fact remains, that this code will never be executed unless there is a bug which would lead to client successfully choosing EXTERNAL despite lack of certificate.

mech_step(#state{creds = Creds}, <<"">>) ->
authorize(Creds);
mech_step(#state{creds = Creds}, User) ->
authorize(mongoose_credentials:set(Creds, requested_name, User)).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment, why do we need to save requested_name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see XEP 178. generally SASL code is not responsible to make an auth decision, it up to auth backend(s)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this field used in the code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can be used by auth module, but the demo pki auth module that we currently have ignores it, as well as most of the cert fields.

])}}
end.

-spec mech_step(State :: tuple(), ClientIn :: binary()) -> R when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types are too generic.
-type saslext_state() :: #state{} and using saslext_state() everywhere.
ClientIn is probably luser().

{error, <<"not-authorized">>};
mech_step(#state{creds = Creds}, <<"">>) ->
authorize(Creds);
mech_step(#state{creds = Creds}, User) ->
Copy link
Contributor

@arcusfelis arcusfelis Feb 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indention, 4 spaces everywhere.
btw, there was a code style guide somewhere, but definitely not inside the repo.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the link to code style, please

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every module in MIM has 4-space indention, maybe except for some old ejabberd code nobody really touched since fork (I think some pieces might still be left...).

authorize(mongoose_credentials:set(Creds, requested_name, User)).

authorize(Creds) ->
%% auth backend is responsible to add username to Creds.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be good to mention that auth backend is most likely ejabberd_auth_pki.
Or something, that does not use password.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ejabberd_auth_pki is just a demo auth backend it assumes that cert is ok if it passes validation, there's a plan to use DB backends in the future.

@@ -0,0 +1,117 @@
-module(ejabberd_auth_pki).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc header.
license header.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would add it with a big pleasure, do we have some doc that describes the format of license/doc header?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be like @kzemek

%%==============================================================================     
%% Copyright 2017 Erlang Solutions Ltd.                                              
%%                                                                                   
%% Licensed under the Apache License, Version 2.0 (the "License");                   
%% you may not use this file except in compliance with the License.                  
%% You may obtain a copy of the License at                                           
%%                                                                                   
%% http://www.apache.org/licenses/LICENSE-2.0                                        
%%                                                                                   
%% Unless required by applicable law or agreed to in writing, software               
%% distributed under the License is distributed on an "AS IS" BASIS,                 
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.          
%% See the License for the specific language governing permissions and               
%% limitations under the License.                                                    
%%==============================================================================     
                                                                                     
-module(mod_global_distrib_utils).                                                   
-author('[email protected]').                                        
                                                                              
                      

It's for new files, not based on ejabberd's code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in a private company dev-handbook.
https://github.com/esl/dev-handbook/blob/master/development_handbook.markdown#module-header

We should have subset of it for public use, but we don't have yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arcusfelis

I'm not so sure if it's OK to put Apache license in our new modules, because ejabberd files already have GPL license. I'm not that good with legal stuff but isn't there a chance of some conflict here?

Standard company header (according to the devbook) is an optimal choice I guess.

Copy link
Contributor

@kzemek kzemek Feb 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fenek We license the whole project under terms covered in the COPYING file. I would interpret files with Apache license header to be additionally available under Apache license. Anyway, correct copyright headers help us see which files still prevent us from moving the whole project from GPL to Apache.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds sane but as far as I understand, we are operating on our assumptions, correct? Not a formal opinion of a lawyer experienced in open source licenses.

Anyway, the truth is that the standard header for dev handbook provides more useful information than the one with Apache license... they can be combined so a header fills the first screen of a source code view. :D

OK, now seriously: I'd prefer the handbook header. And this legal stuff is a mess.

%%-callback stop(Host :: ejabberd:lserver()) -> ok.
stop(_) -> ok.

%%-callback store_type(Host :: ejabberd:lserver()) -> scram | plain | external.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really scram, or not relevant?
maybe external

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really, this scram/plain/external store types has nothing common with sasl mechanisms. it's more about the way how we store the password. and we will add certificates support in DB based auth backends later. but that backends must be configured as scram. other way that won't be possible to distinguish between passwords and certificates

%%-callback authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}.
authorize(Creds) ->
case get_username(Creds) of
{ok,UserName} ->
Copy link
Contributor

@arcusfelis arcusfelis Feb 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespace ,

%%-callback store_type(Host :: ejabberd:lserver()) -> scram | plain | external.
store_type(_) -> scram.

%%-callback set_password( User :: ejabberd:luser(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need callback comments for functions that do nothing (i.e. just return one value always).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course we do need them. it is very basic module, but it can be extended for the client's needs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments don't do any harm.

%% internal functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_username(Cred) ->
case mongoose_credentials:get(Cred,common_name,no_cert) of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespaces, probably indention.
We use style

    case X of
        something ->
            something
    end.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please reference to the doc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't mind lack of newline when all matches in a case are one-liners.

case cyrsasl:listmech(Server) of
[] -> [];
Mechanisms ->
[#xmlel{name = <<"mechanisms">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],
children = [ mechanism(S) || S <- Mechanisms ]}]
children = [ mechanism(M) || M <- Mechanisms, filter_mechanism(M,S) ]}]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

M, S

auth_compression_bind_session,
auth_bind_compression_session,
bind_server_generated_resource]}
[ {c2s_noproc, [], [reset_stream_noproc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to touch the whole block.
unless you want to create functions feature_order_cases(), c2s_noproc_cases(), .....

@@ -256,7 +269,11 @@ clients_can_connect_with_advertised_ciphers(Config) ->
ciphers_working_with_ssl_clients(Config))).

'clients_can_connect_with_DHE-RSA-AES256-SHA_only'(Config) ->
Config1 = [{c2s_port, 5233} | Config],
Port = case ?config(tls_module, Config) of
just_tls -> 5263; %mim3 secondary_c2s port
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% mim...

children = [#xmlel{name = <<"mechanism">>,
children = [#xmlcdata{content = <<"EXTERNAL">>}]}]}];
{bad_cert, CertVerifyRes} ->
check_sasl_tls_certveify(TLSCertverify, CertVerifyRes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in verify

Val = convert_to_bin(V),
case {jid:from_binary(Val), UTF8} of
{#jid{luser = <<"">>, lserver = LD, lresource = <<"">>}, true} ->
case ejabberd_s2s:domain_utf8_to_ascii(LD) of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like calling utility function from ejabberd_s2s in a module that is not dedicated to S2S logic. I think I could live with some code duplication or even better - moving domain_utf8_to_ascii to some util module.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first version of this module is just cut&paste from ejabberd_s2s_in module, than the code was cleaned up to make it reusable from cyrsasl_external

@DenysGonchar DenysGonchar force-pushed the SASL_EXTERNAL_implementation branch 3 times, most recently from 9eede7e to 1b7d0f3 Compare March 7, 2018 08:49
fenek and others added 7 commits March 7, 2018 13:59
Add mam_iq:lookup_params/0 type
Remove remote calls from mam_iq to itself
Log dropped stanzas in parallel stories (configurable in test.config)
Reduce concurrency in mam rsm test cases (separate group for complete
kind of tests)
Use priority=-1 for parallel tests
@DenysGonchar DenysGonchar force-pushed the SASL_EXTERNAL_implementation branch from 1b7d0f3 to 19af40b Compare March 7, 2018 13:07
@DenysGonchar DenysGonchar force-pushed the SASL_EXTERNAL_implementation branch from 19af40b to ef1af53 Compare March 7, 2018 13:38
@codecov-io
Copy link

Codecov Report

Merging #1735 into master will decrease coverage by 0.2%.
The diff coverage is 43.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1735      +/-   ##
==========================================
- Coverage   74.65%   74.45%   -0.21%     
==========================================
  Files         283      288       +5     
  Lines       26578    26760     +182     
==========================================
+ Hits        19843    19923      +80     
- Misses       6735     6837     +102
Impacted Files Coverage Δ
src/ejabberd.erl 31.25% <ø> (ø) ⬆️
src/cyrsasl_external.erl 0% <0%> (ø)
src/cert_utils.erl 0% <0%> (ø)
src/ejabberd_auth_pki.erl 0% <0%> (ø)
...c/global_distrib/mod_global_distrib_server_sup.erl 100% <100%> (ø) ⬆️
src/mam_iq.erl 88.67% <100%> (ø) ⬆️
...c/global_distrib/mod_global_distrib_server_mgr.erl 80% <100%> (ø) ⬆️
src/mod_mam.erl 89.39% <100%> (+0.37%) ⬆️
src/mod_mam_muc.erl 70.37% <100%> (ø) ⬆️
src/mod_mam_utils.erl 87.37% <100%> (+1.36%) ⬆️
... and 28 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0c501f7...ef1af53. Read the comment docs.

@DenysGonchar DenysGonchar merged commit ac965ca into master Mar 7, 2018
@DenysGonchar DenysGonchar deleted the SASL_EXTERNAL_implementation branch March 8, 2018 20:21
@fenek fenek added this to the 3.0.0 milestone Mar 14, 2018
This was referenced May 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants