/* * Copyright (c) 1997,2007 Andrew G. Morgan * * This sets the capabilities of a given file. */ #include #include #include #include #include #include static void usage(void) { fprintf(stderr, "usage: setcap [-q] (-r|-|) " "[ ... (-r|-|) ]\n" "\n" " Note must be a regular (non-symlink) file.\n" ); exit(1); } #define MAXCAP 2048 static int read_caps(int quiet, const char *filename, char *buffer) { int i=MAXCAP; if (!quiet) { fprintf(stderr, "Please enter caps for file [empty line to end]:\n"); } while (i > 0) { int j = read(STDIN_FILENO, buffer, i); if (j < 0) { fprintf(stderr, "\n[Error - aborting]\n"); exit(1); } if (j==0 || buffer[0] == '\n') { /* we're done */ break; } /* move on... */ i -= j; buffer += j; } /* terminate */ buffer[0] = '\0'; return (i < MAXCAP ? 0:-1); } int main(int argc, char **argv) { char buffer[MAXCAP+1]; int retval, quiet=0; cap_t mycaps; cap_value_t capflag; if (argc < 3) { usage(); } mycaps = cap_get_proc(); if (mycaps == NULL) { fprintf(stderr, "warning - unable to get process capabilities" " (old libcap?)\n"); } else { capflag = CAP_SETFCAP; /* * Raise the effective CAP_SETPCAP. */ if (cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag, CAP_SET) != 0) { perror("unable to manipulate CAP_SETFCAP - try a newer libcap?"); exit(1); } if (cap_set_proc(mycaps) != 0) { perror("unable to set CAP_SETFCAP effective capability"); exit(1); } } while (--argc > 0) { const char *text; cap_t cap_d; if (!strcmp(*++argv,"-q")) { quiet = 1; continue; } if (!strcmp(*argv,"-r")) { cap_d = NULL; } else { if (!strcmp(*argv,"-")) { retval = read_caps(quiet, *argv, buffer); if (retval) usage(); text = buffer; } else { text = *argv; } cap_d = cap_from_text(text); if (cap_d == NULL) { perror("fatal error"); usage(); } #ifdef DEBUG { ssize_t length; const char *result; result = cap_to_text(cap_d, &length); fprintf(stderr, "caps set to: [%s]\n", result); } #endif } if (--argc <= 0) usage(); /* * Set the filesystem capability for this file. */ retval = cap_set_file(*++argv, cap_d); if (retval != 0) { fprintf(stderr, "Failed to set capabilities on file `%s' (%s)\n", argv[0], strerror(errno)); usage(); } if (cap_d) { cap_free(cap_d); } } return 0; }