Compdigitec Labs

« | Home | »

A simple su implementation in C

By admin | November 23, 2012

Sometimes, you might need to keep things simple. Here is a very simple su implementation written in portable C that can be used on almost any architecture - e.g. Embedded Linux, Android, Windows, etc as long as it supports C. It is licensed under the 3-clause BSD licence so any use is OK as long as credit is given:

/*
 * Simple su binary
 * Copyright (C) 2012 Compdigitec
 * http://www.compdigitec.com/labs/2012/11/23/a-simple-su-implementation-in-c/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following disclaimer
 *   in the documentation and/or other materials provided with the
 *   distribution.
 * * Neither the name of Compdigitec nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>

#define SHELL "/system/bin/sh"

#define about() do { \
    printf("Simple crude su binary\n"); \
    printf("See http://www.compdigitec.com/labs/2012/11/23/a-simple-su-implementation-in-c/\n"); \
    printf("su [-c <command>] [-h] [-v] [user id to su to, must be integer]\n"); \
    } while(0)

int main(int argc, char* argv[]) {
    char* command = NULL;
    int user = 0; // root
    int group = 0;

    struct option long_opts[] = {
        { "command",	required_argument,		NULL, 'c' },
        { "help", 		no_argument,			NULL, 'h' },
        { "shell",		required_argument,		NULL, 's' },
        { "version",	no_argument,			NULL, 'v' },
        { NULL, 0, NULL, 0 },
    };

    int c;
    while((c = getopt_long(argc, argv, "+c:hsv", long_opts, NULL)) != -1) {
        switch(c) {
            case 'c':
                command = strdup(optarg);
                break;
            case 'h':
                about();
                exit(EXIT_SUCCESS);
                break;
            case 'v':
                about();
                exit(EXIT_SUCCESS);
            default:
                fprintf(stderr, "\n");
                about();
                exit(EXIT_SUCCESS);
        }
    }

    if(command == NULL)
        command = strdup(SHELL);

    if(optind < argc) {
        user = atoi( argv[optind++] );
    }

    // Let's get the group ID as well.
    struct passwd* tempPwdPtr;
#if 0
    struct passwd theentry;
    char* buf = malloc(sysconf(_SC_GETGR_R_SIZE_MAX));
    if(getpwuid_r(user, &theentry, buf, sysconf(_SC_GETGR_R_SIZE_MAX), &tempPwdPtr) == 0) {
        group = theentry.pw_gid;
        free(buf);
    }
#else
    if((tempPwdPtr = getpwuid(user)) != NULL) {
        group = tempPwdPtr->pw_gid;
    }
#endif

    //printf("Command: %s, User to run as: %i, GID = %i\n",command,user,group);
    setgid(group);
    setuid(user);
    system(command);

    free(command);
    return 0;
}

If you found this article helpful or interesting, please help Compdigitec spread the word. Don’t forget to subscribe to Compdigitec Labs for more useful and interesting articles!

Topics: Linux | 1 Comment »

One Response to “A simple su implementation in C”

  1. Exploring and rooting the iPPea TV at Compdigitec Labs Says:
    November 24th, 2012 at 10:22 pm

    [...] A simple su implementation in C | [...]

Comments