3
0

chcon.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * chcon -- change security context, based on coreutils-5.97-13
  3. *
  4. * Port to busybox: KaiGai Kohei <kaigai@kaigai.gr.jp>
  5. *
  6. * Copyright (C) 2006 - 2007 KaiGai Kohei <kaigai@kaigai.gr.jp>
  7. *
  8. * Licensed under GPLv2, see file LICENSE in this tarball for details.
  9. */
  10. #include <getopt.h>
  11. #include <selinux/context.h>
  12. #include "libbb.h"
  13. #define OPT_RECURSIVE (1<<0) /* 'R' */
  14. #define OPT_CHANHES (1<<1) /* 'c' */
  15. #define OPT_NODEREFERENCE (1<<2) /* 'h' */
  16. #define OPT_QUIET (1<<3) /* 'f' */
  17. #define OPT_USER (1<<4) /* 'u' */
  18. #define OPT_ROLE (1<<5) /* 'r' */
  19. #define OPT_TYPE (1<<6) /* 't' */
  20. #define OPT_RANGE (1<<7) /* 'l' */
  21. #define OPT_VERBOSE (1<<8) /* 'v' */
  22. #define OPT_REFERENCE ((1<<9) * ENABLE_FEATURE_CHCON_LONG_OPTIONS)
  23. #define OPT_COMPONENT_SPECIFIED (OPT_USER | OPT_ROLE | OPT_TYPE | OPT_RANGE)
  24. static char *user = NULL;
  25. static char *role = NULL;
  26. static char *type = NULL;
  27. static char *range = NULL;
  28. static char *specified_context = NULL;
  29. static int FAST_FUNC change_filedir_context(
  30. const char *fname,
  31. struct stat *stbuf UNUSED_PARAM,
  32. void *userData UNUSED_PARAM,
  33. int depth UNUSED_PARAM)
  34. {
  35. context_t context = NULL;
  36. security_context_t file_context = NULL;
  37. security_context_t context_string;
  38. int rc = FALSE;
  39. int status = 0;
  40. if (option_mask32 & OPT_NODEREFERENCE) {
  41. status = lgetfilecon(fname, &file_context);
  42. } else {
  43. status = getfilecon(fname, &file_context);
  44. }
  45. if (status < 0 && errno != ENODATA) {
  46. if ((option_mask32 & OPT_QUIET) == 0)
  47. bb_error_msg("can't obtain security context: %s", fname);
  48. goto skip;
  49. }
  50. if (file_context == NULL && specified_context == NULL) {
  51. bb_error_msg("can't apply partial context to unlabeled file %s", fname);
  52. goto skip;
  53. }
  54. if (specified_context == NULL) {
  55. context = set_security_context_component(file_context,
  56. user, role, type, range);
  57. if (!context) {
  58. bb_error_msg("can't compute security context from %s", file_context);
  59. goto skip;
  60. }
  61. } else {
  62. context = context_new(specified_context);
  63. if (!context) {
  64. bb_error_msg("invalid context: %s", specified_context);
  65. goto skip;
  66. }
  67. }
  68. context_string = context_str(context);
  69. if (!context_string) {
  70. bb_error_msg("can't obtain security context in text expression");
  71. goto skip;
  72. }
  73. if (file_context == NULL || strcmp(context_string, file_context) != 0) {
  74. int fail;
  75. if (option_mask32 & OPT_NODEREFERENCE) {
  76. fail = lsetfilecon(fname, context_string);
  77. } else {
  78. fail = setfilecon(fname, context_string);
  79. }
  80. if ((option_mask32 & OPT_VERBOSE) || ((option_mask32 & OPT_CHANHES) && !fail)) {
  81. printf(!fail
  82. ? "context of %s changed to %s\n"
  83. : "failed to change context of %s to %s\n",
  84. fname, context_string);
  85. }
  86. if (!fail) {
  87. rc = TRUE;
  88. } else if ((option_mask32 & OPT_QUIET) == 0) {
  89. bb_error_msg("failed to change context of %s to %s",
  90. fname, context_string);
  91. }
  92. } else if (option_mask32 & OPT_VERBOSE) {
  93. printf("context of %s retained as %s\n", fname, context_string);
  94. rc = TRUE;
  95. }
  96. skip:
  97. context_free(context);
  98. freecon(file_context);
  99. return rc;
  100. }
  101. #if ENABLE_FEATURE_CHCON_LONG_OPTIONS
  102. static const char chcon_longopts[] ALIGN1 =
  103. "recursive\0" No_argument "R"
  104. "changes\0" No_argument "c"
  105. "no-dereference\0" No_argument "h"
  106. "silent\0" No_argument "f"
  107. "quiet\0" No_argument "f"
  108. "user\0" Required_argument "u"
  109. "role\0" Required_argument "r"
  110. "type\0" Required_argument "t"
  111. "range\0" Required_argument "l"
  112. "verbose\0" No_argument "v"
  113. "reference\0" Required_argument "\xff" /* no short option */
  114. ;
  115. #endif
  116. int chcon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  117. int chcon_main(int argc UNUSED_PARAM, char **argv)
  118. {
  119. char *reference_file;
  120. char *fname;
  121. int i, errors = 0;
  122. #if ENABLE_FEATURE_CHCON_LONG_OPTIONS
  123. applet_long_options = chcon_longopts;
  124. #endif
  125. opt_complementary = "-1" /* at least 1 param */
  126. ":?" /* error if exclusivity constraints are violated */
  127. #if ENABLE_FEATURE_CHCON_LONG_OPTIONS
  128. ":\xff--urtl:u--\xff:r--\xff:t--\xff:l--\xff"
  129. #endif
  130. ":f--v:v--f"; /* 'verbose' and 'quiet' are exclusive */
  131. getopt32(argv, "Rchfu:r:t:l:v",
  132. &user, &role, &type, &range, &reference_file);
  133. argv += optind;
  134. #if ENABLE_FEATURE_CHCON_LONG_OPTIONS
  135. if (option_mask32 & OPT_REFERENCE) {
  136. /* FIXME: lgetfilecon() should be used when '-h' is specified.
  137. But current implementation follows the original one. */
  138. if (getfilecon(reference_file, &specified_context) < 0)
  139. bb_perror_msg_and_die("getfilecon('%s') failed", reference_file);
  140. } else
  141. #endif
  142. if ((option_mask32 & OPT_COMPONENT_SPECIFIED) == 0) {
  143. specified_context = *argv++;
  144. /* specified_context is never NULL -
  145. * "-1" in opt_complementary prevents this. */
  146. if (!argv[0])
  147. bb_error_msg_and_die("too few arguments");
  148. }
  149. for (i = 0; (fname = argv[i]) != NULL; i++) {
  150. int fname_len = strlen(fname);
  151. while (fname_len > 1 && fname[fname_len - 1] == '/')
  152. fname_len--;
  153. fname[fname_len] = '\0';
  154. if (recursive_action(fname,
  155. 1<<option_mask32 & OPT_RECURSIVE,
  156. change_filedir_context,
  157. change_filedir_context,
  158. NULL, 0) != TRUE)
  159. errors = 1;
  160. }
  161. return errors;
  162. }