/*! * 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 = RX_SECIDX_NULL; 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 = RX_SECIDX_NULL; if (expires) *expires = NEVERDATE; } out: return code; }
afs_int32 pr_Initialize(IN afs_int32 secLevel, IN const char *confDir, IN char *cell) { afs_int32 code; struct rx_connection *serverconns[MAXSERVERS]; struct rx_securityClass *sc = NULL; static struct afsconf_dir *tdir = (struct afsconf_dir *)NULL; /* only do this once */ static char tconfDir[100] = ""; static char tcell[64] = ""; afs_int32 scIndex; afs_int32 secFlags; static struct afsconf_cell info; afs_int32 i; #if !defined(UKERNEL) char cellstr[64]; #endif afs_int32 gottdir = 0; afs_int32 refresh = 0; initialize_PT_error_table(); initialize_RXK_error_table(); initialize_ACFG_error_table(); initialize_KTC_error_table(); #if defined(UKERNEL) if (!cell) { cell = afs_LclCellName; } #else /* defined(UKERNEL) */ if (!cell) { if (!tdir) tdir = afsconf_Open(confDir); if (!tdir) { if (confDir && strcmp(confDir, "")) fprintf(stderr, "%s: Could not open configuration directory: %s.\n", whoami, confDir); else fprintf(stderr, "%s: No configuration directory specified.\n", whoami); return -1; } gottdir = 1; code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr)); if (code) { fprintf(stderr, "libprot: Could not get local cell. [%d]\n", code); return code; } cell = cellstr; } #endif /* defined(UKERNEL) */ if (tdir == NULL || strcmp(confDir, tconfDir) || strcmp(cell, tcell)) { /* * force re-evaluation. we either don't have an afsconf_dir, * the directory has changed or the cell has changed. */ if (tdir && !gottdir) { afsconf_Close(tdir); tdir = (struct afsconf_dir *)NULL; } pruclient = (struct ubik_client *)NULL; refresh = 1; } if (refresh) { strncpy(tconfDir, confDir, sizeof(tconfDir)); strncpy(tcell, cell, sizeof(tcell)); #if defined(UKERNEL) tdir = afs_cdir; #else /* defined(UKERNEL) */ if (!gottdir) tdir = afsconf_Open(confDir); if (!tdir) { if (confDir && strcmp(confDir, "")) fprintf(stderr, "libprot: Could not open configuration directory: %s.\n", confDir); else fprintf(stderr, "libprot: No configuration directory specified.\n"); return -1; } #endif /* defined(UKERNEL) */ code = afsconf_GetCellInfo(tdir, cell, "afsprot", &info); if (code) { fprintf(stderr, "libprot: Could not locate cell %s in %s/%s\n", cell, confDir, AFSDIR_CELLSERVDB_FILE); return code; } } /* If we already have a client and it is at the security level we * want, don't get a new one. Unless the security level is 2 in * which case we will get one (and re-read the key file). */ if (pruclient && (lastLevel == secLevel) && (secLevel != 2)) { return 0; } code = rx_Init(0); if (code) { fprintf(stderr, "libprot: Could not initialize rx.\n"); return code; } /* Most callers use secLevel==1, however, the fileserver uses secLevel==2 * to force use of the KeyFile. secLevel == 0 implies -noauth was * specified. */ if (secLevel == 2) { code = afsconf_GetLatestKey(tdir, 0, 0); if (code) { afs_com_err(whoami, code, "(getting key from local KeyFile)\n"); } else { /* If secLevel is two assume we're on a file server and use * ClientAuthSecure if possible. */ code = afsconf_ClientAuthSecure(tdir, &sc, &scIndex); if (code) afs_com_err(whoami, code, "(calling client secure)\n"); } } else if (secLevel > 0) { secFlags = 0; if (secLevel > 1) secFlags |= AFSCONF_SECOPTS_ALWAYSENCRYPT; code = afsconf_ClientAuthToken(&info, secFlags, &sc, &scIndex, NULL); if (code) { afs_com_err(whoami, code, "(getting token)"); if (secLevel > 1) return code; } } if (sc == NULL) { sc = rxnull_NewClientSecurityObject(); scIndex = RX_SECIDX_NULL; } if ((scIndex == RX_SECIDX_NULL) && (secLevel != 0)) fprintf(stderr, "%s: Could not get afs tokens, running unauthenticated\n", whoami); memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */ for (i = 0; i < info.numServers; i++) serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port, PRSRV, sc, scIndex); code = ubik_ClientInit(serverconns, &pruclient); if (code) { afs_com_err(whoami, code, "ubik client init failed."); return code; } lastLevel = scIndex; code = rxs_Release(sc); return code; }