rxkad: Use rxi_Alloc not osi_Alloc
[openafs.git] / src / rxkad / rxkad_server.c
index fdde03e..be0abef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
-RCSID("$Header$");
+#include <roken.h>
 
-#include <afs/stds.h>
-#include <sys/types.h>
-#include <time.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
+#if (defined(AFS_AIX_ENV) && defined(KERNEL) && !defined(UKERNEL)) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV)
+#include <sys/systm.h>
 #endif
+
+#include <afs/opr.h>
 #include <rx/rx.h>
 #include <rx/xdr.h>
-#include <des.h>
+#include <rx/rx_packet.h>
 #include <afs/afsutil.h>
+
+#include "stats.h"
 #include "private_data.h"
 #define XPRT_RXKAD_SERVER
 
@@ -36,21 +36,28 @@ RCSID("$Header$");
  * Currently only used by the AFS/DFS protocol translator to recognize
  * Kerberos V5 tickets. The actual code to do that is provided externally.
  */
-afs_int32 (*rxkad_AlternateTicketDecoder)();
+afs_int32(*rxkad_AlternateTicketDecoder) (afs_int32, char *, afs_int32,
+                                         char *, char *, char *,
+                                         struct ktc_encryptionKey *,
+                                         afs_int32 *, afs_uint32 *,
+                                         afs_uint32 *);
 
 static struct rx_securityOps rxkad_server_ops = {
     rxkad_Close,
     rxkad_NewConnection,
-    rxkad_PreparePacket,               /* once per packet creation */
-    0,                                 /* send packet (once per retrans) */
+    rxkad_PreparePacket,       /* once per packet creation */
+    0,                         /* send packet (once per retrans) */
     rxkad_CheckAuthentication,
     rxkad_CreateChallenge,
     rxkad_GetChallenge,
     0,
     rxkad_CheckResponse,
-    rxkad_CheckPacket,                 /* check data packet */
+    rxkad_CheckPacket,         /* check data packet */
     rxkad_DestroyConnection,
     rxkad_GetStats,
+    rxkad_SetConfiguration,
+    0,                         /* spare 2 */
+    0,                         /* spare 3 */
 };
 extern afs_uint32 rx_MyMaxSendSize;
 
@@ -66,32 +73,39 @@ static fc_KeySchedule random_int32_schedule;
  * seed
  */
 
-#include <assert.h>
-pthread_mutex_t rxkad_random_mutex;
-#define LOCK_RM assert(pthread_mutex_lock(&rxkad_random_mutex)==0);
-#define UNLOCK_RM assert(pthread_mutex_unlock(&rxkad_random_mutex)==0);
+pthread_mutex_t rxkad_random_mutex
+#ifdef PTHREAD_MUTEX_INITIALIZER
+= PTHREAD_MUTEX_INITIALIZER
+#endif
+;
+#define LOCK_RM opr_Verify(pthread_mutex_lock(&rxkad_random_mutex)==0)
+#define UNLOCK_RM opr_Verify(pthread_mutex_unlock(&rxkad_random_mutex)==0)
 #else
 #define LOCK_RM
 #define UNLOCK_RM
 #endif /* AFS_PTHREAD_ENV */
 
-static void init_random_int32 ()
-{   struct timeval key;
+static void
+init_random_int32(void)
+{
+    struct timeval key;
 
-    gettimeofday (&key, NULL);
-    LOCK_RM
-    fc_keysched (&key, random_int32_schedule);
-    UNLOCK_RM
+    gettimeofday(&key, NULL);
+    LOCK_RM;
+    fc_keysched((struct ktc_encryptionKey*)&key, random_int32_schedule);
+    UNLOCK_RM;
 }
 
-static afs_int32 get_random_int32 ()
-{   static struct timeval seed;
+static afs_int32
+get_random_int32(void)
+{
+    static struct timeval seed;
     afs_int32 rc;
 
-    LOCK_RM
-    fc_ecb_encrypt (&seed, &seed, random_int32_schedule, ENCRYPT);
+    LOCK_RM;
+    fc_ecb_encrypt(&seed, &seed, random_int32_schedule, ENCRYPT);
     rc = seed.tv_sec;
-    UNLOCK_RM
+    UNLOCK_RM;
     return rc;
 }
 
@@ -106,67 +120,78 @@ static afs_int32 get_random_int32 ()
    the rx connection pointer passed to the RPC routine to obtain information
    about the client. */
 
+/*
+  rxkad_level      level;              * minimum level *
+  char           *get_key_rock;        * rock for get_key implementor *
+  int           (*get_key)();          * passed kvno & addr(key) to fill *
+  int           (*user_ok)();          * passed name, inst, cell => bool *
+*/
+
 struct rx_securityClass *
-rxkad_NewServerSecurityObject (level, get_key_rock, get_key, user_ok)
-  rxkad_level      level;              /* minimum level */
-  char           *get_key_rock;        /* rock for get_key implementor */
-  int           (*get_key)();          /* passed kvno & addr(key) to fill */
-  int           (*user_ok)();          /* passed name, inst, cell => bool */
-{   struct rx_securityClass *tsc;
-    struct rxkad_sprivate   *tsp;
+rxkad_NewServerSecurityObject(rxkad_level level, void *get_key_rock,
+                             int (*get_key) (void *get_key_rock, int kvno,
+                                             struct ktc_encryptionKey *
+                                             serverKey),
+                             int (*user_ok) (char *name, char *instance,
+                                             char *cell, afs_int32 kvno))
+{
+    struct rx_securityClass *tsc;
+    struct rxkad_sprivate *tsp;
     int size;
 
-    if (!get_key) return 0;
-    
+    rxkad_Init();
+
+    if (!get_key)
+       return 0;
+
     size = sizeof(struct rx_securityClass);
-    tsc = (struct rx_securityClass *) osi_Alloc (size);
-    bzero (tsc, size);
-    tsc->refCount = 1;                 /* caller has one reference */
+    tsc = rxi_Alloc(size);
+    memset(tsc, 0, size);
+    tsc->refCount = 1;         /* caller has one reference */
     tsc->ops = &rxkad_server_ops;
     size = sizeof(struct rxkad_sprivate);
-    tsp = (struct rxkad_sprivate *) osi_Alloc (size);
-    bzero (tsp, size);
-    tsc->privateData = (char *) tsp;
+    tsp = rxi_Alloc(size);
+    memset(tsp, 0, size);
+    tsc->privateData = (char *)tsp;
 
-    tsp->type |= rxkad_server;         /* so can identify later */
-    tsp->level = level;                        /* level of encryption */
+    tsp->type |= rxkad_server; /* so can identify later */
+    tsp->level = level;                /* level of encryption */
     tsp->get_key_rock = get_key_rock;
-    tsp->get_key = get_key;            /* to get server ticket */
-    tsp->user_ok = user_ok;            /* to inform server of client id. */
-    init_random_int32 ();
+    tsp->get_key = get_key;    /* to get server ticket */
+    tsp->user_ok = user_ok;    /* to inform server of client id. */
+    init_random_int32();
 
-    LOCK_RXKAD_STATS
-    rxkad_stats_serverObjects++;
-    UNLOCK_RXKAD_STATS
+    INC_RXKAD_STATS(serverObjects);
     return tsc;
 }
 
 /* server: called to tell if a connection authenticated properly */
 
-rxs_return_t rxkad_CheckAuthentication (aobj, aconn)
-  struct rx_securityClass *aobj;
-  struct rx_connection *aconn;
-{   struct rxkad_sconn *sconn;
+int
+rxkad_CheckAuthentication(struct rx_securityClass *aobj,
+                         struct rx_connection *aconn)
+{
+    struct rxkad_sconn *sconn = rx_GetSecurityData(aconn);
 
     /* first make sure the object exists */
-    if (!aconn->securityData) return RXKADINCONSISTENCY;
+    if (!sconn)
+       return RXKADINCONSISTENCY;
 
-    sconn = (struct rxkad_sconn *) aconn->securityData;
     return !sconn->authenticated;
 }
 
 /* server: put the current challenge in the connection structure for later use
    by packet sender */
 
-rxs_return_t rxkad_CreateChallenge(aobj, aconn)
-  struct rx_securityClass *aobj;
-  struct rx_connection *aconn;
-{   struct rxkad_sconn *sconn;
+int
+rxkad_CreateChallenge(struct rx_securityClass *aobj,
+                     struct rx_connection *aconn)
+{
+    struct rxkad_sconn *sconn = rx_GetSecurityData(aconn);
     struct rxkad_sprivate *tsp;
 
-    sconn = (struct rxkad_sconn *) aconn->securityData;
-    sconn->challengeID = get_random_int32 ();
-    sconn->authenticated = 0;          /* conn unauth. 'til we hear back */
+    sconn->challengeID = get_random_int32();
+    sconn->authenticated = 0;  /* conn unauth. 'til we hear back */
     /* initialize level from object's minimum acceptable level */
     tsp = (struct rxkad_sprivate *)aobj->privateData;
     sconn->level = tsp->level;
@@ -175,32 +200,31 @@ rxs_return_t rxkad_CreateChallenge(aobj, aconn)
 
 /* server: fill in a challenge in the packet */
 
-rxs_return_t rxkad_GetChallenge (aobj, aconn, apacket)
-  IN struct rx_securityClass *aobj;
-  IN struct rx_packet *apacket;
-  IN struct rx_connection *aconn;
-{   struct rxkad_sconn *sconn;
-    afs_int32 temp;
+int
+rxkad_GetChallenge(struct rx_securityClass *aobj, struct rx_connection *aconn,
+                  struct rx_packet *apacket)
+{
+    struct rxkad_sconn *sconn = rx_GetSecurityData(aconn);
     char *challenge;
     int challengeSize;
-    struct rxkad_v2Challenge  c_v2;   /* version 2 */
-    struct rxkad_oldChallenge c_old;  /* old style */
+    struct rxkad_v2Challenge c_v2;     /* version 2 */
+    struct rxkad_oldChallenge c_old;   /* old style */
 
-    sconn = (struct rxkad_sconn *) aconn->securityData;
-    if (rx_IsUsingPktCksum(aconn)) sconn->cksumSeen = 1;
+    if (rx_IsUsingPktCksum(aconn))
+       sconn->cksumSeen = 1;
 
     if (sconn->cksumSeen) {
-       bzero (&c_v2, sizeof(c_v2));
+       memset(&c_v2, 0, sizeof(c_v2));
        c_v2.version = htonl(RXKAD_CHALLENGE_PROTOCOL_VERSION);
        c_v2.challengeID = htonl(sconn->challengeID);
-       c_v2.level = htonl((afs_int32)sconn->level);
+       c_v2.level = htonl((afs_int32) sconn->level);
        c_v2.spare = 0;
        challenge = (char *)&c_v2;
        challengeSize = sizeof(c_v2);
     } else {
-       bzero (&c_old, sizeof(c_old));
+       memset(&c_old, 0, sizeof(c_old));
        c_old.challengeID = htonl(sconn->challengeID);
-       c_old.level = htonl((afs_int32)sconn->level);
+       c_old.level = htonl((afs_int32) sconn->level);
        challenge = (char *)&c_old;
        challengeSize = sizeof(c_old);
     }
@@ -208,11 +232,9 @@ rxs_return_t rxkad_GetChallenge (aobj, aconn, apacket)
        return RXKADPACKETSHORT;        /* not enough space */
 
     rx_packetwrite(apacket, 0, challengeSize, challenge);
-    rx_SetDataSize (apacket, challengeSize);
+    rx_SetDataSize(apacket, challengeSize);
     sconn->tried = 1;
-    LOCK_RXKAD_STATS
-    rxkad_stats.challengesSent++;
-    UNLOCK_RXKAD_STATS
+    INC_RXKAD_STATS(challengesSent);
     return 0;
 }
 
@@ -220,53 +242,54 @@ rxs_return_t rxkad_GetChallenge (aobj, aconn, apacket)
 /* XXX this does some copying of data in and out of the packet, but I'll bet it
  * could just do it in place, especially if I used rx_Pullup...
  */
-rxs_return_t rxkad_CheckResponse (aobj, aconn, apacket)
-  struct rx_securityClass *aobj;
-  struct rx_packet *apacket;
-  struct rx_connection *aconn;
-{   struct rxkad_sconn *sconn;
+int
+rxkad_CheckResponse(struct rx_securityClass *aobj,
+                   struct rx_connection *aconn, struct rx_packet *apacket)
+{
+    struct rxkad_sconn *sconn;
     struct rxkad_sprivate *tsp;
     struct ktc_encryptionKey serverKey;
-    struct rxkad_oldChallengeResponse oldr; /* response format */
+    struct rxkad_oldChallengeResponse oldr;    /* response format */
     struct rxkad_v2ChallengeResponse v2r;
-    afs_int32  tlen;                           /* ticket len */
-    afs_int32  kvno;                           /* key version of ticket */
-    char  tix[MAXKTCTICKETLEN];
-    afs_int32  incChallengeID;
+    afs_int32 tlen;            /* ticket len */
+    afs_int32 kvno;            /* key version of ticket */
+    char tix[MAXKTCTICKETLEN];
+    afs_int32 incChallengeID;
     rxkad_level level;
-    int          code;
+    int code;
     /* ticket contents */
     struct ktc_principal client;
     struct ktc_encryptionKey sessionkey;
-    afs_int32    host;
+    afs_int32 host;
     afs_uint32 start;
     afs_uint32 end;
     unsigned int pos;
     struct rxkad_serverinfo *rock;
 
-    sconn = (struct rxkad_sconn *) aconn->securityData;
-    tsp = (struct rxkad_sprivate *) aobj->privateData;
+    sconn = rx_GetSecurityData(aconn);
+    tsp = (struct rxkad_sprivate *)aobj->privateData;
 
     if (sconn->cksumSeen) {
        /* expect v2 response, leave fields in v2r in network order for cksum
-         * computation which follows decryption. */
-       if (rx_GetDataSize(apacket) < sizeof(v2r)) 
-         return RXKADPACKETSHORT;
+        * computation which follows decryption. */
+       if (rx_GetDataSize(apacket) < sizeof(v2r))
+           return RXKADPACKETSHORT;
        rx_packetread(apacket, 0, sizeof(v2r), &v2r);
        pos = sizeof(v2r);
        /* version == 2 */
        /* ignore spare */
-       kvno = ntohl (v2r.kvno);
+       kvno = ntohl(v2r.kvno);
        tlen = ntohl(v2r.ticketLen);
        if (rx_GetDataSize(apacket) < sizeof(v2r) + tlen)
            return RXKADPACKETSHORT;
     } else {
        /* expect old format response */
-       if (rx_GetDataSize(apacket) < sizeof(oldr)) return RXKADPACKETSHORT;
+       if (rx_GetDataSize(apacket) < sizeof(oldr))
+           return RXKADPACKETSHORT;
        rx_packetread(apacket, 0, sizeof(oldr), &oldr);
        pos = sizeof(oldr);
 
-       kvno = ntohl (oldr.kvno);
+       kvno = ntohl(oldr.kvno);
        tlen = ntohl(oldr.ticketLen);
        if (rx_GetDataSize(apacket) != sizeof(oldr) + tlen)
            return RXKADPACKETSHORT;
@@ -284,95 +307,119 @@ rxs_return_t rxkad_CheckResponse (aobj, aconn, apacket)
      * the standard decoder.
      */
     if (rxkad_AlternateTicketDecoder) {
-       code = rxkad_AlternateTicketDecoder
-           (kvno, tix, tlen, client.name, client.instance, client.cell,
-            &sessionkey, &host, &start, &end);
+       code =
+           rxkad_AlternateTicketDecoder(kvno, tix, tlen, client.name,
+                                        client.instance, client.cell,
+                                        &sessionkey, &host, &start, &end);
        if (code && code != -1) {
            return code;
        }
     } else {
-       code = -1;    /* No alternate ticket decoder present */
+       code = -1;              /* No alternate ticket decoder present */
     }
 
     /*
      * If the alternate decoder is not present, or returns -1, then
      * assume the ticket is of the default style.
      */
+    if (code == -1 && ((kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
+       || (kvno == RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY))) {
+       code =
+           tkt_DecodeTicket5(tix, tlen, tsp->get_key, tsp->get_key_rock,
+                             kvno, client.name, client.instance, client.cell,
+                             &sessionkey, &host, &start, &end,
+                             tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
+       if (code)
+           return code;
+    }
+
+    /*
+     * If the alternate decoder/kerberos 5 decoder is not present, or
+     * returns -1, then assume the ticket is of the default style.
+     */
     if (code == -1) {
        /* get ticket's key */
-       code = (*tsp->get_key)(tsp->get_key_rock, kvno, &serverKey);
-       if (code) return RXKADUNKNOWNKEY;       /* invalid kvno */
-       code = tkt_DecodeTicket (tix, tlen, &serverKey,
-                                client.name, client.instance, client.cell,
-                                &sessionkey, &host, &start, &end);
-       if (code) return RXKADBADTICKET;
+       code = (*tsp->get_key) (tsp->get_key_rock, kvno, &serverKey);
+       if (code)
+           return RXKADUNKNOWNKEY;     /* invalid kvno */
+       code =
+           tkt_DecodeTicket(tix, tlen, &serverKey, client.name,
+                            client.instance, client.cell, &sessionkey, &host,
+                            &start, &end);
+       if (code)
+           return code;
     }
-    code = tkt_CheckTimes (start, end, time(0));
-    if (code == -1) return RXKADEXPIRED;
-    else if (code <= 0) return RXKADNOAUTH;
-
-    code = fc_keysched (&sessionkey, sconn->keysched);
-    if (code) return RXKADBADKEY;
-    bcopy (&sessionkey, sconn->ivec, sizeof(sconn->ivec));
+    code = tkt_CheckTimes(start, end, time(0));
+    if (code == 0)
+       return RXKADNOAUTH;
+    else if (code == -1)
+       return RXKADEXPIRED;
+    else if (code < -1)
+       return RXKADBADTICKET;
+
+    code = fc_keysched(&sessionkey, sconn->keysched);
+    if (code)
+       return RXKADBADKEY;
+    memcpy(sconn->ivec, &sessionkey, sizeof(sconn->ivec));
 
     if (sconn->cksumSeen) {
        /* using v2 response */
-       afs_uint32 cksum;                       /* observed cksum */
+       afs_uint32 cksum;       /* observed cksum */
        struct rxkad_endpoint endpoint; /* connections endpoint */
        int i;
        afs_uint32 xor[2];
 
-       bcopy(sconn->ivec, xor, 2*sizeof(afs_int32));
-       fc_cbc_encrypt (&v2r.encrypted, &v2r.encrypted, sizeof(v2r.encrypted),
-                       sconn->keysched, xor, DECRYPT);
-       cksum = rxkad_CksumChallengeResponse (&v2r);
+       memcpy(xor, sconn->ivec, 2 * sizeof(afs_int32));
+       fc_cbc_encrypt(&v2r.encrypted, &v2r.encrypted, sizeof(v2r.encrypted),
+                      sconn->keysched, xor, DECRYPT);
+       cksum = rxkad_CksumChallengeResponse(&v2r);
        if (cksum != v2r.encrypted.endpoint.cksum)
            return RXKADSEALEDINCON;
-       (void) rxkad_SetupEndpoint (aconn, &endpoint);
+       (void)rxkad_SetupEndpoint(aconn, &endpoint);
        v2r.encrypted.endpoint.cksum = 0;
-       if (bcmp (&endpoint, &v2r.encrypted.endpoint, sizeof(endpoint)) != 0)
+       if (memcmp(&endpoint, &v2r.encrypted.endpoint, sizeof(endpoint)) != 0)
            return RXKADSEALEDINCON;
-       for (i=0; i<RX_MAXCALLS; i++) {
-           v2r.encrypted.callNumbers[i] = ntohl(v2r.encrypted.callNumbers[i]);
-           if (v2r.encrypted.callNumbers[i] < 0) return RXKADSEALEDINCON;
+       for (i = 0; i < RX_MAXCALLS; i++) {
+           v2r.encrypted.callNumbers[i] =
+               ntohl(v2r.encrypted.callNumbers[i]);
+           if (v2r.encrypted.callNumbers[i] < 0)
+               return RXKADSEALEDINCON;
        }
 
-       (void) rxi_SetCallNumberVector (aconn, v2r.encrypted.callNumbers);
+       (void)rxi_SetCallNumberVector(aconn, v2r.encrypted.callNumbers);
        incChallengeID = ntohl(v2r.encrypted.incChallengeID);
        level = ntohl(v2r.encrypted.level);
     } else {
        /* expect old format response */
-       fc_ecb_encrypt(&oldr.encrypted, &oldr.encrypted,
-                      sconn->keysched, DECRYPT);
+       fc_ecb_encrypt(&oldr.encrypted, &oldr.encrypted, sconn->keysched,
+                      DECRYPT);
        incChallengeID = ntohl(oldr.encrypted.incChallengeID);
        level = ntohl(oldr.encrypted.level);
     }
-    if (incChallengeID != sconn->challengeID+1)
+    if (incChallengeID != sconn->challengeID + 1)
        return RXKADOUTOFSEQUENCE;      /* replay attempt */
-    if ((level < sconn->level) || (level > rxkad_crypt)) return RXKADLEVELFAIL;
+    if ((level < sconn->level) || (level > rxkad_crypt))
+       return RXKADLEVELFAIL;
     sconn->level = level;
-    rxkad_SetLevel (aconn, sconn->level);
-    LOCK_RXKAD_STATS
-    rxkad_stats.responses[rxkad_LevelIndex(sconn->level)]++;
-    UNLOCK_RXKAD_STATS
-
+    rxkad_SetLevel(aconn, sconn->level);
+    INC_RXKAD_STATS(responses[rxkad_LevelIndex(sconn->level)]);
     /* now compute endpoint-specific info used for computing 16 bit checksum */
-    rxkad_DeriveXORInfo(aconn, sconn->keysched, sconn->ivec, sconn->preSeq);
+    rxkad_DeriveXORInfo(aconn, &sconn->keysched, (char *)sconn->ivec, (char *)sconn->preSeq);
 
     /* otherwise things are ok */
     sconn->expirationTime = end;
     sconn->authenticated = 1;
 
     if (tsp->user_ok) {
-       code = tsp->user_ok (client.name, client.instance, client.cell, kvno);
-       if (code) return RXKADNOAUTH;
-    }
-    else {                             /* save the info for later retreival */
+       code = tsp->user_ok(client.name, client.instance, client.cell, kvno);
+       if (code)
+           return RXKADNOAUTH;
+    } else {                   /* save the info for later retreival */
        int size = sizeof(struct rxkad_serverinfo);
-       rock = (struct rxkad_serverinfo *) osi_Alloc (size);
-       bzero (rock, size);
+       rock = rxi_Alloc(size);
+       memset(rock, 0, size);
        rock->kvno = kvno;
-       bcopy (&client, &rock->client, sizeof(rock->client));
+       memcpy(&rock->client, &client, sizeof(rock->client));
        sconn->rock = rock;
     }
     return 0;
@@ -380,28 +427,52 @@ rxs_return_t rxkad_CheckResponse (aobj, aconn, apacket)
 
 /* return useful authentication info about a server-side connection */
 
-afs_int32 rxkad_GetServerInfo (aconn, level, expiration,
-                                name, instance, cell, kvno)
-  struct rx_connection *aconn;
-  rxkad_level   *level;
-  afs_uint32  *expiration;
-  char          *name;
-  char          *instance;
-  char          *cell;
-  afs_int32             *kvno;
+afs_int32
+rxkad_GetServerInfo(struct rx_connection * aconn, rxkad_level * level,
+                   afs_uint32 * expiration, char *name, char *instance,
+                   char *cell, afs_int32 * kvno)
 {
     struct rxkad_sconn *sconn;
 
-    sconn = (struct rxkad_sconn *) aconn->securityData;
-    if (sconn && sconn->authenticated && sconn->rock &&
-       (time(0) < sconn->expirationTime)) {
-       if (level)      *level = sconn->level;
-       if (expiration) *expiration = sconn->expirationTime;
-       if (name)       strcpy (name, sconn->rock->client.name);
-       if (instance)   strcpy (instance, sconn->rock->client.instance);
-       if (cell)       strcpy (cell, sconn->rock->client.cell);
-       if (kvno)       *kvno = sconn->rock->kvno;
+    sconn = rx_GetSecurityData(aconn);
+    if (sconn && sconn->authenticated && sconn->rock
+       && (time(0) < sconn->expirationTime)) {
+       if (level)
+           *level = sconn->level;
+       if (expiration)
+           *expiration = sconn->expirationTime;
+       if (name)
+           strcpy(name, sconn->rock->client.name);
+       if (instance)
+           strcpy(instance, sconn->rock->client.instance);
+       if (cell)
+           strcpy(cell, sconn->rock->client.cell);
+       if (kvno)
+           *kvno = sconn->rock->kvno;
        return 0;
+    } else
+       return RXKADNOAUTH;
+}
+
+/* Set security object configuration variables */
+afs_int32 rxkad_SetConfiguration(struct rx_securityClass *aobj,
+                                 struct rx_connection *aconn,
+                                 rx_securityConfigVariables atype,
+                                        void * avalue, void **currentValue)
+{
+    struct rxkad_sprivate *private =
+    (struct rxkad_sprivate *) aobj->privateData;
+
+    switch (atype) {
+    case RXS_CONFIG_FLAGS:
+        if (currentValue) {
+            *((afs_uint32 *)currentValue) = private->flags;
+        } else {
+            private->flags = (intptr_t)avalue;
+        }
+        break;
+    default:
+        break;
     }
-    else return RXKADNOAUTH;
+    return 0;
 }