Search code examples
cdebuggingsegmentation-faultrootsetuid

Segmentation Fault in this C wrapper


I am new to C and this is a simple wrapper(rootsetuidwrapper.c) written to execute scripts as a different user. The script I want to execute is ubuntu-server-secure.sh at path (/home/neehar) as root. My operating system is Ubuntu 12.04.03 LTS. Can someone help me fix these errors? I compiled with gcc and called the compiled code as rootsuidwrap by doing gcc -o rootsuidwrap rootsetuidwrapper.c. When I ran it in the terminal by doing ./rootsuidwrap ubuntu-server-secure.sh [0]. Is that the right way to call it? The usage part in the code says to do it this way. It comes up saying: Segmentation Fault (core dumped). Does it have to with this section of the code: *user=cuserid(NULL);. It could be rogue pointer. If so, what would be the fix and what would it look like?

It would be nice if someone could fix these errors and give me the working code. Also, I would like to know what I did wrong.

 * This program must be run as root to work.
 */

#if !defined(lint) && !defined(SABER) || defined(RCS_HDRS)
#endif /* !lint && !SABER || RCS_HDRS */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>

#define TRUSTED_GROUP "trusted"

typedef enum { false = 0, true } bool;

#ifdef __STDC__
bool trusted(char *whoami)
#else
bool trusted(whoami)
  char *whoami;
#endif /* __STDC__ */
{
    char *user;
    char host[BUFSIZ + 1];
    char domain[BUFSIZ + 1];
    struct hostent *hp;

    /* 
     * Figure out whether this user on this host in this domain is
     * trusted.
     */

    /* 
     * Determine our domain name
     */
    memset (domain, '\0', sizeof domain );
    getdomainname (domain, sizeof domain - 1);

    /* 
     * Figure out our fully canonicalized hostname
     */

    memset (host, '\0', sizeof host );
    gethostname (host, sizeof host - 1);
    if ((hp = gethostbyname (host)) == NULL) {
      strcat (host, ".");
      strcat (host, domain);
      fprintf (stderr, 
               "%s: WARNING: can't canonlicalize hostname; assuming %s.\n",
               whoami, host);
    } else {
      strcpy (host, hp->h_name);
    }

    /* 
     * Get login name of current user
     */
    *user = cuserid (NULL);        
    if (user == NULL) {
      fprintf (stderr, " %s: You do not seem to be in the passwd file!\n",
               whoami);
      return false;
    }

    /* 
     * Look this triple up in the trusted netgroup 
     */

    return (innetgr (TRUSTED_GROUP, host, user, domain) == 1) ? true : false;
}


#ifdef __STDC__
main(int argc, char *argv[])
#else
main(argc, argv)
  int argc;
  char *argv[];
#endif /* __STDC__ */
{
    char *whoami;
    int ouruid;         /* uid we set to run chown and chmod */
    int proguid;        /* uid we are chowning program to */
    char *filename;
    struct stat statbuf;
    int error = 0;

    if (whoami = strrchr(argv[0], '/')) 
      whoami++;
    else
      whoami = argv[0];

    if (argc == 3)
      proguid = atoi(argv[2]);
    else if (argc == 2)
      proguid = 0;
    else {
      fprintf (stderr, "usage: %s filename [proguid]\n", whoami);
      exit(1);
    }

    filename = argv[1];

    if (trusted(whoami)) 
      ouruid = 0;
    else
      ouruid = getuid ();

    if (setuid (ouruid) == -1) {
      fprintf (stderr, "%s: Warning: setuid(%d) failed: ", whoami, ouruid);
      perror (NULL);
      exit (1);
    }

    if (stat (filename, &statbuf, sizeof(struct stat)) == -1) {
      fprintf(stderr, "%s: failure statting %s: ", whoami, filename);
      perror(NULL);
      exit(1);
    }

    if (chown (filename, proguid, -1) == -1) {
      error++;
      fprintf (stderr, "%s: chown %d %s failed: ", whoami, proguid, filename);
      perror (NULL);
      fprintf (stderr, "continuing...\n");
    }

    if (chmod (filename, statbuf.st_mode | S_ISUID)) {
      error++;
      fprintf (stderr, "%s: chmod u+s %s failed: ", whoami, filename);
      perror (NULL);
    }

    return(error);
}

Help is appreciated,


Solution

  • Try,

    user = cuserid (NULL);
    

    Instead of

    *user = cuserid (NULL);
    

    While the program compiled, the compiler probably displayed a warning relating to this line. I would study any other warnings you get compiling the program and work to remove them as well.