7/25/2011

Protect KML / KMZ Files from Unauthorized Access Using Cryptography

In this blog post, I want to detail out the way we can protect KML files from unauthorized access in an Enterprise environment. In this approach, we can use the simple cryptography principles to make sure that the access to the KML files is granted only to authorized users, who are already authenticated in an enterprise context. But the problem here is that the KML files are accessed by Google server directly and there is no way for the Google server to send any authentication/authorization information on its own.

To understand this, we need to understand the basic flow of the request when a user accesses the KML from the browser. In the following diagram, I tried to capture this basic flow.
In an enterprise environment, before any of this request, we assume the user is already logged into the server and access the application.  

Google Accessing KML resource without any protection

  1. User accesses the maps application, which will have overlays mentioned as KML Url(which is located in the web server).
  2. The maps applications return the maps related HTML, JavaScript with the KML Url in the JavaScript.
  3. The JavaScript sends a request to the Google Maps server to access and parse the KML file with the KML Url in the request.
  4. Google Maps server accesses the KML Url directly from the server (not via the browser)
  5. The KML request reaches our own server and the server returns the KML content. This is the reason why the KML should be accessible from the Internet directly.
  6. Google Maps server parses the request and sends the parsed response to the JavaScript back and the Maps JavaScript draws the overlays necessary.
With these basic steps in view, let’s see how we can authenticate and authorize the user when the KML request reaches our server from the Google Maps server (Step 4 and 5). The main aim of this method is to establish a token and pass it as part of the KML Url. This token will be used when a KML request reaches the web server to verify the originator of the message, user who really requested the KML file, so that the server can do the verification, validation of the token and also the authorization, access-control for the KML resource (some group or role check). For this description, I am going to use the symmetric key encryption but it’s quite feasible to use the PKI based digital signatures too.

Google accessing the KML resource with cryptography based protection

  1. User accesses the maps application, which will have overlays mentioned as KML Url.
  2. The web/app server upon request for the map application, forms the crypto token to be included as part of the KML Url. This token is just a representation of the user identity (loginId of the user), valid from and valid to timestamps.  The reason for including these two timestamps is to establish a unique token for every request and also to introduce the expiry of the token, so that the same request cannot be replayed after the token is expired. The web server has to establish some secret key for the symmetric encryption.
    An example of the token:
    tokenBuffer = concat(userId, “:”, validFrom, “:”, validTo)  //”:” is used as a delimiter
    token = base64encoding(AESCipher(tokenBuffer, symmetricKey))  //using AES for this example


    This token will be appended as a query string to the KML url. Instead directly accessing the KML file, here we use a component (a servlet, PHP script or similar) for KML request processing. If the KML Url is http://:/test.kml then this Url will become http://:/webapp/KMLController?token=&kmlFile=test.kml
  3. The maps application responds to the browser with the maps HTML+JavaScirpt along with the KML Url containing the token.
  4. Google Maps “google.maps.KmlLayer” JavaScript object requests the Google maps server to fetch and process the KML as indicated by the Url. Please note that the Url contains the token we just formed as part of step 2.
  5. Upon request, the Google maps server sends a request to our web server’s KML Controller component to process a request for the KML file. The KML file name is passed as part of the query string.
  6. When KML controller receives the request for KML file content, it performs the following steps:
    1. It first extracts the token, which is available as part of the query string.
    2. This token is decrypted using the same symmetric key to get the clear text of the token.
    3. Extract the token values using the delimiter. In this step we get the user id, valid from and valid to values.
    4. Do the access control checks and validate the timestamps.
    5. If everything is fine send the KML content in the response with proper mimetype, i.e. application/vnd.google-earth.kml+xml for KML files and application/vnd.google-earth.kmz for KMZ files. (KML file name is available as part of the query string).
    6. If any of the steps failed, send proper response code (401, 403, 400 etc).
  7. Send the response back to the Google server’s HTTP request.
  8. Google server parses the KML if the KML is sent properly. Otherwise, it ignores the errors.
This way, we can protect the KML resource access from an unauthorized access.

References

  1. Book "Beginning Cryptography with Java" by David Hook
  2. Icons used in the above drawings are taken from the following site:
  3. Browser icon: http://www.iconfinder.com/icondetails/17856/128/browser_icon Maps icon: http://lab.iirojappinen.com/idroid/

7/13/2011

Protecting KML Files from general public access in Google Maps

Google provides a way to include the geospatial data in KML (Keyhole Markup Language) format and show that data in the maps (Google maps and earth). For Google to display the KML files in maps applications, those files have to be publicly accessible to the Google server. From an Enterprise perspective, often times, there is a requirement to protect these KML files from unauthorized access. This may be an issue as Enterprises do not want to expose the KML files in the public domains without any authentication.

So, till the time Google comes up with a solution (not sure if it already has any solution), following are my views about the options that can be considered.
  1. Allow access to KML files only from specific IPs or IP ranges. This means we need to get the IP range of the Google map servers and allow access to the KML files only from this IPs.
  2. Instead of using Google APIs to parse the KML files, we can use the client side processing libraries or implement our own KML parsing libraries (client side or server side) and use Google Map APIs to plot the places. As KML files are XMLs in the end, any XML parsing technique can be used. Two of the client side libraries:
    1. http://www.dyasdesigns.com/geoxml
    2. http://econym.org.uk/gmap/egeoxml.htm
  3. I recently found out about the usage of OpenLayers. Following are two examples which are of interest regarding this post.
    1. Usage of OpenLayers to display Google layer http://openlayers.org/dev/examples/google.html
    2. Usage of OpenLayers to display the KML overlays http://openlayers.org/dev/examples/kml-layer.html
  4. May be we can combine both options to display the KML overlays on top of Google Maps. From the view source of the KML OpenLayers example (http://openlayers.org/dev/examples/kml-layer.html), it does not look like the request is being sent to Google for KML parsing. So, all the authentication and authorization can be performed by server side scripts and this server side script will be the URL for the KML file.
  5. Use of digital signatures to protect the KMLs. In this option, we can use the simple public/private key pair to include the digital signature as part of the KML URL and this signature will be verified before providing the access to the KML file. This way, all the unauthorized access to the KMLs can be protected, as we can make sure that the originator is same as our own server with establishing a unique signature for every KML URL. I will detail out this option in the next blog post.
References
  1. KML tutorial from Google: http://code.google.com/apis/kml/documentation/kml_tut.html
  2. http://openlayers.org/
  3. Usage of different map providers using OpenLayers API http://openlayers.org/gallery/multiple.html
  4. Two client side libraries for displaying KML files:
    1. http://www.dyasdesigns.com/geoxml
    2. http://econym.org.uk/gmap/egeoxml.htm

8/08/2009

Using the load method of JQuery to load the selected data from the response

I recently had a requirement where in I had to display documents from a Knowledge management repository in an unordered list items view. There was already a standard server side component which was displaying the documents but not in the format required and I had no control over this component to change it (This is the case for most of us who are working on customizations for some standard product). There were two options for me to implement this requirement.

  • To implement a new server side component which retrieves the data in the format required (or)
  • Use the same server side component, retrieve the data using the Javascript and asynchronous technique and display the partial data (in this case, bunch of links holding a specific class) and decorate these links with an unordered list.

I instantly chose the second option. There were quite a good number of reasons for choosing this option, I would not like to get into those details in this article though. I was implementing the JQuery in my applications for quite some time I found the very good use of "load()" method to display the selected elements from the response of an asynchronous call to the server. And it turned out to be as simple as we talk. Here I am drafting the steps for implementing this.

  1. Create a div in the HTML to hold the dynamically retrieved data from the server. And we can also define the server side URL which needs to be retrieved dynamically.

    <div id="kmContent" href="some server side URL" > </div>

  2. Write the JQuery document ready function to retrieve the contents from the URL specified in the div. In the load method, the first parameter is the URL and the element selector separated by a space and this is the reason why we need to make sure that the URL does not have any space in it. The space should be escaped. But it's better to use the escape function of Javascript to escape the URL for safer side. And the second parameter is the function reference, which will be called by JQuery when the loading is completed.

    $(function() {

    var url = escape($("#kmContent").attr("href"));

    $("#kmContent").load(url +" a.someSpecificClass");

    });


    This piece of script, sends the request to the specified URL and retrieves the response and selects only "a" elements with the specified CSS class "someSpecifiedClass" and inserts that into "kmContent" div.

  3. The next and ofcourse the last step is to define a callback function, which will be called when the loading is complete. This callback function is responsible for decorating the links with unordered list.

    $("#kmContent").load(url +" a.someSpecificClass", function() {

    $('#kmContent a').wrapAll('<ul></ul>').wrap("<li></li>").addClass("someFormattingClass");

    });



    And I placed this HTML with the script as part of my content management system and there you go. JQuery does the job perfectly well.

    In this age of agile development, the frameworks like JQuery are the best fit without any doubt.

2/03/2009

WebDAV MOVE method fails with 502 Bad Gateway Error with HTTPS

I was recently writing a Javascript piece of code to move a bunch files from one location to another in the same WebDAV repository. It worked all well in the lower systems but when I tried the same thing in the Production environment I got the "502 Bad Gateway" exception. I thought probably I was doing some mistake and I tried to use the WebDAV Javascript Ajax API provided in http://www.webdavsystem.com/ajax. But it also suffered the same issue.

Here is the piece of Javascript code to do the simple move.


function doResourceMove(from, to) {
var postParams = '<?xml version="1.0"?gt;<propertybehavior xmlns="DAV:"><keepalive>*</keepalive></propertybehavior>';
var xhr = getXHR(); //gets the HTTP Request object
xhr.open("MOVE",from, false);
xhr.setRequestHeader("Destination",to);
xhr.setRequestHeader("Overwrite","F");
xhr.setRequestHeader("Content-Type",'text/xml; charset="utf-8"');
xhr.send(postParams);

var status = xhr.status;
if(status == 201 status == 204 )
return true;
else {
throw status; //can be 201, 204, 403, 409, 412, 423, 502
}
}

After trying WebDAV Ajax API provided by webdavsystems, it was time for me to roll my sleeves up and analyze the issue.

The main issue was that the production system runs on https and there was a reverse proxy setup for this system. So, all the "https" requests were converted to "http" at this proxy level and forwarded to the main system. This was the main culprit.

Here is an example of HTTP request for the MOVE resource request for a WebDAV resource. For brevity I removed all unnecessary details.

MOVE contentLocation //request line, some https location, URI of webDAV resource
Destination:destinationLocation // this is the HTTP request header, should be absolute URI according to specifications.

Overwrite: "F" // this is also a HTTP request header

So, when the reverse proxy sees the request line, it knows that it has to convert this to HTTP request but the header Destionation also contains an HTTPS request which would be ignored by the proxy. So, when the request reached the server, we are moving the resource from an URI which begins with a http to a URI which begins with an https. Server treats this request as a request to move a WebDAV resource from one server location to another server location.(Refer RFC: http://greenbytes.de/tech/webdav/rfc2518.html#METHOD_MOVE). This was the source of the main problem.

Solution: When I changed the destination location to use the relative URL, it just worked fine. It may not be the solution for all WebDAV based systems but for me, it just did the trick.

Example:Let's assume that the resource you want to move is located at the URL location https://www.abc.com/webdavimpl/folder1/folder2 and you want to move this resource to location https://www.abc.com/webdavimpl/folder1/folder3/folder2. Following are the important HTTP request headers to follow.

MOVE https://www.abc.com/webdavimpl/folder1/folder2

Destination: /webdavimpl/folder1/folder3/folder2

Overwrite: "F".

1/12/2007

Customizing SAP Portal Master Header for Branding

SAP Enterprise Portal provides Theme Editor to edit the themes/styles for Portal environment. We can change the branding by changing the masthead part in the theme editor. But if you want to reposition the elements, add new elements or require more customizations then changing the code is a way to go. But before changing the code, it would be a better idea to check whether by editing the themes will suffice.

Changing the Code:

To change the masthead by changing the code, it would be a better idea to get the existing masthead par file and use it as a starting point. We can even develop whole new portal component using framework library and make it an iview out of it.

To get the mastead par file, go to System Administration -->Support --> Browse Deployment and browse to the directory ROOT/WEB-INF/deployment/temp and you will find com.sap.portal.navigation.masthead.par.bak file. Download it to your local system. If you observe the file extension, it is "bak", because SAP Portal renames the archives after it deployes the par so that it will not deploy it again. Remove the file extension .bak and rename according to the naming standards of your organization. I would recommend you to use the same naming of the file, remove "sap" and use your own company name, like com.mycompany.portal.navigation.masthead.par. After this, you can import this par file in NWDS (Netweaver Developer Studio) by selecting File --> Import. A word of caution, the importing does not import the jar files in the private/lib folder of the project structure. So, copy them manually to the new project you have created.

When you see the project structure, you can find the header related file in dist --> PORTAL-INF -->jsp --> Headerview.jsp. You can change this file according to your needs and deploy it back to the portal.

Create an iView:

In the portal environment, you can create iView out of this new portal component you just uploaded. To do this,go to Content Administration--> Portal Content --> Portal Content and I recommend creating a folder for placing all the customization related objects (iviews, framework page, portal desktop). To create an iview in the newly created folder, right click on the folder name and select "New iview from Par" (In Netweaver 2004s, select "new --> iview" and in the next step select the appropriate option for creating an iview from the portal component). Select the portal application (par file name) you just deployed to portal and select the portal component. It'll create the iview based on the portal component we just changed.


Framework Page:
For testing, we can create a portal framework page (just copy the standard portal framework page available at Portal Content -->Portal Users --> Standard Portal Users -->Default Framework Page ). Open the copied Framework page for editing and make visible checkbox unchecked for exisitng Mastehead iView and add the new masthead iview just created. Go to Page Layout and arrange the masthead so that it appears on the top.


Portal Desktop:
Now, copy the SAP provided standrd Portal Desktop object to the folder we created for placing the custom content. To do this, go to System Administration --> Portal Display -->Desktops & Display Rules and browse to Portal Content -->Content Provided by SAP --> End User Content -->Standard Portal Users and copy Default Portal Desktop and paste it in the your folder. Now, open the copied portal desktop object and add the newly created framework page and make it default framework page for this desktop object.


Changing Master Rule Collection:
Now, you can change the Master Rule Collection which controls the desktop selection for end users based on the criteria specified. To open the Master Rule Collection, go to System Administration --> Portal Display -->Desktops & Display Rules and browse to Portal Content -->Portal Administrators -->Super Administrators --> Master Rule Collection. Add a new rule for displaying the newly created desktop for some user in portal (testing purpose), save the object and close it.


Result:
You can now go and check the new portal desktop containing the new masthead you just created by logging into the portal as the user for whom you set the new rule.

8/17/2006

Using HTML Fieldset

Ajax is all about making websites more dynamic, richer and making them more usable. All the technologies that play part in Ajax are really important to achieve this goal. So, here in this article I explain the usage of fieldset and legend HTML elements, which add more semantic, structure and usability if used properly.

Fieldset is useful in making semantically related fields appear together visually. Grouping fields this way makes it easier for user to understand the semantic relationship of the fields and they are pretty stylish too, which makes it a very useful element.

Legend allows us to give a proper caption to the fieldset and makes it even easier for the user.

Let’s take a quick look at a simple example. Suppose that we are gathering personal and professional information of a user. One way of achieving this is to use markup elements (like, h1, h2, h3…) for these two sections. But using fieldset makes it very simple just by adding two fieldsets, like

<fieldset>
<!—for personal information -->
</fieldset>
<fieldset>
<!—for professional information -->
</fieldset>

This way, it adds semantic relationship among the fields declared inside a fieldset. To give the legend, just use element inside the fieldset, like

<fieldset>
<legend>Personal Information</legend>
for personal information
</fieldset>
<fieldset>
<legend>Professional Information</legend>
for professional information
</fieldset>

I added some styles to the fieldset and legend fields. Here is the result page:

http://pavankeely.brinkster.net/fieldset_example.html

We can style these elements the same way we style other elements using CSS. Change the border color, font, background color and much more.

Fieldsets can also be nested producing nested semantic relationship to the HTML document and will help the user to understand the relationship.

IE Specific Info: By default IE adds a rounded cornered border. But once you change the border style, width or color using styles, the rounded corners disappear.

7/06/2006

System error: -1072896658 in IE

Problem:
Recently my team reported a problem while integrating one of the Ajax features I developed. Whenever they try to access that feature, it throws up an error "System error: -1072896658". I was suprised because that is working fine when I access in my test environment. Later after debugging in the integration environment, I found out that the problem is with charset. While configuring the server environment, they mistakenly specified the charset as "UTF8" (instead of utf-8) and that is the culprit of this error. So, whenever the response is received in the browser and accessed using xhr.responseText, MSXMl.dll (MSXML component) is not able to interpret the response and throwing a system error.

Solution:
By changing the charset to "utf-8", it started working absolutely fine.

Conclusion:
Make sure to specify the correct charset.