Wednesday, June 5, 2013

Uploading files using 2-way SSL connection between Apache Server and Android


In this post I am going to show you how to configure Apache Server(Version 2) for 2-way SSL authentication and HTTP Put and Through the SSL connection upload files from android device to Apache server. 

Software I used for configuring the SSL connection and developing android app are listed below. I configured the system in Windows 7. So I used windows distributions for almost all of these software.
  • Apache server (I used Apache 2.2)
  • OpenSSL Windows executable
  • BouncyCastle Provider
  • Portecle
  • Java Standard Oracle distribution    
  • Eclipse 
  • Eclipse plug-in for Android : Android Development Tools (ADT)  
  • Android SDK

Step 1: 

First you need to generate keys and certificates for both client and server. Download and install OpenSSL Windows executable. This software will be used for creating keys and certificates for 2-way SSL authentication.

(1)Create Certificate Authority (CA)

First create a private key using the following command which will create 1024-bit key and save to the file ca.key.
openssl genrsa -out ca.key 1024

Generate a Certificate Signing Request. The following command will create a a key request ca.csr. 
openssl req -new -key ca.key -out ca.csr -config path/to/openssl.cfg 
Follow the on-screen prompts for the required certificate request information. The most important field is "common name(CN) or fqdn". Here provide your full website domain name(e.g: www.domainname.com). The config file can be with “cfg” or “cnf” extension depending the version of Openssl you installed in your computer.

Now generate a self-signed certificate using the certificate request created above.The following command will create a self-signed certificate "ca.crt" which will be of x509 format  and will have 1 year validity.
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt

(2)Setup the Web Server Certificate

For Apache server, create private key and server certificate using the same commands mentioned above:
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr -config openssl.cfg
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
(3) Install the CA Certificate and Server Certificate on the Apache server

Create a new folder “ssl.crt” in [apache installation folder]/conf/. Copy the CA certificate in the ssl.crt folder.
Open the [apache installation folder]/conf/httpd.cnf file in text editor. Remove the pound sign from the line

LoadModule ssl_module modules/mod_ssl.so 

and

Include conf/extra/httpd_ssl.conf

Open the [apache installation folder]/conf/extra/httpd_ssl.conf.  Path of httpd_ssl.cnf file can be different based on Apache version installed in your computer.

Modify the following section according to your need:
<VirtualHost _default_:443>
    ServerAdmin some@email.com
    DocumentRoot "Your Root folder location"
    ServerName www.domain.com:443
    ServerAlias domain.com:443
    ErrorLog "logs/anyFile-error.log"
    CustomLog "logs/anyFile-access.log" common
    SSLEngine on

    SSLCertificateFile "[apache installation folder]/conf/server.crt"

    SSLCertificateKeyFile "[apache installation folder]/conf/server.key"

    SSLCACertificateFile "[apache installation folder]/conf/ssl.crt/ca.crt"

</VirtualHost>
Make sure the SSLCertificateFile, SSLCertificateKeyFile and SSLCACertificateFile are located in the right locations.Restart the Apache server.

Step 2:

(1)Generate client private key and certificate:

Private Key:
openssl genrsa -out client.key 1024
Certificate request:
openssl req -new -key client.key -out client.csr -config openssl.cfg
Here for common name field, put different name other than you provided when generating certificate authority and server certificate.

Allow the Authority to sign the client certificate:
openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt
Create a PKCS#12 file from the client private key "client. key" and the signed certificate "client.crt":
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12


Step 3:

Converting server and client certificate in Android specific format

Now you have the server certificate “server.crt” and client certificate "client.p12". If you want to use the server and client certificate in android application, you need to convert the certificate in BKS format because android accept only that format.

You can use a tool Portecle to convert the client certificate "client.p12" in BKS format. There is a Java executable in Portecle website which will launch the Portecle UI.  In the UI, go to File -> New Keystore -> BKS.  Then go to Tools -> Import Key Pair and select the .P12 file. Save the key store by providing a password of your choice.

For exporting the server certificate into BKS format, you need tool called BouncyCastle Provider. You need to download the jar file and store in a known location. Now execute the following command using keytool. Keytool can be found in standard Oracle Java distribution installation folder.
keytool -import -v -trustcacerts -alias 0 -file "[apache installation folder]/conf/server.crt"   -keystore "/path/of/bksfile/client.bks"   -storetype BKS  -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path/of/bcprov-jdk15on-146.jar"  -storepass password
Here storepass is the password that you should provide to export the server.crt into bks format. 
Here you have specified the input  server.crt, output client. bks, the provider name, in this case BouncyCastleProvider and the path of the provider file. 

Create a new project in android.  Add the client certificate and server certificate in res/raw/ inside the application. Add the following code in your application to test one way SSL connection(Server authentication)

The MainActivity code can be found here.
And the SSL connection code can be found here


Android does not allow handling network connection in UI thread. So you should put all the code for ssl connection in separate thread as I did in MainActivity.java. The URL specified MyHttpClient.java file for httpGet(https://10.0.2.2) should be replaced by the actual website address(e.g: https://yourdomain.com). The password for truststore and keystore are the passwords you provided to convert the files in bks format.
If you run the code, you should get  simple plain text output of a html file located in the path specified. 

Step 4:

Configuring client side authentication: 

You have already created the client certificate and added that in the android application. Now you need to configure Apache server so that it requires client authentication. To do that, remove comment in the following lines in httpd_ssl.cnf file.
SSLVerifyClient require

SSLVerifyDepth 10
In this case the length of client certificate that you created above is length of 1. So change the SSLVerifyDepth to 1. Restart the Apache server.

Now if you run the previous code, you will get exception because now the client’s identify is needed to be verified by the server. So comment the line in the code.  
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
And remove the comment the line
SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "keystore password", trustStore, null, null);     
I marked this portion of code as green above. Now if you run the program, you will get the HTTP get output. 

Step 5: 


Using HTTP Put for uploading files from Android to the server


So far you have the 2-way SSL connection between Apache server and the android client. Now time to upload files to the server from android device.  For that you again need to configure Apache server and add some code in your android app.

Apache server does not allow HTTP Put by default for security reason. There is a HTTP extension called Web-based Distributed Authoring and Versioning (WebDAV) that allows users reading and writing server folders and files via HTTP. For enabling HTTP Put in Apache server, you need to enable WebDAV in Apache server using the following steps:

(1) Uncomment the following lines in httpd.cnf

LoadModule alias_module modules/mod_alias.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so
LoadModule setenvif_module modules/mod_setenvif.so

Include conf/extra/httpd-dav.conf

(2) Create user and password for WebDav using the following command
htdigest -c "[apache installation folder]/user.passwd" DAV-upload admin

This will prompt to enter user password. This command creates a user “admin” with the password provided by user and stores the user-password in the "[apache installation folder]/user.passwd" file.

(3) Configure WEBDAV config file.

There should be a file named [apache installation folder]/extra/httpd-dav.cnf. The path of this config file may vary for different Apache distribution. Open the file in text editor and add the following content.
DavLockDB "[apache installation folder]/var/DavLock"

Alias /htdocs "[apache installation folder]/[the folder where user will upload their files]"

<Directory "[apache installation folder]/[the folder where user will upload their files">
    Dav On
    Order Allow,Deny
    Allow from all

    AuthType Digest
    AuthName DAV-upload

    # You can use the htdigest program to create the password database:
    #   htdigest -c "[apache installation folder]/user.passwd" DAV-upload admin
    AuthUserFile "path/of/user.passwd"
    AuthDigestProvider file

    # Allow universal read-access, but writes are restricted
    # to the admin user.
    <LimitExcept GET OPTIONS>
        require user admin
    </LimitExcept>
</Directory>
Make sure all the specified folders exist in respective paths.

(4) Restart Apache server.

(5)Add the user and password in your android app by adding the following piece of code.   
final String username = "admin";
final String password = "password for WEBDAV";
UsernamePasswordCredentials c = new UsernamePasswordCredentials(username,password);
BasicCredentialsProvider cP = new BasicCredentialsProvider();
cP.setCredentials(AuthScope.ANY, c);
sClient.setCredentialsProvider(cP);              

(6) Add the following code for uploading files.   
String filepath="https://10.0.2.2/" + filename;
HttpPut httpPut = new HttpPut(filepath);
httpPut.setEntity(new StringEntity(fileContent));
HttpResponse response2 = sClient.execute(httpPut);

HttpEntity httpEntity2 = response2.getEntity();
Log.i("Mainactivity", "result " + response2.getStatusLine().getStatusCode());
Log.i("Mainactivity", "response  " + response2.getStatusLine()); responseCode=response2.getStatusLine().getStatusCode();                    
if (response2.getStatusLine().getStatusCode()  == 200)
             {
         InputStream is2 = response2.getEntity().getContent();
         int ch;
         StringBuffer sb = new StringBuffer();
while ((ch = is2.read()) != -1) {
          sb.append((char) ch);
                 }
Log.i("Mainactivity", "result inside " + sb.toString());                        
             }      
        }
Again change the filepath into your appropriate path that you gave write permission in previous step. Also filecontent contains contents of the file.
Run the code. The code should upload the file in to the specified path in server. 


Some notes:

Some points that needs attention.
(1) Every time you make new keys and certificates and link the keys and certificates in .cnf files, restart the server.

Saturday, January 2, 2010

troubleshooting font problem, Unicode character is not showing

go Start - Settings - Control Panel - Regional and Language Options - Languages

Tick both boxes (you will need the Windows CD).

troubleshooting sound card problem after installing windows Xp professional SP2

I have recently installed a fresh copy of windows xp professional SP2 in my pc. After installation completed I found that my pc's sound system is not working, As it could not find the sound card. But I have a build-in sound card in my intel motherboard.

I checked Control Panel > Sounds and Audio Devices and found that there has been written
"no audio device" and other options in the window are disabled .

Then I checked Device Manager and here I found that every option under "Video And Game Controllers" is ok.
I started googling and found out the following website from where I got help for fixing this.

http://forums.techguy.org/hardware/578721-solved-no-audio-device-problem.html

This is all I have done.

1. Download PC Wiizard from
http://www.cpuid.com/pcwizard.php

This will give the all information about system's hardware.
Note the description of Mainboard and chipset.
For my case,
Intel Mainboard : Intel D945GCNL
Chipset : Intel i945G/GZ

2. download and install Intel® Chipset Software Installation Utility for the chipset. Reboot the system.
I have found my one from


http://www.intel.com/support/chipsets/sb/CS-020683.htm

3. download and install the audio driver for the Intel Mainboard(Desktop board) of the system
.

Done!

All these should make the sound card working again.


Saturday, August 29, 2009

useful website for GRE

There is a website where you can find the Barron's words list.
You can download the word list in pdf or txt form.
The website is :
http://postech.ac.kr/~gla/gre/

Useful website for IELTS

While I was preparing for IELTS exam I found a website which seemed very useful.
The website is:
http://ielts-exam.net/
the website has many practice tests, writing part 2 samples, speaking cue card topics.
I think this will also help you to get prepared for IELTS exam.

Hiding hard drives in windows system

hello all,
In this article I am going to tell you how can you hide your hard drives in windows system.
In order to do that what you have to do is:
go start->run->gpedit.msc
A window of 'group policy' will be opened. At the left hand side go to the
local computer policy->User configuration ->Administrative Templates->windows components
->windows explorer.
It will open a list of options in the middle of the "group policy" window.
Double click on the "hide these specified drives in my computer" option.
A new window will be opened.
From "setting" tab check the "Enabled" option.
And from the "pick one of the following options" select the drives that you want to hide.
click apply/ok to get out of the window.

Done.
now your desired drives that you wish to hide will be hidden.

Tuesday, June 23, 2009

Java oracle connection

In this article I am going to describe how to set up connection with oracle database from a java application.

Requirement:
To develop an application using Java and Oracle pc should have the configuration to support
java,Oracle Database, Apache-Tomcat Web Server , sufficient Space to store script.

Installation:
For developing java and Oracle based application, i proceeded in the following way:

1. installed "jdk-1_5_0_08-windows-i586-p" in C: / Program Files

2.installed oracle 9i.

3. Installed "jakarta-tomcat-5.5.7”, just unzipped it in D: \java2 folder like “D:\java-2\jakarta-
tomcat-5.5.7”

Java configuration:

I set up the following environment variables as user variable

1. “CATALINA_HOME “---- “D:\java-2\jakarta-tomcat-5.5.7”

2. “JAVA_HOME “----- “C:\Program Files\Java\jdk1.5.0_08”

3. “PATH “---- “C:\Program Files\Java\jdk1.5.0_08 \bin”

4. “CLASSPATH “---- “D:\java-2\jakarta-tomcat-5.5.7\common\lib\servlet-api.jar”

DSN configuration:

1. To get connection with oracle first I had to create a user that has a name “aditi” password “aditi” in oracle 9i.

The command is

create user aditi identified by aditi;
grant connect,resource to aditi;

2. Went to the System DSN and and click add button in the right side.

3. Selected “
Oracle in orahome90

4. Set “
myora” as Data Source Name and “dns for oracle” in Description.

5.Pressed test connection at the right side of this page and set “
aditi” in the service name and “aditi” in the password. Press ok.

6.It will give a confirmation massage like “connection successful”.

Now the DSN setting is finished.

Starting running my project:

Before I started the project at first I needed to run Oracle database server then “Apache-Tomcat" To start apache-tomcat I went to “D:\java-2\jakarta-tomcat-5.5.7\bin” then started the “startup.bat” file. After running the servers, went to “C:\apache-tomcat-5.5.15\webapps\” this folder, and created a new folder give a name to this folder like “OurEx” copied my project files in this folder.

Now I started my project

To start I opened my browser and in address bar write this

http://localhost:8081/OurEx/main and pressed enter after a few second it shows a login page.

The code for the login page is resides in main.java file. so when i ran the main.java from localhost, it shows the login page to me.

if I type my user name and password, it checks the username and password against the username and password stored in the oracle database, if matched it allows me to enter into the appliaction, other wise shows me a message that "wrong username or password"

For the port number 8080, a user may face problem, so he can change the port from 8080 to 8081.

This thing can be done as follows:

Go to this folder “D:\java-2\jakarta-tomcat-5.5.7\conf” then open “server.xml” file there find this

[ Connector port="8080" maxHttpHeaderSize="8192" ………..]

Change it to this

[Connector port="8081" maxHttpHeaderSize="8192" ………..]

Save and close the file then restart web server .

the port number that is used either in 8081 or 8080 or something other than this, should also be used in the code where ever port number is used. Unless application will not work correctly.

After this I hope there isn’t any problem that may be faced.