From fff6f24ca00f041f046ac7e154adc38986e0b43e Mon Sep 17 00:00:00 2001 From: rufustfirefly Date: Tue, 2 Jan 2001 23:00:35 +0000 Subject: [PATCH] half of FORCE_UIDGID commits for afpd (STILL HORRENDOUSLY BROKEN, PROBABLY) --- ChangeLog | 5 ++ acconfig.h | 1 + configure.in | 14 +++- etc/afpd/Makefile.am | 10 ++- etc/afpd/directory.c | 148 +++++++++++++++++++++++++++++++++++++++++-- etc/afpd/file.c | 52 +++++++++++++++ etc/afpd/uid.c | 102 +++++++++++++++++++++++++++++ etc/afpd/uid.h | 27 ++++++++ etc/afpd/volume.c | 43 ++++++++++++- etc/afpd/volume.h | 4 ++ 10 files changed, 396 insertions(+), 10 deletions(-) create mode 100644 etc/afpd/uid.c create mode 100644 etc/afpd/uid.h diff --git a/ChangeLog b/ChangeLog index ad3211ab..d9a2d58f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2001-01-02 jeff b + + * etc/afpd/uid.c, etc/afpd/uid.h, ...: added support for forcing + uid/gid per volume for afpd + 2000-09-22 Roland Schulz * etc/afpd/volume.c (setvoltime): fix for multiple clients diff --git a/acconfig.h b/acconfig.h index 8eb40ba5..96377224 100644 --- a/acconfig.h +++ b/acconfig.h @@ -7,6 +7,7 @@ #undef DEBUG #undef DLSYM_PREPEND_UNDERSCORE #undef DROPKLUDGE +#undef FORCE_UIDGID #undef HAVE_2ARG_DBTOB #undef HAVE_64BIT_LONGS #undef HAVE_BROKEN_CPP diff --git a/configure.in b/configure.in index cf1ef1dc..997b3f4a 100644 --- a/configure.in +++ b/configure.in @@ -215,8 +215,18 @@ dnl ----------- AC_ARG_ENABLE(dropkludge, [ --enable-dropkludge enable the experimental dropbox fix (INSECURE!) ], - AC_DEFINE(DROPKLUDGE, 1) - AC_MSG_RESULT([enabling experimental dropbox support]) + if test "$enableval" = "yes"; then + AC_DEFINE(DROPKLUDGE, 1) + AC_MSG_RESULT([enabling experimental dropbox support]) + fi +) + +AC_ARG_ENABLE(force-uidgid, + [ --enable-force-uidgid allow forcing of uid/gid per volume (INSECURE?) ], + if test "$enableval" = "yes"; then + AC_DEFINE(FORCE_UIDGID, 1) + AC_MSG_RESULT([enabling forcing of uid/gid per volume]) + fi ) AC_ARG_ENABLE(lastdid, diff --git a/etc/afpd/Makefile.am b/etc/afpd/Makefile.am index 13b97972..23badcf3 100644 --- a/etc/afpd/Makefile.am +++ b/etc/afpd/Makefile.am @@ -4,11 +4,17 @@ SUBDIRS = nls sbin_PROGRAMS = afpd -afpd_SOURCES = unix.c ofork.c main.c switch.c auth.c volume.c directory.c file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c afp_config.c nfsquota.c codepage.c quota.c uam.c afs.c +afpd_SOURCES = unix.c ofork.c main.c switch.c auth.c volume.c directory.c \ + file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c status.c \ + afp_options.c afp_asp.c afp_dsi.c messages.c afp_config.c nfsquota.c \ + codepage.c quota.c uam.c afs.c uid.c + afpd_LDADD = $(top_srcdir)/libatalk/libatalk.a -latalk afpd_LDFLAGS = -rdynamic -noinst_HEADERS = auth.h codepage.h afp_config.h desktop.h directory.h file.h filedir.h fork.h globals.h icon.h misc.h status.h switch.h uam_auth.h unix.h volume.h +noinst_HEADERS = auth.h codepage.h afp_config.h desktop.h directory.h file.h \ + filedir.h fork.h globals.h icon.h misc.h status.h switch.h uam_auth.h \ + uid.h unix.h volume.h CFLAGS = @CFLAGS@ \ -D_PATH_AFPDDEFVOL=\"$(CONFIG_DIR)/AppleVolumes.default\" \ diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index b8dfece0..7880f207 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -38,6 +38,10 @@ #include "globals.h" #include "unix.h" +#ifdef FORCE_UIDGID +#include "uid.h" +#endif FORCE_UIDGID + struct dir *curdir; #define SENTINEL (&sentinel) @@ -808,8 +812,17 @@ int getdirparams(vol, bitmap, upath, dir, st, buf, buflen ) int bit = 0, isad = 1; u_int32_t aint; u_int16_t ashort; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID memset(&ad, 0, sizeof(ad)); + +#ifdef FORCE_UIDGID + save_uidgid ( uidgid ); + set_uidgid ( vol ); +#endif FORCE_UIDGID + if ( ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY, DIRBITS | 0777, &ad) < 0 ) { isad = 0; @@ -972,6 +985,9 @@ int getdirparams(vol, bitmap, upath, dir, st, buf, buflen ) if ( isad ) { ad_close( &ad, ADFLAGS_HF ); } +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_BITMAP ); } bitmap = bitmap>>1; @@ -1059,9 +1075,15 @@ int setdirparams(vol, path, bitmap, buf ) int bit = 0, aint, isad = 1; u_int16_t ashort, bshort; int err = AFP_OK; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID upath = mtoupath(vol, path); memset(&ad, 0, sizeof(ad)); +#ifdef FORCE_UIDGID + save_uidgid ( uidgid ); +#endif FORCE_UIDGID if (ad_open( upath, vol_noadouble(vol)|ADFLAGS_HF|ADFLAGS_DIR, O_RDWR|O_CREAT, 0666, &ad) < 0) { /* @@ -1074,8 +1096,12 @@ int setdirparams(vol, path, bitmap, buf ) */ if (!vol_noadouble(vol) && (bitmap & ~((1<d_did, sizeof( u_int32_t )); *rbuflen = sizeof( u_int32_t ); setvoltime(obj, vol ); +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFP_OK ); } @@ -1503,6 +1560,9 @@ int deletecurdir( vol, path, pathlen ) struct stat st; struct dir *fdir; DIR *dp; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID if ( curdir->d_parent == NULL ) { return( AFPERR_ACCESS ); @@ -1514,6 +1574,11 @@ int deletecurdir( vol, path, pathlen ) fdir = curdir; +#ifdef FORCE_UIDGID + save_uidgid ( uidgid ); + set_uidgid ( vol ); +#endif FORCE_UIDGID + /* delete stray .AppleDouble files. this happens to get .Parent files as well. */ if ((dp = opendir(".AppleDouble"))) { @@ -1527,6 +1592,9 @@ int deletecurdir( vol, path, pathlen ) * note: this will not fail with dangling symlinks */ if (stat(de->d_name, &st) == 0) { closedir(dp); +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_DIRNEMPT; } @@ -1536,12 +1604,21 @@ int deletecurdir( vol, path, pathlen ) switch (errno) { case EPERM: case EACCES : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_ACCESS ); case EROFS: +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_VLOCK; case ENOENT : continue; default : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_PARAM ); } } @@ -1554,13 +1631,25 @@ int deletecurdir( vol, path, pathlen ) case ENOENT : break; case ENOTEMPTY : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_DIRNEMPT ); case EROFS: +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_VLOCK; case EPERM: case EACCES : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_ACCESS ); default : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_PARAM ); } } @@ -1573,19 +1662,32 @@ int deletecurdir( vol, path, pathlen ) continue; /* bail if it's not a symlink */ - if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) + if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) { +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_DIRNEMPT; + } if (unlink(de->d_name) < 0) { switch (errno) { case EPERM: case EACCES : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_ACCESS ); case EROFS: +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_VLOCK; case ENOENT : continue; default : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_PARAM ); } } @@ -1594,21 +1696,39 @@ int deletecurdir( vol, path, pathlen ) } if ( movecwd( vol, curdir->d_parent ) < 0 ) { +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_NOOBJ ); } if ( rmdir(mtoupath(vol, fdir->d_name)) < 0 ) { switch ( errno ) { case ENOENT : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_NOOBJ ); case ENOTEMPTY : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_DIRNEMPT ); case EPERM: case EACCES : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_ACCESS ); case EROFS: +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_VLOCK; default : +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_PARAM ); } } @@ -1619,6 +1739,9 @@ int deletecurdir( vol, path, pathlen ) #endif dir_remove( vol, fdir ); +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFP_OK ); } @@ -1769,6 +1892,9 @@ int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen ) char *path, *upath; u_int32_t did; u_int16_t vid; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID *rbuflen = 0; ibuf += 2; @@ -1807,12 +1933,24 @@ int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen ) dir = (dir == parentdir->d_child->d_prev) ? NULL : dir->d_next; } +#ifdef FORCE_UIDGID + save_uidgid ( uidgid ); + set_uidgid ( vol ); +#endif FORCE_UIDGID + /* we don't already have a did. add one in. */ if ((dir = adddir(vol, parentdir, path, strlen(path), - upath, strlen(upath), &st)) == NULL) + upath, strlen(upath), &st)) == NULL) { +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFPERR_MISC; + } memcpy(rbuf, &dir->d_did, sizeof(dir->d_did)); *rbuflen = sizeof(dir->d_did); +#ifdef FORCE_UIDGID + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return AFP_OK; } diff --git a/etc/afpd/file.c b/etc/afpd/file.c index a5529df7..52b56a0a 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -37,6 +37,10 @@ #include "filedir.h" #include "globals.h" +#ifdef FORCE_UIDGID +#include "uid.h" +#endif FORCE_UIDGID + /* the format for the finderinfo fields (from IM: Toolbox Essentials): * field bytes subfield bytes * @@ -333,6 +337,9 @@ int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen ) char *path, *upath; int creatf, did, openf, retvalue = AFP_OK; u_int16_t vid; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID #ifdef DEBUG syslog(LOG_INFO, "begin afp_createfile:"); @@ -390,12 +397,30 @@ int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen ) openf = O_RDWR|O_CREAT|O_EXCL; } +#ifdef FORCE_UIDGID + + /* preserve current euid, egid */ + save_uidgid ( uidgid ); + + /* perform all switching of users */ + set_uidgid ( vol ); + +#endif FORCE_UIDGID + if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF, openf, 0666, adp) < 0 ) { switch ( errno ) { case EEXIST : +#ifdef FORCE_UIDGID + /* bring everything back to old euid, egid */ + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_EXIST ); case EACCES : +#ifdef FORCE_UIDGID + /* bring everything back to old euid, egid */ + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_ACCESS ); case ENOENT: /* on noadouble volumes, just creating the data fork is ok */ @@ -403,6 +428,10 @@ int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen ) goto createfile_done; /* fallthrough */ default : +#ifdef FORCE_UIDGID + /* bring everything back to old euid, egid */ + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID return( AFPERR_PARAM ); } } @@ -425,6 +454,11 @@ createfile_done: syslog(LOG_INFO, "end afp_createfile"); #endif DEBUG +#ifdef FORCE_UIDGID + /* bring everything back to old euid, egid */ + restore_uidgid ( uidgid ); +#endif FORCE_UIDGID + return (retvalue); } @@ -500,6 +534,10 @@ int setfilparams(vol, path, bitmap, buf ) u_int32_t aint; struct utimbuf ut; +#ifdef FORCE_UIDGID + uidgidset *uidgid; +#endif FORCE_UIDGID + #ifdef DEBUG syslog(LOG_INFO, "begin setfilparams:"); #endif DEBUG @@ -511,10 +549,19 @@ int setfilparams(vol, path, bitmap, buf ) memset(&ad, 0, sizeof(ad)); adp = &ad; } + +#ifdef FORCE_UIDGID + save_uidgid ( uidgid ); + set_uidgid ( vol ); +#endif FORCE_UIDGID + if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF, O_RDWR|O_CREAT, 0666, adp) < 0) { /* for some things, we don't need an adouble header */ if (bitmap & ~(1< +#include +#include + +/* functions for username and group */ +#include +#include +#include "uid.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +void save_uidgid ( pair ) + uidgidset *pair; +{ + (pair)->uid = geteuid (); + (pair)->gid = getegid (); +} /* end function void save_uidgid ( pair ) */ + +void restore_uidgid ( pair ) + uidgidset *pair; +{ + if ( seteuid ( (pair)->uid ) < 0 ) + syslog ( LOG_ERR, "restore_uidgid: unable to seteuid '%s': %m", + (pair)->uid ); + if ( setegid ( (pair)->gid ) < 0 ) + syslog ( LOG_ERR, "restore_uidgid: unable to setegid '%s': %m", + (pair)->gid ); +} /* end function void restore_uidgid ( pair ) */ + +void set_uidgid ( this_volume ) + struct vol *this_volume; +{ + int uid, gid; /* derived ones go in here */ + + /* check to see if we have to switch users */ + if ( uid = user_to_uid ( (this_volume)->v_forceuid ) ) { + if ( seteuid ( uid ) < 0 ) + syslog ( LOG_ERR, "set_uidgid: unable to seteuid '%s': %m", + (this_volume)->v_forceuid ); + } /* end of checking for (this_volume)->v_forceuid */ + + /* check to see if we have to switch groups */ + if ( gid = group_to_gid ( (this_volume)->v_forcegid ) ) { + if ( seteuid ( gid ) < 0 ) + syslog ( LOG_ERR, "set_uidgid: unable to setegid '%s': %m", + (this_volume)->v_forcegid ); + } /* end of checking for (this_volume)->v_forcegid */ + +} /* end function void set_uidgid ( username, group ) */ + +int user_to_uid ( username ) + char *username; +{ + struct passwd *this_passwd; + + /* check for anything */ + if ( strlen ( username ) < 1 ) return 0; + + /* grab the /etc/passwd record relating to username */ + this_passwd = getpwnam ( username ); + + /* return false if there is no structure returned */ + if (this_passwd == NULL) return 0; + + /* return proper uid */ + return this_passwd->pw_uid; + +} /* end function int user_to_uid ( username ) */ + +int group_to_gid ( group ) + char *group; +{ + struct group *this_group; + + /* check for anything */ + if ( strlen ( group ) < 1 ) return 0; + + /* grab the /etc/groups record relating to group */ + this_group = getgrnam ( group ); + + /* return false if there is no structure returned */ + if (this_group == NULL) return 0; + + /* return proper gid */ + return this_group->gr_gid; + +} /* end function int group_to_gid ( group ) */ diff --git a/etc/afpd/uid.h b/etc/afpd/uid.h new file mode 100644 index 00000000..106b86cd --- /dev/null +++ b/etc/afpd/uid.h @@ -0,0 +1,27 @@ +/* + * $Id: uid.h,v 1.1 2001-01-02 23:00:35 rufustfirefly Exp $ + * code: jeff@univrel.pr.uconn.edu + */ + +#ifndef AFPD_UID_H +#define AFPD_UID_H 1 + +/* have to make sure struct vol is defined */ +#include "volume.h" + +/* set up a structure for this */ +typedef struct uidgidset_t { + int uid; + int gid; +} uidgidset; + +/* functions to save and restore uid/gid pairs */ +extern void save_uidgid ( uidgidset * ); +extern void restore_uidgid ( uidgidset * ); +extern void set_uidgid ( struct vol * ); + +/* internal functions to convert user and group names to ids */ +extern int user_to_uid ( char * ); +extern int group_to_gid ( char * ); + +#endif diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 567d2d71..6c286851 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -77,7 +77,13 @@ static struct extmap *extmap = NULL, *defextmap = NULL; ~u -> make u illegal only as the first part of a double-byte character. */ -#define VOLOPT_MAX 9 + +#ifdef FORCE_UIDGID +#define VOLOPT_FORCEUID 10 /* force uid for username x */ +#define VOLOPT_FORCEGID 11 /* force gid for group x */ +#endif FORCE_UIDGID + +#define VOLOPT_MAX 11 #define VOLOPT_NUM (VOLOPT_MAX + 1) #define VOLPASSLEN 8 @@ -246,6 +252,9 @@ static __inline__ char *get_codepage_path(const char *path, const char *name) page = strdup(name); } + /* debug: show which codepage directory we are using */ + syslog(LOG_DEBUG, "using codepage directory: %s", page); + return page; } @@ -338,6 +347,21 @@ static void volset(struct vol_option *options, char *volname, int vlen, if (options[VOLOPT_PASSWORD].c_value) free(options[VOLOPT_PASSWORD].c_value); options[VOLOPT_PASSWORD].c_value = strdup(val + 1); + +#ifdef FORCE_UIDGID + + /* this code allows forced uid/gid per volume settings */ + } else if (optionok(tmp, "forceuid:", val)) { + if (options[VOLOPT_FORCEUID].c_value) + free(options[VOLOPT_FORCEUID].c_value); + options[VOLOPT_FORCEUID].c_value = strdup(val + 1); + } else if (optionok(tmp, "forcegid:", val)) { + if (options[VOLOPT_FORCEGID].c_value) + free(options[VOLOPT_FORCEGID].c_value); + options[VOLOPT_FORCEGID].c_value = strdup(val + 1); + +#endif FORCE_UIDGID + } else if (val) { /* ignore unknown options */ syslog(LOG_DEBUG, "ignoring unknown volume option: %s", tmp); @@ -422,6 +446,23 @@ static int creatvol(const char *path, char *name, struct vol_option *options) if (options[VOLOPT_DBPATH].c_value) volume->v_dbpath = strdup(options[VOLOPT_DBPATH].c_value); #endif + +#ifdef FORCE_UIDGID + + if (options[VOLOPT_FORCEUID].c_value) { + volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value); + } else { + volume->v_forceuid = NULL; /* set as null so as to return 0 later on */ + } + + if (options[VOLOPT_FORCEGID].c_value) { + volume->v_forcegid = strdup(options[VOLOPT_FORCEGID].c_value); + } else { + volume->v_forcegid = NULL; /* set as null so as to return 0 later on */ + } + +#endif FORCE_UIDGID + } volume->v_next = volumes; diff --git a/etc/afpd/volume.h b/etc/afpd/volume.h index 86274f34..67ac2d0b 100644 --- a/etc/afpd/volume.h +++ b/etc/afpd/volume.h @@ -51,6 +51,10 @@ struct vol { void *v_db; char *v_dbpath; #endif +#ifdef FORCE_UIDGID + char *v_forceuid; + char *v_forcegid; +#endif FORCE_UIDGID }; #ifdef NO_LARGE_VOL_SUPPORT -- 2.39.2