Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 1 | #include <unistd.h> |
| 2 | #include <sys/types.h> |
| 3 | #include <fcntl.h> |
| 4 | #include <stdio.h> |
| 5 | #include <stdlib.h> |
| 6 | #include <errno.h> |
| 7 | #include <string.h> |
| 8 | #include <ctype.h> |
| 9 | #include <selinux/selinux.h> |
| 10 | #include <selinux/get_context_list.h> |
| 11 | |
William Roberts | e4f2bcc | 2016-11-01 14:23:10 -0700 | [diff] [blame] | 12 | static __attribute__ ((__noreturn__)) void usage(const char *name, const char *detail, int rc) |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 13 | { |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 14 | fprintf(stderr, "usage: %s [-l level] [-s service] user [fromcon]\n", name); |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 15 | if (detail) |
| 16 | fprintf(stderr, "%s: %s\n", name, detail); |
| 17 | exit(rc); |
| 18 | } |
| 19 | |
| 20 | int main(int argc, char **argv) |
| 21 | { |
Stephen Smalley | 9eb9c93 | 2014-02-19 09:16:17 -0500 | [diff] [blame] | 22 | char * usercon = NULL, *cur_context = NULL; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 23 | char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 24 | char *service = NULL; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 25 | int ret, opt; |
Daniel J Walsh | 20eff2b | 2009-05-14 15:43:18 -0400 | [diff] [blame] | 26 | int verbose = 0; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 27 | |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 28 | while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) { |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 29 | switch (opt) { |
| 30 | case 'l': |
| 31 | level = strdup(optarg); |
| 32 | break; |
| 33 | case 'r': |
| 34 | role = strdup(optarg); |
| 35 | break; |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 36 | case 's': |
| 37 | service = strdup(optarg); |
| 38 | break; |
Daniel J Walsh | 20eff2b | 2009-05-14 15:43:18 -0400 | [diff] [blame] | 39 | case 'v': |
| 40 | verbose = 1; |
| 41 | break; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 42 | default: |
| 43 | usage(argv[0], "invalid option", 1); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | if (((argc - optind) < 1) || ((argc - optind) > 2)) |
| 48 | usage(argv[0], "invalid number of arguments", 2); |
| 49 | |
| 50 | /* If selinux isn't available, bail out. */ |
| 51 | if (!is_selinux_enabled()) { |
| 52 | fprintf(stderr, |
| 53 | "%s may be used only on a SELinux kernel.\n", argv[0]); |
| 54 | return 1; |
| 55 | } |
| 56 | |
| 57 | user = argv[optind]; |
| 58 | |
| 59 | /* If a context wasn't passed, use the current context. */ |
| 60 | if (((argc - optind) < 2)) { |
| 61 | if (getcon(&cur_context) < 0) { |
| 62 | fprintf(stderr, "Couldn't get current context.\n"); |
| 63 | return 2; |
| 64 | } |
| 65 | } else |
| 66 | cur_context = argv[optind + 1]; |
| 67 | |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 68 | if ((ret = getseuser(user, service, &seuser, &dlevel)) == 0) { |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 69 | if (! level) level=dlevel; |
| 70 | if (role != NULL && role[0]) |
| 71 | ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon); |
| 72 | else |
| 73 | ret=get_default_context_with_level(seuser, level, cur_context,&usercon); |
| 74 | } |
| 75 | if (ret < 0) |
| 76 | perror(argv[0]); |
Daniel J Walsh | 20eff2b | 2009-05-14 15:43:18 -0400 | [diff] [blame] | 77 | else { |
| 78 | if (verbose) { |
| 79 | printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); |
| 80 | } else { |
Eric Paris | 056f23c | 2012-06-21 15:44:45 -0400 | [diff] [blame] | 81 | printf("%s\n", usercon); |
Daniel J Walsh | 20eff2b | 2009-05-14 15:43:18 -0400 | [diff] [blame] | 82 | } |
| 83 | } |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 84 | |
| 85 | free(role); |
| 86 | free(seuser); |
| 87 | if (level != dlevel) free(level); |
| 88 | free(dlevel); |
| 89 | free(usercon); |
| 90 | |
Daniel J Walsh | 20eff2b | 2009-05-14 15:43:18 -0400 | [diff] [blame] | 91 | return ret >= 0; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 92 | } |