Playing with Jaas and Apache.

Comments Off on Playing with Jaas and Apache.

If you havent read my blog post “Playing with JAAS” i wouldd suggest you read that before reading this one. Here is a quick primer on configuring Jaas with apache.

  • In this case our jaas.config will have just one LoginContext called ApacheExample
    ApacheExample {
    	com.module.DummyLoginModule required username="user" password="pass" role="admin";
    };
  • As part of the login process, JAASRealm registers its own CallbackHandler, called (unsurprisingly) JAASCallbackHandler. This handler supplies the HTTP requests’s username and credentials to the user-supplied LoginModule. At present, JAASCallbackHandler knows how to handle callbacks of type NameCallback and PasswordCallback.
     
    Here is the login method of our DummyLoginModule. As soon as the user would click on ‘Login’ button on the UI, the login method of this DummyLoginModule is called. Within the login method we call the callbackhandler’s handle method (callbackHandler.handle(…)) which would expect JAASCallbackHandler to populate NameCallback and PasswordCallback objects.

    On success we create the HelloWorldUser and HelloWorldRole which we will use later. Both implement Principal.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    public boolean login() throws LoginException {
     
    	if ( callbackHandler == null ) {
    		throw new LoginException("no handler");
    	}
     
    	// Callback is just like a VO object, that the handler will populate!
    	NameCallback nameCallback=new NameCallback("username");
    	PasswordCallback passwordCallback=new PasswordCallback("password", false);
    	Callback[] callbacks = new Callback[] { nameCallback, passwordCallback };
     
    	try {
    		callbackHandler.handle(callbacks);		
    	} catch (IOException e) {			
    		throw new LoginException("handler io error");
    	} catch (UnsupportedCallbackException e) {		
    		throw new LoginException("unsupported callback error");
    	}
     
    	String username = nameCallback.getName();
    	String password = new String(passwordCallback.getPassword());
     
    	if ( options.get("username").equals(username) && options.get("password").equals(password) ) {			
    		// add these if commit was called!
    		myUser=new HelloWorldUser(username);
    		myRole=new HelloWorldRole(String.valueOf(options.get("role")));			
    		success = true;				
    	} else {			
    		throw new LoginException("incorrect username/password");
    	}
     
    	return true;
    }
  • You can download the whole JAAS implementation from here [Source] or the [binary which is jar+jaas.config]. Place the jar and jaas.config into your lib folder.
  • Apache uses realms to authenticate users. By default its set to UserDatabaseRealm which authenticates users from the conf/tomcat-users.xml. We need to switch that to JAASRealm in the conf/server.xml. Locate Realm element with class=org.apache.catalina.realm.UserDatabaseRealm, comment it out and add the following realm code.
    1
    2
    3
    4
    
    <Realm className="org.apache.catalina.realm.JAASRealm"
                    appName="ApacheExample"
    					userClassNames="com.principal.HelloWorldUser"
    						roleClassNames="com.principal.HelloWorldRole"/>
  • You need to make changes in your webapps web.xml to specify “login-config” and “security-constraint” elements (which are out of scope of this article). Here is a good article explaining Tomcat Security Overview and Analysis. Here is a sample web.xml for our helloworld webapp. You can download the sample helloworld apache jaas webapp from here. Notice how we have added the “role-name” element with value “admin” under the “auth-constraint” element. This means that the subject who was authenticated has to have a admin role. We are taking care of that in our jaas implementation by adding HelloWorldRole as one of our Principals in our Subject.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.or<a href='https://www.softwareeverydayblog.com/wp-content/uploads/2012/11/helloworld.zip'>Apache+Jaas helloworld app</a>g/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
        version="2.5">
        <description>Hello World</description>
        <display-name>Hello World</display-name>
     
    	<context-param>
    		<param-name>Name</param-name>
    		<param-value>Hello World</param-value>
    	</context-param>
     
    	<security-constraint>
    		<web-resource-collection>
    			<web-resource-name>Wildcard means whole app requires authentication</web-resource-name>
    			<url-pattern>/*</url-pattern>
    			<http-method>GET</http-method>
    			<http-method>POST</http-method>
    		</web-resource-collection>
     
    		<auth-constraint>
    			<role-name>admin</role-name>
    		</auth-constraint>
     
    		<user-data-constraint>
    			<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
    			<transport-guarantee>NONE</transport-guarantee>
    		</user-data-constraint>
    	</security-constraint>
     
    	<login-config>
    		<auth-method>FORM</auth-method>
    		<form-login-config>
    		<form-login-page>/login.jsp</form-login-page>
    		<form-error-page>/fail_login.html</form-error-page>
    		</form-login-config>
    	</login-config>
     
    </web-app>

Why should hashtable size be prime number?

Comments Off on Why should hashtable size be prime number?

  • Lets say our hashtable size is 100 (which is NOT a prime number).
  • Say we wish to hash some value x and its multiples 2x, 3x, 4x and so on. If x was = 2 then {2, 4, 6, 8, .., inf} would be our values. Since our hashtable is of size 100, only 50% buckets would be occupied.
  • If x was = 3 then {3, 6, 9, 12, …, inf} would be our values. Only 33% would be occupied.
  • I hope you see the problem there ^. We want a situation where for any key would be spread across buckets in the whole table and not just some % of the table.
  • To formalize, for any x, your values are going to be spread in s number of buckets (given by the formula below).
    spread (s) = table_length / GreatestCommonFactor(table_length, x)

    table_length = 10
    x = 2

    s = 10 / GreatestCommonFactor(10, 2)
    s = 10 / 2
    s = 5

    Meaning values will be spread only in 5 out of 10 buckets (i.e. 50% of the table)

  • We need GreatestCommonFactor(table length, x) to be 1 if we want to spread (s) to be table length (meaning map to all buckets in hashtable). So lets make x and table length co-prime1 for which we need to make table length prime!

[1] In number theory, two integers a and b are said to be coprime if the only positive integer that divides both of them is 1.