/*
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * @(#)secbasicClient.java	1.2 02/01/12
 */


package com.sun.cts.common.tests.jspServletClient;

import com.sun.cts.util.*;
import com.sun.cts.porting.*;
import com.sun.cts.harness.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.rmi.*;
import javasoft.sqe.javatest.Status;

public class secbasicClient extends EETest
{
    // Configurable constants:
    protected String hostname = null;
    protected int portnum  = 0;
    private String pageBase = null;
    private String pageSec = null;
    private String pageGuest = null;
    private String pageUnprotected = null;
    private String pageRoleReverse = null;

    private String pageJspBase = "/jsp_secbasic";
    private String pageJspSec = pageJspBase + "/jspSec.jsp";
    private String pageJspGuest = pageJspBase + "/guestPage.jsp";
    private String pageJspUnprotected = pageJspBase + "/unprotected.jsp";
    private String pageJspRoleReverse = pageJspBase + "/rolereverse.jsp";

    private String pageServletBase = "/servlet_secbasic";
    private String pageServletSec = pageServletBase + "/ServletSecTest";
    private String pageServletGuest = pageServletBase + "/GuestPageTest";
    private String pageServletUnprotected = pageServletBase + "/UnProtectedTest";
    private String pageServletRoleReverse = pageServletBase + "/RoleReverseTest";


    private String searchFor = "The user principal is: "; // (+username)
    private String searchForGetRemoteUser = "getRemoteUser(): "; // (+username)
    private String username = "";
    private String password = "";
    private String unauthUsername = "";
    private String unauthPassword = "";

    // Constants:
    protected final String WebHostProp = "webServerHost";
    protected final String WebPortProp = "webServerPort";
    protected final String UserNameProp = "user";
    protected final String PasswordProp = "password";
    protected final String unauthUserNameProp = "authuser";
    protected final String unauthPasswordProp = "authpassword";

    private String testDir = System.getProperty("user.dir");

    // Shared test variables:
    private Properties props = null;
    private String request = null;
    private WebUtil.Response response = null;

    private CTSURL ctsurl = new CTSURL();

   /*
    *   @class.setup_props: webServerHost;
    *                       webServerPort;
    *			    user;
    *			    password;
    *			    authuser;
    *                       authpassword;
    *
    *         
    *    
    */
    //Note:Based on the input argument setup will intialize JSP or servlet pages
  
    public void setup(String[] args, Properties p) throws Fault
    {
       props = p;

        try {
            hostname = p.getProperty(WebHostProp);
	    portnum = Integer.parseInt(p.getProperty(WebPortProp));
	    username = p.getProperty(UserNameProp);
	    password = p.getProperty(PasswordProp);
	    unauthUsername = p.getProperty(unauthUserNameProp);
	    unauthPassword = p.getProperty(unauthPasswordProp);

            if (args[0].equals("jsp"))
            {
              	pageBase = pageJspBase;
              	pageSec  = pageJspSec;
              	pageGuest = pageJspGuest;
	      	pageUnprotected = pageJspUnprotected;
		pageRoleReverse = pageJspRoleReverse;

            }
            else
	    {
              	pageBase = pageServletBase;
              	pageSec  = pageServletSec;
              	pageGuest = pageServletGuest;
	      	pageUnprotected = pageServletUnprotected;
		pageRoleReverse = pageServletRoleReverse;

            }
	} catch ( Exception e ) {
	   logErr("Error: got exception: ", e);
	} 
    } 
  
    /*
     * @testName:  test1
     *
     * @assertion: Test BASIC authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.  
     *
     *              1. If user has not been authenticated and user attempts
     *                 to access a protected web resource, the web server
     *                 requests authentication.
     *
     * @test_Strategy: 
     *              1. Send request to access jspSec.jsp
     *              2. Receive authentication request.
     */

    public void test1() throws Fault {
        try {
	    request = pageSec;
	    TestUtil.logMsg( "Sending request \"" + request + "\"" );
            System.out.println("HostName= "+hostname);
            System.out.println("portnum = "+portnum);

	    response = WebUtil.sendRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null );
            
	    // Check that authentication was requested:
	    if( !response.authenticationRequested ) {
		TestUtil.logErr( "No authentication requested for page." );
		throw new Fault( "test1 failed." );
	    }

	    TestUtil.logMsg( "Authentication requested." );
	} catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test1 failed: ", e);
	}
    }

    /*
     * @testName:  test2
     *
     * @assertion: Test BASIC authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.  Also tests
     *             API assertions in section 11.3.
     *
     *              1. If user has not been authenticated and user attempts
     *                 to access a protected web resource, and user enters
     *                 a valid username and password, the original web resource
     *                 is returned and user is authenticated.
     *              2. getRemoteUser() returns the user name that the client
     *                 authenticated with.
     *
     * @test_Strategy: 
     *              1. Send request with correct authentication.
     *              2. Receive page (ensure principal is correct, and
     *                 ensure that getRemoteUser() returns the correct name)
     */

    public void test2() throws Fault {
        try {
	    request = pageSec;
	    // Request page, this time sending authentication:
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with BASIC authentication." );
            response = WebUtil.sendAuthenticatedRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null, username, password );

            // Check that the page was retrieved (no error)
	    if( response.isError() ) {
		TestUtil.logErr( "Could not access " + request );
		throw new Fault( "test2 failed." );
	    }

	    // Test to make sure we are authenticated by checking the
	    // page content.  The jsp should output 
	    // "The user principal is: j2ee"
	    String searchString = searchFor + username;
	    if( response.content.indexOf( searchString ) == -1 ) {
		TestUtil.logErr( "User Principal incorrect.  Page received: ");
		TestUtil.logErr( response.content );
		TestUtil.logErr( "(Should say: \"" + searchString + "\")" );
		throw new Fault( "test2 failed." );
	    }

	    TestUtil.logMsg( "User Principal Correct." );

	    // Test to make sure getRemoteUser returns j2ee.
	    searchString = searchForGetRemoteUser + username;
	    if( response.content.indexOf( searchString ) == -1 ) {
		TestUtil.logErr( "getRemoteUser() did not return " + 
		    username + ": ");
		TestUtil.logErr( response.content );
		TestUtil.logErr( "(Should say: \"" + searchString + "\")" );
		throw new Fault( "test2 failed." );
	    }

	    TestUtil.logMsg( "getRemoteUser() correct." );

	    // Check to make sure isUserInRole is working properly:
	    Hashtable roleCheck = new Hashtable();
	    roleCheck.put( "ADM", new Boolean( true ) );
	    roleCheck.put( "MGR", new Boolean( false ) );
	    roleCheck.put( "VP", new Boolean( false ) );
	    roleCheck.put( "EMP", new Boolean( true ) );

	    //roleCheck.put( "Administrator", new Boolean( false ) );
	    if( !checkRoles( response.content, roleCheck ) ) {
		TestUtil.logErr( "isUserInRole() does not work correctly." );
		TestUtil.logErr( "Page Received:" );
		TestUtil.logErr( response.content );
		throw new Fault( "test2 failed." );
	    }
	    TestUtil.logMsg( "isUserInRole() correct." );

	} catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test2 failed: ", e);
	}
    }

    /*
     * @testName:  test3
     *
     * @assertion: Test BASIC authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.
     *
     *              1. If user has not been authenticated and user attempts
     *                 to access a protected web resource, and user enters
     *                 an invalid username and password, the container
     *                 denies access to the web resource.
     *
     * @test_Strategy: 
     *              1. Re-send request with incorrect authentication.
     *              2. Receive authentication request.
     */

    public void test3() throws Fault {
        try {
	    request = pageSec;
	    // Request page again, this time sending incorrect authentication:
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with incorrect BASIC authentication." );
            response = WebUtil.sendAuthenticatedRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null, username, "incorrect" + password );

            // Check that the page was not retrieved (error)
	    if( !response.isError() ) {
		TestUtil.logErr( "Access granted to " + request + 
		    " without proper authentication." );
		TestUtil.logErr( "Page content:" );
		TestUtil.logErr( response.content );
		throw new Fault( "test3 failed." );
	    }

	    TestUtil.logMsg( "Invalid request rejected as expected." );

	} catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test3 failed: ", e);
	}
    }

    /*
     * @testName:  test4
     *
     * @assertion: Test BASIC authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.
     *
     *              1. If user has not been authenticated and user attempts
     *                 to access a protected web resource, and user enters
     *                 an valid username and password, but for a role that
     *                 is not authorized to access the resource, the container
     *                 denies access to the web resource.
     *
     * @test_Strategy: 
     *		    1. Send request with correct authentication for user
     *                 javajoe for a page javajoe is allowed to access.
     *              2. Receive page (this verifies that the javajoe user 
     *                 is set up properly).
     *	 	    3. Send request with correct authentication, but
     *                 incorrect authorization to access resource
     *   	    4. Receive error
     */

    public void test4() throws Fault {
        try {
	    request = pageGuest;
	    // Request guest page, sending correct authentication.
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with correct BASIC authentication, but incorrect" +
		" authorization for this resource.." );
            response = WebUtil.sendAuthenticatedRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null, unauthUsername, unauthPassword );

            // Check that the page was retrieved.
	    if( response.isError() ) {
		TestUtil.logErr( "Access not granted to " + request + "." );
		TestUtil.logErr( "Possible cause: User " + unauthUsername +
		    " is not set up properly." );
		throw new Fault( "test4 failed." );
	    }

	    TestUtil.logMsg( "Valid request processed successfully." );

            // Check to make sure we are authenticated by checking the page
            // content.  The jsp should output "The user principal is: javajoe"
            String searchString = searchFor + unauthUsername;
            if( response.content.indexOf( searchString ) == -1 ) {
                TestUtil.logErr( "User Principal incorrect.  Page received:" );
                TestUtil.logErr( response.content );
                TestUtil.logErr( "(Should say: \"" + searchString + "\")" );
                throw new Fault( "test4 failed." );
            }
            TestUtil.logMsg( "User Principal correct." );

	    request = pageSec;
	    // Request page, this time sending correct authentication,
	    // but incorrect authorization to access resource:
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with correct BASIC authentication, but incorrect" +
		" authorization for this resource.." );
            response = WebUtil.sendAuthenticatedRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null, unauthUsername, unauthPassword );

            // Check that the page was not retrieved (error)
	    if( !response.isError() ) {
		TestUtil.logErr( "Access granted to " + request + 
		    " without authorization." );
		TestUtil.logErr( "Page content:" );
		TestUtil.logErr( response.content );
		throw new Fault( "test4 failed." );
	    }

	    TestUtil.logMsg( "Invalid request rejected as expected." );

	} catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test4 failed: ", e);
	}
    }

    /*
     * @testName:  test5
     *
     * @assertion: Test BASIC authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.  Also tests
     *             assertions in section 11.3.
     *
     *              1. If user has not been authenticated and user attempts
     *                 to access an unprotected web resource, the web resource
     *		       is returned without need to authenticate.
     *              2. isUserInRole() must return false for any valid or
     *                 invalid role reference.
     *              3. getRemoteUser() must return false
     *
     * @test_Strategy: 
     *              1. Send request for unprotected.jsp with no authentication.
     *              2. Receive page 
     *              3. Search the returned page for "!true!", which would
     *                 indicate that at least one call to isUserInRole
     *                 attempted by unprotected.jsp returned true.
     *              4. check that getRemoteUser() returns null.
     */

    public void test5() throws Fault {
        try {
	    request = pageUnprotected;
	    // Request page, this time sending authentication:
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with no authentication." );
            response = WebUtil.sendRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null );

            TestUtil.logMsg("response.statusToken :"+response.statusToken);
            TestUtil.logMsg("response.location :"+response.location);
            TestUtil.logMsg("response.authenticationRequested :"+response.authenticationRequested);

            // Check that the page was retrieved (no error)
	    if( response.isError() ) {
		TestUtil.logErr( "Could not access " + request );
		throw new Fault( "test5 failed." );
	    }

	    // Test to make sure the correct page was returned.
	    String searchString = searchFor;
	    if( response.content.indexOf( searchString ) == -1 ) {
		TestUtil.logErr( "Incorrect page received:" );
		TestUtil.logErr( response.content );
		TestUtil.logErr( "(Should contain: \"" + searchString + "\")");
		throw new Fault( "test5 failed." );
	    }

	    TestUtil.logMsg( "Correct page returned." );

            // Check to see if any of the calls to isUserInRole returned true:
            TestUtil.logMsg( "Checking isUserInRole..." );
            searchString = "!true!";
            if( response.content.indexOf( searchString ) != -1 ) {
                TestUtil.logErr(
                    "At least one call to isUserInRole returned true." );
                TestUtil.logErr( "Page received:" );
                TestUtil.logErr( response.content );
                throw new Fault( "test5 failed." );
            }

            TestUtil.logMsg( "isUserInRole test passed." );

            // Check to see that getRemoteUser() returns null.
            TestUtil.logMsg( "Checking getRemoteUser()..." );
            searchString = searchForGetRemoteUser + "null";
            if( response.content.indexOf( searchString ) == -1 ) {
                TestUtil.logErr(
                    "getRemoteUser() did not return null." );
                TestUtil.logErr( "Page received:" );
                TestUtil.logErr( response.content );
                throw new Fault( "test5 failed." );
            }
            TestUtil.logMsg( "getRemoteUser() test passed." );

	} catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test5 failed: ", e);
	}
    }

    /*
     * @testName:  test6
     *
     * @assertion: Test HTTP-Basic authentication, specified in the Java 
     *             Servlet Specification v2.2, Sec 11.5.1.  Also tests
     *             assertions from section 11.3.
     *
     *		   Given two servlets in the same application, each of
     *		   which calls isUserInRole(X), and where X is linked to
     *		   different roles in the scope of each of the servlets
     *		   (i.e. R1 for servlet 1 and R2 for servlet 2), then a user
     *		   whose identity is mapped to R1 but not R2, shall get a true 
     *		   return value from isUserInRole( X ) in servlet 1, and
     *		   a false return value from servlet 2 (a user whose
     *		   identity is mapped to R2 but not R1 should get the
     *		   inverse set of return values).
     *
     * @test_Strategy: 
     *		    Since test1 already verifies the functionality for 
     *		    isUserInRole returning true, this test needs only verify
     *		    that it should return false for the other jsp.  For this
     *		    test, MGR and ADM are swapped, so isUserInRole() should
     *		    return opposite values from test1.
     *
     *              1. Send request to access rolereverse.jsp
     *              2. Receive redirect to login page, extract location and 
     *                 session id cookie.
     *              3. Send request to access new location, send cookie
     *              4. Receive login page
     *              5. Send form response with username and password
     *              6. Receive redirect to resource
     *              7. Request resource
     *              8. Receive resource (check isUserInRole for all known 
     *                 roles)
     */
    public void test6() throws Fault {
	try {
	    request = pageRoleReverse;
	    // Request page, this time sending authentication:
	    TestUtil.logMsg( "Sending request \"" + request + "\"" +
		" with BASIC authentication." );
            response = WebUtil.sendAuthenticatedRequest( "GET",
		InetAddress.getByName( hostname ), portnum, ctsurl.getRequest(request), null,
		null, username, password );

            // Check that the page was retrieved (no error)
	    if( response.isError() ) {
		TestUtil.logErr( "Could not access " + request );
		throw new Fault( "test6 failed." );
	    }

	    // Check to make sure we are authenticated by checking the page
	    // content.  The jsp should output "The user principal is: j2ee"
	    String searchString = searchFor + username;
	    if( response.content.indexOf( searchString ) == -1 ) {
		TestUtil.logErr( "User Principal incorrect.  Page received:" );
		TestUtil.logErr( response.content );
		TestUtil.logErr( "(Should say: \"" + searchString + "\")" );
		throw new Fault( "test6 failed." );
	    }
	    TestUtil.logMsg( "User Principal correct." );

	    // Check to make sure isUserInRole is working properly:
	    Hashtable roleCheck = new Hashtable();
	    roleCheck.put( "ADM", new Boolean( false ) );
	    roleCheck.put( "MGR", new Boolean( true ) );
	    roleCheck.put( "VP", new Boolean( false ) );
	    roleCheck.put( "EMP", new Boolean( true ) );
	    //roleCheck.put( "Manager", new Boolean( false ) );
	    if( !checkRoles( response.content, roleCheck ) ) {
		TestUtil.logErr( "isUserInRole() does not work correctly." );
		TestUtil.logErr( "Page Received:" );
		TestUtil.logErr( response.content );
		throw new Fault( "test6 failed." );
	    }
	    TestUtil.logMsg( "isUserInRole() correct." );

        } catch (Exception e) {
	    TestUtil.logErr("Caught exception: " + e.getMessage());
	    e.printStackTrace();
	    throw new Fault("test6 failed: ", e);
	}
    }

    /** 
     * Helper method to check that isUserInRole is working correctly.
     * Searches the given page content for "isUserInRole( x ): !y!" for
     * each x = key in Hashtable and y = corresponding value in hashtable.
     * If all results are as expected, returns true, else returns false.
     */
    private boolean checkRoles( String content, Hashtable roleCheck ) {
	Enumeration keys = roleCheck.keys();
	boolean pass = true;

	while( pass && keys.hasMoreElements() ) {
	    String key = (String)keys.nextElement();
	    boolean expected = ((Boolean)roleCheck.get( key )).booleanValue();

	    String search = 
		"isUserInRole(\"" + key + "\"): !" + expected + "!";
	    String logMsg = "Searching for \"" + search + "\": ";

	    if( content.indexOf( search ) == -1 ) {
		pass = false;
		logMsg += "NOT FOUND!";
	    }
	    else {
		logMsg += "found.";
	    }

	    TestUtil.logMsg( logMsg );
	}

	return pass;
    }

    public void cleanup()  throws Fault {
        logMsg("cleanup");
    }
    
}

