Created an in-memory UnboundID LDAP server. The server listens on an unencrypted port and a TLS port. I can bind to it with LDAP on the first port, and LDAPS on the second port. However, I cannot connect to it using startTLS. The error is:
LDAPException(resultCode=53 (unwilling to perform), errorMessage='No
extended operation handler is defined for extended request OID
'1.3.6.1.4.1.1466.20037'.', diagnosticMessage='No extended operation
handler is defined for extended request OID
'1.3.6.1.4.1.1466.20037'.')
Here is how the server is configured:
try {
InMemoryListenerConfig ldapsConfig = InMemoryListenerConfig.createLDAPSConfig("ldaps",
LDAPS_PORT,
getServerSSLContext().getServerSocketFactory());
InMemoryListenerConfig ldapConfig = InMemoryListenerConfig.createLDAPConfig("ldap",
LDAP_PORT);
InMemoryDirectoryServerConfig serverConfig serverConfig = new InMemoryDirectoryServerConfig(BASE_DN);
serverConfig.addAdditionalBindCredentials(BIND_RDN, BIND_PASSWORD);
serverConfig.setListenerConfigs(ldapConfig, ldapsConfig);
server = new InMemoryDirectoryServer(serverConfig);
server.startListening();
} catch (LDAPException e) {
fail(e.getMessage());
}
The message tells me I need to add some kind of handler to the server, but I cannot find an example in the docs I've skimmed.
Related
It is a known problem to use the Java FTPSClient of Apache commons-net with session resumption. Session resumption is a security feature which a FTPS server can require for data connections. The Apache FTPSClient does not support session resumption, and the JDK APIs make it hard to build a custom implementation. There are a couple of workarounds using reflection, see e.g. this answer and this commons-net bug entry.
I use such a workaround (see snipped below) in JDK 11 and tested it against a local FileZilla Server. It works with FileZilla Server 0.9.6, but it doesn't with FileZilla Server 1.2.0, which is the latest version at the time of writing. With that version, when trying to establish a data connection, the server responds with:
425 Unable to build data connection: TLS session of data connection not resumed.
As I said, FileZilla Server 0.9.6 is fine with how I do session resumption, and I made sure that the setting for requiring session resumption is activated.
In FileZilla Server 1.2.0, such settings are now set implicitly and cannot be changed via the GUI, maybe not at all. Are there some server settings that I can tweak for this to work? Or is it an issue with how I implemented the workaround? Does anyone experience similar issues?
This is the workaround I am using:
public class FTPSClientWithSessionResumption extends FTPSClient {
static {
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
System.setProperty("jdk.tls.client.enableSessionTicketExtension", "false");
}
#Override
protected void _connectAction_() throws IOException {
super._connectAction_();
execPBSZ(0);
execPROT("P");
}
#Override
protected void _prepareDataSocket_(Socket socket) throws IOException {
if (useSessionResumption && socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket)_socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
putMethod.setAccessible(true);
Method getHostMethod;
try {
getHostMethod = socket.getClass().getMethod("getPeerHost");
}
catch (NoSuchMethodException e) {
// Running in IKVM
getHostMethod = socket.getClass().getDeclaredMethod("getHost");
}
getHostMethod.setAccessible(true);
Object peerHost = getHostMethod.invoke(socket);
InetAddress iAddr = socket.getInetAddress();
int port = socket.getPort();
putMethod.invoke(cache, String.format("%s:%s", peerHost, port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostName(), port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostAddress(), port).toLowerCase(Locale.ROOT), session);
}
catch (Exception e) {
throw new IOException(e);
}
}
else {
throw new IOException("Invalid SSL Session");
}
}
}
}
The address under which the socket is cached is determined using getPeerHost, getInetAddress().getHostName(), and getInetAddress().getHostAddress(). I tried several combinations of doing or not doing these three, but I always get the same result.
Edit:
Here is a screenshot of the server logs of the full session:
As stated in this StackOverflow post it is possible to tell the JVM that only TLS 1.2 should be used.
Here is the link to the original answer which worked for me: command for java to use TLS1.2 only
You have to add a command line parameter at the start of the JVM in this case this is: java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here>
This simple parameter worked for me, now I can connect and transfer data from a FTP-Server wich runs FileZilla FTP-Server 1.3.0
I have a system where (registered) users have the possibility to add their own SMTP server for mail sending. Thus I don't know in advance what server a user might add and whether this one supports SMTPUTF8. Now starting from JavaMail 1.6 support for SMTPUTF8 has been added.
After enabling this for some servers the following line is printed to the log:
mail.mime.allowutf8 set but server doesn't advertise SMTPUTF8 support
This is correct for that server, however how can I detect whether a server supports this or not? I see two possibilities:
Somehow detect whether a mail server supports SMTPUTF8 - if that is possible?
Add another parameter to the stmp configuration and then the users decide (which in most cases they don't really know I would guess)
So is there a way to detect whether a server supports SMTPUTF8?
I checked the implementation and the com.sun.mail.SMTPTransport seems to provide such a query possibility.
public boolean supportsExtension(String ext)
So calling
SMTPTransport transport = new SMTPTransport(...);
boolean smtputf8 = transport.supportsExtension("SMTPUTF8");
should work. It is using an EHLO command (defined in rfc1869) when connecting to the server. However in my implementation I just call
...
Transport.send(Message msg);
So I do not directly access SMTPTransport. One should not directly access com.sun packages, right?
Using ESMTP with the EHLO command one can query the smtp server for supported extensions. mail.smtp.ehlo=true; must be enabled.
boolean detectUTF8(String smtpServerHost, int smtpServerPort, String smtpUserName, String smtpUserAccessToken) {
Transport transport = null;
try {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props);
//session.setDebug(true);
transport = session.getTransport();
transport.connect(smtpServerHost, smtpServerPort, smtpUserName, smtpUserAccessToken);
if(transport instanceof SMTPTransport || transport instanceof SMTPSSLTransport) {
return ((SMTPTransport)transport).supportsExtension("SMTPUTF8");
}
return false;
}
catch (Exception ex) {
//Proper loggin & exception handling!!!
//return false;
}
finally {
if(transport!=null) {
try {
transport.close();
}
catch (MessagingException e) {
}
}
}
}
It would be nice if the supportsExtension(...) method would make it into the Transport interface so that javax.mail could be used.
I'd like to send mail from my GAE project. I've followed the documentation example...
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try {
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("xxx#xxxx.appspotmail.com", "Example.com Admin"));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress("xxxxx#gmail.com", "Mr. User"));
msg.setSubject("Your Example.com account has been activated");
msg.setText("This is a test");
Transport.send(msg);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
After deployment, I get this exception message
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;
But the documentation says that:
When you create a JavaMail Session, if you do not provide any SMTP server configuration, App Engine uses the Mail service for sending messages
But it seems to try connecting to a SMTP server... and obviously there is no SMTP server on localhost...
I've never used this service... my quotas are full available.
Please, help me !
had the same issue today. just got it working. app engine sdk already includes the classes you will need to send email:
https://cloud.google.com/appengine/docs/standard/java/javadoc/com/google/appengine/api/mail/MailService.Message
that and the related classes are the way to invoke the mail service. replace your message classes with those, remove all references to javax.mail. one other thing in case you're referencing this (as I was):
https://cloud.google.com/appengine/docs/standard/java/mail/sending-mail-with-mail-api
I couldn't get it to work, doesn't looks like it would without an smtp host at least. Nice of google to provide nonsensical documentation for a non-working example in their example code base
also, if you follow the "who can send mail" link it tells you that any address of the form anything#[APP_NAME].appspotmail.com or anything#[APP_ALIAS].appspotmail.com should work. using my apps name resulted in "unauthorized sender", but using the app id from the dashboard worked. what should have been a ten minute solution turned into hours of drudgery, but I have a working emailer. thanks, google.
The Mail service API supports the JavaMail (javax.mail) interface which is included with the App Engine SDK. Using any other jars may create the issue. You may follow the code sample in Java 7 and Java 8 which demonstrate how to send mail.
I should note that outbound connections on ports 25, 465, and 587 are not allowed due to spam concerns, so the sender address of a message must be one of the optioned in this link.
You can take your application ID/name (which is the same as the project ID/name) through the dashboard.
Kindly note that Issue Tracker is reserved for reporting bugs and feature requests. If you encounter any issue related to APP_NAME or APP_ALIAS, it is recommended to report the issue there so that we would be able to dig into the problem.
How to get a list of active users from ActiveMQ server, for ActiveMQ client in iOS?
Code, I've used to create a client
let host = "10.10.10.10"
let port = 61613
let login = "admin"
let password = "admin"
//inital connection
func createClient() -> Void {
let crvStompClient = CRVStompClient(host: host, port: UInt(port), login: login, passcode: password, delegate: self, autoconnect: true)
crvStompClient?.connect()
}
Connection with ActiveMQ server is successful.
Here is list of all delegate methods, available with CRVStompClient iOS client lib.
// Delegates
- (void)stompClient:(CRVStompClient *)stompService messageReceived:(NSString *)body withHeader:(NSDictionary *)messageHeader;
#optional
- (void)stompClientDidDisconnect:(CRVStompClient *)stompService;
- (void)stompClientWillDisconnect:(CRVStompClient *)stompService withError:(NSError*)error;
- (void)stompClientDidConnect:(CRVStompClient *)stompService;
- (void)serverDidSendReceipt:(CRVStompClient *)stompService withReceiptId:(NSString *)receiptId;
- (void)serverDidSendError:(CRVStompClient *)stompService withErrorMessage:(NSString *)description detailedErrorMessage:(NSString *) theMessage;
None of these are providing active users list. Now, how to get a list of active users (connected with) from ActiveMQ server?
(my source code is in Swift 3 and lib source code is available in Objective-C)
I am using ActiveMQ 5.8.0, which supports AMQP 1.0 as a queue broker. I am trying to communicate with this from a Java client using the Qpid AMQP1.0 client jms library but do not see a method of specifying keystore and truststore information.
I have successfully configured a client by passing in the SSL credentials via the Java VM options (e.g. -Djavax.net.ssl.keyStore), however this is not an acceptable method for my final solution... I need to be able to specify this information from within the code.
I am currently using the createFromURL method to generate the connection from a URL that includes SSL parameters as defined here, but the keystore information (and potentially failover params) do not appear to be parsed from the URL.
String connectionUrl = "amqps://localhost/?brokerlist='tcp://localhost:5671?ssl='true'&key_store='C:/apache-activemq-5.8.0/conf/client.ks'&key_store_password='password'&trust_store='C:/apache-activemq-5.8.0/conf/client.ts'&trust_store_password='password'";
ConnectionFactoryImpl connectionFactory = ConnectionFactoryImpl.createFromURL(connectionUrl);
Does anyone know a better way of providing the security information into the connection?
Update:
Right, so doing some digging through the API I have identified that the library uses the Default SSLSocketFactory
See: org.apache.qpid.amqp_1_0.client.Connection
final Socket s;
if(ssl)
{
s = SSLSocketFactory.getDefault().createSocket(address, port);
}
Therefore, there seems no way of specifying this information outside of the JVM options to set the default values... at least in the current version of the Qpid client library.
The connection URL parameters for the QPID JMS AMQP 1.0 client are a little bit different than the parameters for the previous AMQP version.
Here is an example for a connection URL that works for the 1.0 client:
amqp://myhost:myport?ssl=true&ssl-cert-alias=myalias&clientid=myclientid&remote-host=default&sync-publish=false&trust-store=C:/trusstore.ts&trust-store-password=mytrustkeypass&key-store=C:/keystore.ks&key-store-password=mykeypass
see also this link
Is the URL the right place to put the SSL parameters?
Should the ConnectionFactory not be getting a javax.net.ssl.SSLContext and then creating the connection?
(I'm not familiar with the particulars of the ActiveMQ API.)
For version 0.9.0 of QPid, which supports AMQP version 1.0.0, the client configuration page at QPID can also help with doing this programmatically.
I've also provided sample code of a successful program (NOTE: config is a class I created that stores all my configuration values):
String ampqProtocol = "amqp";
List<String> queryVariables = new ArrayList<String>();
if(config.isUseSSL()) {
queryVariables.add("transport.keyStoreLocation="+config.getKeyStorePath());
queryVariables.add("transport.keyStorePassword="+config.getKeyStorePassword());
queryVariables.add("transport.trustStoreLocation="+config.getTrustStorePath());
queryVariables.add("transport.trustStorePassword="+config.getTrustStorePassword());
queryVariables.add("transport.keyAlias="+config.getKeyStoreAlias());
queryVariables.add("transport.contextProtocol="+config.getSslProtocol());
queryVariables.add("transport.verifyHost="+!config.isDontValidateSSLHostname());
ampqProtocol = "amqps";
}
String connectionString = ampqProtocol+"://"+config.getAddress()+":"+config.getPort();
if(!queryVariables.isEmpty()) {
try {
connectionString += "?"+URLEncoder.encode(StringUtils.join(queryVariables, "&"), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
env.put("connectionfactory.myFactoryLookup", connectionString);
Context context = null;
ConnectionFactory connectionFactory = null;
try {
context = new InitialContext(env);
connectionFactory = (ConnectionFactory) context.lookup("myFactoryLookup");
} catch (NamingException e) {
e.printStackTrace();
}
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
} catch (JMSException e) {
e.printStackTrace();
}