X509TrustManager unsafe implementation but no such method is used on the code - android-security

I got this mail rejecting my new uploaded app on play store
Your app(s) listed at the end of this email use an unsafe
implementation of the interface X509TrustManager. Specifically, the
implementation ignores all SSL certificate validation errors when
establishing an HTTPS connection to a remote host, thereby making your
app vulnerable to man-in-the-middle attacks.
To properly handle SSL certificate validation, change your code in the
checkServerTrusted method of your custom X509TrustManager interface to
raise either CertificateException or IllegalArgumentException whenever
the certificate presented by the server does not meet your
expectations.
While taking a look on the code I found no such method (checkServerTrusted - X509TrustManager). only X509EncodedKeySpec is used for the In-App Billing.
package util;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
public class Security {
private static final String TAG = "IABUtil/Security";
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||
TextUtils.isEmpty(signature)) {
Log.e(TAG, "Purchase verification failed: missing data.");
return false;
}
PublicKey key = Security.generatePublicKey(base64PublicKey);
return Security.verify(key, signedData, signature);
}
public static PublicKey generatePublicKey(String encodedPublicKey) {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
Log.e(TAG, "Invalid key specification.");
throw new IllegalArgumentException(e);
} catch (Base64DecoderException e) {
Log.e(TAG, "Base64 decoding failed.");
throw new IllegalArgumentException(e);
}
}
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (!sig.verify(Base64.decode(signature))) {
Log.e(TAG, "Signature verification failed.");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "NoSuchAlgorithmException.");
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
} catch (Base64DecoderException e) {
Log.e(TAG, "Base64 decoding failed.");
}
return false;
}
}
How can this code be modified to fix the above issue? Need help to fix it.

Related

JMS listener with netty TCP

I'm trying to develop Netty using TCP. I am using the IBM MQ client to connect to the MQ broker, and the idea is I need to develop a TCP server that receives a message passes it to MQ and if the server responds send it to the client that sent the request. Therefore, I need to implement a JMS listener for async message. The problem is that the JMS listener is outside of the Netty channel and I'm trying to figure out how to read the message add it to a Netty channel and send it immediately to the client connected to TCP socket. I can send messages perfectly. The problem is when the server responds. I receive the message, get the context/channel from the clientConnectionProvider and I writeAndFlush, but I don't see the message arrive at the client.
I create the listener in the main class.
public class Main {
private final Integer port;
private final Destination sendDestination;
private final JMSContext jmsSendContext;
private final JMSConsumer consumer;
private final JMSContext jmsRecieveContext;
private final Destination consumerDestination;
private final ClientConnectionProvider clientConnectionProvider;
public Main(Properties properties)
throws JMSException {
if (properties.containsKey(ConfigurationEnum.SERVER_PORT) {
this.port = properties.getProperty(ConfigurationEnum.SERVER_PORT)
} else {
log.error("server.port not defined in properties"
throw new ConfigException(
String.format("server.port not defined in properties");
}
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(JmsConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
// Set the properties
cf.setStringProperty(CommonConstants.WMQ_HOST_NAME,
properties.getProperty(ConfigurationEnum.IBM_MQ_HOST.getValue()));
cf.setIntProperty(CommonConstants.WMQ_PORT,
Integer.parseInt(properties.getProperty(ConfigurationEnum.IBM_MQ_PORT.getValue())));
cf.setStringProperty(CommonConstants.WMQ_CHANNEL,
properties.getProperty(ConfigurationEnum.IBM_MQ_CHANNEL.getValue()));
cf.setIntProperty(CommonConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(CommonConstants.WMQ_QUEUE_MANAGER,
properties.getProperty(ConfigurationEnum.IBM_QUEUE_MANAGER.getValue()));
cf.setStringProperty(CommonConstants.WMQ_APPLICATIONNAME, "FIX Orchestra Gateway");
cf.setBooleanProperty(JmsConstants.USER_AUTHENTICATION_MQCSP, true);
cf.setStringProperty(JmsConstants.USERID, properties.getProperty(ConfigurationEnum.IBM_APP_USER.getValue()));
cf.setStringProperty(JmsConstants.PASSWORD, properties.getProperty(ConfigurationEnum.IBM_APP_PASS.getValue()));
clientConnectionProvider = new ClientConnectionProvider();
jmsRecieveContext = cf.createContext();
consumerDestination = jmsRecieveContext
.createQueue(properties.getProperty(ConfigurationEnum.IBM_QUEUE_CONSUMER.getValue()));
consumer = jmsRecieveContext.createConsumer(consumerDestination);
consumer.setMessageListener(new JMSMessageListener(clientConnectionProvider));
jmsRecieveContext.start();
jmsSendContext = cf.createContext();
sendDestination = jmsSendContext
.createQueue(properties.getProperty(ConfigurationEnum.IBM_QUEUE_TRANSACTION.getValue()));
}
public void start() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(10);
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100).option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new DefaultChannelInitializer());
// Start the server.
ChannelFuture f = serverBootstrap.bind(port).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
jmsRecieveContext.stop();
jmsRecieveContext.close();
jmsSendContext.close();
}
}
public static void main(String[] args) throws InterruptedException {
Properties properties = new Properties();
try (InputStream inputStream = new FileInputStream(args[0])) {
properties.load(inputStream);
new Main(properties).start();
} catch (FileNotFoundException e) {
log.error("Properties file specified in path {} was not found.", args[0], e);
} catch (IOException e) {
log.error("There was an IO error.", e);
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConfigException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The listener is a simple class.
#AllArgsConstructor
public class JMSMessageListener implements MessageListener {
private final ClientConnectionProvider clientConnectionProvider;
#Override
public void onMessage(Message message) {
try {
String messageString = message.getBody(String.class);
if (clientConnectionProvider.contains(ClientID.get(messageString))) {
ClientConnection cc = clientConnectionProvider.getConnection(ClientID.get(messageString));
if (cc.getCtx() == null) {
// TODO: Need to save message when client reconects
} else {
cc.getCtx().channel().write(messageString);
}
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
You should call writeAndFlush(...) and attach a ChannelFutureListener to the ChannelFuture returned to it. In the listener you can check if the write did succeed or fail (and if so print the exception). In your current code you only call write(...) which only put the message in the outboundbuffer of the Channel but not actually flush it to the socket.

Why would BizTalk 2016 kill custom pipeline component threads?

I have a BizTalk Custom Pipeline Component that writes an SFTP file (using SSH.net), triggered by an SFTP (WinSCP) receive location.
The code within the Retry occasionally (around half the time) does not hit either the "Success" nor the logging catch block and no further processing occurs within the Pipeline. I assume that means the thread has been destroyed.
I added the Retry code later to make it try a few times but with the thread being destroyed I don't always get a success or 3 failures.
What could cause this behaviour in BizTalk 2016?
public void Archive(byte[] content,
string archivePath,
string userName,
string password,
string serverAddress,
string sshHostKeyFingerprint)
{
Retry(3, () =>
{
try
{
using (var sftpClient = new SftpClient(serverAddress, userName, password))
{
if (!string.IsNullOrWhiteSpace(sshHostKeyFingerprint))
{
sshHostKeyFingerprint = sshHostKeyFingerprint.Split(' ').Last();
sftpClient.HostKeyReceived += delegate (object sender, HostKeyEventArgs e)
{
if (e.FingerPrint.SequenceEqual(ConvertFingerprintToByteArray(sshHostKeyFingerprint)))
e.CanTrust = true;
else
e.CanTrust = false;
};
}
sftpClient.Connect();
sftpClient.WriteAllBytes(archivePath, content);
sftpClient.Disconnect();
LogInfo($"Success");
}
}
catch (Exception exception)
{
// show the bad path for "No such file" errors
throw new InvalidOperationException($"Failed to create file '{archivePath}'", exception);
}
});
}
private void Retry(int maxAttempts, Action action)
{
int attempt = 1;
while (attempt <= maxAttempts)
{
try
{
action();
break; // success
}
catch (Exception exception)
{
LogWarning($"Attempt {attempt} Error: {exception.ToString()}");
if (attempt == maxAttempts)
throw; // final attempt exception propagated
}
finally
{
attempt++;
}
}
}

Which is the best way to validate current password?

I created a form where the user can update his data account. In this form the user is also able to change the account password, before doing so, I ask him the current password, this is the field:
<div class="form-group">
<label>Current Password</label>
<input class="form-control" id="oldPassword"
asp-for="#Model.ExistingPassword" type="password" />
<div class="invalid-feedback"></div>
</div>
as you can see the oldPassword input bound the property ExistingPassword which is part of the ViewModel of that View and have the following declaration:
[Required, MinLength(6), MaxLength(50), DataType(DataType.Password)]
public string ExistingPassword { get; set; }
when the form is submitted I call the following ajax function:
$.post(url, user, function (response) {
//Some stuff
}).done(function (response) {
alert("Updated executed");
}).fail(function (jqXHR, textStatus, errorThrown) {
alert("Error happened!");
});
the parameter of the function are taken by the form, in particular:
url: $(this).attr('action');
user: $(this).serialize();
the action of the form will call the following controller: User\UpdateUser.
Inside the UpdateUser method I execute the following check:
public async Task<UserProfileViewModel> UpdateUserAsync(UserProfileViewModel updatedUser)
{
if (!await _userManager.CheckPasswordAsync(originalUser, updatedUser.ExistingPassword))
throw new Exception("Invalid password");
essentially, the condition check if the current password is correct, if not, then an exception will raised.
Now, my question with this is: how can I know which type of exception the method has generated?
I need to know which type of exception the method UpdateUser has generated because there are different exceptions in the method.
Suppose the Invalid Password exceptions is raised, I need to display a message inside invalid-feedback div, next to oldPassword, so the user know why the update has failed.
Thanks in advance for any help.
Normally, I recommend not using an exception except in actual exception circumstances, but given the way you've designed this, you have a few options.
I'd suggest creating a custom "UpdateUserException" that you can throw that will include additional information, which can be provided by an enum or just string.
public class UpdateUserException : Exception {
public UpdateUserError ErrorCondition;
public UpdateUserException(UpdateUserError error, string message)
{
ErrorCondition = error;
Message = message;
}
}
then you would throw it
throw new UpdateUserException(UpdateUserError.BadPassword, "Invalid Password");
then you would catch it
try {}
catch (UpdateUserException e)
{
if (e.ErrorCondition == UpdateUserException.BadPassword)
{
// handle your exception.
}
}
Have a look at the UserManager ChangePassword Method.
You can bind the UserManager to use DependencyInjection like this (in Startup.cs)
public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
app.UseMvc();
var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
UserManager<User> userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
}
}
And then in your Controller s Constructor
private readonly UserManager<User> _userManager;
public AccountController(UserManager<User> userManager)
{
_userManager = userManager;
}
And finally your endpoint:
[HttpPost("ChangePassword")]
public async Task<IActionResult> ChangePassword([FromBody]ChangePasswordRequest changePasswordParams)
{
if (changePasswordParams == null)
return BadRequest($"{nameof(changePasswordParams)} must not be null!");
if (string.IsNullOrWhiteSpace(changePasswordParams.OldPassword) || string.IsNullOrWhiteSpace(changePasswordParams.NewPassword))
return BadRequest("old and new passwords have to be provided, but they both are empty.");
var userId = User.Claims.FirstOrDefault(c => c.Type == "id")?.Value;
var user = await _userManager.FindByIdAsync(userId);
var result = await _userManager.ChangePasswordAsync(user, changePasswordParams.OldPassword, changePasswordParams.NewPassword);
if (result.Succeeded)
return NoContent();
return BadRequest(result.Errors);
}
after that you can handle the errors in a switch statement.
Using Exceptions for handled errors are not recommended since they generally ends up with Internal Server error and actually It is beyond of its purpose.
The best approach would be to send BadRequest as It is stated by #maerlin.
However, If you insist to use Exceptions in your application or your applciation is architected to work in this way. I suggest you to inherit new CustomApplcationException class from ApplicationException and then inherit UpdateUserException and vs. from CustomApplicationException class. After that, I Suggest you to handle your exceptions in ErrorHandlingMiddleware and return HandledExceptions at least with BadRequest (400) status code.
The Example Code would be
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILoggerManager _logger;
public ExceptionMiddleware(RequestDelegate next, ILoggerManager logger)
{
_logger = logger;
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (CustomApplicationException cae)
{
await HandleCustomExceptionAsync(httpContext, cae);
}
catch (Exception ex)
{
_logger.LogError($"Something went wrong: {ex}");
await HandleExceptionAsync(httpContext, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return context.Response.WriteAsync(new ErrorDetails()
{
StatusCode = context.Response.StatusCode,
Message = "Internal Server Error from the custom middleware."
}.ToString());
}
private static Task HandleCustomExceptionAsync(HttpContext context, Exception exception)
{
context.Response.StatusCode = 400;
return context.Response.WriteAsync(new ErrorDetails()
{
StatusCode = context.Response.StatusCode,
Message = exception.Message
}.ToString());
}
}
then you need to regiter middleware in your Startup.cs
app.UseMiddleware<ExceptionMiddleware>();
please see https://code-maze.com/global-error-handling-aspnetcore/ and http://www.talkingdotnet.com/global-exception-handling-in-aspnet-core-webapi/ for further details.

rxjava - how to handle exception within map()

I am new to RxJava and still exploring its wonders.
I am transforming the Response object into a LoginSession object using map() operator but there can be an IOException thrown during transformation. Following is the example code.
Observable
public Observable<LoginSession> login(#NonNull String username, #NonNull String password) {
return Observable.create(new Observable.OnSubscribe<Response>() {
#Override
public void call(Subscriber<? super Response> subscriber) {
loginInternal(username, password, subscriber);
}
}).map(response -> {
try {
LoginSession session = Utils.methodThatCanReturnAnIoException(response.body().byteStream(), LoginSession.class);
return session;
} catch(IOException e){
return null; // what should I do here ????
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread());
}
Subscriber
login("username", "password").subscribe( loginSession -> {
//i hate checking for null here. there should be a better way...
if(loginSession != null){
Log.d("MY_SESSION", "Login session successful.");
} else {
Log.d("MY_SESSION", "Login Session is null unfortunately.");
}
});
What is the best way to handle this scenario? except checking for null in subscribe() which I am sure not the best way of doing it.
The pattern you are after is to use flatMap:
public Observable<LoginSession> login(#NonNull String username, #NonNull String password) {
return Observable.create(new Observable.OnSubscribe<Response>() {
#Override
public void call(Subscriber<? super Response> subscriber) {
loginInternal(username, password, subscriber);
}
}).flatMap(response -> {
try {
LoginSession session = Utils.methodThatCanReturnAnIoException(response.body().byteStream(), LoginSession.class);
return Observable.just(session);
} catch(IOException e){
return Observable.error(e);
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread());
}
Then use the onError method in the subscriber.

Jersey2 Client reuse not working AsyncInvoker

I am trying to reuse a Jersey2(Jersey 2.16) Client for async invocation. However after 2 requests, I see that the threads going into a waiting state, waiting on a lock. Since client creation is an expensive operation, I am trying to reuse the client in the async calls. The issue occurs only with ApacheConnectorProvider as the connector class. I want to use ApacheConnectorProvider, as I need to use a proxy and set SSL properties and I want to use PoolingHttpClientConnectionManager.
The sample code is given below:
public class Example {
Integer eventId = 0;
private ClientConfig getClientConfig()
{
ClientConfig clientConfig = new ClientConfig();
ApacheConnectorProvider provider = new ApacheConnectorProvider();
clientConfig.property(ClientProperties.REQUEST_ENTITY_PROCESSING,RequestEntityProcessing.BUFFERED);
clientConfig.connectorProvider(provider);
return clientConfig;
}
private Client createClient()
{
Client client = ClientBuilder.newClient(getClientConfig());
return client;
}
public void testAsyncCall()
{
Client client = createClient();
System.out.println("Testing a new Async call on thread " + Thread.currentThread().getId());
JSONObject jsonObject = new JSONObject();
jsonObject.put("value", eventId++);
invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
client.close();
}
private void invoker(Client client, String URI, JSONObject jsonObject)
{
final Future<Response> responseFuture = client.target(URI)
.request()
.async()
.post(Entity.entity(jsonObject.toJSONString(), MediaType.TEXT_PLAIN));
try {
Response r = responseFuture.get();
System.out.println("Response is on URI " + URI + " : " + r.getStatus());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[])
{
Example client1 = new Example();
client1.testAsyncCall();
return;
}
}
The response I see is:
Testing a new Async call on thread 1
Response is on URI http://requestb.in/nn0sffnn : 200
Response is on URI http://requestb.in/nn0sffnn : 200
On looking at the thread stack, I see the following trace:
"jersey-client-async-executor-0" prio=6 tid=0x043a4c00 nid=0x56f0 waiting on condition [0x03e5f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x238ee148> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:133)
at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:282)
at org.apache.http.pool.AbstractConnPool.access$000(AbstractConnPool.java:64)
at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:177)
at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:170)
Can someone give me a suggestion as to how to reuse Client objects for async requests and may be how to get over this issue as well.

Resources