/* * cfg_HostPartitionTableRemoveEntry() -- Remove AFS partition table entry. */ int ADMINAPI cfg_HostPartitionTableRemoveEntry(void *hostHandle, /* host config handle */ const char *partName, /* partition name */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; #ifdef AFS_NT40_ENV /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (partName == NULL) { tst = ADMCFGPARTITIONNAMENULL; } else if (!vpt_PartitionNameValid(partName)) { tst = ADMCFGPARTITIONNAMEBAD; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* remove entry from table */ if (tst == 0) { if (vpt_RemoveEntry(partName)) { /* ENOENT implies entry does not exist; consider to be removed */ if (errno != ENOENT) { if (errno == EACCES) { tst = ADMNOPRIV; } else if (errno == EINVAL) { /* shouldn't happen since checked partition/dev names */ tst = ADMCFGPARTITIONNAMEBAD; } else { tst = ADMCFGVPTABLEWRITEFAILED; } } } } #else /* function not yet implemented for unix */ if (tst == 0) { tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_ClientStart() -- Start the client (cache manager) on host. * * Timeout is the maximum time (in seconds) to wait for client to start. */ int ADMINAPI cfg_ClientStart(void *hostHandle, /* host config handle */ unsigned int timeout, /* timeout in seconds */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* start client */ if (tst == 0) { if (!CacheManagerStart(timeout, &tst2)) { tst = tst2; } } if (tst != 0) { /* indicate failure */ rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostClose() -- Release host configuration handle. */ int ADMINAPI cfg_HostClose(void *hostHandle, /* host config handle */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } /* free handle; can assume no other thread using this handle */ if (tst == 0) { /* mark cfg handle invalid in case use after free (bug catcher) */ cfg_host->is_valid = 0; if (cfg_host->bosHandle != NULL) { if (!bos_ServerClose(cfg_host->bosHandle, &tst2)) { tst = tst2; } } free(cfg_host->hostName); (void)pthread_mutex_destroy(&cfg_host->mutex); free(cfg_host); } if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * ClientCellServDbUpdate() -- add or remove a client CellServDB entry. * * Common function implementing cfg_ClientCellServDb{Add/Remove}(). */ static int ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName, const char *dbentry, afs_status_p st) { int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; char dbentryFull[MAXHOSTCHARS]; /* validate parameters and resolve dbentry to fully qualified name */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (cellName == NULL || *cellName == '\0') { tst = ADMCFGCELLNAMENULL; } else if (strlen(cellName) > (MAXCELLCHARS - 1)) { tst = ADMCFGCELLNAMETOOLONG; } else if (dbentry == NULL || *dbentry == '\0') { tst = ADMCFGHOSTNAMENULL; } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) { tst = ADMCFGHOSTNAMETOOLONG; } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) { tst = tst2; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* modify local client CellServDB entry for specified cell */ #ifdef AFS_NT40_ENV if (tst == 0) { CELLSERVDB clientDb; if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) { tst = ADMCFGCLIENTCELLSERVDBNOTREAD; } else { CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName); CELLDBLINE *serverLinep = NULL; int serverLineCount = 0; if (cellLinep != NULL) { /* found cellName, now find server to add/remove */ CELLDBLINE *workingLinep; for (workingLinep = cellLinep->pNext; workingLinep != NULL; workingLinep = workingLinep->pNext) { CELLDBLINEINFO lineInfo; if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) { /* not a server (or cell) line; perhaps a comment */ continue; } else if (lineInfo.szCell[0] != '\0') { /* hit a new cell line */ break; } else { /* found a server line; check if is host of interest */ short isValid; int dbentryAddr = ntohl(lineInfo.ipServer); serverLineCount++; if (!cfgutil_HostAddressIsValid (dbentryFull, dbentryAddr, &isValid, &tst2)) { tst = tst2; break; } else if (isValid) { /* found server of interest */ serverLinep = workingLinep; break; } } } } if (tst == 0) { if (updateOp == CSDB_OP_ADD && serverLinep == NULL) { if (cellLinep == NULL) { cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL); } if (cellLinep == NULL) { tst = ADMNOMEM; } else if (serverLineCount >= MAXHOSTSPERCELL) { tst = ADMCFGCLIENTCELLSERVDBNOSPACE; } else { const char *dbentryAddrStr; if (!cfgutil_HostNameGetAddressString (dbentryFull, &dbentryAddrStr, &tst2)) { tst = tst2; } else { serverLinep = CSDB_AddCellServer(&clientDb, cellLinep, dbentryAddrStr, dbentryFull); if (serverLinep == NULL) { tst = ADMNOMEM; } } } } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) { (void)CSDB_RemoveLine(&clientDb, serverLinep); } if (tst == 0) { if (!CSDB_WriteFile(&clientDb)) { tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN; } } } CSDB_FreeFile(&clientDb); } } #else if (tst == 0) { /* function not yet implemented for Unix */ tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ if (tst != 0) { /* indicate failure */ rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_ClientSetCell() -- Define default client cell for host. * * The cellDbHosts argument is a multistring containing the names of * the existing database servers already configured in the cell; this * multistring list can be obtained via cfg_CellServDbEnumerate(). * If configuring the first server in a new cell then the cellDbHosts * list contains only the name of that host. * * Warning: client (cache-manager) should be stopped prior to setting cell. */ int ADMINAPI cfg_ClientSetCell(void *hostHandle, /* host config handle */ const char *cellName, /* cell name */ const char *cellDbHosts, /* cell database hosts */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (cellName == NULL || *cellName == '\0') { tst = ADMCFGCELLNAMENULL; } else if (strlen(cellName) > (MAXCELLCHARS - 1)) { tst = ADMCFGCELLNAMETOOLONG; } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) { tst = ADMCFGCELLNAMECONFLICT; } else if (cellDbHosts == NULL || *cellDbHosts == '\0') { tst = ADMCFGCELLDBHOSTSNULL; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* define cell database hosts */ #ifdef AFS_NT40_ENV if (tst == 0) { CELLSERVDB clientDb; if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) { tst = ADMCFGCLIENTCELLSERVDBNOTREAD; } else { CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName); if (cellLinep != NULL) { /* cell entry exists; remove host entries */ if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) { /* should never happen */ tst = ADMCFGCLIENTCELLSERVDBEDITFAILED; } } else { /* cell entry does not exist; add it */ cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL); if (cellLinep == NULL) { tst = ADMNOMEM; } } if (tst == 0) { /* add new host entries to cell */ const char *dbHost = cellDbHosts; int dbHostCount = 0; while (*dbHost != '\0' && tst == 0) { size_t dbHostLen = strlen(dbHost); const char *dbHostAddrStr; if (dbHostLen > (MAXHOSTCHARS - 1)) { tst = ADMCFGHOSTNAMETOOLONG; } else if (dbHostCount >= MAXHOSTSPERCELL) { tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE; } else if (!cfgutil_HostNameGetAddressString (dbHost, &dbHostAddrStr, &tst2)) { tst = tst2; } else if (CSDB_AddCellServer (&clientDb, cellLinep, dbHostAddrStr, dbHost) == NULL) { tst = ADMNOMEM; } else { dbHostCount++; dbHost += dbHostLen + 1; } } if (tst == 0) { /* edit successful; write CellServDB */ if (!CSDB_WriteFile(&clientDb)) { tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN; } } } CSDB_FreeFile(&clientDb); } } #else if (tst == 0) { /* function not yet implemented for Unix */ tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ /* define default client cell */ #ifdef AFS_NT40_ENV if (tst == 0) { if (afssw_SetClientCellName(cellName)) { /* failed to set cell name in registry (ThisCell equivalent) */ if (errno == EACCES) { tst = ADMNOPRIV; } else { tst = ADMCFGCLIENTTHISCELLNOTWRITTEN; } } } #else if (tst == 0) { /* function not yet implemented for Unix */ tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ /* help any underlying packages adjust to cell change */ if (tst == 0) { int rc; if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) { tst = rc; } } if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * CellServDbUpdate() -- add or remove a server CellServDB entry. * * Common function implementing cfg_CellServDb{Add/Remove}Host(). */ static int CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost, cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, afs_status_p st) { int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; char fullSysHostName[MAXHOSTCHARS]; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (sysControlHost != NULL && *sysControlHost == '\0') { tst = ADMCFGHOSTNAMENULL; } else if (callBack == NULL) { tst = ADMCFGCALLBACKNULL; } else if (maxUpdates == NULL) { tst = ADMCFGUPDATECOUNTNULL; } /* resolve sys ctrl host to fully qualified name (if extant) */ if (tst == 0) { if (sysControlHost != NULL) { if (!cfgutil_HostNameGetFull (sysControlHost, fullSysHostName, &tst2)) { tst = tst2; } else { sysControlHost = fullSysHostName; } } } /* Update cell-wide server CellServDb as follows: * * 1) If system control machine is in use then update the following: * system control host + database server hosts + configuration host * * Updating the system control machine is theoretically sufficient, * as all server hosts should be getting configuration information * from there. However, we don't want to have to delay further * configuration until this update occurs (which could be set for * any time interval). Therefore, we compromise by manually * updating the database server hosts and the host being configured. * * 2) If no system control machine is in use then update the following: * fileserver hosts + database server hosts + configuration host * * General algorithm: * We create a set of server name blocks, with one thread per name * block that is responsible for updating the servers in that block. * All server name blocks share a single control block that stores * common data and coordinates start/abort and cleanup activities. * All threads wait for the start/abort signal before performing * update operations so that this function is atomic. */ if (tst == 0) { cfg_csdb_update_ctrl_t *ctrlBlockp = NULL; *maxUpdates = 0; /* create control block */ ctrlBlockp = (cfg_csdb_update_ctrl_t *) malloc(sizeof(*ctrlBlockp)); if (ctrlBlockp == NULL) { tst = ADMNOMEM; } else { ctrlBlockp->cfg_host = cfg_host; ctrlBlockp->op = updateOp; ctrlBlockp->callBack = callBack; ctrlBlockp->callBackId = callBackId; ctrlBlockp->disposition = CSDB_WAIT; ctrlBlockp->workersActive = 0; if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) { tst = ADMMUTEXINIT; } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) { tst = ADMCONDINIT; } else { /* Unfortunately the bosserver adds/removes entries from * the server CellServDB based on a case-sensitive string * comparison, rather than using an address comparison * to handle aliasing. So we must use the name for the * configuration host exactly as listed in the CellServDB. * * Of course the 3.5 bosserver can and should be modified to * handle aliases, but we still have to deal with down-level * servers in this library. * * To get reasonable performance, the presumption is made * that all server CellServDB are identical. This way we * can look up the configuration host alias once and use * it everywhere. If this proves to be insufficient then * this lookup will have to be done for every server to be * updated which will be very costly; such individual lookups * would naturally be handled by the update worker threads. * * A final presumption is that we can just look at the * server CellServDB on the current database servers to * get the configuration host alias. The only time this * might get us into trouble is in a re-do scenario. */ if (!CfgHostGetCellServDbAlias (cfg_host, ctrlBlockp->opHostAlias, &tst2)) { tst = tst2; } else if (*ctrlBlockp->opHostAlias == '\0') { /* no alias found; go with config host working name */ strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName); } } if (tst != 0) { free(ctrlBlockp); } else { /* fill name blocks, handing each to a worker thread */ void *nameBlockIter = NULL; short workersStarted = 0; if (!NameBlockGetBegin (cfg_host, sysControlHost, ctrlBlockp, &nameBlockIter, &tst2)) { tst = tst2; } else { cfg_csdb_update_name_t *nameBlockp = NULL; short nameBlockDone = 0; while (!nameBlockDone) { nameBlockp = ((cfg_csdb_update_name_t *) malloc(sizeof(*nameBlockp))); if (nameBlockp == NULL) { tst = ADMNOMEM; nameBlockDone = 1; } else if (!NameBlockGetNext (nameBlockIter, nameBlockp, &tst2)) { /* no more entries (or failure) */ if (tst2 != ADMITERATORDONE) { tst = tst2; } free(nameBlockp); nameBlockDone = 1; } else { *maxUpdates += nameBlockp->serverCount; if (StartUpdateWorkerThread(nameBlockp, &tst2)) { /* increment worker count; lock not required * until workers given start/abort signal. */ ctrlBlockp->workersActive++; workersStarted = 1; } else { tst = tst2; free(nameBlockp); nameBlockDone = 1; } } } if (!NameBlockGetDone(nameBlockIter, &tst2)) { tst = tst2; } } if (workersStarted) { /* worker threads started; set disposition and signal */ if (pthread_mutex_lock(&ctrlBlockp->mutex)) { tst = ADMMUTEXLOCK; } else { if (tst == 0) { /* tell workers to proceed with updates */ ctrlBlockp->disposition = CSDB_GO; } else { /* tell workers to abort */ ctrlBlockp->disposition = CSDB_ABORT; } if (pthread_mutex_unlock(&ctrlBlockp->mutex)) { tst = ADMMUTEXUNLOCK; } if (pthread_cond_broadcast(&ctrlBlockp->event)) { tst = ADMCONDSIGNAL; } } } else { /* no worker threads started */ free(ctrlBlockp); } } } } if (tst != 0) { /* indicate failure */ rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostPartitionTableAddEntry() -- Add or update AFS partition table entry. */ int ADMINAPI cfg_HostPartitionTableAddEntry(void *hostHandle, /* host config handle */ const char *partName, /* partition name */ const char *devName, /* device name */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; #ifdef AFS_NT40_ENV /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (partName == NULL) { tst = ADMCFGPARTITIONNAMENULL; } else if (!vpt_PartitionNameValid(partName)) { tst = ADMCFGPARTITIONNAMEBAD; } else if (devName == NULL) { tst = ADMCFGDEVICENAMENULL; } else if (!vpt_DeviceNameValid(devName)) { tst = ADMCFGDEVICENAMEBAD; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* add entry to table */ if (tst == 0) { struct vptab vpentry; strcpy(vpentry.vp_name, partName); strcpy(vpentry.vp_dev, devName); if (vpt_AddEntry(&vpentry)) { if (errno == EACCES) { tst = ADMNOPRIV; } else if (errno == EINVAL) { /* shouldn't happen since checked partition/dev names */ tst = ADMCFGVPTABLEENTRYBAD; } else { tst = ADMCFGVPTABLEWRITEFAILED; } } } #else /* function not yet implemented for unix */ if (tst == 0) { tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostPartitionTableEnumerate() -- Enumerate AFS partition table entries. * * If the partition table is empty (or does not exist) then *tablePP * is set to NULL and *nEntriesP is set to zero (0). * * Partitions in table are not necessarily those being exported; a table * entry may have been added or removed since the fileserver last started. */ int ADMINAPI cfg_HostPartitionTableEnumerate(void *hostHandle, /* host config handle */ cfg_partitionEntry_t ** tablePP, /* table */ int *nEntriesP, /* table entry count */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (tablePP == NULL) { tst = ADMCFGVPTABLEPNULL; } else if (nEntriesP == NULL) { tst = ADMCFGVPTABLECOUNTPNULL; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* enumerate the vice partition table */ #ifdef AFS_NT40_ENV if (tst == 0) { struct vpt_iter vpiter; struct vptab vpentry; int vpentryCountMax = 0; /* count table entries */ if (vpt_Start(&vpiter)) { /* ENOENT implies table does not exist (which is OK) */ if (errno != ENOENT) { if (errno == EACCES) { tst = ADMNOPRIV; } else { tst = ADMCFGVPTABLEREADFAILED; } } } else { while (!vpt_NextEntry(&vpiter, &vpentry)) { vpentryCountMax++; } if (errno != ENOENT) { tst = ADMCFGVPTABLEREADFAILED; } (void)vpt_Finish(&vpiter); } /* alloc storage for table entries; handle any entry count change */ if (tst == 0) { if (vpentryCountMax == 0) { *nEntriesP = 0; *tablePP = NULL; } else { /* return a two-part table; first points into second */ void *metaTablep; size_t metaTableSize; metaTableSize = vpentryCountMax * (sizeof(cfg_partitionEntry_t) + sizeof(struct vptab)); if ((metaTablep = (void *)malloc(metaTableSize)) == NULL) { tst = ADMNOMEM; } else { int i; cfg_partitionEntry_t *cpePart; struct vptab *vptPart; int vpentryCount = 0; cpePart = (cfg_partitionEntry_t *) metaTablep; vptPart = (struct vptab *)(&cpePart[vpentryCountMax]); for (i = 0; i < vpentryCountMax; i++) { cpePart[i].partitionName = vptPart[i].vp_name; cpePart[i].deviceName = vptPart[i].vp_dev; } if (vpt_Start(&vpiter)) { /* ENOENT implies table does not exist (which is OK) */ if (errno != ENOENT) { if (errno == EACCES) { tst = ADMNOPRIV; } else { tst = ADMCFGVPTABLEREADFAILED; } } } else { for (i = 0; i < vpentryCountMax; i++) { if (vpt_NextEntry(&vpiter, &vptPart[i])) { break; } } if (i < vpentryCountMax && errno != ENOENT) { tst = ADMCFGVPTABLEREADFAILED; } else { vpentryCount = i; } (void)vpt_Finish(&vpiter); } if (tst == 0) { *nEntriesP = vpentryCount; if (vpentryCount != 0) { *tablePP = (cfg_partitionEntry_t *) metaTablep; } else { *tablePP = NULL; free(metaTablep); } } else { free(metaTablep); } } } } } #else /* function not yet implemented for Unix */ if (tst == 0) { tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostInvalidate() -- Invalidate static server configuration on host. * * Server configuration invalidated only if BOS server is not running. */ int ADMINAPI cfg_HostInvalidate(void *hostHandle, /* host config handle */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* make sure bosserver is not running on host */ #ifdef AFS_NT40_ENV /* Windows - bosserver is controlled via the BOS control service */ if (tst == 0) { DWORD svcState; if (!cfgutil_WindowsServiceQuery (AFSREG_SVR_SVC_NAME, &svcState, &tst2)) { tst = tst2; } else if (svcState != SERVICE_STOPPED) { tst = ADMCFGBOSSERVERACTIVE; } } #else if (tst == 0) { /* function not yet implemented for Unix */ tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ /* remove server state files */ if (tst == 0) { int i; const char *cfgdir[3]; cfgdir[0] = AFSDIR_SERVER_ETC_DIRPATH; cfgdir[1] = AFSDIR_SERVER_DB_DIRPATH; cfgdir[2] = AFSDIR_SERVER_LOCAL_DIRPATH; for (i = 0; i < 3 && tst == 0; i++) { if (!cfgutil_CleanDirectory(cfgdir[i], &tst2)) { tst = tst2; } } } /* remove all vice partition table entries */ #ifdef AFS_NT40_ENV if (tst == 0) { struct vpt_iter vpiter; struct vptab vpentry; /* note: ignore errors except from removal attempts */ if (!vpt_Start(&vpiter)) { while (!vpt_NextEntry(&vpiter, &vpentry)) { if (vpt_RemoveEntry(vpentry.vp_name)) { /* ENOENT implies entry does not exist; consider removed */ if (errno != ENOENT) { if (errno == EACCES) { tst = ADMNOPRIV; } else { tst = ADMCFGVPTABLEWRITEFAILED; } } } } (void)vpt_Finish(&vpiter); } } #else /* function not yet implemented for unix */ if (tst == 0) { tst = ADMCFGNOTSUPPORTED; } #endif /* AFS_NT40_ENV */ if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostSetAdminPrincipal() -- Put generic administrator principal in * host's UserList; principal is created if it does not exist. * * If first server host in cell, passwd and afsUid must be the initial * password and the AFS UID for the admin principal; the admin principal * is created. * * If additional server host, passwd and afsUid are ignored; the admin * principal is assumed to exist. * * ASSUMPTIONS: Client configured and BOS server started; if first host in * cell then Authentication and Protection servers must be started as well. */ int ADMINAPI cfg_HostSetAdminPrincipal(void *hostHandle, /* host config handle */ short isFirst, /* first server in cell flag */ const char *admin, /* admin principal name */ const char *passwd, /* admin initial password */ unsigned int afsUid, /* admin AFS UID */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters and prepare host handle for bos functions */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (admin == NULL || *admin == '\0') { tst = ADMCFGADMINPRINCIPALNULL; } else if (strlen(admin) > (KAS_MAX_NAME_LEN - 1)) { tst = ADMCFGADMINPRINCIPALTOOLONG; } else if (isFirst && (passwd == NULL || *passwd == '\0')) { tst = ADMCFGPASSWDNULL; } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) { tst = tst2; } /* put admin in host's UserList */ if (tst == 0) { if (isFirst) { /* first server host in cell; create admin principal */ kas_identity_t adminIdentity; int adminUid = afsUid; kas_admin_t adminFlag = KAS_ADMIN; strcpy(adminIdentity.principal, admin); adminIdentity.instance[0] = '\0'; if (!kas_PrincipalCreate (cfg_host->cellHandle, NULL, &adminIdentity, passwd, &tst2) && tst2 != KAEXIST) { /* failed to create principal (and not because existed) */ tst = tst2; } else if (!kas_PrincipalFieldsSet (cfg_host->cellHandle, NULL, &adminIdentity, &adminFlag, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &tst2)) { /* failed to set admin attributes */ tst = tst2; } else if (!pts_UserCreate (cfg_host->cellHandle, admin, &adminUid, &tst2) && tst2 != PREXIST) { /* failed to create user (and not because existed) */ tst = tst2; } else if (!pts_GroupMemberAdd (cfg_host->cellHandle, admin, "system:administrators", &tst2) && tst2 != PRIDEXIST) { /* failed to add to group (not because already there) */ tst = tst2; } } if (tst == 0) { /* add admin to host's UserList */ if (!bos_AdminCreate(cfg_host->bosHandle, admin, &tst2) && tst2 != EEXIST) { /* failed to add admin (and not because existed) */ /* DANGER: platform-specific errno values being returned */ tst = tst2; } } } if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostSetAfsPrincipal() -- Put AFS server principal (afs) key in * host's KeyFile; principal is created if it does not exist. * * If first server host in cell, passwd must be initial password for * the afs principal; the afs principal is created. * * If additional server host, passwd can be specified or NULL; the * afs principal must already exist by definition. If passwd is NULL * then an attempt is made to fetch the afs key. If the key fetch fails * because pre 3.5 database servers are in use (which will only return a * key checksum) then the function fails with a return status of * ADMCFGAFSKEYNOTAVAILABLE; in this case the function should be called * again with passwd specified. If passwd is specified (not NULL) but the * password key fails a checksum comparison with the current afs key * then the function fails with a return status of ADMCFGAFSPASSWDINVALID. * * ASSUMPTIONS: Client configured and BOS server started; if first host in * cell then Authentication server must be started as well. */ int ADMINAPI cfg_HostSetAfsPrincipal(void *hostHandle, /* host config handle */ short isFirst, /* first server in cell flag */ const char *passwd, /* afs initial password */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if ((isFirst && passwd == NULL) || (passwd != NULL && *passwd == '\0')) { tst = ADMCFGPASSWDNULL; } /* put afs key in host's KeyFile */ if (tst == 0) { kas_identity_t afsIdentity; kas_encryptionKey_t afsKey; int afsKvno = 0; strcpy(afsIdentity.principal, "afs"); afsIdentity.instance[0] = '\0'; if (isFirst) { /* create afs principal */ if (!kas_PrincipalCreate (cfg_host->cellHandle, NULL, &afsIdentity, passwd, &tst2) && tst2 != KAEXIST) { /* failed to create principal (and not because existed) */ tst = tst2; } } if (tst == 0) { /* retrive afs principal information to verify or obtain key */ kas_principalEntry_t afsEntry; if (!kas_PrincipalGet (cfg_host->cellHandle, NULL, &afsIdentity, &afsEntry, &tst2)) { tst = tst2; } else { if (passwd != NULL) { /* password given; form key and verify as most recent */ kas_encryptionKey_t passwdKey; unsigned int passwdKeyCksum; if (!kas_StringToKey (cfg_host->cellName, passwd, &passwdKey, &tst2) || !kas_KeyCheckSum(&passwdKey, &passwdKeyCksum, &tst2)) { /* failed to form key or key checksum */ tst = tst2; } else if (passwdKeyCksum != afsEntry.keyCheckSum) { /* passwd string does not generate most recent key; * check if passwd string embeds key directly. */ if (KasKeyEmbeddedInString(passwd, &passwdKey)) { /* passwd string embeds kas key */ if (!kas_KeyCheckSum (&passwdKey, &passwdKeyCksum, &tst2)) { tst = tst2; } else if (passwdKeyCksum != afsEntry.keyCheckSum) { /* passwd string does not embed valid key */ tst = ADMCFGAFSPASSWDINVALID; } } else { /* passwd string does NOT embed key */ tst = ADMCFGAFSPASSWDINVALID; } } if (tst == 0) { /* passwd seems to generate/embed most recent key */ afsKey = passwdKey; afsKvno = afsEntry.keyVersion; } } else { /* password NOT given; check if key retrieved since * pre 3.5 database servers only return key checksum */ if (KasKeyIsZero(&afsEntry.key)) { tst = ADMCFGAFSKEYNOTAVAILABLE; } else { afsKey = afsEntry.key; afsKvno = afsEntry.keyVersion; } } } } if (tst == 0) { /* add key to host's KeyFile; RPC must be unauthenticated; * bosserver is presumed to be in noauth mode. */ void *cellHandle, *bosHandle; if (!afsclient_NullCellOpen(&cellHandle, &tst2)) { tst = tst2; } else { if (!bos_ServerOpen (cellHandle, cfg_host->hostName, &bosHandle, &tst2)) { tst = tst2; } else { if (!bos_KeyCreate(bosHandle, afsKvno, &afsKey, &tst2) && tst2 != BZKEYINUSE) { /* failed to add key (and not because existed) */ tst = tst2; } if (!bos_ServerClose(bosHandle, &tst2)) { tst = tst2; } } if (!afsclient_CellClose(cellHandle, &tst2)) { tst = tst2; } } } } if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }
/* * cfg_HostSetCell() -- Define server cell membership for host. * * The cellDbHosts argument is a multistring containing the names of * the existing database servers already configured in the cell; this * multistring list can be obtained via cfg_CellServDbEnumerate(). * If configuring the first server in a new cell then the cellDbHosts * list contains only the name of that host. * * Note: The names in cellDbHosts MUST exactly match those in the * cell-wide server CellServDB; using cfg_CellServDbEnumerate() * is highly recommended. */ int ADMINAPI cfg_HostSetCell(void *hostHandle, /* host config handle */ const char *cellName, /* cell name */ const char *cellDbHosts, /* cell database hosts */ afs_status_p st) { /* completion status */ int rc = 1; afs_status_t tst2, tst = 0; cfg_host_p cfg_host = (cfg_host_p) hostHandle; /* validate parameters */ if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { tst = tst2; } else if (cellName == NULL || *cellName == '\0') { tst = ADMCFGCELLNAMENULL; } else if (strlen(cellName) > (MAXCELLCHARS - 1)) { tst = ADMCFGCELLNAMETOOLONG; } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) { tst = ADMCFGCELLNAMECONFLICT; } else if (cellDbHosts == NULL || *cellDbHosts == '\0') { tst = ADMCFGCELLDBHOSTSNULL; } /* remote configuration not yet supported in this function */ if (tst == 0) { if (!cfg_host->is_local) { tst = ADMCFGNOTSUPPORTED; } } /* define server cell and cell database hosts */ if (tst == 0) { const char *dbHost = cellDbHosts; struct afsconf_cell hostCell; memset(&hostCell, 0, sizeof(hostCell)); strcpy(hostCell.name, cellName); hostCell.numServers = 0; while (*dbHost != '\0' && tst == 0) { /* fill in each database host */ size_t dbHostLen = strlen(dbHost); if (dbHostLen > (MAXHOSTCHARS - 1)) { tst = ADMCFGHOSTNAMETOOLONG; } else if (hostCell.numServers >= MAXHOSTSPERCELL) { tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE; } else { strcpy(hostCell.hostName[hostCell.numServers++], dbHost); dbHost += dbHostLen + 1; } } if (tst == 0) { /* create server ThisCell/CellServDB dir if it does not exist */ #ifdef AFS_NT40_ENV (void)mkdir(AFSDIR_USR_DIRPATH); (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH); (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH); #else (void)mkdir(AFSDIR_USR_DIRPATH, 0755); (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH, 0755); (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH, 0755); #endif if (afsconf_SetCellInfo (NULL, AFSDIR_SERVER_ETC_DIRPATH, &hostCell)) { /* failed; most likely cause is bad host name */ tst = ADMCFGSERVERSETCELLFAILED; } } } if (tst != 0) { rc = 0; } if (st != NULL) { *st = tst; } return rc; }