Thread: setuid to switch user

  1. #1
    Registered User
    Join Date
    Jun 2017
    Posts
    18

    setuid to switch user

    Hi,
    I have a program that sets the UID and GID of the user, however, after setting it is not running the expected program as the user it is supposed to be.

    For example,
    Program to be run only as user X belonging to group X. The permissions look like this for the executable

    r-xr-x--- X X usrprog

    Now I user Y execute the C program that will call the above program 'usrprog' when a normal user executed the helper. The helper has the following mode

    rwsr-xr-x X X helprprog

    Because of the 's' mode at the owner, the setuid or seteuid works fine. After setting this I call the 'usrprog' using system or exec command to be run as user X, but could not achieve the goal. The message I get is permission denied due to others ot having an execute permission for 'usrprog'.

    Any help would be much appreciated.

    PS: User X doesn't have a login shell or a password

    Thanks
    Nethaji

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Works for me using execl.
    No need for setuid.
    If you still have a problem, actual code is better than vague descriptions.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Jun 2017
    Posts
    18
    Hi John,
    I had no luck. Please see the code below:

    This program when compiled will have the user and group assigned to the progusr whilst the x permission is set to others. Also, the executable will have owner sticky mode 's'

    The actual program as mentioned earlier will have r and x only for the owner and group, which is the progusr.

    Code:
                            #include <stdio.h>
    #include <strings.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    /*Global variables:*/
    int status;
    
    struct passwd *progusrUID; /*A structure defined in pwd.h that will return a list of value for the given user. See 'man getpwnam' for more details:*/
    /*Global variables ends*/
    
    /*Restore the effective UIDs to its original value:*/
    int dosetuid(pid_t realUID, pid_t effectiveUID)
    {
     int status;
    
     #ifdef _POSIX_SAVED_IDS
      status = seteuid(effectiveUID);
     #else
      status = setreuid(realUID, effectiveUID);
     #endif
    
     /*
     if(status < 0)
      {
       fprintf (stderr, "Couldn't set uid.\n");
       exit(status);
      }
     */
     return status;
    }
    
    /*Set the effective UID to the real UID:*/
    int undosetuid(pid_t realUID, pid_t effectiveUID)
    {
     int status;
    
     #ifdef _POSIX_SAVED_IDS
      status = seteuid(realUID);
     #else
      status = setreuid(effectiveUID, realUID);
     #endif
    
     /*
     if(status < 0)
      {
       fprintf(stderr, "Couldn't reset uid.\n");
       exit(status);
      }
     */
     return status;
    }
    
    void main()
    {
     /*UID global variables:*/
     static uid_t effectiveUID, realUID;
     /*Process and parent process ids:*/
     int pPID = -1, pPPID = -1, cPID = -1, cPPID = -1;
     int statu = -10;
    
     /*Get the real and effective UIDs:*/
     realUID = getuid();
     effectiveUID = geteuid();
    
     printf("%d %d\n", realUID, effectiveUID);
     if((progusrUID = getpwnam("progusr")) != NULL)
      {/*Do nothing:*/
       printf("progusrUID: %d\n", progusrUID->pw_uid);
      }
    
     /*Call a function to execute GTK+ software from here:*/
     pid_t PID = fork();
     switch(PID)
     {
      case -1:
      {
       perror("Fork failed\n");
       break;
      }
      case 0:
      {
       cPID = getpid(); cPPID = getppid();
       printf("Child process\n");
       printf("PPID= %d PPPID= %d\n", cPID, cPPID);
       printf("Before: %d %d\n", getuid(), geteuid());
       status = dosetuid(realUID, progusrUID->pw_uid);
       if(status < 0) {fprintf(stderr, "Couldn't set uid.\n");}
       printf("After dosetuid: %d %d\n", getuid(), geteuid());
       system("who am i");
       system("/path/to/usrprog");
       printf("After exec: %d %d\n", getuid(), geteuid());
       if(status == 0) {status = undosetuid(realUID, ApNetSoftUID->pw_uid);}
       if(status < 0) {fprintf(stderr, "Couldn't reset uid.\n");}
       printf("After reset: %d %d\n", getuid(), geteuid());
       break;
      }
      default:
      {
       pPID = getpid(); pPPID = getppid();
       printf("This is default: Parent process\n");
       printf("PPID= %d PPPID= %d\n", pPID, pPPID);
       break;
      }
     }
    
     while((PID = waitpid(-1, &status, 0)) != -1)
     {/*Wait till all child processes finishes and then exit:*/
     }
     return;
    }

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Try execl, not system (you said the user doesn't have a shell).
    Get rid of all the setuid stuff.
    I don't see the point of the fork.
    And main returns an int.
    Code:
    #include <stdio.h>
    #include <unistd.h>
     
    int main()
    {
        execl("/full/path/to/prog", "prog", (char*)NULL);
        perror("execl");
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Jun 2017
    Posts
    18
    Thanks John. It works now.

    Best regards
    Nethaji

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. convert user input for use in switch
    By MedicineMan25 in forum C Programming
    Replies: 3
    Last Post: 08-31-2017, 04:50 AM
  2. Switch case User interface menu helpp
    By cnandha19 in forum C Programming
    Replies: 0
    Last Post: 05-25-2017, 06:35 AM
  3. Setuid function ???
    By wampire in forum Linux Programming
    Replies: 9
    Last Post: 12-25-2007, 09:18 PM
  4. Firefox user switch
    By cerin in forum Tech Board
    Replies: 11
    Last Post: 03-13-2005, 12:06 AM
  5. A switch that doesn't switch
    By Death_Wraith in forum C++ Programming
    Replies: 5
    Last Post: 11-06-2004, 12:18 PM

Tags for this Thread