X-Git-Url: http://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fauth%2Fauthcon.c;h=5f415a676f869ddbaf1f7507e707ed5e09d34c62;hp=ff4fcdfd9c9c9283315cbadebfde97f23ac01dd3;hb=d008089a79ef268bbca91d660a840f32cb416865;hpb=e7ec0d4213853117dc463a3629651e280c6cf0fa diff --git a/src/auth/authcon.c b/src/auth/authcon.c index ff4fcdf..5f415a6 100644 --- a/src/auth/authcon.c +++ b/src/auth/authcon.c @@ -7,27 +7,27 @@ * directory or online at http://www.openafs.org/dl/license10.html */ +#include #if defined(UKERNEL) -#include "../afs/param.h" +#include "afs/param.h" #else #include #endif -#include -RCSID("$Header$"); #if defined(UKERNEL) -#include "../afs/sysincludes.h" -#include "../afs/afsincludes.h" -#include "../afs/stds.h" -#include "../afs/pthread_glock.h" -#include "../des/des.h" -#include "../rx/rxkad.h" -#include "../rx/rx.h" -#include "../afs/cellconfig.h" -#include "../afs/keys.h" -#include "../afs/auth.h" -#include "../afs/pthread_glock.h" +#include "afs/sysincludes.h" +#include "afsincludes.h" +#include "afs/stds.h" +#include "afs/pthread_glock.h" +#include "rx/rxkad.h" +#include "rx/rx.h" +#include "afs/cellconfig.h" +#include "afs/keys.h" +#include "afs/auth.h" +#include "afs/pthread_glock.h" +#include "des.h" +#include "des_prototypes.h" #else /* defined(UKERNEL) */ #include #include @@ -40,7 +40,10 @@ RCSID("$Header$"); #include #include #endif +#include +#include #include +#include #include #include #include "cellconfig.h" @@ -48,18 +51,12 @@ RCSID("$Header$"); #include "auth.h" #endif /* defined(UKERNEL) */ - -extern afs_int32 afsconf_Authenticate(); -extern int afsconf_GetKey(); -extern struct rx_securityClass *rxkad_NewServerSecurityObject(); -extern struct rx_securityClass *rxkad_NewClientSecurityObject(); - /* return a null security object if nothing else can be done */ -static afs_int32 QuickAuth(astr, aindex) -struct rx_securityClass **astr; -afs_int32 *aindex; { +static afs_int32 +QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex) +{ register struct rx_securityClass *tc; - tc = (struct rx_securityClass *) rxnull_NewClientSecurityObject(); + tc = rxnull_NewClientSecurityObject(); *astr = tc; *aindex = 0; return 0; @@ -67,62 +64,64 @@ afs_int32 *aindex; { #if !defined(UKERNEL) /* Return an appropriate security class and index */ -afs_int32 afsconf_ServerAuth(adir, astr, aindex) -register struct afsconf_dir *adir; -struct rx_securityClass **astr; -afs_int32 *aindex; { +afs_int32 +afsconf_ServerAuth(void *arock, + struct rx_securityClass **astr, + afs_int32 *aindex) +{ + struct afsconf_dir *adir = (struct afsconf_dir *) arock; register struct rx_securityClass *tclass; - - LOCK_GLOBAL_MUTEX + + LOCK_GLOBAL_MUTEX; tclass = (struct rx_securityClass *) - rxkad_NewServerSecurityObject(0, adir, afsconf_GetKey, (char *) 0); + rxkad_NewServerSecurityObject(0, adir, afsconf_GetKey, NULL); if (tclass) { *astr = tclass; - *aindex = 2; /* kerberos security index */ - UNLOCK_GLOBAL_MUTEX + *aindex = 2; /* kerberos security index */ + UNLOCK_GLOBAL_MUTEX; return 0; - } - else { - UNLOCK_GLOBAL_MUTEX + } else { + UNLOCK_GLOBAL_MUTEX; return 2; } } #endif /* !defined(UKERNEL) */ -static afs_int32 GenericAuth(adir, astr, aindex, enclevel) -struct afsconf_dir *adir; -struct rx_securityClass **astr; -afs_int32 *aindex; -rxkad_level enclevel; { +static afs_int32 +GenericAuth(struct afsconf_dir *adir, + struct rx_securityClass **astr, + afs_int32 *aindex, + rxkad_level enclevel) +{ char tbuffer[256]; struct ktc_encryptionKey key, session; struct rx_securityClass *tclass; afs_int32 kvno; afs_int32 ticketLen; - struct timeval tv; - Key_schedule schedule; - register afs_int32 i, code; - + register afs_int32 code; + /* first, find the right key and kvno to use */ code = afsconf_GetLatestKey(adir, &kvno, &key); if (code) { return QuickAuth(astr, aindex); } - + /* next create random session key, using key for seed to good random */ - des_init_random_number_generator (&key); - code = des_random_key (&session); + des_init_random_number_generator(ktc_to_cblock(&key)); + code = des_random_key(ktc_to_cblock(&session)); if (code) { return QuickAuth(astr, aindex); } - + /* now create the actual ticket */ ticketLen = sizeof(tbuffer); - code = tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0, - 0xffffffff, &session, 0, "afs", ""); + memset(tbuffer, '\0', sizeof(tbuffer)); + code = + tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0, + 0xffffffff, &session, 0, "afs", ""); /* parms were buffer, ticketlen, key to seal ticket with, principal - name, instance and cell, start time, end time, session key to seal - in ticket, inet host, server name and server instance */ + * name, instance and cell, start time, end time, session key to seal + * in ticket, inet host, server name and server instance */ if (code) { return QuickAuth(astr, aindex); } @@ -132,25 +131,26 @@ rxkad_level enclevel; { * order when compiling the system from scratch (rx/rxkad.h isn't installed * yet). */ tclass = (struct rx_securityClass *) - rxkad_NewClientSecurityObject(enclevel, &session, kvno, - ticketLen, tbuffer); + rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen, + tbuffer); *astr = tclass; - *aindex = 2; /* kerberos security index */ + *aindex = 2; /* kerberos security index */ return 0; } /* build a fake ticket for 'afs' using keys from adir, returning an * appropriate security class and index */ -afs_int32 afsconf_ClientAuth(adir, astr, aindex) -struct afsconf_dir *adir; -struct rx_securityClass **astr; -afs_int32 *aindex; { +afs_int32 +afsconf_ClientAuth(void *arock, struct rx_securityClass ** astr, + afs_int32 * aindex) +{ + struct afsconf_dir * adir = (struct afsconf_dir *) arock; afs_int32 rc; - LOCK_GLOBAL_MUTEX + LOCK_GLOBAL_MUTEX; rc = GenericAuth(adir, astr, aindex, rxkad_clear); - UNLOCK_GLOBAL_MUTEX + UNLOCK_GLOBAL_MUTEX; return rc; } @@ -158,15 +158,208 @@ afs_int32 *aindex; { * appropriate security class and index. This one, unlike the above, * tells rxkad to encrypt the data, too. */ -afs_int32 afsconf_ClientAuthSecure(adir, astr, aindex) -struct afsconf_dir *adir; -struct rx_securityClass **astr; -afs_int32 *aindex; { +afs_int32 +afsconf_ClientAuthSecure(void *arock, + struct rx_securityClass **astr, + afs_int32 *aindex) +{ + struct afsconf_dir *adir = (struct afsconf_dir *) arock; afs_int32 rc; - LOCK_GLOBAL_MUTEX + LOCK_GLOBAL_MUTEX; rc = GenericAuth(adir, astr, aindex, rxkad_crypt); - UNLOCK_GLOBAL_MUTEX + UNLOCK_GLOBAL_MUTEX; return rc; } +/*! + * Build a security class from the user's current tokens + * + * This function constructs an RX security class from a user's current + * tokens. + * + * @param[in] info The cell information structure + * @param[in] flags Security flags describing the desired mechanism + * @param[out] sc The selected security class + * @param[out] scIndex The index of the selected class + * @parma[out] expires The expiry time of the tokens used to build the class + * + * Only the AFSCONF_SECOPTS_ALWAYSENCRYPT flag will modify the behaviour of + * this function - it determines whether a cleartext, or encrypting, security + * class is provided. + * + * @return + * 0 on success, non-zero on failure. An error code of + * AFSCONF_NO_SECURITY_CLASS indicates that were were unable to build a + * security class using the selected tokens. + */ + +afs_int32 +afsconf_ClientAuthToken(struct afsconf_cell *info, + afsconf_secflags flags, + struct rx_securityClass **sc, + afs_int32 *scIndex, + time_t *expires) +{ + struct ktc_principal sname; + struct ktc_token ttoken; + int encryptLevel; + afs_int32 code; + + *sc = NULL; + *scIndex = 0; + + strcpy(sname.cell, info->name); + sname.instance[0] = 0; + strcpy(sname.name, "afs"); + code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL); + + if (code == 0) { + /* XXX - We should think about how to handle this */ + if (ttoken.kvno < 0 || ttoken.kvno > 256) { + fprintf(stderr, + "funny kvno (%d) in ticket, proceeding\n", + ttoken.kvno); + } + if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT) + encryptLevel = rxkad_crypt; + else + encryptLevel = rxkad_clear; + *sc = rxkad_NewClientSecurityObject(encryptLevel, + &ttoken.sessionKey, + ttoken.kvno, + ttoken.ticketLen, + ttoken.ticket); + *scIndex = 2; + if (expires) + *expires = ttoken.endTime; + } + if (*sc == NULL) + return AFSCONF_NO_SECURITY_CLASS; + + return code; +} + +/*! + * Build a set of security classes suitable for a server accepting + * incoming connections + */ +#if !defined(UKERNEL) +void +afsconf_BuildServerSecurityObjects(struct afsconf_dir *dir, + afs_uint32 flags, + struct rx_securityClass ***classes, + afs_int32 *numClasses) +{ + if (flags & AFSCONF_SEC_OBJS_RXKAD_CRYPT) + *numClasses = 4; + else + *numClasses = 3; + + *classes = calloc(*numClasses, sizeof(**classes)); + + (*classes)[0] = rxnull_NewServerSecurityObject(); + (*classes)[1] = NULL; + (*classes)[2] = rxkad_NewServerSecurityObject(0, dir, + afsconf_GetKey, NULL); + if (flags & AFSCONF_SEC_OBJS_RXKAD_CRYPT) + (*classes)[3] = rxkad_NewServerSecurityObject(rxkad_crypt, dir, + afsconf_GetKey, NULL); +} +#endif + +/*! + * Pick a security class to use for an outgoing connection + * + * This function selects an RX security class to use for an outgoing + * connection, based on the set of security flags provided. + * + * @param[in] dir + * The configuration directory structure for this cell. If NULL, + * no classes requiring local configuration will be returned. + * @param[in] flags + * A set of flags to determine the properties of the security class which + * is selected + * - AFSCONF_SECOPTS_NOAUTH - return an anonymous secirty class + * - AFSCONF_SECOPTS_LOCALAUTH - use classes which have local key + * material available. + * - AFSCONF_SECOPTS_ALWAYSENCRYPT - use classes in encrypting, rather + * than authentication or integrity modes. + * - AFSCONF_SECOPTS_FALLBACK_NULL - if no suitable class can be found, + * then fallback to the rxnull security class. + * @param[in] info + * The cell information structure for the current cell. If this is NULL, + * then use a version locally obtained using the cellName. + * @param[in] cellName + * The cellName to use when obtaining cell information (may be NULL if + * info is specified) + * @param[out] sc + * The selected security class + * @param[out] scIndex + * The index of the selected security class + * @param[out] expires + * The expiry time of the tokens used to construct the class. Will be + * NEVER_DATE if the class has an unlimited lifetime. If NULL, the + * function won't store the expiry date. + * + * @return + * Returns 0 on success, or a com_err error code on failure. + */ +afs_int32 +afsconf_PickClientSecObj(struct afsconf_dir *dir, afsconf_secflags flags, + struct afsconf_cell *info, + char *cellName, struct rx_securityClass **sc, + afs_int32 *scIndex, time_t *expires) { + struct afsconf_cell localInfo; + afs_int32 code = 0; + + *sc = NULL; + *scIndex = 0; + if (expires) + expires = 0; + + if ( !(flags & AFSCONF_SECOPTS_NOAUTH) ) { + if (!dir) + return AFSCONF_NOCELLDB; + + if (flags & AFSCONF_SECOPTS_LOCALAUTH) { + code = afsconf_GetLatestKey(dir, 0, 0); + if (code) + goto out; + + if (flags & AFSCONF_SECOPTS_ALWAYSENCRYPT) + code = afsconf_ClientAuthSecure(dir, sc, scIndex); + else + code = afsconf_ClientAuth(dir, sc, scIndex); + + if (code) + goto out; + + if (expires) + *expires = NEVERDATE; + } else { + if (info == NULL) { + code = afsconf_GetCellInfo(dir, cellName, NULL, &localInfo); + if (code) + goto out; + info = &localInfo; + } + + code = afsconf_ClientAuthToken(info, flags, sc, scIndex, expires); + if (code && !(flags & AFSCONF_SECOPTS_FALLBACK_NULL)) + goto out; + + /* If we didn't get a token, we'll just run anonymously */ + code = 0; + } + } + if (*sc == NULL) { + *sc = rxnull_NewClientSecurityObject(); + *scIndex = 0; + if (expires) + *expires = NEVERDATE; + } + +out: + return code; +}