Пример #1
0
/*
 * 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;
}
Пример #2
0
/*
 * 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;
}
Пример #3
0
/*
 * 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;
}
Пример #4
0
/*
 * 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;
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
/*
 * 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;
}
Пример #7
0
/*
 * 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;
}
Пример #8
0
/*
 * 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;
}
Пример #9
0
/*
 * 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;
}
Пример #10
0
/*
 * 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;
}
Пример #11
0
/*
 * 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;
}
Пример #12
0
/*
 * 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;
}