Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/coreutils/id.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/coreutils/id.c

    r1765 r2725  
    44 *
    55 * Copyright (C) 2000 by Randolph Chung <tausq@debian.org>
     6 * Copyright (C) 2008 by Tito Ragusa <farmatito@tiscali.it>
    67 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    89 */
    910
    10 /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
    11 /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
    12  * be more similar to GNU id.
     11/* BB_AUDIT SUSv3 compliant. */
     12/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever
     13 * length and to be more similar to GNU id.
    1314 * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
     15 * Added -G option Tito Ragusa (C) 2008 for SUSv3.
    1416 */
    1517
    1618#include "libbb.h"
    1719
    18 #define PRINT_REAL        1
    19 #define NAME_NOT_NUMBER   2
    20 #define JUST_USER         4
    21 #define JUST_GROUP        8
    22 #if ENABLE_SELINUX
    23 #define JUST_CONTEXT     16
    24 #endif
    25 
    26 static int printf_full(unsigned int id, const char *arg, const char prefix)
    27 {
    28     const char *fmt = "%cid=%u";
    29     int status = EXIT_FAILURE;
    30 
    31     if (arg) {
    32         fmt = "%cid=%u(%s)";
    33         status = EXIT_SUCCESS;
    34     }
    35     printf(fmt, prefix, id, arg);
    36     return status;
    37 }
    38 
    39 int id_main(int argc, char **argv);
    40 int id_main(int argc, char **argv)
    41 {
    42     struct passwd *p;
    43     uid_t uid;
    44     gid_t gid;
    45     unsigned long flags;
    46     short status;
    47 #if ENABLE_SELINUX
    48     security_context_t scontext;
    49 #endif
    50     /* Don't allow -n -r -nr -ug -rug -nug -rnug */
     20/* This is a NOEXEC applet. Be very careful! */
     21
     22#if !ENABLE_USE_BB_PWD_GRP
     23#if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0)
     24#if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 &&  __UCLIBC_SUBLEVEL__ < 30)
     25#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build"
     26#endif
     27#endif
     28#endif
     29
     30enum {
     31    PRINT_REAL      = (1 << 0),
     32    NAME_NOT_NUMBER = (1 << 1),
     33    JUST_USER       = (1 << 2),
     34    JUST_GROUP      = (1 << 3),
     35    JUST_ALL_GROUPS = (1 << 4),
     36#if ENABLE_SELINUX
     37    JUST_CONTEXT    = (1 << 5),
     38#endif
     39};
     40
     41static int print_common(unsigned id, const char *name, const char *prefix)
     42{
     43    if (prefix) {
     44        printf("%s", prefix);
     45    }
     46    if (!(option_mask32 & NAME_NOT_NUMBER) || !name) {
     47        printf("%u", id);
     48    }
     49    if (!option_mask32 || (option_mask32 & NAME_NOT_NUMBER)) {
     50        if (name) {
     51            printf(option_mask32 ? "%s" : "(%s)", name);
     52        } else {
     53            /* Don't set error status flag in default mode */
     54            if (option_mask32) {
     55                if (ENABLE_DESKTOP)
     56                    bb_error_msg("unknown ID %u", id);
     57                return EXIT_FAILURE;
     58            }
     59        }
     60    }
     61    return EXIT_SUCCESS;
     62}
     63
     64static int print_group(gid_t id, const char *prefix)
     65{
     66    return print_common(id, gid2group(id), prefix);
     67}
     68
     69static int print_user(uid_t id, const char *prefix)
     70{
     71    return print_common(id, uid2uname(id), prefix);
     72}
     73
     74/* On error set *n < 0 and return >= 0
     75 * If *n is too small, update it and return < 0
     76 *  (ok to trash groups[] in both cases)
     77 * Otherwise fill in groups[] and return >= 0
     78 */
     79static int get_groups(const char *username, gid_t rgid, gid_t *groups, int *n)
     80{
     81    int m;
     82
     83    if (username) {
     84        /* If the user is a member of more than
     85         * *n groups, then -1 is returned. Otherwise >= 0.
     86         * (and no defined way of detecting errors?!) */
     87        m = getgrouplist(username, rgid, groups, n);
     88        /* I guess *n < 0 might indicate error. Anyway,
     89         * malloc'ing -1 bytes won't be good, so: */
     90        //if (*n < 0)
     91        //  return 0;
     92        //return m;
     93        //commented out here, happens below anyway
     94    } else {
     95        /* On error -1 is returned, which ends up in *n */
     96        int nn = getgroups(*n, groups);
     97        /* 0: nn <= *n, groups[] was big enough; -1 otherwise */
     98        m = - (nn > *n);
     99        *n = nn;
     100    }
     101    if (*n < 0)
     102        return 0; /* error, don't return < 0! */
     103    return m;
     104}
     105
     106int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     107int id_main(int argc UNUSED_PARAM, char **argv)
     108{
     109    uid_t ruid;
     110    gid_t rgid;
     111    uid_t euid;
     112    gid_t egid;
     113    unsigned opt;
     114    int i;
     115    int status = EXIT_SUCCESS;
     116    const char *prefix;
     117    const char *username;
     118#if ENABLE_SELINUX
     119    security_context_t scontext = NULL;
     120#endif
     121    /* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/
    51122    /* Don't allow more than one username */
    52     opt_complementary = "?1:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
    53     flags = getopt32(argv, "rnug" USE_SELINUX("Z"));
    54 
    55     /* This values could be overwritten later */
    56     uid = geteuid();
    57     gid = getegid();
    58     if (flags & PRINT_REAL) {
    59         uid = getuid();
    60         gid = getgid();
    61     }
    62 
    63     if (argv[optind]) {
    64         p = getpwnam(argv[optind]);
    65         /* xuname2uid is needed because it exits on failure */
    66         uid = xuname2uid(argv[optind]);
    67         gid = p->pw_gid;
    68         /* in this case PRINT_REAL is the same */
    69     }
    70 
    71     if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
    72         /* JUST_GROUP and JUST_USER are mutually exclusive */
    73         if (flags & NAME_NOT_NUMBER) {
    74             /* bb_getXXXid(-1) exit on failure, puts cannot segfault */
    75             puts((flags & JUST_USER) ? bb_getpwuid(NULL, -1, uid) : bb_getgrgid(NULL, -1, gid));
     123    opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG"
     124             IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G");
     125    opt = getopt32(argv, "rnugG" IF_SELINUX("Z"));
     126
     127    username = argv[optind];
     128    if (username) {
     129        struct passwd *p = xgetpwnam(username);
     130        euid = ruid = p->pw_uid;
     131        egid = rgid = p->pw_gid;
     132    } else {
     133        egid = getegid();
     134        rgid = getgid();
     135        euid = geteuid();
     136        ruid = getuid();
     137    }
     138    /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */
     139    /* id says: print the real ID instead of the effective ID, with -ugG */
     140    /* in fact in this case egid is always printed if egid != rgid */
     141    if (!opt || (opt & JUST_ALL_GROUPS)) {
     142        gid_t *groups;
     143        int n;
     144
     145        if (!opt) {
     146            /* Default Mode */
     147            status |= print_user(ruid, "uid=");
     148            status |= print_group(rgid, " gid=");
     149            if (euid != ruid)
     150                status |= print_user(euid, " euid=");
     151            if (egid != rgid)
     152                status |= print_group(egid, " egid=");
    76153        } else {
    77             if (flags & JUST_USER) {
    78                 printf("%u\n", uid);
     154            /* JUST_ALL_GROUPS */
     155            status |= print_group(rgid, NULL);
     156            if (egid != rgid)
     157                status |= print_group(egid, " ");
     158        }
     159        /* We are supplying largish buffer, trying
     160         * to not run get_groups() twice. That might be slow
     161         * ("user database in remote SQL server" case) */
     162        groups = xmalloc(64 * sizeof(gid_t));
     163        n = 64;
     164        if (get_groups(username, rgid, groups, &n) < 0) {
     165            /* Need bigger buffer after all */
     166            groups = xrealloc(groups, n * sizeof(gid_t));
     167            get_groups(username, rgid, groups, &n);
     168        }
     169        if (n > 0) {
     170            /* Print the list */
     171            prefix = " groups=";
     172            for (i = 0; i < n; i++) {
     173                if (opt && (groups[i] == rgid || groups[i] == egid))
     174                    continue;
     175                status |= print_group(groups[i], opt ? " " : prefix);
     176                prefix = ",";
    79177            }
    80             if (flags & JUST_GROUP) {
    81                 printf("%u\n", gid);
    82             }
    83         }
    84 
    85 #if ENABLE_SELINUX
    86         if (flags & JUST_CONTEXT) {
    87             selinux_or_die();
    88             if (argc - optind == 1) {
    89                 bb_error_msg_and_die("user name can't be passed with -Z");
    90             }
    91 
    92             if (getcon(&scontext)) {
    93                 bb_error_msg_and_die("can't get process context");
    94             }
    95             printf("%s\n", scontext);
    96         }
    97 #endif
    98         /* exit */
    99         fflush_stdout_and_exit(EXIT_SUCCESS);
    100     }
    101 
    102     /* Print full info like GNU id */
    103     /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
    104     status = printf_full(uid, bb_getpwuid(NULL, 0, uid), 'u');
    105     putchar(' ');
    106     status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), 'g');
    107 
    108 #if ENABLE_SELINUX
    109     if (is_selinux_enabled()) {
    110         security_context_t mysid;
    111         const char *context;
    112 
    113         context = "unknown";
    114         getcon(&mysid);
    115         if (mysid) {
    116             context = alloca(strlen(mysid) + 1);
    117             strcpy((char*)context, mysid);
    118             freecon(mysid);
    119         }
    120         printf(" context=%s", context);
    121     }
    122 #endif
    123 
    124     putchar('\n');
     178        } else if (n < 0) { /* error in get_groups() */
     179            if (!ENABLE_DESKTOP)
     180                bb_error_msg_and_die("can't get groups");
     181            else
     182                return EXIT_FAILURE;
     183        }
     184        if (ENABLE_FEATURE_CLEAN_UP)
     185            free(groups);
     186#if ENABLE_SELINUX
     187        if (is_selinux_enabled()) {
     188            if (getcon(&scontext) == 0)
     189                printf(" context=%s", scontext);
     190        }
     191#endif
     192    } else if (opt & PRINT_REAL) {
     193        euid = ruid;
     194        egid = rgid;
     195    }
     196
     197    if (opt & JUST_USER)
     198        status |= print_user(euid, NULL);
     199    else if (opt & JUST_GROUP)
     200        status |= print_group(egid, NULL);
     201#if ENABLE_SELINUX
     202    else if (opt & JUST_CONTEXT) {
     203        selinux_or_die();
     204        if (username || getcon(&scontext)) {
     205            bb_error_msg_and_die("can't get process context%s",
     206                username ? " for a different user" : "");
     207        }
     208        fputs(scontext, stdout);
     209    }
     210    /* freecon(NULL) seems to be harmless */
     211    if (ENABLE_FEATURE_CLEAN_UP)
     212        freecon(scontext);
     213#endif
     214    bb_putchar('\n');
    125215    fflush_stdout_and_exit(status);
    126216}
Note: See TracChangeset for help on using the changeset viewer.