Listing 1: checker_proc.c
/*
* Processing routings for Distributed File Checker
*
* Filename checker_proc.c
* Author: Clive King
* Comment: Server routines
* Version 1.1
* Date 05 Nov 1993
*
*/
#include <sys/time.h>
#include <malloc.h>
#include <rpc/rpc.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
#ifdef SVR4
#include <sys/dirent.h>
#include <string.h>
#else
#include <sys/dir.h>
#include <strings.h>
#endif
#include "checker.h"
#include "checker_proc.h"
char *dirname;
namelist nl= NULL;
namelist *nlp;
/*
* routine called from server stub to check the attributes of the file
* and to return the state of the file in question
*/
access_struct *access_1(details)
nametype *details;
{
struct stat buf;
static access_struct file_report; /* head of the linked list */
char *perms; /* pointer to string to store permissions */
char *owner; /* pointer to string to store owener */
char *grp; /* pointer to string to store group */
char *date; /* pointer to string to store date */
dirname = (char *)malloc( FILEMAX );
perms = (char *)malloc( PERMAX );
owner = (char *)malloc( NAMEMAX );
grp = (char *)malloc( NAMEMAX );
date = (char *)malloc( DATEMAX );
/* split the fields up into the consituent parts */
split_fields(details, dirname, perms, owner, grp, date);
xdr_free(xdr_access_struct, (char *)&file_report);
nlp = &file_report.access_struct_u.list;
nl = *nlp = (namenode *)malloc(sizeof(namenode));
file_report.access_struct_u.list->result = 0;
if (access(dirname, F_OK) != 0) {
add_error("", "Can not access file");
return (&file_report);
}
if (stat(dirname, &buf) == -1) {
add_error("", "Can not stat file");
return (&file_report);
}
/* check permissions of the file */
check_perms(&buf, perms[0], S_ISUID, S_ISGID, S_ISVTX, "permissions");
check_perms(&buf, perms[1], S_IRUSR, S_IWUSR, S_IXUSR, "owner permissions");
check_perms(&buf, perms[2], S_IRGRP, S_IWGRP, S_IXGRP, "group permissions");
check_perms(&buf, perms[3], S_IROTH, S_IWOTH, S_IXOTH, "other permissions");
check_owner(&buf, owner); /* check ownership */
check_grp(&buf, grp); /* check group */
/* do not check date field if NO_DATE_CHECK, */
if (strchr(date, NO_DATE_CHECK) == NULL)
check_date(&buf, date);
/* If the checks went well, put O.K. in the error field */
/* The client checks result to determine the test outcome */
if (file_report.access_struct_u.list->result == 0) {
/* allocate first element in list to avoid xdr problems */
add_error("", "O.K.");
file_report.access_struct_u.list->result = 0;
}
return (&file_report);
}
/* ********************************************************* */
/* check_perms -- determine if file permissions are correct
*
* Argument - pointer to files stat structure
* Argument - string value of the correct file permissions
* Argument - Mask to check read (or setuid) field
* Argument - Mask to check write (or setgid) field
* Argument - Mask to check execute (or sticky bit) field
* Argument - error message base string
* Result
* 0 for correct permissions
* 1 for incorrect permissions
* If an error occurs, then the global err_string is set.
*
* Global array err_string set with type of permissions error
*
*/
void check_perms(buf, value, rmask, wmask, xmask, errstr)
struct stat *buf;
char value;
int rmask;
int wmask;
int xmask;
char *errstr;
{
int tmp;
/* convert char to int */
tmp = value - '0';
if (buf->st_mode & rmask) { /* check read permssions */
if (tmp >= 4)
tmp -= 4; /* the order of the = and - is important here */
else
if (rmask == S_ISUID)
add_error("set uid", errstr);
else
add_error("read", errstr);
}
else
if (tmp >= 4) {
if (rmask == S_ISUID)
add_error("set uid", errstr);
else
add_error("read", errstr);
tmp -= 4;
}
if (buf->st_mode & wmask) { /* check write permissions */
if (tmp >= 2)
tmp -= 2;
else
if (wmask == S_ISGID)
add_error("set gid", errstr);
else
add_error("write", errstr);
}
else
if (tmp >= 2) {
if (wmask == S_ISGID)
add_error("set gid", errstr);
else
add_error("write", errstr);
tmp -= 2;
}
if (buf->st_mode & xmask) { /* check execute permissions */
if (tmp >= 1)
tmp -= 1;
else
if (xmask == S_ISVTX)
add_error("sticky", errstr);
else
add_error("execute", errstr);
}
else
if (tmp >= 1) {
if (xmask == S_ISVTX)
add_error("sticky", errstr);
else
add_error("execute", errstr);
tmp -= 1;
}
}
/* *********************************************************** */
/* check_owner -- determine if the owner of the file is correct
*
* Argument - pointer to files stat structure
* Argument - string value the group should be
* Result
* 0 for correct ownership
* 1 for incorrect ownership
* If an error occurs, then the global err_string is set.
*
* Global array err_string is set with error string and correct owner name
*
*/
void check_owner(buffer, own)
struct stat *buffer;
char *own;
{
struct passwd *pass;
if ((pass = getpwnam(own)) == NULL) {
add_error(own, " : no such user on this system");
return;
}
if (buffer->st_uid != pass->pw_uid)
add_error("incorrect owner : should be ", own);
}
/* *********************************************************** */
/* check_owner -- determine if the group of the file is correct
*
* Argument - pointer to files stat structure
* Argument - string value the group should be
* Result
* 0 for correct group
* 1 for incorrect group
* If an error occurs, then the global err_string is set.
*
* Global array err_string is set with error string and correct group name
*
*/
void check_grp(buffer, grp)
struct stat *buffer;
char *grp;
{
struct passwd *pass;
struct group *gr;
/* search through the groups file for the appropriate gid */
if ((gr = getgrnam(grp)) == NULL) {
/* if the gid is not in groups but the file is owned by a user
we need to check the gid field in the passwd file */
if ((pass = getpwuid(atoi(grp))) == NULL) {
add_error(grp, " : no such group on this system");
return;
}
else
if (buffer->st_gid != pass->pw_gid) {
add_error("incorrect group : should be ", grp);
return;
}
}
else
if (buffer->st_gid != gr->gr_gid) {
add_error("incorrect group : should be ", grp);
return;
}
}
/* *********************************************************** */
/* check_date -- Checks the date of the last modification time of the file
* is after the latest acceptable revision date for that file
*
* Argument - pointer to files stat structure
* Argument - string value the date should be
*
* Result
* 0 for correct date
* 1 for incorrect date
* If an error occurs, then the global err_string is set.
*
* Global array err_string is set with error string and correct date
*
* Notes
* Both UK and US date styles available, UK by default
* Compile with -DUSDATE for US style dates
*/
void check_date(buffer, dat)
struct stat *buffer;
char *dat;
{
char *tmp;
int sep_count=0;
char day[3];
char month[3];
char year[5];
char nowdate[18];
char thedate[18];
struct tm tmtime;
int x = 0;
tmp = dat;
while(*tmp != NULL) {
if ( *tmp == DATE_SEPARATOR ) {
x = 0;
sep_count++;
}
else {
switch (sep_count) {
case DATE_FIELD_ONE : {
day[x] = *tmp;
day[x+1] = NULL;
break;
}
case DATE_FIELD_TWO : {
month[x] = *tmp;
month[x+1] = NULL;
break;
}
case 2 : {
year[x] = *tmp;
year[x+1] = NULL;
break;
}
}
x++;
}
tmp++;
}
/* get the date of the file */
tmtime = *gmtime(&buffer->st_mtime);
/* get it into a useable format of 01 0 and 1991 */
if (strftime(thedate, 18, "%Y%m%d", &tmtime) == 0) {
add_error("strftime failed", "possible problem with date field");
return;
}
(void) sprintf(nowdate,"%s%s%s", year, month, day);
if (atoi(thedate) < atoi(nowdate)) {
add_error(dat, " is too old");
return;
}
}
/* *********************************************************** */
/* add_error -- adds an error to the current node
* Arguments
* char * - the type of error
* char * - nature of problem
* Result
* adds an error message to the err_string field of the current node
*/
void add_error(type, str)
char *type;
char *str;
{
char error_string[100];
unsigned int strlength;
(void) sprintf(error_string, "%s %s", type, str);
if ((nl = *nlp = (namenode *)malloc(sizeof(namenode))) == NULL) {
(void) syslog(LOG_ERR, "malloc failed for checker client");
exit(1);
}
strlength = strlen(error_string)+ strlen(dirname) + 5;
if ((nl->err_string = (char *) malloc(strlength)) == NULL) {
(void) fprintf(stderr, "malloc failed");
exit(1);
}
(void) sprintf(nl->err_string, "%s : %s", dirname, error_string);
nl->result = 1;
nlp = &nl->next;
*nlp = NULL;
}
/* *********************************************************** */
/* split_fields -- Split a line passed to client into constituent parts
*
* Arguments
* details - Line passed from the client
* filename - name of the file : derived from details
* perm - permissions on the file : derived from details
* own - owner of the file : derived from details
* grp -group of the file : derived from details
* dates - : derived from details
*
* Result - returned via filename, perm, own, grp and dates
*/
void split_fields(details, filename, perm, own, grp, dates)
nametype *details;
char *filename;
char *perm;
char *own;
char *grp;
char *dates;
{
int x=0;
int seperator_count=0;
char *det;
/* to add more field, add to the case statement */
for(det=*details;(*det != '\n') && (*det != NULL);det++) {
if (*det == DETAILS_SEPARATOR) {
seperator_count++;
x=0;
}
else {
switch (seperator_count) {
case 0: {
filename[x] = *det;
filename[x+1] = NULL;
break;
}
case 1 : {
perm[x] = *det;
perm[x+1] = NULL;
break;
}
case 2 : {
own[x] = *det;
own[x+1] = NULL;
break;
}
case 3 : {
grp[x] = *det;
grp[x+1] = NULL;
break;
}
case 4 : {
dates[x] = *det;
dates[x+1] = NULL;
break;
}
}
x++;
}
}
}
/* End of File */
|