home *** CD-ROM | disk | FTP | other *** search
- /*
- * Amiga support routines for chroot() emulation
- * © 1994 Blaz Zupan, <blaz.zupan@uni-mb.si>
- * All Rights Reserved
- *
- * Contains:
- *
- * chroot()
- * CheckAccess()
- * amiga_seteuid()
- * amiga_getuid()
- * amiga_getpwnam()
- * amiga_getgrnam()
- * amiga_umask()
- *
- */
-
- #include <libraries/multiuser.h>
- #include <proto/multiuser.h>
- #include <proto/dos.h>
- #include <proto/usergroup.h>
- #include <string.h>
- #include <stdio.h>
- #include "extensions.h"
- #include "config.h"
-
- extern char *amigausername;
- extern struct muBase *muBase;
-
- /*
- * This routine is an attempt to emulate the Unix chroot()
- * function. It only saves the name supplied in the global
- * AmigaRootDir. Everything else must be done by CheckAccess().
- */
- extern int anonymous, guest;
- char AmigaRootDir[MAXPATHLEN + 2] = "";
-
- int
- chroot (char *dir)
- {
- BPTR lock;
-
- if (lock = Lock (dir, SHARED_LOCK))
- {
- NameFromLock (lock, AmigaRootDir, MAXPATHLEN);
- UnLock (lock);
- return 0;
- }
- return -1;
- }
-
- /*
- * Checks if pathname "name1" is above
- * "name" in directory structure.
- */
- static BOOL
- IsParent (char *name1, char *name2)
- {
- BOOL ret = FALSE;
- BPTR l1;
-
- if (l1 = Lock (name1, SHARED_LOCK))
- {
- BPTR l2;
-
- if (l2 = Lock (name2, SHARED_LOCK))
- {
- switch (SameLock (l1, l2))
- {
- case LOCK_DIFFERENT:
- break;
- case LOCK_SAME:
- ret = TRUE;
- break;
- case LOCK_SAME_VOLUME:
- {
- BPTR l;
-
- while (l2)
- {
- l = l2;
- l2 = ParentDir (l);
- UnLock (l);
- if (SameLock (l1, l2) == LOCK_SAME)
- {
- ret = TRUE;
- break;
- }
- }
- break;
- }
- }
- UnLock (l2);
- }
- UnLock (l1);
- }
- return ret;
- }
-
- /* Compare two strings with pattern matching */
- static BOOL
- mymatch (char *pattern, char *string)
- {
- BOOL ret = FALSE;
- char *parsedpattern;
- long len = strlen (pattern) * 2 + 10;
- long oldflags = DOSBase->dl_Root->rn_Flags;
-
- DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR; /* turn on recognitions of star as wildcard */
- if (parsedpattern = malloc (len))
- {
- if (ParsePattern (pattern, parsedpattern, len) != -1)
- ret = MatchPattern (parsedpattern, string);
- free (parsedpattern);
- }
- DOSBase->dl_Root->rn_Flags = oldflags; /* restore original flags */
- return ret;
- }
-
- /* Checks if user is allowed to access file/directory.
- * If create == TRUE check for parent of specified name
- * (this is used if we want to check if user is allowed
- * to access the directory into which a file should be
- * created - so now "put <something> AmiTCP:db/passwd"
- * hacks are possible).
- */
- BOOL
- CheckAccess (char *dir, BOOL create)
- {
- BPTR lock;
- char name[MAXPATHLEN];
- struct aclmember *entry = NULL;
-
- strcpy (name, dir);
- lock = Lock (name, SHARED_LOCK);
- if (!lock && create)
- {
- *(FilePart (name)) = 0;
- lock = Lock (name, SHARED_LOCK);
- }
-
- if (lock)
- UnLock (lock);
- else
- /* If we could not access file/directory then return "OK"
- * for now because access will be denied later by the
- * command that called us.
- */
- return TRUE;
-
-
- /* first check if directory is on "deny" list */
- while (getaclentry ("denydir", &entry) && ARG0 && ARG1)
- {
- if (mymatch (ARG1, amigausername) && IsParent (ARG0, name))
- return FALSE;
- }
- /* now see if it is under root dir */
- if (IsParent (AmigaRootDir, name))
- return TRUE;
- /* check if access is allowed even if dir is not under root */
- else
- {
- entry = NULL;
- while (getaclentry ("allowdir", &entry) && ARG0 && ARG1)
- {
- if (mymatch (ARG1, amigausername) && IsParent (ARG0, name))
- return TRUE;
- }
- }
- /* If directory is not on deny or allow list and not
- * under root directory then we allow access for
- * real users and don't allow access for guests.
- */
- if (!anonymous && !guest)
- return TRUE;
- else
- return FALSE;
- }
-
- /*
- * Simulate Unix geteuid() call with MultiUser.
- */
- int
- amiga_geteuid (void)
- {
- if (muBase)
- return ((muGetTaskOwner (FindTask (NULL)) & muMASK_UID) >> 16);
- else
- #undef geteuid
- return (geteuid ());
- }
-
- /*
- * Simulate Unix seteuid() call with MultiUser.
- * You have to be logged in as root initially for this
- * routine to work (after that it correctly keeps track
- * of the user).
- */
- int
- amiga_seteuid (int u)
- {
- if (muBase)
- {
- ULONG tags[5];
- int res = -1;
-
- if (u == 0)
- {
- int uid;
-
- uid = amiga_geteuid ();
-
- /* Are we already root? */
- if (uid == muROOT_UID)
- return 0;
-
- /* We can't set effective user ID to root
- * if we are currently logged in as nobody
- */
- if (uid == muNOBODY_UID)
- return -1;
-
- /* Now logout until we become either root or
- * nobody. If we become nobody we fail.
- */
- do
- {
- tags[0] = muT_Quiet;
- tags[1] = TRUE;
- tags[2] = TAG_END;
- muLogoutA (tags);
- uid = amiga_geteuid ();
- }
- while (uid != muROOT_UID && uid != muNOBODY_UID);
-
- return ((uid == muROOT_UID) ? 0 : -1);
- }
-
- /* Check if we are maybe already logged in as that user. */
- if (u == amiga_geteuid ())
- return 0;
-
- /* Ok, so we are trying to login as someone else.
- * first make sure that we are root. */
- if (amiga_seteuid (0) != -1)
- {
- struct muUserInfo *ui;
-
- if (ui = muAllocUserInfo ())
- {
- ui->uid = u;
- if (muGetUserInfo (ui, muKeyType_uid))
- {
- tags[0] = muT_UserID;
- tags[1] = (ULONG) ui->UserID;
- tags[2] = muT_NoLog;
- tags[3] = TRUE;
- tags[4] = TAG_END;
- res = (muLoginA (tags) ? 0 : -1);
- }
- muFreeUserInfo (ui);
- }
- }
- return res;
- }
- /* MultiUser is not installed so use dummy
- * usergroup.library call.
- */
- #undef seteuid
- return (seteuid (u));
- }
-
- /*
- * Simulate Unix seteuid() call with MultiUser.
- * You have to be logged in as root initially for this
- * routine to work (after that it correctly keeps track
- * of the user).
- */
- int
- amiga_setegid (int g)
- {
- /* We can't set another group under
- * MultiUser so we fail.
- */
- if (muBase)
- return -1;
- /* MultiUser is not installed so use dummy
- * usergroup.library call.
- */
- #undef setegid
- return (setegid (g));
- }
-
-
- /*
- * Simulate Unix getpwnam() call with MultiUser.
- */
-
- static struct passwd p;
-
- struct passwd *
- amiga_getpwnam (char *name)
- {
- if (muBase)
- {
- struct muUserInfo *ui;
- BOOL ok = FALSE;
-
- if (ui = muAllocUserInfo ())
- {
- strcpy (ui->UserID, name);
- if (muGetUserInfo (ui, muKeyType_UserID))
- {
- p.pw_uid = ui->uid;
- p.pw_gid = ui->gid;
- if (p.pw_name)
- free (p.pw_name);
- p.pw_name = malloc (strlen (ui->UserID) + 1);
- if (p.pw_name)
- strcpy (p.pw_name, ui->UserID);
- p.pw_passwd = NULL;
- if (p.pw_gecos)
- free (p.pw_gecos);
- p.pw_gecos = malloc (strlen (ui->UserName) + 1);
- if (p.pw_gecos)
- strcpy (p.pw_gecos, ui->UserName);
- if (p.pw_dir)
- free (p.pw_dir);
- p.pw_dir = malloc (strlen (ui->HomeDir) + 1);
- if (p.pw_dir)
- strcpy (p.pw_dir, ui->HomeDir);
- if (p.pw_shell)
- free (p.pw_shell);
- p.pw_shell = malloc (strlen (ui->Shell) + 1);
- if (p.pw_shell)
- strcpy (p.pw_shell, ui->Shell);
- ok = TRUE;
- }
- muFreeUserInfo (ui);
- }
- if (!ok)
- return (NULL);
- return (&p);
- }
- #undef getpwnam
- return (getpwnam (name));
- }
-
- /*
- * Simulate Unix getgrnam() call with MultiUser.
- */
-
- static struct group g;
-
- struct group *
- amiga_getgrnam (char *name)
- {
- if (muBase)
- {
- struct muGroupInfo *gi;
- BOOL ok = FALSE;
-
- if (gi = muAllocGroupInfo ())
- {
- strcpy (gi->GroupID, name);
- if (muGetGroupInfo (gi, muKeyType_GroupID))
- {
- static char *dummy_memb = NULL;
-
- g.gr_gid = gi->gid;
- if (g.gr_name)
- free (g.gr_name);
- g.gr_name = malloc (strlen (gi->GroupID) + 1);
- if (g.gr_name)
- strcpy (g.gr_name, gi->GroupID);
- g.gr_passwd = NULL;
- g.gr_mem = &dummy_memb;;
- ok = TRUE;
- }
- muFreeGroupInfo (gi);
- }
- if (!ok)
- return (NULL);
- return (&g);
- }
- #undef getgrnam
- return (getgrnam (name));
- }
-
- /*
- * Simulate Unix umask() call with MultiUser.
- */
-
- const static BYTE abits[8] =
- {
- 0, 0x2, 0x5, 0x7, 0x8, 0xA, 0xD, 0xF,
- };
-
- const static BYTE ubits[16] =
- {
- 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7
- };
-
- ULONG
- U2A_prot (int mode)
- {
- return ((abits[mode & 7] << FIBB_OTR_DELETE) |
- (abits[(mode >> 3) & 7] << FIBB_GRP_DELETE) |
- (abits[(mode >> 6) & 7] ^ 0xf));
- }
-
- int
- A2U_prot (ULONG mode)
- {
- return ((ubits[(mode >> 12) & 15] << 6) |
- (ubits[(mode >> 8) & 15] << 3) |
- (ubits[mode & 15]));
- }
-
- int
- amiga_umask (int m)
- {
- if (muBase)
- {
- ULONG tags[3];
- ULONG oldmask;
-
- tags[0] = muT_DefProtection;
- tags[1] = U2A_prot (m);
- tags[2] = TAG_END;
- oldmask = muGetDefProtection (NULL);
- muSetDefProtection (tags);
- return (A2U_prot (oldmask));
- }
- #undef umask
- return (umask (m));
- }
-
- /* dummy stub function for compatibility with original source */
- FILE *
- ftpd_popen (char *program, char *type, int closestderr)
- {
- return (popen (program, type));
- }
-
- /* dummy stub function for compatibility with original source */
- void
- ftpd_pclose (FILE * iop)
- {
- pclose (iop);
- }
-