home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: credential.c,v 4.2 1994/05/18 15:43:02 ppessi Exp $";
- /*
- * credential.c --- handle credentials
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * This file is part of the AmiTCP/IP User Library.
- *
- * Copyright © 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
- * Helsinki University of Technology, Finland.
- *
- * Created : Wed Sep 15 01:25:26 1993 ppessi
- * Last modified: Wed May 18 18:42:43 1994 ppessi
- */
-
- #include "base.h"
- #include "credential.h"
- #include "libfunc.h"
-
- #include <exec/memory.h>
- #include <exec/alerts.h>
- #include <string.h>
- #include <assert.h>
-
- struct CredentialResource *CredentialBase;
-
- #ifdef notyet
- typedef struct CredentialResource *(*resident_init_fp)(void);
-
- /*
- * Create credential resource
- */
- struct CredentialResource *CredentialInit(const char *name)
- {
- BPTR resseg = LoadSeg(_PATH_CREDENTIAL);
-
- if (resseg) {
- resident_init_fp initf = (resident_init_fp)((LONG *)(resseg << 2) + 1);
- struct CredentialResource *res = initf();
-
- if (res)
- return res;
-
- UnLoadSeg(resseg);
- }
-
- return NULL;
- }
- #endif
-
- /****** usergroup.library/getspgrp ********************************************
-
- NAME
- getpgrp - get process group identification
-
- SYNOPSIS
- #include <libraries/usergroup.h>
-
- sessionid = getpgrp()
- D0
- pid_t getpgrp(void);
-
- FUNCTION
- The getpgrp() function returns the process group id for the current
- process. Currently, the process group ID is the same as the session
- ID. The 0 is valid process group ID for console session.
-
- RESULTS
- Upon successful completion, the value of the process group ID is
- returned. Otherwise, a value of -1 is returned and an error code is
- stored to global errno location.
-
- ERRORS
- [ESRCH] The calling process don't belong to any process group.
-
- SEE ALSO
- setsid(), exec.library/FindTask()
-
- ******************************************************************************
- */
-
- SAVEDS ASM pid_t R_getpgrp(void)
- {
- struct proc *p = procfind(NULL);
-
- return p->p_session->s_leader;
- }
-
- /****** usergroup.library/setsid *********************************************
-
- NAME
- setsid - create a new session
-
- SYNOPSIS
- #include <unistd.h>
-
- sessionid = setsid()
- D0
- pid_t setsid(void);
-
- FUNCTION
- The setsid() function creates a new session when the calling
- process is not a process group leader. The calling process
- then becomes the session leader of this session and the only
- process in the new session.
-
- RESULTS
- Upon successful completion, the value of the new session ID is
- returned. Otherwise, a value of -1 is returned and an error
- code is stored to global errno location.
-
- ERRORS
- [EPERM] The calling process is already a session leader.
-
- SEE ALSO
- getpgrp()
-
- ******************************************************************************
- */
-
- SAVEDS ASM pid_t R_setsid(void)
- {
- #ifdef notyet
- pid_t pid = (pid_t)FindTask(NULL);
- struct proc *p = procfind(pid);
- int error;
-
- if (p->p_session->s_leader == pid) {
- error = EPERM;
- } else {
- struct session *session;
-
- while (!(session = AllocMem(sizeof(*session), MEMF_CLEAR|MEMF_PUBLIC))) {
- Alert(AG_NoMemory | UG_CredRes);
- Wait(0L);
- }
- InitList((struct List *)session->s_pgrpl);
- Forbid();
- p = proccopy(p, pid);
- p->p_ucred->cr_ref++;
- p->p_ucred = crcopy(p->p_ucred);
-
- /* Remove from old process group */
- rempgrp(p);
- p->p_session = session;
- MinAddHead(session->s_pgrpl, p->p_pgrp);
- session->s_consoletask = GetConsoleTask();
- session->s_leader = pid;
- Permit();
- return pid;
- }
-
- SetErrno(error);
- return -1;
- #endif
- return 0;
- }
-
- #ifdef notyet
- /*
- * Remove a process from session's process group and
- * free session if last process is removed
- */
- void
- rempgrp(struct proc *p)
- {
- Forbid();
- /* Free the session structure if the last task in process group dies */
- MinRemove((struct Node *)p->p_pgrp);
- if (IsMinListEmpty(p->p_session->s_pgrpl)) {
- FreeMem(p->p_session, sizeof(*p->p_session));
- } else if (p->p_session->s_leader == (pid_t)p->p_task) {
- }
- Permit();
- }
- #endif
-
- /*
- * Check super-user
- */
- int
- suser(struct ucred *cred)
- {
- if (cred->cr_uid == 0)
- return 0;
- return EPERM;
- }
-
- /*
- * Search credentials
- */
- static struct pcred *crfind(pid_t pid)
- {
- return procfind(pid)->p_cred;
- }
-
- /****** usergroup.library/getuid *********************************************
-
- NAME
- getuid, geteuid - get user process identification
- getgid, getegid - get group process identification
-
- SYNOPSIS
- ruid = getuid()
- D0
-
- uid_t getuid(void);
-
- euid = geteuid()
- D0
-
- uid_t geteuid(void);
-
- rgid = getgid()
- D0
-
- gid_t getgid(void);
-
- egid = getegid()
- D0
-
- gid_t getegid(void);
-
- FUNCTION
- The getuid() function returns the real user ID of the calling
- process, geteuid() returns the effective user ID of the calling
- process.
-
- The getgid() function returns the real group ID of the calling
- process, getegid() returns the effective group ID of the calling
- process.
-
- The real user ID and real group ID is specified at login time.
-
- The real ID is the ID of the user who invoked the program. As the
- effective user and gourp ID gives the process additional permissions
- during the execution of `set-user-ID' or `set-group-ID' mode
- programs, functions getgid() and getuid () are used to determine the
- real-ids of the calling process.
-
- RESULT
- The getuid(), geteuid(), getgid(), and getegid() functions are
- always successful, and no return value is reserved to indicate an
- error.
-
- NOTES
- Any task can call these functions
-
- SEE ALSO
- getgroups(), setuid(), setreuid(), setgid(), setregid(), setgroups()
-
- ******************************************************************************
- */
-
- SAVEDS ASM uid_t R_getuid(void)
- {
- return crfind(NULL)->p_ruid;
- }
-
- SAVEDS ASM uid_t R_geteuid(void)
- {
- return crfind(NULL)->p_euid;
- }
-
- SAVEDS ASM gid_t R_getgid(void)
- {
- return crfind(NULL)->p_rgid;
- }
-
- SAVEDS ASM gid_t R_getegid(void)
- {
- return crfind(NULL)->p_egid;
- }
-
- /****** usergroup.library/getgroups *******************************************
-
- NAME
- getgroups - get group access list
-
- SYNOPSIS
- len = getgroups(gidsetlen, gidset[])
- D0 D0 A0
-
- int getgroups(int, gid_t *);
-
- FUNCTION
- Getgroups() gets the current group access list of the user process
- and stores it in the array gidset. The parameter gidsetlen indicates
- the number of entries that may be placed in gidset. The function
- getgroups() returns the actual number of groups returned in gidset.
- No more than NGROUPS, as defined in <libraries/usergroup.h>, will
- ever be returned.
-
- RESULT
- A successful call returns the number of groups in the group set. A
- value of -1 indicates that the argument gidsetlen is smaller than
- the number of groups in the group set.
-
- ERRORS
- [EINVAL] The argument gidsetlen is smaller than the number of
- groups in the group set.
- [EFAULT] The argument gidset specifies an invalid address.
-
- SEE ALSO
- setgroups(), initgroups(), getgid(), getegid()
-
- HISTORY
- The getgroups function call appeared in 4.2BSD.
-
- ****************************************************************************
- */
-
- SAVEDS ASM int R_getgroups(REG(d0) int ngroups, REG(a1) gid_t *groups)
- {
- struct pcred *pc = crfind(NULL);
- gid_t *getgroups;
- short error;
-
- if (ngroups == 0) {
- return pc->p_ngroups;
- } else if (ngroups < pc->p_ngroups) {
- error = EINVAL;
- } else if (groups == NULL || ((LONG)groups & 1) != 0) {
- error = EFAULT;
- } else {
- /* This does also UWORD -> gid_t conversion */
- getgroups = pc->p_groups;
- ngroups = pc->p_ngroups;
- while (ngroups-- > 0) {
- *groups++ = *getgroups++;
- }
- return pc->p_ngroups;
- }
-
- SetErrno(error);
- return -1;
- }
-
- /****** usergroup.library/setuid ***********************************************
-
- NAME
- setuid, setreuid - set real and effective user ID's
- setgid, setregid - set real and effective group ID's
-
- SYNOPSIS
- success = setuid(uid)
- D0 D0
-
- int setuid(uid_t);
-
- success = setreuid(ruid, euid);
- D0 D0 D1
-
- int setreuid(uid_t, uid_t);
-
- success = setgid(gid)
- D0 D0
-
- int setgid(gid_t);
-
- success = setregid(ruid, euid)
- D0 D0 D1
-
- int setregid(gid_t ruid, gid_t euid);
-
- FUNCTION
- The real and effective ID's of the current process are set according
- to the arguments. If ruid or euid is -1, the current uid is filled
- in by the system. Unprivileged users may change the real ID to the
- effective ID and vice-versa; only the super-user may make other
- changes.
-
- RETURN VALUES
- Upon successful completion, a value of 0 is returned. Otherwise, a
- value of -1 is returned and errno is set to indicate the error.
-
- ERRORS
- [EPERM] The current process is not the super-user and a change
- other than changing the effective id to the real id was
- specified.
-
- SEE ALSO
- getuid(), getgid(), geteuid(), getegid()
-
- NOTES
- Any task can call these functions.
-
- HISTORY
- A setuid() and setgid() function calls appeared in Version 6 AT&T
- UNIX. The setreuid() and setregid() function calls appeared in
- 4.2BSD.
-
- ****************************************************************************
- */
-
- SAVEDS ASM int R_setuid(REG(d0) uid_t uid)
- {
- return R_setreuid(uid, uid);
- }
-
- SAVEDS ASM int R_setreuid(REG(d0) uid_t ruid, REG(d1) uid_t euid)
- {
- struct pcred *pc = crfind(NULL);
- short error;
-
- if (ruid == NOID)
- ruid = pc->p_ruid;
- if (euid == NOID)
- euid = pc->pc_ucred->cr_uid;
-
- /*
- * Allow setting real uid to previous effective, for swapping real and
- * effective. This should be:
- *
- * if (ruid != pc->p_ruid &&
- * (error = suser(pc->pc_ucred, &p->p_acflag)))
- */
- #if 1
- /* allow setreuid(-1, 0) to emulate SUID */
- if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
- (error = suser(pc->pc_ucred))) ||
- (/* euid != pc->pc_ucred->cr_uid */ 0 && euid != pc->p_ruid &&
- (error = suser(pc->pc_ucred))))
- #else
- if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
- (error = suser(pc->pc_ucred))) ||
- (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
- (error = suser(pc->pc_ucred))))
- #endif
- {
- unlock(&credential_list);
- SetErrno(error);
- return -1;
- } else {
- /*
- * Everything's okay, do it. Copy credentials so other references do
- * not see our changes.
- */
- pc->pc_ucred = crcopy(pc->pc_ucred);
- pc->pc_ucred->cr_uid = euid;
- pc->p_ruid = ruid;
-
- return 0;
- }
- }
-
- SAVEDS ASM int R_setgid(REG(d0) gid_t gid)
- {
- return R_setregid(gid, gid);
- }
-
- SAVEDS ASM int R_setregid(REG(d0) gid_t rgid, REG(d1) gid_t egid)
- {
- struct pcred *pc = crfind(NULL);
- short error;
-
- if (rgid == NOID)
- rgid = pc->p_rgid;
- if (egid == NOID)
- egid = pc->pc_ucred->cr_gid;
-
- /*
- * Allow setting real gid to previous effective, for swapping real and
- * effective. This should be:
- *
- * if (rgid != pc->p_rgid &&
- * (error = suser(pc->pc_ucred, &p->p_acflag)))
- */
- if ((rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_gid /* XXX */ &&
- (error = suser(pc->pc_ucred))) ||
- (egid != pc->pc_ucred->cr_gid && egid != pc->p_rgid &&
- (error = suser(pc->pc_ucred)))) {
- SetErrno(error);
- return -1;
- } else {
- /*
- * Everything's okay, do it. Copy credentials so other references do
- * not see our changes.
- */
- pc->pc_ucred = crcopy(pc->pc_ucred);
- pc->pc_ucred->cr_gid = egid;
- pc->p_rgid = rgid;
-
- return 0;
- }
- }
-
- /****** usergroup.library/setgroups ******************************************
-
- NAME
- setgroups - set group access list
-
- SYNOPSIS
- success = setgroups(ngroups, gidset)
- D0 D0 A0
-
- int setgroups(int, const gid_t *);
-
- FUNCTION
- Setgroups() sets the group access list of the current user process
- according to the array gidset. The parameter ngroups indicates the
- number of entries in the array and must be no more than NGROUPS, as
- defined in <libraries/usergroup.h>.
-
- Only the super-user may set new groups. The super-user can not
- set illegal groups (-1).
-
- RESULT
- A 0 value is returned on success, -1 on error, with an error
- code stored in errno and available with ug_GetErr() function.
-
- ERRORS
- [EINVAL] An illegal group id was specified.
- [EPERM] The caller has got no necessary privileges.
- [EFAULT] The address specified for gidset is illegal.
-
- NOTES
- Any task can call this function.
-
- SEE ALSO
- getgroups(), initgroups()
-
- ****************************************************************************
- */
-
- SAVEDS ASM int R_setgroups(REG(d0) int ngrp,
- REG(a1) const gid_t *groups)
- {
- register struct pcred *pc = crfind(NULL);
- register gid_t *gp;
- register const gid_t *lp;
- short error;
-
- if (error = suser(pc->pc_ucred /*, &p->p_acflag */)) {
-
- } else if (ngrp > NGROUPS) {
- error = EINVAL;
- } else if (groups == NULL || ((LONG)groups & 1) != 0) {
- error = EFAULT;
- } else {
- pc->pc_ucred = crcopy(pc->pc_ucred);
- pc->pc_ucred->cr_ngroups = ngrp;
- for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
- *gp++ = *lp++;
- return 0;
- }
-
- SetErrno(error);
- return -1;
- }
-
-
- /****** usergroup.library/MU2UG **********************************************
-
- NAME
- MU2ID - macro converting MultiUser id to usergroup id
- ID2MU - macro converting usergroup id to MultiUser id
-
- SYNOPSIS
- ug_id = MU2ID(mu_id)
-
- mu_id = ID2MU(ug_id)
-
- FUNCTION
- These macros are used to convert between different user ID
- formats. The mu_id is in the format used by MultiUser filesystem
- and multiuser.library. The ug_id is the format used by Unix and
- usergroup.library.
-
- Most of the id values are identical in usergroup.library and
- multiuser.library. However, these two exceptions have values as
- follows:
-
- usergroup.library multiuser.library
- super-user 0 65535
- nobody -2 0
-
- INPUTS AND RESULTS
- mu_id - user ID in MultiUser format.
- ug_id - user ID in usergroup format.
-
- BUGS
- The usergroup id values that won't fit into UWORD are truncated.
-
- SEE ALSO
- ******************************************************************************
- */
-
- #if 0
- ASM uid_t R_ug_mu2id(REG(d0) UWORD id)
- {
- if (id == 0) {
- return -2;
- } else if (id == 65535) {
- return 0;
- } else {
- return id;
- }
- }
-
- ASM UWORD R_ug_id2mu(REG(d0) uid_t id)
- {
- if (id == 0) {
- return 65535;
- } else if (id == -2) {
- return 0;
- } else {
- return id;
- }
- }
- #endif
-
- /****** usergroup.library/umask *********************************************
-
- NAME
- umask - set file creation mode mask
-
- SYNOPSIS
- #include <sys/stat.h>
-
- oldmask = umask(newmask)
- D0 D0
-
- mode_t umask(mode_t);
-
- FUNCTION
- The umask() routine sets the process's file mode creation mask to
- numask and returns the previous value of the mask. The 9 low-order
- access permission bits of numask are used by Unix-compatible
- filesystems, for examble by NFS, to turn off corresponding bits
- requested in file mode. This clearing allows each user to restrict
- the default access to his files.
-
- The default mask value is 022 (write access for owner only). Child
- processes should inherit the mask of the calling process.
-
- RESULT
- The previous value of the file mode mask is returned by the call.
-
- ERRORS
- The umask() function is always successful.
-
- SEE ALSO
- getumask()
- ******************************************************************************
- */
-
- SAVEDS ASM mode_t R_umask(REG(d0) mode_t newmask)
- {
- struct proc *p = procfind(NULL);
-
- mode_t oldmask = p->p_umask;
-
- p->p_umask = newmask;
-
- return oldmask ;
- }
-
- /****** usergroup.library/getumask *********************************************
-
- NAME
- getumask - get file creation mode mask
-
- SYNOPSIS
- #include <sys/stat.h>
-
- oldmask = getumask()
- D0
-
- mode_t getumask(void);
-
- FUNCTION
- The getumask() routine sets the process's file mode creation mask to
- numask and returns the previous value of the mask. The 9 low-order
- access permission bits of numask are used by Unix-compatible
- filesystems, for examble by NFS, to turn off corresponding bits
- requested in file mode.
-
- RESULT
- The value of the file mode mask is returned by the call.
-
- ERRORS
- The getumask() function is always successful.
-
- SEE ALSO
- umask()
- ******************************************************************************
- */
-
- SAVEDS ASM mode_t R_getumask(void)
- {
- struct proc *p = procfind(NULL);
-
- return p->p_umask;
- }
-
-
- /****** usergroup.library/getcredentials *************************************
-
- NAME
- getcredentials -- get credentials of given task. (V4)
-
- SYNOPSIS
- #include <libraries/usergroup.h>
-
- credentials = getcredentials(task)
- D0 A0
-
- struct UserGroupCredentials *getcredentials(struct Task *);
-
- FUNCTION
- The function getcredentials() returns all credentials of the given
- task. The credentials include real and effective user and group IDs,
- umask, login name and session ID. If the task pointer is NULL, the
- credentials of current task are returned.
-
- RESULT
- A getcredentials() function returns a valid pointer to structure
- UserGroupCredentials on success and a null pointer if an error
- occurs.
-
- ERRORS
- [EINVAL] An illegal task pointer was specified.
-
- BUGS
- This function leave its result in an internal static object and
- return a pointer to that object. Subsequent calls to this function
- will modify the same object.
-
- SEE ALSO
-
- ******************************************************************************
- */
-
- static struct UserGroupCredentials creds[1];
-
- SAVEDS ASM struct UserGroupCredentials
- *R_getcredentials(REG(a0) struct Task *task)
- {
- register struct proc *p = procfind(task);
-
- if (p != NULL) {
- register struct UserGroupCredentials *c = creds;
-
- c->cr_ruid = p->p_cred->p_ruid;
- c->cr_rgid = p->p_cred->p_rgid;
- c->cr_umask = p->p_umask;
- c->cr_euid = p->p_cred->p_euid;
- c->cr_ngroups = p->p_cred->p_ngroups;
- c->cr_session = p->p_session->s_leader;
- memcpy(c->cr_groups, p->p_cred->p_groups, sizeof(c->cr_groups));
- memcpy(c->cr_login, p->p_session->s_login, sizeof(c->cr_login));
-
- return c;
- }
-
- return NULL;
- }
-