Verify file contexts from file security context patterns.
authorjbj <devnull@localhost>
Thu, 25 Dec 2003 19:02:01 +0000 (19:02 +0000)
committerjbj <devnull@localhost>
Thu, 25 Dec 2003 19:02:01 +0000 (19:02 +0000)
CVS patchset: 7005
CVS date: 2003/12/25 19:02:01

lib/poptQV.c
lib/query.c
lib/rpmcli.h
lib/rpmts.c
lib/rpmts.h
lib/verify.c
macros.in

index 0df54e4..dc2820d 100644 (file)
@@ -299,6 +299,8 @@ struct poptOption rpmVerifyPoptTable[] = {
        &rpmQVKArgs.qva_flags, VERIFY_RDEV,
         N_("don't verify mode of files"), NULL },
 
+ { "nocontexts", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, &rpmQVKArgs.qva_flags, VERIFY_CONTEXTS,
+       N_("don't verify file contexts"), NULL},
  { "nofiles", '\0', POPT_BIT_SET, &rpmQVKArgs.qva_flags, VERIFY_FILES,
        N_("don't verify files in package"), NULL},
 #ifdef DYING
index 767182f..08e46af 100644 (file)
@@ -801,6 +801,22 @@ int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv)
     if (qva->qva_flags & VERIFY_HDRCHK)
        vsflags |= RPMVSF_NOHDRCHK;
 
+#ifdef NOTYET
+    /* Initialize security context patterns (if not already done). */
+    if (!(qva->qva_flags & VERIFY_CONTEXTS)) {
+       rpmsx sx = rpmtsREContext(ts);
+       if (sx == NULL) {
+           arg = rpmGetPath("%{?_verify_file_context_path}", NULL);
+           if (arg != NULL && *arg != '\0') {
+               sx = rpmsxNew(arg);
+               (void) rpmtsSetREContext(ts, sx);
+           }
+           arg = _free(arg);
+       }
+       sx = rpmsxFree(sx);
+    }
+#endif
+
     ovsflags = rpmtsSetVSFlags(ts, vsflags);
     if (qva->qva_source == RPMQV_ALL) {
        /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
index b64ae1e..36e5baf 100644 (file)
@@ -120,16 +120,18 @@ typedef enum rpmVerifyAttrs_e {
     RPMVERIFY_MTIME    = (1 << 5),     /*!< from %verify(mtime) */
     RPMVERIFY_MODE     = (1 << 6),     /*!< from %verify(mode) */
     RPMVERIFY_RDEV     = (1 << 7),     /*!< from %verify(rdev) */
-       /* bits 8-15 unused, reserved for rpmVerifyAttrs */
-       /* bits 16-20 used in rpmVerifyFlags */
-       /* bits 21-22 unused */
+       /* bits 8-14 unused, reserved for rpmVerifyAttrs */
+    RPMVERIFY_CONTEXTS = (1 << 15),    /*!< verify: from --nocontexts */
+       /* bits 16-22 used in rpmVerifyFlags */
        /* bits 23-27 used in rpmQueryFlags */
-    RPMVERIFY_READLINKFAIL= (1 << 28), /*!< */
-    RPMVERIFY_READFAIL = (1 << 29),    /*!< */
-    RPMVERIFY_LSTATFAIL        = (1 << 30)     /*!< */
-       /* bit 31 unused */
+    RPMVERIFY_READLINKFAIL= (1 << 28), /*!< readlink failed */
+    RPMVERIFY_READFAIL = (1 << 29),    /*!< file read failed */
+    RPMVERIFY_LSTATFAIL        = (1 << 30),    /*!< lstat failed */
+    RPMVERIFY_LGETFILECONFAIL  = (1 << 31)     /*!< lgetfilecon failed */
 } rpmVerifyAttrs;
 #define        RPMVERIFY_ALL           ~(RPMVERIFY_NONE)
+#define        RPMVERIFY_FAILURES      \
+  (RPMVERIFY_LSTATFAIL|RPMVERIFY_READFAIL|RPMVERIFY_READLINKFAIL|RPMVERIFY_LGETFILECONFAIL)
 
 /** \ingroup rpmcli
  * Bit(s) to control rpmQuery() operation, stored in qva_flags.
@@ -146,13 +148,14 @@ typedef enum rpmQueryFlags_e {
     QUERY_MTIME                = (1 << 5),     /*!< from --nomtime) */
     QUERY_MODE         = (1 << 6),     /*!< from --nomode) */
     QUERY_RDEV         = (1 << 7),     /*!< from --nodev */
-       /* bits 8-15 unused, reserved for rpmVerifyAttrs */
+       /* bits 8-14 unused, reserved for rpmVerifyAttrs */
+    QUERY_CONTEXTS     = (1 << 15),    /*!< verify: from --nocontexts */
     QUERY_FILES                = (1 << 16),    /*!< verify: from --nofiles */
     QUERY_DEPS         = (1 << 17),    /*!< verify: from --nodeps */
     QUERY_SCRIPT       = (1 << 18),    /*!< verify: from --noscripts */
     QUERY_DIGEST       = (1 << 19),    /*!< verify: from --nodigest */
     QUERY_SIGNATURE    = (1 << 20),    /*!< verify: from --nosignature */
-    QUERY_PATCHES      = (1 << 21),    /*!< placeholder (SuSE) */
+    QUERY_PATCHES      = (1 << 21),    /*!< verify: from --nopatches */
     QUERY_HDRCHK       = (1 << 22),    /*!< verify: from --nohdrchk */
 /*@=enummemuse@*/
     QUERY_FOR_LIST     = (1 << 23),    /*!< query:  from --list */
@@ -188,13 +191,14 @@ typedef enum rpmVerifyFlags_e {
     VERIFY_MTIME       = (1 << 5),     /*!< from --nomtime */
     VERIFY_MODE                = (1 << 6),     /*!< from --nomode */
     VERIFY_RDEV                = (1 << 7),     /*!< from --nodev */
-       /* bits 8-15 unused, reserved for rpmVerifyAttrs */
+       /* bits 8-14 unused, reserved for rpmVerifyAttrs */
+    VERIFY_CONTEXTS    = (1 << 15),    /*!< verify: from --nocontexts */
     VERIFY_FILES       = (1 << 16),    /*!< verify: from --nofiles */
     VERIFY_DEPS                = (1 << 17),    /*!< verify: from --nodeps */
     VERIFY_SCRIPT      = (1 << 18),    /*!< verify: from --noscripts */
     VERIFY_DIGEST      = (1 << 19),    /*!< verify: from --nodigest */
     VERIFY_SIGNATURE   = (1 << 20),    /*!< verify: from --nosignature */
-    VERIFY_PATCHES     = (1 << 21),    /*!< placeholder (SuSE) */
+    VERIFY_PATCHES     = (1 << 21),    /*!< verify: from --nopatches */
     VERIFY_HDRCHK      = (1 << 22),    /*!< verify: from --nohdrchk */
 /*@-enummemuse@*/
     VERIFY_FOR_LIST    = (1 << 23),    /*!< query:  from --list */
@@ -203,12 +207,12 @@ typedef enum rpmVerifyFlags_e {
     VERIFY_FOR_CONFIG  = (1 << 26),    /*!< query:  from --configfiles */
     VERIFY_FOR_DUMPFILES= (1 << 27)    /*!< query:  from --dump */
 /*@=enummemuse@*/
-       /* bits 28-30 used in rpmVerifyAttrs */
+       /* bits 28-31 used in rpmVerifyAttrs */
 } rpmVerifyFlags;
 
 #define        VERIFY_ATTRS    \
   ( VERIFY_MD5 | VERIFY_SIZE | VERIFY_LINKTO | VERIFY_USER | VERIFY_GROUP | \
-    VERIFY_MTIME | VERIFY_MODE | VERIFY_RDEV )
+    VERIFY_MTIME | VERIFY_MODE | VERIFY_RDEV | VERIFY_CONTEXTS )
 #define        VERIFY_ALL      \
   ( VERIFY_ATTRS | VERIFY_FILES | VERIFY_DEPS | VERIFY_SCRIPT | VERIFY_DIGEST |\
     VERIFY_SIGNATURE | VERIFY_HDRCHK )
index 5a022ae..3157281 100644 (file)
@@ -794,6 +794,8 @@ rpmts rpmtsFree(rpmts ts)
 
     (void) rpmtsCloseSDB(ts);
 
+    ts->sx = rpmsxFree(ts->sx);
+
     ts->removedPackages = _free(ts->removedPackages);
 
     ts->availablePackages = rpmalFree(ts->availablePackages);
@@ -957,6 +959,23 @@ int rpmtsSetChrootDone(rpmts ts, int chrootDone)
     return ochrootDone;
 }
 
+rpmsx rpmtsREContext(rpmts ts)
+{
+    return ( (ts && ts->sx ? rpmsxLink(ts->sx, __func__) : NULL) );
+}
+
+int rpmtsSetREContext(rpmts ts, rpmsx sx)
+{
+    int rc = -1;
+    if (ts != NULL) {
+       ts->sx = rpmsxFree(ts->sx);
+       ts->sx = rpmsxLink(sx, __func__);
+       if (ts->sx != NULL)
+           rc = 0;
+    }
+    return rc;
+}
+
 int_32 rpmtsGetTid(rpmts ts)
 {
     int_32 tid = 0;
index 4cea165..229bc1e 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "rpmps.h"
 #include "rpmsw.h"
+#include "rpmsx.h"
 
 /*@-exportlocal@*/
 /*@unchecked@*/
@@ -184,6 +185,9 @@ struct rpmts_s {
     int numAvailablePackages;  /*!< No. available package instances. */
 #endif
 
+/*@refcounted@*/ /*@null@*/
+    rpmsx sx;                  /*!< Security context patterns. */
+
 /*@null@*/
     rpmte relocateElement;     /*!< Element to use when relocating packages. */
 
@@ -583,9 +587,27 @@ int rpmtsSetChrootDone(rpmts ts, int chrootDone)
        /*@modifies ts @*/;
 
 /** \ingroup rpmts
+ * Get file security context patterns.
+ * @param ts           transaction set
+ * @return             file security context patterns
+ */
+/*@null@*/
+rpmsx rpmtsREContext(rpmts ts)
+       /*@*/;
+
+/** \ingroup rpmts
+ * Get file security context patterns.
+ * @param ts           transaction set
+ * @param sx           security context patterns
+ * @return             0 on success
+ */
+int rpmtsSetREContext(rpmts ts, rpmsx sx)
+       /*@*/;
+
+/** \ingroup rpmts
  * Get transaction id, i.e. transaction time stamp.
  * @param ts           transaction set
- * @return             chrootDone flag
+ * @return             transaction id
  */
 int_32 rpmtsGetTid(rpmts ts)
        /*@*/;
index d4c1155..1890a1a 100644 (file)
@@ -77,6 +77,8 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
        return 1;
     }
 
+    flags |= RPMVERIFY_CONTEXTS;       /* no disable from package. */
+
     /*
      * Not all attributes of non-regular files can be verified.
      */
@@ -112,7 +114,34 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
     /*
      * Don't verify any features in omitMask.
      */
-    flags &= ~(omitMask | RPMVERIFY_LSTATFAIL|RPMVERIFY_READFAIL|RPMVERIFY_READLINKFAIL);
+    flags &= ~(omitMask | RPMVERIFY_FAILURES);
+
+    /*
+     * Verify file security context.
+     */
+    if (flags & RPMVERIFY_CONTEXTS) {
+       security_context_t con;
+
+       rc = lgetfilecon(fn, &con);
+       if (rc == -1)
+           *res |= (RPMVERIFY_LGETFILECONFAIL|RPMVERIFY_CONTEXTS);
+       else {
+           rpmsx sx = rpmtsREContext(ts);
+           const char * fcontext;
+
+           if (sx != NULL) {
+               /* Get file security context from patterns. */
+               fcontext = rpmsxFContext(sx, fn, fmode);
+               sx = rpmsxFree(sx);
+           } else {
+               /* Get file security context from package. */
+               fcontext = rpmfiFContext(fi);
+           }
+           if (fcontext == NULL || strcmp(fcontext, con))
+               *res |= RPMVERIFY_CONTEXTS;
+           freecon(con);
+       }
+    }
 
     if (flags & RPMVERIFY_MD5) {
        unsigned char md5sum[16];
@@ -298,7 +327,7 @@ static int verifyHeader(QVA_t qva, const rpmts ts, rpmfi fi)
            }
        } else if (verifyResult) {
            const char * size, * MD5, * link, * mtime, * mode;
-           const char * group, * user, * rdev;
+           const char * group, * user, * rdev, *ctxt;
            /*@observer@*/ static const char *const aok = ".";
            /*@observer@*/ static const char *const unknown = "?";
 
@@ -312,6 +341,9 @@ static int verifyHeader(QVA_t qva, const rpmts ts, rpmfi fi)
 #define        _verifyfile(_RPMVERIFY_F, _C)   \
        ((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
         (verifyResult & _RPMVERIFY_F) ? _C : aok)
+#define        _verifyctxt(_RPMVERIFY_F, _C)   \
+       ((verifyResult & RPMVERIFY_LGETFILECONFAIL) ? unknown : \
+        (verifyResult & _RPMVERIFY_F) ? _C : aok)
        
            MD5 = _verifyfile(RPMVERIFY_MD5, "5");
            size = _verify(RPMVERIFY_FILESIZE, "S");
@@ -321,13 +353,15 @@ static int verifyHeader(QVA_t qva, const rpmts ts, rpmfi fi)
            user = _verify(RPMVERIFY_USER, "U");
            group = _verify(RPMVERIFY_GROUP, "G");
            mode = _verify(RPMVERIFY_MODE, "M");
+           ctxt = _verifyctxt(RPMVERIFY_CONTEXTS, "C");
 
-#undef _verify
-#undef _verifylink
+#undef _verifyctxt
 #undef _verifyfile
+#undef _verifylink
+#undef _verify
 
-           sprintf(te, "%s%s%s%s%s%s%s%s %c %s",
-                       size, mode, MD5, rdev, link, user, group, mtime, 
+           sprintf(te, "%s%s%s%s%s%s%s%s%s %c %s",
+                       size, mode, MD5, rdev, link, user, group, mtime, ctxt,
                        ((fileAttrs & RPMFILE_CONFIG)   ? 'c' :
                         (fileAttrs & RPMFILE_DOC)      ? 'd' :
                         (fileAttrs & RPMFILE_GHOST)    ? 'g' :
@@ -482,6 +516,20 @@ int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv)
        vsflags |= RPMVSF_NOHDRCHK;
     vsflags &= ~RPMVSF_NEEDPAYLOAD;
 
+    /* Initialize security context patterns (if not already done). */
+    if (qva->qva_flags & VERIFY_CONTEXTS) {
+       rpmsx sx = rpmtsREContext(ts);
+       if (sx == NULL) {
+           arg = rpmGetPath("%{?_verify_file_context_path}", NULL);
+           if (arg != NULL && *arg != '\0') {
+               sx = rpmsxNew(arg);
+               (void) rpmtsSetREContext(ts, sx);
+           }
+           arg = _free(arg);
+       }
+       sx = rpmsxFree(sx);
+    }
+
     ovsflags = rpmtsSetVSFlags(ts, vsflags);
     if (qva->qva_source == RPMQV_ALL) {
        /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
index 62e9d04..03d18c7 100644 (file)
--- a/macros.in
+++ b/macros.in
@@ -1,7 +1,7 @@
 #/*! \page config_macros Default configuration: @RPMCONFIGDIR@/macros
 # \verbatim
 #
-# $Id: macros.in,v 1.141 2003/12/23 07:51:10 jbj Exp $
+# $Id: macros.in,v 1.142 2003/12/25 19:02:01 jbj Exp $
 #
 # This is a global RPM configuration file. All changes made here will
 # be lost when the rpm package is upgraded. Any per-system configuration
@@ -324,10 +324,10 @@ package or when debugging this package.\
 %_use_internal_dependency_generator    1
 
 #
-# Filter GLIBC_PRIVATE Provides:/Requires:
+# Filter GLIBC_PRIVATE Provides: and Requires:
 %_filter_GLIBC_PRIVATE                 0
 
-# Path to selinux src policy file context patterns.
+# Path to selinux source policy file context patterns.
 %__file_context_path /etc/security/selinux/src/policy/file_contexts/file_contexts
 
 #
@@ -335,7 +335,7 @@ package or when debugging this package.\
 # RPMTAG_FILECONTEXTS to packages when building.
 #
 # Undefined, missing or %{nil} will disable.
-#%_build_file_context_path     %{__file_context_path}
+%_build_file_context_path      %{__file_context_path}
 
 #
 # Path to selinux src policy file context patterns used to set
@@ -348,7 +348,7 @@ package or when debugging this package.\
 # Path to selinux src policy file context patterns used to verify
 # file contexts on file system.
 #
-# Undefined, missing or %{nil} will use package content.
+# Undefined, missing or %{nil} will use package content (if available).
 %_verify_file_context_path     %{__file_context_path}
 
 #