+2001-01-02 jeff b <jeff@univrel.pr.uconn.edu>
+
+ * etc/afpd/uid.c, etc/afpd/uid.h, ...: added support for forcing
+ uid/gid per volume for afpd
+
2000-09-22 Roland Schulz <rdschulz@abarrach.franken.de>
* etc/afpd/volume.c (setvoltime): fix for multiple clients
#undef DEBUG
#undef DLSYM_PREPEND_UNDERSCORE
#undef DROPKLUDGE
+#undef FORCE_UIDGID
#undef HAVE_2ARG_DBTOB
#undef HAVE_64BIT_LONGS
#undef HAVE_BROKEN_CPP
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,
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\" \
#include "globals.h"
#include "unix.h"
+#ifdef FORCE_UIDGID
+#include "uid.h"
+#endif FORCE_UIDGID
+
struct dir *curdir;
#define SENTINEL (&sentinel)
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;
if ( isad ) {
ad_close( &ad, ADFLAGS_HF );
}
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return( AFPERR_BITMAP );
}
bitmap = bitmap>>1;
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) {
/*
*/
if (!vol_noadouble(vol) && (bitmap &
~((1<<DIRPBIT_ACCESS)|(1<<DIRPBIT_UID)|(1<<DIRPBIT_GID)|
- (1<<DIRPBIT_MDATE)|(1<<DIRPBIT_PDINFO))))
+ (1<<DIRPBIT_MDATE)|(1<<DIRPBIT_PDINFO)))) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return AFPERR_ACCESS;
+ }
isad = 0;
} else {
ad_close( &ad, ADFLAGS_HF );
}
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return err;
}
char *path, *upath;
u_int32_t did;
u_int16_t vid;
+#ifdef FORCE_UIDGID
+ uidgidset *uidgid;
+#endif FORCE_UIDGID
*rbuflen = 0;
ibuf += 2;
if (!validupath(vol, upath))
return AFPERR_EXIST;
+#ifdef FORCE_UIDGID
+ save_uidgid ( uidgid );
+ set_uidgid ( vol );
+#endif FORCE_UIDGID
+
if ( ad_mkdir( upath, DIRBITS | 0777 ) < 0 ) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
switch ( errno ) {
case ENOENT :
return( AFPERR_NOOBJ );
}
}
- if (stat(upath, &st) < 0)
+ if (stat(upath, &st) < 0) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return AFPERR_MISC;
+ }
if ((dir = adddir( vol, curdir, path, strlen( path ), upath,
- strlen(upath), &st)) == NULL)
+ strlen(upath), &st)) == NULL) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return AFPERR_MISC;
+ }
if ( movecwd( vol, dir ) < 0 ) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return( AFPERR_PARAM );
}
O_RDWR|O_CREAT, 0666, &ad ) < 0) {
if (vol_noadouble(vol))
goto createdir_done;
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return( AFPERR_ACCESS );
}
memcpy( rbuf, &dir->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 );
}
struct stat st;
struct dir *fdir;
DIR *dp;
+#ifdef FORCE_UIDGID
+ uidgidset *uidgid;
+#endif FORCE_UIDGID
if ( curdir->d_parent == NULL ) {
return( AFPERR_ACCESS );
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"))) {
* 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;
}
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 );
}
}
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 );
}
}
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 );
}
}
}
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 );
}
}
#endif
dir_remove( vol, fdir );
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return( AFP_OK );
}
char *path, *upath;
u_int32_t did;
u_int16_t vid;
+#ifdef FORCE_UIDGID
+ uidgidset *uidgid;
+#endif FORCE_UIDGID
*rbuflen = 0;
ibuf += 2;
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;
}
#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
*
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:");
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 */
goto createfile_done;
/* fallthrough */
default :
+#ifdef FORCE_UIDGID
+ /* bring everything back to old euid, egid */
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return( AFPERR_PARAM );
}
}
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);
}
u_int32_t aint;
struct utimbuf ut;
+#ifdef FORCE_UIDGID
+ uidgidset *uidgid;
+#endif FORCE_UIDGID
+
#ifdef DEBUG
syslog(LOG_INFO, "begin setfilparams:");
#endif DEBUG
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<<FILPBIT_MDATE)) {
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
}
isad = 0;
if (isad) {
ad_flush( adp, ADFLAGS_HF );
ad_close( adp, ADFLAGS_HF );
+
+#ifdef FORCE_UIDGID
+ restore_uidgid ( uidgid );
+#endif FORCE_UIDGID
+
}
#ifdef DEBUG
--- /dev/null
+/*
+ * $Id: uid.c,v 1.1 2001-01-02 23:00:35 rufustfirefly Exp $
+ * code: jeff@univrel.pr.uconn.edu
+ *
+ * These functions are abstracted here, so that all calls for resolving
+ * user/group names can be centrally changed (good for OS dependant calls
+ * across the package).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+
+/* functions for username and group */
+#include <pwd.h>
+#include <grp.h>
+#include "uid.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#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 ) */
--- /dev/null
+/*
+ * $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
~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
page = strdup(name);
}
+ /* debug: show which codepage directory we are using */
+ syslog(LOG_DEBUG, "using codepage directory: %s", page);
+
return page;
}
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);
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;
void *v_db;
char *v_dbpath;
#endif
+#ifdef FORCE_UIDGID
+ char *v_forceuid;
+ char *v_forcegid;
+#endif FORCE_UIDGID
};
#ifdef NO_LARGE_VOL_SUPPORT