I know cleartext been disabled by default by android. May I know where exactly I can enable in aosp instead of adding in all packages with network config files?
Where I can permit by adding the below line?
cleartextTrafficPermitted="true
external/okhttp/android/main/java/com/squareup/okttp/Handler
public static OkUrlFactory createHttpOkUrlFactory(Proxy proxy) {
OkHttpClient client = new OkHttpClient();
// Explicitly set the timeouts to infinity.
client.setConnectTimeout(0, TimeUnit.MILLISECONDS);
client.setReadTimeout(0, TimeUnit.MILLISECONDS);
client.setWriteTimeout(0, TimeUnit.MILLISECONDS);
// Set the default (same protocol) redirect behavior. The default can be overridden for
// each instance using HttpURLConnection.setInstanceFollowRedirects().
client.setFollowRedirects(HttpURLConnection.getFollowRedirects());
// Do not permit http -> https and https -> http redirects.
client.setFollowSslRedirects(false);
// Permit cleartext traffic only (this is a handler for HTTP, not for HTTPS).
client.setConnectionSpecs(CLEARTEXT_ONLY);
// When we do not set the Proxy explicitly OkHttp picks up a ProxySelector using
// ProxySelector.getDefault().
if (proxy != null) {
client.setProxy(proxy);
}
// OkHttp requires that we explicitly set the response cache.
OkUrlFactory okUrlFactory = new OkUrlFactory(client);
// Use the installed NetworkSecurityPolicy to determine which requests are permitted over
// http.
OkUrlFactories.setUrlFilter(okUrlFactory, CLEARTEXT_FILTER);
ResponseCache responseCache = ResponseCache.getDefault();
if (responseCache != null) {
AndroidInternal.setResponseCache(okUrlFactory, responseCache);
}
return okUrlFactory;
}
private static final class CleartextURLFilter implements URLFilter {
#Override
public void checkURLPermitted(URL url) throws IOException {
String host = url.getHost();
if (!NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted(host)) {
throw new IOException("Cleartext HTTP traffic to " + host + " not permitted");
}
}
}
In any apps if I use http, I get error as Cleartext HTTP traffic to 124.60.5.6 not permitted";
So instead of changing in apps, is it possible to change in aosp?
Seems like its enough if you do
builder.setCleartextTrafficPermitted(true);
in line 189 seems sufficient since you are using older applications which probably doesn't have any network config and only uses default ones.
source: https://android.googlesource.com/platform/frameworks/base.git/+/refs/heads/master/core/java/android/security/net/config/NetworkSecurityConfig.java#189
Old Answer
I hope you have done your homework on the implications on bypassing a security feature. That being said, the class responsible for the exception is in framework with package android.security.net.config and class responsible is NetworkSecurityConfig.
As of writing this answer, the static builder class has a property boolean mCleartextTrafficPermittedSet which is set to false by default. You might have to default it to true which makes the method getEffectiveCleartextTrafficPermitted() in the NetworkSecurityConfig class return mCleartextTrafficPermitted which in return returns DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED which is by default set to true
The flow would be
getEffectiveCleartextTrafficPermitted() returns mCleartextTrafficPermitted returns DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED returns true by default.
If this is all confusing, call setCleartextTrafficPermitted(true) on the builder whenever the builder is created.
The source for the class is available here: https://android.googlesource.com/platform/frameworks/base.git/+/refs/heads/master/core/java/android/security/net/config/NetworkSecurityConfig.java
Note: I have not tried this and merely gone through the source and inferred the above. You are welcome to try and correct me if something is wrong.
Edit by updating from #Shadow:
In NetworkSecurityConfig, change the boolean variable from true to false.
//public static final boolean DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED = true;
public static final boolean DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED = false;
Also in ManifestConfigSource, comment the below line,
/*boolean usesCleartextTraffic =
(mApplicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0
&& mApplicationInfo.targetSandboxVersion < 2;*/
and directly apply as usesCleartextTraffic as true.
boolean usesCleartextTraffic =true;
You need to go to AndroidManifest.xml and add
<application
android:usesCleartextTraffic="true"
android:networkSecurityConfig="#xml/network_security_config"
....
</application>
I strongly advise that you create the network_security_config to only allow your domain and subdomain. Here is a quick tutorial
Related
I would like to use the Jira REST Client API for Java in an application that needs to go through a proxy to access the desired Jira instance. Unfortunately I didn't find a way to set it when using the given factory from that library:
JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
String authentication = Base64.getEncoder().encodeToString("username:password".toBytes());
return factory.createWithAuthenticationHandler(URI.create(JIRA_URL), new BasicAuthenticationHandler(authentication));
How can we use the Jira API and set a proxy ?
The only solution I found on the internet was to set it with system parameters (see solution 1 below). Unfortunately that did not fit my requirements as in the company I work for, there are multiple proxies and depending on the service to call, it has to use another proxy configuration. In that case, I cannot set the system properties without destroying all calls to other services that would need another proxy.
Nevertheless, I was able to find a way to set it by re-implementing some classes (see solution 2).
Important limitation: the proxy server must not ask for credentials.
Context
Maybe as context before, I created a class containing proxy configuration:
#Data
#AllArgsConstructor
public class ProxyConfiguration {
public static final Pattern PROXY_PATTERN = Pattern.compile("(https?):\\/\\/(.*):(\\d+)");
private String scheme;
private String host;
private Integer port;
public static ProxyConfiguration fromPath(String path) {
Matcher matcher = PROXY_PATTERN.matcher(path);
if (matcher.find()) {
return new ProxyConfiguration(matcher.group(1), matcher.group(2), toInt(matcher.group(3)));
}
return null;
}
public String getPath() {
return scheme + "://" + host + ":" + port;
}
}
Set system properties for proxy
Call the following method with your proxy configuration at the start of the application or before using the Jira REST API:
public static void configureProxy(ProxyConfiguration proxy) {
if (proxy != null) {
System.getProperties().setProperty("http.proxyHost", proxy.getHost());
System.getProperties().setProperty("http.proxyPort", proxy.getPort().toString());
System.getProperties().setProperty("https.proxyHost", proxy.getHost());
System.getProperties().setProperty("https.proxyPort", proxy.getPort().toString());
}
}
Re-implement AsynchronousHttpClientFactory
Unfortunately, as this class has many private inner classes and methods, you will have to do an ugly copy paste and change the following code to give the wanted proxy configuration:
public DisposableHttpClient createClient(URI serverUri, ProxyConfiguration proxy, AuthenticationHandler authenticationHandler) {
HttpClientOptions options = new HttpClientOptions();
if (proxy != null) {
options.setProxyOptions(new ProxyOptions.ProxyOptionsBuilder()
.withProxy(HTTP, new Host(proxy.getHost(), proxy.getPort()))
.withProxy(HTTPS, new Host(proxy.getHost(), proxy.getPort()))
.build());
}
DefaultHttpClientFactory<?> defaultHttpClientFactory = ...
}
You can then use it (in the following example, my re-implementation of AsynchronousHttpClientFactory is called AtlassianHttpClientFactory):
URI url = URI.create(JIRA_URL);
String authentication = Base64.getEncoder().encodeToString("username:password".toBytes());
DisposableHttpClient client = new AtlassianHttpClientFactory().createClient(url, proxy, new BasicAuthenticationHandler(authentication));
return new AsynchronousJiraRestClient(url, client);
Note that after all those problems, I also decided to write a Jira client library supporting authentication, proxy, multiple HTTP clients and working asynchronously with CompletableFuture.
I am trying to create an instance using the Cloud API Client Library for Java. I have worked my way through the different Builder classes, using the "Equivalent REST" button in the console to see what items I might be missing, but now the call to insertInstance() is returning an UnavailableException. Checking in the console I see nothing was created. Who can help me find what I did wrong? All the URLs seem to be correct: when they are not I get a helpful exception with detailed errors.
The SETUP_NO_BOT constant is the text of my setup script, which creates a user, copies files from a bucket, that sort of stuff. That should not be the problem however, because then I would expect a running VM with errors in the startup logs.
All the examples I could find either used the older com.google.api.services packages or the com.google.cloud.compute.deprecated packages, and neither use a comparable class structure.
If I use the same code with a mistake in the URLs (now produced by getUrl() calls) I get a nice error return. This version consistently returns a 503.
private Instance createInstance() {
logger.debug("createInstance(): Creating boot disk based on \"{}\".", getBaseImage());
AttachedDiskInitializeParams diskParams;
if (ifSet(getBaseImageProject())) {
diskParams = AttachedDiskInitializeParams.newBuilder()
.setSourceImage(getUrl(getBaseImageProject(), "images", getBaseImage()))
.setDiskSizeGb("10")
.setDiskType(getUrl(context, "diskTypes", "pd-standard"))
.build();
}
else {
diskParams = AttachedDiskInitializeParams.newBuilder()
.setSourceImage(getUrl("images", getBaseImage()))
.setDiskSizeGb("10")
.setDiskType(getUrl(context, "diskTypes", "pd-standard"))
.build();
}
AttachedDisk disk = AttachedDisk.newBuilder()
.setType("PERSISTENT")
.setBoot(true)
.setMode("READ_WRITE")
.setAutoDelete(true)
.setDeviceName(getName())
.setInitializeParams(diskParams)
.build();
logger.debug("createInstance(): Creating network interface to network \"{}\".", getNetwork());
AccessConfig accessConfig = AccessConfig.newBuilder()
.setName("External NAT")
.setType("ONE_TO_ONE_NAT")
.setNetworkTier("PREMIUM")
.build();
NetworkInterface netIntf = NetworkInterface.newBuilder()
.setNetwork(getUrl(context, "networks", getNetwork()))
.setSubnetwork(getRegionalUrl(context, "subnetworks", "default"))
.addAccessConfigs(accessConfig)
.build();
logger.debug("createInstane(): Creating startup script metadata.");
Items metadataItems = Items.newBuilder()
.setKey("startup-script")
.setValue(SETUP_NO_BOT)
.build();
Metadata metadata = Metadata.newBuilder()
.addItems(metadataItems)
.build();
logger.debug("createInstance(): Create the instance...");
Instance inst = Instance.newBuilder()
.setName(getName())
.setZone(getUrl(context, "zones", context.getZone()))
.setMachineType(getZonalUrl(context, "machineTypes", getMachineType()))
.addDisks(disk)
.setCanIpForward(false)
.addNetworkInterfaces(netIntf)
.setMetadata(metadata)
.build();
return gceUtil.createInstance(inst) ? gceUtil.getInstance(getName()) : null;
}
createInstance is very simple:
/**
* Create an {#link Instance}.
*/
public boolean createInstance(Instance instance) {
logger.debug("createInstance(): project = \"{}\", zone = \"{}\".", getProjectName(), getZoneName());
Operation response = instClient.insertInstance(ProjectZoneName.of(getProjectName(), getZoneName()), instance);
return isHttp2xx(response);
}
I need to change the thread pool of the underlying Grizzly transport layer.
According to the docs of GrizzlyHttpServerFactory:
Should you need to fine tune the underlying Grizzly transport layer, you can obtain direct access to the corresponding Grizzly structures with server.getListener("grizzly").getTransport().
and
To make certain options take effect, you need to work with an inactive HttpServer instance (that is the one that has not been started yet). To obtain such an instance, use one of the below factory methods with start parameter set to false
Since I like to put my self in the worse situations :-) the method I need shuld be:
HttpServer server= GrizzlyHttpServerFactory
.createHttpServer(getURI(), this.config, serviceLocator, false);
but the only method available (nearest to my case) is:
public static HttpServer createHttpServer(final URI uri,
final GrizzlyHttpContainer handler, final boolean secure,
final SSLEngineConfigurator sslEngineConfigurator, final boolean start) {
//....
}
If I understand the GrizzlyHttpContainer is private so I should use:
GrizzlyHttpContainer httpContainer =
new GrizzlyHttpContainerProvider().createContainer(GrizzlyHttpContainer.class, config);
But, since I'm sharing a ServiceLocator between resources and internal classes (a couple of ActiveMQ subscribers). I wonder if it were possible to achieve something like this:
GrizzlyHttpContainer httpContainer =
new GrizzlyHttpContainerProvider()
.createContainer(GrizzlyHttpContainer.class, configuration, serviceLocator);
Ideally what i need is a method like this:
public class GrizzlyHttpContainerProvider implements ContainerProvider {
#Override
public <T> T createContainer(Class<T> type, Application application, Object parentContext) throws ProcessingException {
if (HttpHandler.class == type || GrizzlyHttpContainer.class == type) {
return type.cast(new GrizzlyHttpContainer(application, parentContext));
}
return null;
}
}
Any suggestion about how to achieve this?
I'd would prefer a cleaner solution then creating the server with one of the provided methods that (for my case) auto start the server. Then stop it (waiting for termination somehow) and then finally:
this.server.getListener("grizzly").getTransport().setWorkerThreadPool(....);
and restarting it.
Best Regards,
Luca
Edit
This is cheating :-) ... this is the "dark way" (don't do it at home):
private GrizzlyHttpContainer getGrizzlyHttpContainer(final Application application,
final Object context) {
try {
Class<?> cls = Class.forName(
"org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer");
Constructor<?> cons = cls.getDeclaredConstructor(Application.class, Object.class);
//System.out.println("Constructor Name--->>>"+cons.getName());
cons.setAccessible(true);
return (GrizzlyHttpContainer)cons.newInstance(application, context);
} catch (Exception err) {
return null;
}
}
I need to add certain functionality to an existing ejb projects.
Specifically - the client info, such as IP addres, login credentials (who is connected) and client application name
My bean is a stateless, so I worry there is an issue with such an approach..
My client code currently has the following:
private static MySession getmySession() throws RemoteException {
if(mySession != null) return mySession; //mySession is a private variable
try {
Properties h = new Properties();
h.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
h.put(Context.PROVIDER_URL, serverUrl ); //t3://localhost
InitialContext ctx = new InitialContext(h);
mySessionHome home = (mySessionHome) ctx.lookup( "mySessionEJB" );
mySession = home.create();
return mySession;
} catch(NamingException ne) {
throw new RemoteException(ne.getMessage());
} catch(CreateException ce) {
throw new RemoteException(ce.getMessage());
}
}
Ideally, I would like my 'mySession' know about the client at the point it is returned.
If that may not be possible,
I would like to send a client info at the time a particular method of MySession is called.
Somewhere in this code
public static List getAllMembers() throws RemoteException, CatalogException
{
getMySession();
List list = mySession.getAllMembers() );
return list;
}
There are quite many such methods, so this is less desirable. but I will take it if it solves the task.
At the end of the day, when "getAllMembers()" executes on the server, I want to know particular info of which client has called it. (there can be many different, including webservices)
Thanks
First thing - what are you doing with the client information? If you're planning to use it for auditing, this sounds like a perfect use for Interceptors!
The EJB way to access user information is via the user's Principal, and there's no problem using this in a stateless bean. You may find that this doesn't get all the information you would like - this answer suggests getting the user IP isn't entirely supported.
This code has been taken from org.glassfish.jersey.grizzly2 project, like the method name indicate, createHttpServer should be responsible "only" for creating and returning an instance of the HttpServer class, I just wonder why should the HttpServer.start call be encapsulated in such way ?
public static HttpServer createHttpServer(final URI uri,
final GrizzlyHttpContainer handler,
final boolean secure,
final SSLEngineConfigurator sslEngineConfigurator
final boolean start) {
final String host = (uri.getHost() == null) ? NetworkListener.DEFAULT_NETWORK_HOST : uri.getHost();
final int port = (uri.getPort() == -1) ? DEFAULT_HTTP_PORT : uri.getPort();
final NetworkListener listener = new NetworkListener("grizzly", host, port);
listener.setSecure(secure);
if (sslEngineConfigurator != null) {
listener.setSSLEngineConfig(sslEngineConfigurator);
}
final HttpServer server = new HttpServer();
server.addListener(listener);
// Map the path to the processor.
final ServerConfiguration config = server.getServerConfiguration();
if (handler != null) {
config.addHttpHandler(handler, uri.getPath());
}
config.setPassTraceRequest(true);
if (start) {
try {
// Start the server.
server.start();
} catch (IOException ex) {
throw new ProcessingException(LocalizationMessages.FAILED_TO_START_SERVER(ex.getMessage()), ex);
}
}
return server;
}
This is a public API method, not a class.
Single responsibility principle in wiki says
Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.
SRP is intended for loose coupling and robustness. It definitely helps developers in maintaining the same while keeping it well functioning.
So had it been some internal method or class, I would have agreed.
The design goals of public API are completely different.
First thing you have to make sure about is ease of use.
Your software should hide internal idiosyncrasies of the implementation and design as well.
If a user is calling this method, and is unaware of requirement to call other method for starting, he/she'd be confused. We can not force users to know entire workflow of the software i.e. calling each small step manually.
Hope this helps.
The only advantage I see is that the user has to write less code. I totally disagree with this practice. If it says "create", then it should only create. Anyway, as far as its clearly specified in the documntation, it shoul be "ok" to do that... It's not the worst violation of the SRP I have seen...