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

ZOOKEEPER-3008: Potential NPE in SaslQuorumAuthLearner#authenticate and SaslQuorumAuthServer#authenticate #496

Open
wants to merge 70 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
7d8d523
d
Mar 26, 2018
700dfb7
fix NPE bug
Mar 27, 2018
1ad4da8
NPE inZOOKEEPER-3008
Mar 28, 2018
4458bb3
del unuse
Mar 28, 2018
7fad199
keep up with master
Mar 28, 2018
765180f
add NPE place
Mar 28, 2018
cf611d1
fix code
Mar 28, 2018
5eec876
fix jenkins error
Mar 28, 2018
925bfd2
del catch
Mar 28, 2018
c787912
fix code
Mar 28, 2018
5c9b577
delete annotation in code
Apr 20, 2018
e967e0f
del test file
Apr 20, 2018
c4db5e2
recover zookeeper master same with apache:master
brettKK Apr 22, 2018
cf9fb5f
recover code
brettKK Apr 22, 2018
f7da9b9
change ZOOK3007 to compare with apache master
brettKK Apr 22, 2018
a12b13f
fix format
brettKK Apr 22, 2018
0b85882
del logger error and fix error message
Apr 25, 2018
7eb9e1c
fix RTE message in ReferenceCountedACLCache class
Apr 26, 2018
fb36cf8
Merge remote-tracking branch 'upstream/master'
brettKK Apr 27, 2018
4df1044
merge with new apache master
brettKK Apr 27, 2018
841cc4f
fix test
brettKK Apr 27, 2018
b1c4856
add a test , and need to do
Apr 27, 2018
ddf1c6c
del test file
brettKK Apr 29, 2018
86910c6
apply anmolnar's patch
brettKK May 4, 2018
843e3db
Merge remote-tracking branch 'upstream/master' into ZOOKEEPER-3008
brettKK Jun 1, 2018
974d8b5
ZOOKEEPER-3027: Accidently removed public API of FileTxnLog.setPreall…
anmolnar Apr 27, 2018
4d07262
ZOOKEEPER-2988: NPE triggered if server receives a vote for a server …
Apr 30, 2018
aa6d016
ZOOKEEPER-2982: Re-try DNS hostname -> IP resolution if node connecti…
May 8, 2018
d0536b3
ZOOKEEPER-2901: TTL Nodes don't work with Server IDs > 127
Randgalt May 9, 2018
989a35a
ZOOKEEPER-3012: Fix unit test: testDataDirAndDataLogDir should not us…
anmolnar May 9, 2018
60e592f
ZOOKEEPER-2959: ignore accepted epoch and LEADERINFO ack from observers
May 10, 2018
fe31819
ZOOKEEPER-3038: Cleanup some nitpicks in TTL implementation
anmolnar May 10, 2018
8bfbd4a
ZOOKEEPER-3039: TxnLogToolkit uses Scanner badly
anmolnar May 10, 2018
2234630
ZOOKEEPER-3041: Typo in error message, affects log analysis; charater…
hughobrienjet May 16, 2018
4f9da0d
ZOOKEEPER-3046: added junit timeout to precede 'ant' timeout
lavacat May 21, 2018
97ee54c
ZOOKEEPER-3050: update to the newest version of Jetty
phunt May 22, 2018
a56d309
ZOOKEEPER-3051: Updated jackson to the latest version
phunt May 23, 2018
13f0efa
ZOOKEEPER-2993: Removed 'generated' line from .gitignore
May 23, 2018
dc8e7dd
ZOOKEEPER-1919 Update the C implementation of removeWatches to have i…
anmolnar May 29, 2018
3486086
ZOOKEEPER-3043: QuorumKerberosHostBasedAuthTest fails on Linux box: U…
eolivelli May 30, 2018
d010be3
ZOOKEEPER-2317: Ensure that OSGi versions are valid
timothyjward May 30, 2018
78ff7f0
ZOOKEEPER-2920: Upgrade OWASP Dependency Check to 3.2.1
phunt May 31, 2018
e08f199
ZOOKEEPER-2968: Add C client code coverage tests
May 31, 2018
841e582
Merge branch 'ZOOKEEPER-3008' of https://github.com/brettKK/zookeeper…
brettKK Jun 1, 2018
6f1a618
Merge remote-tracking branch 'upstream/master'
brettKK Jun 1, 2018
32baa8b
Merge branch 'master' into ZOOKEEPER-3008
brettKK Jun 1, 2018
ad6245d
NPE inZOOKEEPER-3008
Mar 28, 2018
5f96907
Merge branch 'ZOOKEEPER-3008' of https://github.com/brettKK/zookeeper…
brettKK Jun 2, 2018
acf8d22
del unuse
Mar 28, 2018
490efd7
keep up with master
Mar 28, 2018
76b56e7
fix jenkins error
Mar 28, 2018
7517635
del catch
Mar 28, 2018
521b441
fix code
Mar 28, 2018
1723a27
recover zookeeper master same with apache:master
brettKK Apr 22, 2018
ca7ba07
fix conficit
brettKK Jun 2, 2018
7a6894a
ZOOKEEPER-3027: Accidently removed public API of FileTxnLog.setPreall…
anmolnar Apr 27, 2018
712151d
conflict
brettKK Jun 2, 2018
890addd
ZOOKEEPER-3027: Accidently removed public API of FileTxnLog.setPreall…
anmolnar Apr 27, 2018
3dfa3f6
NPE inZOOKEEPER-3008
Mar 28, 2018
1193ecc
conflict
brettKK Jun 2, 2018
c451947
fix conflict
brettKK Jun 2, 2018
1cfbe2b
# This is a combination of 11 commits.
Mar 27, 2018
0fd753a
merge info
brettKK Jun 2, 2018
b83abd7
merge
brettKK Jun 2, 2018
eae2702
fix NPE bug
Mar 27, 2018
72d3ded
merge info
brettKK Jun 2, 2018
3fc2f21
fix conflict
brettKK Jun 2, 2018
464f002
recover build.xml
brettKK Jun 2, 2018
ac95ac3
mock
brettKK Aug 12, 2018
47df0e0
mock object
brettKK Aug 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/java/main/org/apache/zookeeper/LoginFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

package org.apache.zookeeper;

import org.apache.zookeeper.common.ZKConfig;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;

public interface LoginFactory {
Login createLogin(final String loginContextName, CallbackHandler callbackHandler, final ZKConfig zkConfig) throws LoginException;
}
31 changes: 31 additions & 0 deletions src/java/main/org/apache/zookeeper/LoginFactoryImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

package org.apache.zookeeper;

import org.apache.zookeeper.common.ZKConfig;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;

public class LoginFactoryImpl implements LoginFactory {
@Override
public Login createLogin(String loginContextName, CallbackHandler callbackHandler, ZKConfig zkConfig) throws LoginException {
return new Login(loginContextName, callbackHandler, zkConfig);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import javax.security.sasl.SaslException;

import org.apache.zookeeper.KeeperException.BadArgumentsException;
import org.apache.zookeeper.LoginFactoryImpl;
import org.apache.zookeeper.common.AtomicFileWritingIdiom;
import org.apache.zookeeper.common.AtomicFileWritingIdiom.WriterStatement;
import org.apache.zookeeper.common.Time;
Expand Down Expand Up @@ -833,7 +834,7 @@ public void initialize() throws SaslException {
authServer = new SaslQuorumAuthServer(isQuorumServerSaslAuthRequired(),
quorumServerLoginContext, authzHosts);
authLearner = new SaslQuorumAuthLearner(isQuorumLearnerSaslAuthRequired(),
quorumServicePrincipal, quorumLearnerLoginContext);
quorumServicePrincipal, quorumLearnerLoginContext, new LoginFactoryImpl());
} else {
authServer = new NullQuorumAuthServer();
authLearner = new NullQuorumAuthLearner();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.apache.jute.BinaryInputArchive;
import org.apache.jute.BinaryOutputArchive;
import org.apache.zookeeper.Login;
import org.apache.zookeeper.LoginFactory;
import org.apache.zookeeper.SaslClientCallbackHandler;
import org.apache.zookeeper.common.ZKConfig;
import org.apache.zookeeper.server.quorum.QuorumAuthPacket;
Expand All @@ -52,7 +53,7 @@ public class SaslQuorumAuthLearner implements QuorumAuthLearner {
private final String quorumServicePrincipal;

public SaslQuorumAuthLearner(boolean quorumRequireSasl,
String quorumServicePrincipal, String loginContext)
String quorumServicePrincipal, String loginContext, LoginFactory loginFactory)
throws SaslException {
this.quorumRequireSasl = quorumRequireSasl;
this.quorumServicePrincipal = quorumServicePrincipal;
Expand All @@ -66,8 +67,8 @@ public SaslQuorumAuthLearner(boolean quorumRequireSasl,
+ "section '" + loginContext
+ "' could not be found.");
}
this.learnerLogin = new Login(loginContext,
new SaslClientCallbackHandler(null, "QuorumLearner"), new ZKConfig());
this.learnerLogin = loginFactory.createLogin(loginContext,
new SaslClientCallbackHandler(null, "QuorumLearner"), new ZKConfig());

Choose a reason for hiding this comment

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

this can be put on above line. makes it more readable.

this.learnerLogin.startThreadIfNeeded();
} catch (LoginException e) {
throw new SaslException("Failed to initialize authentication mechanism using SASL", e);
Expand All @@ -94,7 +95,10 @@ public void authenticate(Socket sock, String hostName) throws IOException {
principalConfig,
QuorumAuth.QUORUM_SERVER_PROTOCOL_NAME,
QuorumAuth.QUORUM_SERVER_SASL_DIGEST, LOG, "QuorumLearner");

if (sc == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same feedback as #495

  1. check the callers and see if it's handled properly. Likely it will be logged there as well. Verify/report.
  2. No need to say exception in an exception. The text of LOG.error line seems like it would have been a good error string for the exception itself.
  3. as previously noted, add a test.

Choose a reason for hiding this comment

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

For #1:
Follower#77,Observer#69,QuorumCnxManager#333 all have same patern:
try { //root caller } catch (IOException e) {//handler code}
#2 and #3, @brettKK .

Choose a reason for hiding this comment

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

Hum, it is hard for me to write a unit test for this bug, any suggestion? @brettKK @anmolnar @phunt @nkalmar @Others

Choose a reason for hiding this comment

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

I will try unit test written by @brettKK ~~

LOG.error("SaslClient object is null while trying to create SASL client");
throw new SaslException("Exception while trying to create SASL client");
}
if (sc.hasInitialResponse()) {
responseToken = createSaslToken(new byte[0], sc, learnerLogin);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

package org.apache.zookeeper.server.quorum.auth;

import org.apache.zookeeper.Login;
import org.apache.zookeeper.LoginFactory;
import org.apache.zookeeper.common.ZKConfig;
import org.junit.Before;
import org.junit.Test;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import javax.security.sasl.SaslException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.Principal;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class SaslQuorumAuthLearnerTest {

private SaslQuorumAuthLearner learner;

@Before
public void setUp() throws SaslException, LoginException {
Configuration configMock = mock(Configuration.class);
when(configMock.getAppConfigurationEntry(any(String.class))).thenReturn(new AppConfigurationEntry[1]);
Configuration.setConfiguration(configMock);
//mock object
Login loginMock = mock(Login.class);
Subject subjectMock = new Subject();
Principal principalMock = mock(Principal.class);
when(principalMock.getName()).thenReturn("hello");
subjectMock.getPrincipals().add(principalMock);
when(loginMock.getSubject()).thenReturn(subjectMock);

LoginFactory loginFactoryMock = mock(LoginFactory.class);
when(loginFactoryMock.createLogin(any(String.class), any(CallbackHandler.class), any(ZKConfig.class))).thenReturn(loginMock);

learner = new SaslQuorumAuthLearner(true, null, "andorContext", loginFactoryMock);
}

@Test(expected = SaslException.class)
public void testNullCheckSc() throws IOException {
assertThat(learner, is(notNullValue()));

Socket socketMock = mock(Socket.class);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(new byte[0]);
when(socketMock.getOutputStream()).thenReturn(byteArrayOutputStream);
when(socketMock.getInputStream()).thenReturn(byteArrayInputStream);

learner.authenticate(socketMock, null);
}
}