ITEM: BL8384L

how to set real-uid to non-superuser and regain superuser later



Response:

ENV: AIX 4

DESC:

Need to change the effective and real user ids of a single process 
during while the program is running.  The sequence of user id changes
must be as follows.

1. real-uid = root , effective-uid = root, saved-uid = root
2. real-uid = non-root, effective-uid = non-root, saved-uid = root
3. real-uid = root,  effective-uid = root, saved-uid = root.

ACTION:

Changes the user ids of a process in the above order requires
two different programs on AIX 4.2 and AIX 4.1.  The primary reason
for the two different programs is that the setreuid() function
has been changed to support SPEC 1170 (VSU).
Included in this item are each procedure.  Standard documented 
system calls can be used on AIX 4.2 to accomplish the above 
sequence of user ids.  ON AIX 4.1 however, a number of
undocumented functions setgidx(), and setuidx must be used.

*********************** ON AIX 4.2  ******************************

The following program will produced the desired results
on AIX 4.2.

1. Make the executable owned by root with setuid bit set.
   When it is invoked by a non-root user (e.g., 100), the
   real user id will be non-root and the effective user id will be
   root.
   The commands that you can use (as the root user) to get the 
   proper initial setting of the executable file is:
     
     chown root 'program'
     chmod +s 'program'
     chmod g-s 'program'

AIX 4.2 Sample code below:

\#include \
\#include \
\#include \

void printids()
{  printf("uid = %d\\teuid = %d\\n", 
         getuid(), geteuid());
}main ()
{  uid_t uid; 

  uid = 203;

  printf(" 0.  Starts with...\\n");
  printids();
  printf(" 1.  seteuid (uid)\\n");
  if (seteuid (uid) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 2.  setreuid (uid, 0)\\n");
  if (setreuid( uid, 0 ) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 3.  setuid (0)\\n");
  if (setuid (0) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 4.  setreuid (uid, 0)\\n");
  if (setreuid (uid,0) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 1.  seteuid (uid)\\n");
  if (seteuid (uid) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 2.  setreuid (uid, 0)\\n");
  if (setreuid( uid, 0 ) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 3.  setuid (0)\\n");
  if (setuid (0) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
  printf(" 4.  setreuid (uid, 0)\\n");
  if (setreuid (uid,0) \< 0)
    printf("failed.  errno = %d '%s'\\n", errno, strerror (errno));
  printids();
}
End AIX 4.2 sample code

*********************** ON AIX 4.1 ******************************

The following is a program (testcreds) that can be used on AIX 4.1
to change the real and effective user ids in the indicated 
sequence above.
The setuidx() function is an internal routine that is visible
in .h files because they have to be.  Documentation on this 
unsupported function is not intended to be available.

$ ls -la testcreds
-rwsrwsr-x   1 root     staff      14751 Sep 09 10:39 testcreds

$ id
uid=202(bartula) gid=1(staff)

AIX 4.1 Sample code begin:

\#include \
\#include \
\#include \
\#include \
\#define _LLPL_TYPES_ONLY
\#if 0
\#include \
\#include \
\#include \
\#include \
\#endif /* 0 */
/********************************/
/*     external functions       */
/********************************/
typedef unsigned long uid_t;
typedef unsigned long gid_t;
\#include \
\#include \
\#include \
\#include \  // Error checking
extern "C" int getpriv(int which, priv_t *privset, size_t privsiz);
extern "C" int setpriv(int which, priv_t *privset, size_t privsiz);
extern "C" void sigaddset (void *, int);

extern "C" int   setresuid(uid_t ruid, uid_t euid, uid_t suid);
extern "C" int   setresgid(gid_t rgid, gid_t egid, gid_t sgid);
\#define seteuid(euid) setresuid( -1, (euid), -1)
\#define setegid(egid) setresgid( -1, (egid), -1)

extern "C" uid_t geteuid();
extern "C" gid_t getegid();
extern "C" int   getgroups(int max_n_groups, gid_t *gidset);
extern "C" int   setgroups(int n_groups, gid_t *gidset);

void setcreds(int an_id ,int a_gid );
void re_setcreds();
void printids();

int saved_privs[2];

main(int argc, char *argv[])
{  if (argc != 3) {
    cerr \<\< "USAGE: testpriv uid gid";
    exit(1);
  }
    int id = atoi(argv[1]);
    int gid = atoi(argv[2]);
    printids();
    cout \<\< "setting credentials " \<\< endl;
    setcreds(id,gid);
    cout \<\< "re-setting credentials " \<\< endl;
    re_setcreds();

    cout \<\< "setting credentials " \<\< endl;
    setcreds(id,gid);
    cout \<\< "re-setting credentials " \<\< endl;
    re_setcreds();
}void setcreds(int owner, int group)
{  priv_t ps;
  ps.pv_priv[0] = 0;
  ps.pv_priv[1] = 0;

  /* we want no privileges except the ability to get back */
  sigaddset ((void *)&ps, SET_PROC_DAC);

  int r = setpriv (PRIV_SET | PRIV_EFFECTIVE, &ps, sizeof (ps));

  if(r != 0) {
        cerr \<\<   "setpriv failed to reduce privs: " \<\< endl;
 cerr \<\<   "errno = " \<\< errno \<\< endl;  // Error checking
  }

  r = setgidx (ID_SAVED | ID_REAL | ID_EFFECTIVE, group);

  if(r != 0) {
        cerr \<\<   "setgidx failed to reduce privs: " \<\< endl;
 cerr \<\<   "errno = " \<\< errno \<\< endl;  // Error checking
  }

  r = setuidx (ID_SAVED | ID_REAL | ID_EFFECTIVE, owner);
  if(r != 0) {
        cerr \<\<   "setuidx failed to reduce privs: " \<\< endl;
 cerr \<\<   "errno = " \<\< errno \<\< endl;  // Error checking
  }
  printids();
}
void re_setcreds()
{  int r = setuidx (ID_SAVED | ID_REAL | ID_EFFECTIVE, 0); // Set back to root.
  if(r != 0) {
    cerr \<\<   "setpriv failed to reduce privs: " \<\< endl;
    cerr \<\<   "errno = " \<\< errno \<\< endl;  // Error checking
  }
  printids();
}
void printids()
{  printf("uid = %d\\teuid = %d\\n",
         getuid(), geteuid());
}
End of AIX 4.1 Sample Code


Support Line: how to set real-uid to non-superuser and regain superuser later ITEM: BL8384L
Dated: March 1997 Category: N/A
This HTML file was generated 99/06/24~13:30:21
Comments or suggestions? Contact us