Gateway with separate security sessions using delegation

The Open Server application can also act as a gateway between the client and another server, but the gateway application uses the delegated client credentials when establishing the security session with the remote server. A client can delegate only its own credentials.

The client needs to request the CS_SEC_DELEGATION service so that the Open Server application can obtain the delegated credentials once the security session is established.

As in “Simple application using a security session”, the security session between the client and the gateway Open Server application is established, except for the final login acknowledgment.

In the connection handler, the gateway application:

  1. Retrieves the delegated credentials using srv_thread_props(CS_GET, SRV_T_SEC_DELEGCRED).

  2. Using ct_con_props(CS_SET, CS_SEC_CREDENTIALS), sets the delegated credentials in the Client-Library connection structure for use in connecting to the remote server.

  3. Attempts to connect to the remote server using ct_connect.

  4. Sends a srv_senddone(SRV_DONE_FINAL), to acknowledge the client’s login.

An example connection handler follows:

CS_RETCODE CS_PUBLIC connect_handler(spp) 
 SRV_PROC *spp;
 {
    CS_CONNECTION *conn;    /* Connection handle */
    CS_VOID       *creds;     /* security credentials */
    CS_BOOL       trueval = CS_TRUE;
    CS_BOOL       boolval;
    CS_CHAR       mechanismname[MAX_NAMESIZE];
    CS_CHAR       username[MAX_NAMESIZE];
    CS_INT        outlen;
   ......
   allocate and set user data in spp
   ......
   /* Allocate a connection handle for the connection attempt. */
    if (ct_con_alloc(Context, &(userdata->conn)) == CS_FAIL)
    {
       return(CS_FAIL);
    }
   ......
   conn = userdata->conn;
   /* 
    ** Initiate security session based login to the target server
    */
   /* Retrieve the client user name */
    if (srv_thread_props(spp, CS_GET, SRV_T_USER,
        (CS_VOID *)username, MAX_NAMESIZE, &outlen) == CS_FAIL) 
    {
       handle failure...
   }
   /* 
    ** Set the client’s security principal name to connect to the
    ** target server
    */
    if (ct_con_props(conn, CS_SET, CS_USERNAME,
       (CS_VOID *)username, outlen, (CS_INT *)NULL) == CS_FAIL)
    {
       handle failure...
   }
   /* Retrieve and set the security mechanism */
    if (srv_thread_props(spp, CS_GET, SRV_T_SEC_MECHANISM,
        (CS_VOID *)mechanismname, MAX_NAMESIZE, &outlen)
        == CS_FAIL) 
    {
       handle failure...
   }
   if (ct_con_props(conn, CS_SET, CS_SEC_MECHANISM,
       (CS_VOID *)mechanismname, outlen, (CS_INT *)NULL)
        == CS_FAIL)
    {
       handle failure...
   }
   /*
    ** Set security service-network authentication. Alternatively
    ** retrieve services from the current thread and set it.
    */
    if (ct_con_props(conn, CS_SET, CS_SEC_NETWORKAUTH,
       (CS_VOID *)&trueval, CS_SIZEOF(CS_BOOL), (CS_INT *)NULL)
       == CS_FAIL)
    {
       handle failure...
   }
   set other security services if needed...
   /* Ensure that the client enabled security delegation */
    if (srv_thread_props(spp, CS_GET, SRV_T_SEC_DELEGATION,
       (CS_VOID *)&boolval, CS_SIZEOF(CS_BOOL), (CS_INT *)NULL)
       == CS_FAIL)
    {
        handle failure...
    }
   if (boolval != CS_TRUE)
    {
       /* delegation not handled on this dialog */
      handle failure...
   }
   /* Retrieve the delegated credentials */
    if (srv_thread_props(spp, CS_GET, SRV_T_SEC_DELEGCRED,
       (CS_VOID *)&creds, CS_SIZEOF(CS_VOID*), (CS_INT *)NULL)
       == CS_FAIL)
    {
        handle failure...
    }
   /* 
    ** Set the delegated credentials to authenticate to the target
    ** server.
    */
    if (ct_con_props(conn, CS_SET, CS_SEC_CREDENTIALS,
       (CS_VOID *)&creds, CS_SIZEOF(CS_VOID *), (CS_INT *)NULL)
       == CS_FAIL)
    {
       handle failure...
   }
   get and set the user’s application name and response 
    capabilities...
   set the locale and other properties...
   /* Attempt a connection to the remote server */
    if (ct_connect(conn, Servername, CS_NULLTERM) == CS_FAIL)
    {
       handle failure...
   }
   Get and set the REQUEST capabilities...
   Get and set the RESPONSE capabilities...
   ......
   /* 
    ** You do not need to test this srv_senddone’s return value
    ** since Open Server will kill this thread if this call fails. 
    */
    (CS_VOID)srv_senddone(spp, SRV_DONE_FINAL, CS_TRAN_UNDEFINED,
                  (CS_INT)0);
    return(CS_SUCCEED);
 }