summaryrefslogtreecommitdiffstats
path: root/usr.sbin/setfmac/setfmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/setfmac/setfmac.c')
-rw-r--r--usr.sbin/setfmac/setfmac.c498
1 files changed, 0 insertions, 498 deletions
diff --git a/usr.sbin/setfmac/setfmac.c b/usr.sbin/setfmac/setfmac.c
deleted file mode 100644
index e3da25d..0000000
--- a/usr.sbin/setfmac/setfmac.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*-
- * Copyright (c) 2002, 2004 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by NAI Labs, the
- * Security Research Division of Network Associates, Inc. under
- * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
- * CHATS research program.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/types.h>
-#include <sys/mac.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fts.h>
-#include <libgen.h>
-#include <regex.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-struct label_spec {
- struct label_spec_entry {
- regex_t regex; /* compiled regular expression to match */
- char *regexstr; /* uncompiled regular expression */
- mode_t mode; /* mode to possibly match */
- const char *modestr; /* print-worthy ",-?" mode string */
- char *mactext; /* MAC label to apply */
- int flags; /* miscellaneous flags */
-#define F_DONTLABEL 0x01
-#define F_ALWAYSMATCH 0x02
- } *entries, /* entries[0..nentries] */
- *match; /* cached decision for MAC label to apply */
- size_t nentries; /* size of entries list */
- STAILQ_ENTRY(label_spec) link;
-};
-
-struct label_specs {
- STAILQ_HEAD(label_specs_head, label_spec) head;
-};
-
-void usage(int) __dead2;
-struct label_specs *new_specs(void);
-void add_specs(struct label_specs *, const char *, int);
-void add_setfmac_specs(struct label_specs *, char *);
-void add_spec_line(const char *, int, struct label_spec_entry *, char *);
-int apply_specs(struct label_specs *, FTSENT *, int, int);
-int specs_empty(struct label_specs *);
-
-static int qflag;
-
-int
-main(int argc, char **argv)
-{
- FTSENT *ftsent;
- FTS *fts;
- struct label_specs *specs;
- int eflag = 0, xflag = 0, vflag = 0, Rflag = 0, hflag;
- int ch, is_setfmac;
- char *bn;
-
- bn = basename(argv[0]);
- if (bn == NULL)
- err(1, "basename");
- is_setfmac = strcmp(bn, "setfmac") == 0;
- hflag = is_setfmac ? FTS_LOGICAL : FTS_PHYSICAL;
- specs = new_specs();
- while ((ch = getopt(argc, argv, is_setfmac ? "Rhq" : "ef:qs:vx")) !=
- -1) {
- switch (ch) {
- case 'R':
- Rflag = 1;
- break;
- case 'e':
- eflag = 1;
- break;
- case 'f':
- add_specs(specs, optarg, 0);
- break;
- case 'h':
- hflag = FTS_PHYSICAL;
- break;
- case 'q':
- qflag = 1;
- break;
- case 's':
- add_specs(specs, optarg, 1);
- break;
- case 'v':
- vflag++;
- break;
- case 'x':
- xflag = FTS_XDEV;
- break;
- default:
- usage(is_setfmac);
- }
- }
- argc -= optind;
- argv += optind;
-
- if (is_setfmac) {
- if (argc <= 1)
- usage(is_setfmac);
- add_setfmac_specs(specs, *argv);
- argc--;
- argv++;
- } else {
- if (argc == 0 || specs_empty(specs))
- usage(is_setfmac);
- }
- fts = fts_open(argv, hflag | xflag, NULL);
- if (fts == NULL)
- err(1, "cannot traverse filesystem%s", argc ? "s" : "");
- while ((ftsent = fts_read(fts)) != NULL) {
- switch (ftsent->fts_info) {
- case FTS_DP: /* skip post-order */
- break;
- case FTS_D: /* do pre-order */
- case FTS_DC: /* do cyclic? */
- /* don't ever recurse directories as setfmac(8) */
- if (is_setfmac && !Rflag)
- fts_set(fts, ftsent, FTS_SKIP);
- case FTS_DEFAULT: /* do default */
- case FTS_F: /* do regular */
- case FTS_SL: /* do symlink */
- case FTS_SLNONE: /* do symlink */
- case FTS_W: /* do whiteout */
- if (apply_specs(specs, ftsent, hflag, vflag)) {
- if (eflag) {
- errx(1, "labeling not supported in %s",
- ftsent->fts_path);
- }
- if (!qflag)
- warnx("labeling not supported in %s",
- ftsent->fts_path);
- fts_set(fts, ftsent, FTS_SKIP);
- }
- break;
- case FTS_DNR: /* die on all errors */
- case FTS_ERR:
- case FTS_NS:
- err(1, "traversing %s", ftsent->fts_path);
- default:
- errx(1, "CANNOT HAPPEN (%d) traversing %s",
- ftsent->fts_info, ftsent->fts_path);
- }
- }
- fts_close(fts);
- exit(0);
-}
-
-void
-usage(int is_setfmac)
-{
-
- if (is_setfmac)
- fprintf(stderr, "usage: setfmac [-Rhq] label file ...\n");
- else
- fprintf(stderr, "usage: setfsmac [-ehqvx] [-f specfile [...]] [-s specfile [...]] file ...\n");
- exit(1);
-}
-
-static int
-chomp_line(char **line, size_t *linesize)
-{
- char *s;
- int freeme = 0;
-
- for (s = *line; (unsigned)(s - *line) < *linesize; s++) {
- if (!isspace(*s))
- break;
- }
- if (*s == '#') {
- **line = '\0';
- *linesize = 0;
- return (freeme);
- }
- memmove(*line, s, *linesize - (s - *line));
- *linesize -= s - *line;
- for (s = &(*line)[*linesize - 1]; s >= *line; s--) {
- if (!isspace(*s))
- break;
- }
- if (s != &(*line)[*linesize - 1]) {
- *linesize = s - *line + 1;
- } else {
- s = malloc(*linesize + 1);
- if (s == NULL)
- err(1, "malloc");
- strncpy(s, *line, *linesize);
- *line = s;
- freeme = 1;
- }
- (*line)[*linesize] = '\0';
- return (freeme);
-}
-
-void
-add_specs(struct label_specs *specs, const char *file, int is_sebsd)
-{
- struct label_spec *spec;
- FILE *fp;
- char *line;
- size_t nlines = 0, linesize;
- int freeline;
-
- spec = malloc(sizeof(*spec));
- if (spec == NULL)
- err(1, "malloc");
- fp = fopen(file, "r");
- if (fp == NULL)
- err(1, "opening %s", file);
- while ((line = fgetln(fp, &linesize)) != NULL) {
- freeline = chomp_line(&line, &linesize);
- if (linesize > 0) /* only allocate space for non-comments */
- nlines++;
- if (freeline)
- free(line);
- }
- if (ferror(fp))
- err(1, "fgetln on %s", file);
- rewind(fp);
- spec->entries = calloc(nlines, sizeof(*spec->entries));
- if (spec->entries == NULL)
- err(1, "malloc");
- spec->nentries = nlines;
- while (nlines > 0) {
- line = fgetln(fp, &linesize);
- if (line == NULL) {
- if (feof(fp))
- errx(1, "%s ended prematurely", file);
- else
- err(1, "failure reading %s", file);
- }
- freeline = chomp_line(&line, &linesize);
- if (linesize == 0) {
- if (freeline)
- free(line);
- continue;
- }
- add_spec_line(file, is_sebsd, &spec->entries[--nlines], line);
- if (freeline)
- free(line);
- }
- fclose(fp);
- if (!qflag)
- warnx("%s: read %lu specifications", file,
- (long)spec->nentries);
- STAILQ_INSERT_TAIL(&specs->head, spec, link);
-}
-
-void
-add_setfmac_specs(struct label_specs *specs, char *label)
-{
- struct label_spec *spec;
-
- spec = malloc(sizeof(*spec));
- if (spec == NULL)
- err(1, "malloc");
- spec->nentries = 1;
- spec->entries = calloc(spec->nentries, sizeof(*spec->entries));
- if (spec->entries == NULL)
- err(1, "malloc");
- /* The _only_ thing specified here is the mactext! */
- spec->entries->mactext = label;
- spec->entries->flags |= F_ALWAYSMATCH;
- STAILQ_INSERT_TAIL(&specs->head, spec, link);
-}
-
-void
-add_spec_line(const char *file, int is_sebsd, struct label_spec_entry *entry,
- char *line)
-{
- char *regexstr, *modestr, *macstr, *regerrorstr;
- size_t size;
- int error;
-
- regexstr = strtok(line, " \t");
- if (regexstr == NULL)
- errx(1, "%s: need regular expression", file);
- modestr = strtok(NULL, " \t");
- if (modestr == NULL)
- errx(1, "%s: need a label", file);
- macstr = strtok(NULL, " \t");
- if (macstr == NULL) { /* the mode is just optional */
- macstr = modestr;
- modestr = NULL;
- }
- if (strtok(NULL, " \t") != NULL)
- errx(1, "%s: extraneous fields at end of line", file);
- /* assume we need to anchor this regex */
- if (asprintf(&regexstr, "^%s$", regexstr) == -1)
- err(1, "%s: processing regular expression", file);
- entry->regexstr = regexstr;
- error = regcomp(&entry->regex, regexstr, REG_EXTENDED | REG_NOSUB);
- if (error) {
- size = regerror(error, &entry->regex, NULL, 0);
- regerrorstr = malloc(size);
- if (regerrorstr == NULL)
- err(1, "malloc");
- (void)regerror(error, &entry->regex, regerrorstr, size);
- errx(1, "%s: %s: %s", file, entry->regexstr, regerrorstr);
- }
- if (!is_sebsd) {
- entry->mactext = strdup(macstr);
- if (entry->mactext == NULL)
- err(1, "strdup");
- } else {
- if (asprintf(&entry->mactext, "sebsd/%s", macstr) == -1)
- err(1, "asprintf");
- if (strcmp(macstr, "<<none>>") == 0)
- entry->flags |= F_DONTLABEL;
- }
- if (modestr != NULL) {
- if (strlen(modestr) != 2 || modestr[0] != '-')
- errx(1, "%s: invalid mode string: %s", file, modestr);
- switch (modestr[1]) {
- case 'b':
- entry->mode = S_IFBLK;
- entry->modestr = ",-b";
- break;
- case 'c':
- entry->mode = S_IFCHR;
- entry->modestr = ",-c";
- break;
- case 'd':
- entry->mode = S_IFDIR;
- entry->modestr = ",-d";
- break;
- case 'p':
- entry->mode = S_IFIFO;
- entry->modestr = ",-p";
- break;
- case 'l':
- entry->mode = S_IFLNK;
- entry->modestr = ",-l";
- break;
- case 's':
- entry->mode = S_IFSOCK;
- entry->modestr = ",-s";
- break;
- case '-':
- entry->mode = S_IFREG;
- entry->modestr = ",--";
- break;
- default:
- errx(1, "%s: invalid mode string: %s", file, modestr);
- }
- } else {
- entry->modestr = "";
- }
-}
-
-int
-specs_empty(struct label_specs *specs)
-{
-
- return (STAILQ_EMPTY(&specs->head));
-}
-
-int
-apply_specs(struct label_specs *specs, FTSENT *ftsent, int hflag, int vflag)
-{
- regmatch_t pmatch;
- struct label_spec *ls;
- struct label_spec_entry *ent;
- char *regerrorstr, *macstr;
- size_t size;
- mac_t mac;
- int error, matchedby;
-
- /*
- * Work through file context sources in order of specification
- * on the command line, and through their entries in reverse
- * order to find the "last" (hopefully "best") match.
- */
- matchedby = 0;
- STAILQ_FOREACH(ls, &specs->head, link) {
- for (ls->match = NULL, ent = ls->entries;
- ent < &ls->entries[ls->nentries]; ent++) {
- if (ent->flags & F_ALWAYSMATCH)
- goto matched;
- if (ent->mode != 0 &&
- (ftsent->fts_statp->st_mode & S_IFMT) != ent->mode)
- continue;
- pmatch.rm_so = 0;
- pmatch.rm_eo = ftsent->fts_pathlen;
- error = regexec(&ent->regex, ftsent->fts_path, 1,
- &pmatch, REG_STARTEND);
- switch (error) {
- case REG_NOMATCH:
- continue;
- case 0:
- break;
- default:
- size = regerror(error, &ent->regex, NULL, 0);
- regerrorstr = malloc(size);
- if (regerrorstr == NULL)
- err(1, "malloc");
- (void)regerror(error, &ent->regex, regerrorstr,
- size);
- errx(1, "%s: %s", ent->regexstr, regerrorstr);
- }
- matched:
- ls->match = ent;
- if (vflag) {
- if (matchedby == 0) {
- printf("%s matched by ",
- ftsent->fts_path);
- matchedby = 1;
- }
- printf("%s(%s%s,%s)", matchedby == 2 ? "," : "",
- ent->regexstr, ent->modestr, ent->mactext);
- if (matchedby == 1)
- matchedby = 2;
- }
- break;
- }
- }
- if (vflag && matchedby)
- printf("\n");
- size = 0;
- STAILQ_FOREACH(ls, &specs->head, link) {
- /* cached match decision */
- if (ls->match && (ls->match->flags & F_DONTLABEL) == 0)
- /* add length of "x\0"/"y," */
- size += strlen(ls->match->mactext) + 1;
- }
- if (size == 0)
- return (0);
- macstr = malloc(size);
- if (macstr == NULL)
- err(1, "malloc");
- *macstr = '\0';
- STAILQ_FOREACH(ls, &specs->head, link) {
- /* cached match decision */
- if (ls->match && (ls->match->flags & F_DONTLABEL) == 0) {
- if (*macstr != '\0')
- strcat(macstr, ",");
- strcat(macstr, ls->match->mactext);
- }
- }
- if (mac_from_text(&mac, macstr))
- err(1, "mac_from_text(%s)", macstr);
- if ((hflag == FTS_PHYSICAL ? mac_set_link(ftsent->fts_accpath, mac) :
- mac_set_file(ftsent->fts_accpath, mac)) != 0) {
- if (errno == EOPNOTSUPP) {
- mac_free(mac);
- free(macstr);
- return (1);
- }
- err(1, "mac_set_link(%s, %s)", ftsent->fts_path, macstr);
- }
- mac_free(mac);
- free(macstr);
- return (0);
-}
-
-struct label_specs *
-new_specs(void)
-{
- struct label_specs *specs;
-
- specs = malloc(sizeof(*specs));
- if (specs == NULL)
- err(1, "malloc");
- STAILQ_INIT(&specs->head);
- return (specs);
-}
OpenPOWER on IntegriCloud