Mon, 28 Jan 2013 17:37:18 +0100
Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.
michael@428 | 1 | -----BEGIN PGP SIGNED MESSAGE----- |
michael@428 | 2 | Hash: SHA1 |
michael@428 | 3 | |
michael@428 | 4 | - -- |
michael@428 | 5 | - -- OpenPKG Framework License Processor |
michael@428 | 6 | - -- Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/> |
michael@428 | 7 | - -- |
michael@428 | 8 | - -- This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
michael@428 | 9 | - -- All rights reserved. Licenses which grant limited permission to use, |
michael@428 | 10 | - -- copy, modify and distribute this software are available from the |
michael@428 | 11 | - -- OpenPKG GmbH. |
michael@428 | 12 | - -- |
michael@428 | 13 | - -- THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
michael@428 | 14 | - -- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
michael@428 | 15 | - -- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
michael@428 | 16 | - -- IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
michael@428 | 17 | - -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@428 | 18 | - -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@428 | 19 | - -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
michael@428 | 20 | - -- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@428 | 21 | - -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
michael@428 | 22 | - -- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
michael@428 | 23 | - -- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@428 | 24 | - -- SUCH DAMAGE. |
michael@428 | 25 | - -- |
michael@428 | 26 | |
michael@428 | 27 | - -- This is the RPM run-time integrity processor of the OpenPKG |
michael@428 | 28 | - -- Framework. It currently checks the OpenPKG Framework run-time |
michael@428 | 29 | - -- license only. The following grammar specifies and documents all |
michael@428 | 30 | - -- currently supported license parameters. |
michael@428 | 31 | - -- |
michael@428 | 32 | - -- license ::= "Assertion-MinProcVersion:" version |
michael@428 | 33 | - -- # require a minimum version of the license integrity processor |
michael@428 | 34 | - -- |
michael@428 | 35 | - -- | "Assertion-ErrorToWarning:" yes-no |
michael@428 | 36 | - -- # allow all fatal integrity checking errors to be |
michael@428 | 37 | - -- # converted to non-fatal warnings |
michael@428 | 38 | - -- |
michael@428 | 39 | - -- | "Assertion-OnlineApproval:" url |
michael@428 | 40 | - -- # require an online approval by receiving an "OK" from |
michael@428 | 41 | - -- # specified remote service |
michael@428 | 42 | - -- |
michael@428 | 43 | - -- | "Assertion-OnlineReporting:" url |
michael@428 | 44 | - -- # perform an asynchronous online reporting to |
michael@428 | 45 | - -- # specified remote service |
michael@428 | 46 | - -- |
michael@428 | 47 | - -- | "Assertion-Prefix:" path |
michael@428 | 48 | - -- # require %{l_prefix} to match specified path |
michael@428 | 49 | - -- |
michael@428 | 50 | - -- | "Assertion-User:" user |
michael@428 | 51 | - -- # require %{l_musr} to match specified username |
michael@428 | 52 | - -- |
michael@428 | 53 | - -- | "Assertion-Group:" group |
michael@428 | 54 | - -- # require %{l_mgrp} to match specified groupname |
michael@428 | 55 | - -- |
michael@428 | 56 | - -- | "Assertion-Domain:" domain |
michael@428 | 57 | - -- # require domain of host to match specified domain name |
michael@428 | 58 | - -- |
michael@428 | 59 | - -- | "Assertion-LifeTime:" iso-date.":".iso-date |
michael@428 | 60 | - -- # require current real-time to be within specified |
michael@428 | 61 | - -- # begin and end date |
michael@428 | 62 | - -- |
michael@428 | 63 | - -- | "Assertion-GrantTime:" iso-date.":".iso-date |
michael@428 | 64 | - -- # require current OpenPKG Framework %{RELEASE} |
michael@428 | 65 | - -- # (release time) to be within specified begin and end |
michael@428 | 66 | - -- # date |
michael@428 | 67 | - -- |
michael@428 | 68 | - -- | "Assertion-InstanceAge:" duration |
michael@428 | 69 | - -- # require current OpenPKG Framework %{ORIGINTIME} |
michael@428 | 70 | - -- # (first install time) to be within specified begin |
michael@428 | 71 | - -- # and end date |
michael@428 | 72 | - -- |
michael@428 | 73 | - -- | "Assertion-FromSourceOnTarget:" yes-no |
michael@428 | 74 | - -- # require either (if "yes") that all package |
michael@428 | 75 | - -- # %{BUILDHOST} are equal the host name or (if "no") |
michael@428 | 76 | - -- # that all package %{BUILDHOST} are not equal the host |
michael@428 | 77 | - -- # name |
michael@428 | 78 | - -- |
michael@428 | 79 | - -- | "Assertion-PackageNames:" |
michael@428 | 80 | - -- ("!"?.mode-regex.":"."!"?.package-regex)+ |
michael@428 | 81 | - -- # require all package %{NAME} to (not) match the |
michael@428 | 82 | - -- # specified regex while the current RPM run-time mode |
michael@428 | 83 | - -- # has to (not) match the specified regex. RPM run-time |
michael@428 | 84 | - -- # modes are: query, verify, checksig, resign, install, |
michael@428 | 85 | - -- # erase, build rebuild, recompile, tarbuild, initdb, |
michael@428 | 86 | - -- # rebuilddb and verifydb. |
michael@428 | 87 | - -- |
michael@428 | 88 | - -- | "Assertion-PackageReleaseAge:" |
michael@428 | 89 | - -- percent.":".duration.":".dist-regex ((package-name|"*").":".release)+ |
michael@428 | 90 | - -- # require that for at least the specified amount (in |
michael@428 | 91 | - -- # percent) of packages, which %{DISTRIBUTION} matches |
michael@428 | 92 | - -- # the specified regex, the %{RELEASE} is at least as |
michael@428 | 93 | - -- # old as the specified release or at least not older |
michael@428 | 94 | - -- # than the specified duration. |
michael@428 | 95 | - -- |
michael@428 | 96 | - -- | "Assertion-Expression:" expression |
michael@428 | 97 | - -- # evaluates the Lua boolean expression after expanding |
michael@428 | 98 | - -- # RPM macros %{VARNAME} and expanding the construct |
michael@428 | 99 | - -- # "<string>" ~~ /<regex>/ into the corresponding PCRE |
michael@428 | 100 | - -- # based regular expression match. |
michael@428 | 101 | - -- |
michael@428 | 102 | - -- version ::= /^\d+\.\d+\.\d+$/ |
michael@428 | 103 | - -- yes-no ::= /^yes|no$/ |
michael@428 | 104 | - -- url ::= /^https?:\/\/.+$/ |
michael@428 | 105 | - -- path ::= /^\/.+$/ |
michael@428 | 106 | - -- user ::= /^[a-z][a-zA-Z0-9_]*$/ |
michael@428 | 107 | - -- group ::= /^[a-z][a-zA-Z0-9_]*$/ |
michael@428 | 108 | - -- domain ::= /^(?:[^.]+\.)+[^.]+$/ |
michael@428 | 109 | - -- mode-regex ::= /^.+$/ |
michael@428 | 110 | - -- package-regex ::= /^.+$/ |
michael@428 | 111 | - -- package-name ::= /^[a-z][a-zA-Z0-9-]*$/ |
michael@428 | 112 | - -- percent ::= /^\d+%$/ |
michael@428 | 113 | - -- duration ::= /^\d+[smhdw]?$/ |
michael@428 | 114 | - -- release ::= /^\d{8}$/ |
michael@428 | 115 | - -- iso-date ::= /^\d{4}-\d{2}-\d{2}$/ |
michael@428 | 116 | - -- expression ::= /^.+$/ |
michael@428 | 117 | |
michael@428 | 118 | - -- integrity processor version |
michael@428 | 119 | integrity.version = "1.0.0" |
michael@428 | 120 | |
michael@428 | 121 | - -- integrity processor validation callback function |
michael@428 | 122 | function integrity.validate(ctx, cfg) |
michael@428 | 123 | integrity.util.debug(1, "OpenPKG run-time license integrity validation") |
michael@428 | 124 | integrity.util.debug(4, function (ctx) return "dump: ctx = " .. util.dump(ctx) end, ctx) |
michael@428 | 125 | integrity.util.debug(4, function (cfg) return "dump: cfg = " .. util.dump(cfg) end, cfg) |
michael@428 | 126 | |
michael@428 | 127 | -- process "Assertion-OnlineApproval" constraint |
michael@428 | 128 | if os.getenv("OPENPKG_LICENSE_EXCEPTION") ~= nil then |
michael@428 | 129 | -- support explicitly requested license exception |
michael@428 | 130 | cfg["Assertion-OnlineApproval"] = "http://openpkg.com/go/framework-license-exception" |
michael@428 | 131 | end |
michael@428 | 132 | if cfg["Assertion-OnlineApproval"] ~= nil then |
michael@428 | 133 | integrity.util.debug(2, "checking: Assertion-OnlineApproval: \"%s\"", cfg["Assertion-OnlineApproval"]) |
michael@428 | 134 | local uuids = integrity.util.uuids() |
michael@428 | 135 | if uuids["UUID_REGISTRY"] == "" then |
michael@428 | 136 | uuids["UUID_REGISTRY"] = "unknown" |
michael@428 | 137 | end |
michael@428 | 138 | if uuids["UUID_INSTANCE"] == "" then |
michael@428 | 139 | uuids["UUID_INSTANCE"] = "unknown" |
michael@428 | 140 | end |
michael@428 | 141 | if uuids["UUID_PLATFORM"] == "" then |
michael@428 | 142 | uuids["UUID_PLATFORM"] = "unknown" |
michael@428 | 143 | end |
michael@428 | 144 | local request = cfg["Assertion-OnlineApproval"] |
michael@428 | 145 | request = request .. "?UUID_REGISTRY=" .. uuids["UUID_REGISTRY"] |
michael@428 | 146 | request = request .. "&UUID_INSTANCE=" .. uuids["UUID_INSTANCE"] |
michael@428 | 147 | request = request .. "&UUID_PLATFORM=" .. uuids["UUID_PLATFORM"] |
michael@428 | 148 | integrity.util.debug(3, "info: remote request \"%s\"", request) |
michael@428 | 149 | local response = rpm.expand("%(%{l_prefix}/bin/openpkg curl -s -L -R '" .. request .. "')") |
michael@428 | 150 | integrity.util.debug(3, "info: remote response \"%s\"", response) |
michael@428 | 151 | if util.rmatch(response, "(?s)^\\s*OK\\s*$") then |
michael@428 | 152 | -- approved |
michael@428 | 153 | if os.getenv("OPENPKG_LICENSE_EXCEPTION") ~= nil then |
michael@428 | 154 | -- support explicitly requested license exception |
michael@428 | 155 | cfg["Assertion-ErrorToWarning"] = "yes" |
michael@428 | 156 | end |
michael@428 | 157 | else |
michael@428 | 158 | -- rejected |
michael@428 | 159 | cfg["Assertion-ErrorToWarning"] = "no" |
michael@428 | 160 | return integrity.util.error(ctx, cfg, |
michael@428 | 161 | "license requires online approval but we failed to get " .. |
michael@428 | 162 | "an \"OK\" response from the online service") |
michael@428 | 163 | end |
michael@428 | 164 | end |
michael@428 | 165 | |
michael@428 | 166 | -- process "Assertion-MinProcVersion" constraint |
michael@428 | 167 | integrity.util.debug(2, "checking: Assertion-MinProcVersion: \"%s\"", cfg["Assertion-MinProcVersion"]) |
michael@428 | 168 | if cfg["Assertion-MinProcVersion"] == nil then |
michael@428 | 169 | return integrity.util.error(ctx, cfg, |
michael@428 | 170 | "license configuration is missing required \"Assertion-MinProcVersion\" parameter") |
michael@428 | 171 | end |
michael@428 | 172 | integrity.util.debug(3, "require: %s <= %s", cfg["Assertion-MinProcVersion"], integrity.version) |
michael@428 | 173 | if rpm.vercmp(cfg["Assertion-MinProcVersion"], integrity.version) > 0 then |
michael@428 | 174 | return integrity.util.error(ctx, cfg, |
michael@428 | 175 | "license configuration requires a license processor of " .. |
michael@428 | 176 | "at least version \"" .. cfg["Assertion-MinProcVersion"] .. "\"") |
michael@428 | 177 | end |
michael@428 | 178 | |
michael@428 | 179 | -- process "Assertion-OnlineReporting" constraint |
michael@428 | 180 | if cfg["Assertion-OnlineReporting"] ~= nil then |
michael@428 | 181 | integrity.util.debug(2, "checking: Assertion-OnlineReporting: \"%s\"", cfg["Assertion-OnlineReporting"]) |
michael@428 | 182 | local uuids = integrity.util.uuids() |
michael@428 | 183 | if uuids["UUID_REGISTRY"] == "" then |
michael@428 | 184 | uuids["UUID_REGISTRY"] = "unknown" |
michael@428 | 185 | end |
michael@428 | 186 | if uuids["UUID_INSTANCE"] == "" then |
michael@428 | 187 | uuids["UUID_INSTANCE"] = "unknown" |
michael@428 | 188 | end |
michael@428 | 189 | if uuids["UUID_PLATFORM"] == "" then |
michael@428 | 190 | uuids["UUID_PLATFORM"] = "unknown" |
michael@428 | 191 | end |
michael@428 | 192 | local request = cfg["Assertion-OnlineReporting"] |
michael@428 | 193 | request = request .. "?UUID_REGISTRY=" .. uuids["UUID_REGISTRY"] |
michael@428 | 194 | request = request .. "&UUID_INSTANCE=" .. uuids["UUID_INSTANCE"] |
michael@428 | 195 | request = request .. "&UUID_PLATFORM=" .. uuids["UUID_PLATFORM"] |
michael@428 | 196 | integrity.util.debug(3, "info: remote request \"%s\"", request) |
michael@428 | 197 | rpm.expand("%(nohup %{l_prefix}/bin/openpkg curl -s -L -R '" .. request .. "' >/dev/null 2>&1 &)") |
michael@428 | 198 | integrity.util.debug(3, "response: (ignored, because asynchronous operation)") |
michael@428 | 199 | end |
michael@428 | 200 | |
michael@428 | 201 | -- process "Assertion-Prefix" constraint |
michael@428 | 202 | if cfg["Assertion-Prefix"] ~= nil then |
michael@428 | 203 | integrity.util.debug(2, "checking: Assertion-Prefix: \"%s\"", cfg["Assertion-Prefix"]) |
michael@428 | 204 | local prefix = rpm.expand("%{l_prefix}") |
michael@428 | 205 | integrity.util.debug(3, "require: \"%s\" == \"%s\"", cfg["Assertion-Prefix"], prefix) |
michael@428 | 206 | if cfg["Assertion-Prefix"] ~= prefix then |
michael@428 | 207 | return integrity.util.error(ctx, cfg, |
michael@428 | 208 | "instance prefix \"" .. prefix .. "\" " .. |
michael@428 | 209 | "does not match value \"" .. cfg["Assertion-Prefix"] .. "\" of " .. |
michael@428 | 210 | "license configuration parameter \"Assertion-Prefix\"") |
michael@428 | 211 | end |
michael@428 | 212 | end |
michael@428 | 213 | |
michael@428 | 214 | -- process "Assertion-User" constraint |
michael@428 | 215 | if cfg["Assertion-User"] ~= nil then |
michael@428 | 216 | integrity.util.debug(2, "checking: Assertion-User: \"%s\"", cfg["Assertion-User"]) |
michael@428 | 217 | local user = rpm.expand("%{l_musr}") |
michael@428 | 218 | integrity.util.debug(3, "require: \"%s\" == \"%s\"", cfg["Assertion-User"], user) |
michael@428 | 219 | if cfg["Assertion-User"] ~= user then |
michael@428 | 220 | return integrity.util.error(ctx, cfg, |
michael@428 | 221 | "instance management user \"" .. user .. "\" " .. |
michael@428 | 222 | "does not match value \"" .. cfg["Assertion-User"] .. "\" of " .. |
michael@428 | 223 | "license configuration parameter \"Assertion-User\"") |
michael@428 | 224 | end |
michael@428 | 225 | end |
michael@428 | 226 | |
michael@428 | 227 | -- process "Assertion-Group" constraint |
michael@428 | 228 | if cfg["Assertion-Group"] ~= nil then |
michael@428 | 229 | integrity.util.debug(2, "checking: Assertion-Group: \"%s\"", cfg["Assertion-Group"]) |
michael@428 | 230 | local group = rpm.expand("%{l_mgrp}") |
michael@428 | 231 | integrity.util.debug(3, "require: \"%s\" == \"%s\"", cfg["Assertion-Group"], group) |
michael@428 | 232 | if cfg["Assertion-Group"] ~= group then |
michael@428 | 233 | return integrity.util.error(ctx, cfg, |
michael@428 | 234 | "instance management group \"" .. group .. "\" " .. |
michael@428 | 235 | "does not match value \"" .. cfg["Assertion-Group"] .. "\" of " .. |
michael@428 | 236 | "license configuration parameter \"Assertion-Group\"") |
michael@428 | 237 | end |
michael@428 | 238 | end |
michael@428 | 239 | |
michael@428 | 240 | -- process "Assertion-Domain" constraint |
michael@428 | 241 | if cfg["Assertion-Domain"] ~= nil then |
michael@428 | 242 | integrity.util.debug(2, "checking: Assertion-Domain: \"%s\"", cfg["Assertion-Domain"]) |
michael@428 | 243 | local domain = rpm.expand("%(%{l_shtool} echo -n -e '%d')") |
michael@428 | 244 | integrity.util.debug(3, "require: \"%s\" ~~ /(?s)^.*%s$/", domain, cfg["Assertion-Domain"]) |
michael@428 | 245 | local s, _, m = util.rmatch(domain, "(?s)^.*" .. cfg["Assertion-Domain"] .. "$") |
michael@428 | 246 | if s == nil then |
michael@428 | 247 | return integrity.util.error(ctx, cfg, |
michael@428 | 248 | "host domain \"" .. domain .. "\" " .. |
michael@428 | 249 | "does not end in pattern \"" .. cfg["Assertion-Domain"] .. "\") " .. |
michael@428 | 250 | "of license configuration parameter \"Assertion-Domain\"") |
michael@428 | 251 | end |
michael@428 | 252 | end |
michael@428 | 253 | |
michael@428 | 254 | -- process "Assertion-LifeTime" constraint |
michael@428 | 255 | if cfg["Assertion-LifeTime"] ~= nil then |
michael@428 | 256 | integrity.util.debug(2, "checking: Assertion-LifeTime: \"%s\"", cfg["Assertion-LifeTime"]) |
michael@428 | 257 | |
michael@428 | 258 | -- determine lifetime begin and end |
michael@428 | 259 | local lifetime = cfg["Assertion-LifeTime"] |
michael@428 | 260 | local s, _, m = util.rmatch(lifetime, "^(?s)(\\d{4})-(\\d{2})-(\\d{2})\\s*:\\s*(\\d{4})-(\\d{2})-(\\d{2})$") |
michael@428 | 261 | if s == nil then |
michael@428 | 262 | return integrity.util.error(ctx, cfg, |
michael@428 | 263 | "failed to extract time information from " .. |
michael@428 | 264 | "license configuration parameter \"Assertion-LifeTime\"") |
michael@428 | 265 | end |
michael@428 | 266 | local lifetime_begin = os.time({ |
michael@428 | 267 | year = tonumber(m[1]), |
michael@428 | 268 | month = tonumber(m[2]), |
michael@428 | 269 | day = tonumber(m[3]), |
michael@428 | 270 | hour = 0, |
michael@428 | 271 | min = 0, |
michael@428 | 272 | sec = 0 |
michael@428 | 273 | }) |
michael@428 | 274 | local lifetime_end = os.time({ |
michael@428 | 275 | year = tonumber(m[4]), |
michael@428 | 276 | month = tonumber(m[5]), |
michael@428 | 277 | day = tonumber(m[6]), |
michael@428 | 278 | hour = 23, |
michael@428 | 279 | min = 59, |
michael@428 | 280 | sec = 59 |
michael@428 | 281 | }) |
michael@428 | 282 | |
michael@428 | 283 | -- check whether current run-time is within lifetime |
michael@428 | 284 | local t_now = os.time() |
michael@428 | 285 | integrity.util.debug(3, "require: %d <= %d <= %d", lifetime_begin, t_now, lifetime_end) |
michael@428 | 286 | if not (lifetime_begin <= t_now and t_now <= lifetime_end) then |
michael@428 | 287 | return integrity.util.error(ctx, cfg, |
michael@428 | 288 | "current time \"" .. os.date("!%Y-%m-%d %H:%M:%S UTC", t_now) .. "\" " .. |
michael@428 | 289 | "is not within the timerange \"" .. cfg["Assertion-LifeTime"] .. "\" " .. |
michael@428 | 290 | "of license configuration parameter \"Assertion-LifeTime\"") |
michael@428 | 291 | end |
michael@428 | 292 | end |
michael@428 | 293 | |
michael@428 | 294 | -- process "Assertion-GrantTime" constraint |
michael@428 | 295 | if cfg["Assertion-GrantTime"] ~= nil then |
michael@428 | 296 | integrity.util.debug(2, "checking: Assertion-GrantTime: \"%s\"", cfg["Assertion-GrantTime"]) |
michael@428 | 297 | |
michael@428 | 298 | -- determine granttime begin and end |
michael@428 | 299 | local granttime = cfg["Assertion-GrantTime"] |
michael@428 | 300 | local s, _, m = util.rmatch(granttime, "^(?s)(\\d{4})-(\\d{2})-(\\d{2})\\s*:\\s*(\\d{4})-(\\d{2})-(\\d{2})$") |
michael@428 | 301 | if s == nil then |
michael@428 | 302 | return integrity.util.error(ctx, cfg, |
michael@428 | 303 | "failed to extract time information from " .. |
michael@428 | 304 | "license configuration parameter \"Assertion-GrantTime\"") |
michael@428 | 305 | end |
michael@428 | 306 | local granttime_begin = os.time({ |
michael@428 | 307 | year = tonumber(m[1]), |
michael@428 | 308 | month = tonumber(m[2]), |
michael@428 | 309 | day = tonumber(m[3]), |
michael@428 | 310 | hour = 0, |
michael@428 | 311 | min = 0, |
michael@428 | 312 | sec = 0 |
michael@428 | 313 | }) |
michael@428 | 314 | local granttime_end = os.time({ |
michael@428 | 315 | year = tonumber(m[4]), |
michael@428 | 316 | month = tonumber(m[5]), |
michael@428 | 317 | day = tonumber(m[6]), |
michael@428 | 318 | hour = 23, |
michael@428 | 319 | min = 59, |
michael@428 | 320 | sec = 59 |
michael@428 | 321 | }) |
michael@428 | 322 | |
michael@428 | 323 | -- determine OpenPKG Framework release time |
michael@428 | 324 | -- (allow openpkg.spec:%pre to override with a higher value for pre-checking) |
michael@428 | 325 | local t_release = 0 |
michael@428 | 326 | local result = {} |
michael@428 | 327 | for _, line in ipairs(rpm.query("Q:%{RELEASE}", false, "openpkg")) do |
michael@428 | 328 | local s, _, m = util.rmatch(line, "(?s)^Q:(.+)$") |
michael@428 | 329 | if s ~= nil then |
michael@428 | 330 | table.insert(result, m[1]) |
michael@428 | 331 | end |
michael@428 | 332 | end |
michael@428 | 333 | if result[1] ~= nil then |
michael@428 | 334 | local s, _, m = util.rmatch(result[1], "^(?s)(\\d{4})(\\d{2})(\\d{2})$") |
michael@428 | 335 | if s ~= nil then |
michael@428 | 336 | t_release = os.time({ |
michael@428 | 337 | year = tonumber(m[1]), |
michael@428 | 338 | month = tonumber(m[2]), |
michael@428 | 339 | day = tonumber(m[3]), |
michael@428 | 340 | hour = 0, |
michael@428 | 341 | min = 0, |
michael@428 | 342 | sec = 0 |
michael@428 | 343 | }) |
michael@428 | 344 | end |
michael@428 | 345 | end |
michael@428 | 346 | if t_release == 0 then |
michael@428 | 347 | return integrity.util.error(ctx, cfg, |
michael@428 | 348 | "failed to determine OpenPKG Framework release time") |
michael@428 | 349 | end |
michael@428 | 350 | local override = os.getenv("OPENPKG_FRAMEWORK_RELEASE") |
michael@428 | 351 | if override ~= nil then |
michael@428 | 352 | local s, _, m = util.rmatch(override, "^(?s)(\\d{4})(\\d{2})(\\d{2})$") |
michael@428 | 353 | if s ~= nil then |
michael@428 | 354 | local t_override = os.time({ |
michael@428 | 355 | year = tonumber(m[1]), |
michael@428 | 356 | month = tonumber(m[2]), |
michael@428 | 357 | day = tonumber(m[3]), |
michael@428 | 358 | hour = 0, |
michael@428 | 359 | min = 0, |
michael@428 | 360 | sec = 0 |
michael@428 | 361 | }) |
michael@428 | 362 | if t_release < t_override then |
michael@428 | 363 | t_release = t_override |
michael@428 | 364 | end |
michael@428 | 365 | end |
michael@428 | 366 | end |
michael@428 | 367 | |
michael@428 | 368 | -- check whether current OpenPKG Framework release time is within granttime |
michael@428 | 369 | integrity.util.debug(3, "require: %d <= %d <= %d", granttime_begin, t_release, granttime_end) |
michael@428 | 370 | if not (granttime_begin <= t_release and t_release <= granttime_end) then |
michael@428 | 371 | return integrity.util.error(ctx, cfg, |
michael@428 | 372 | "current OpenPKG Framework release time \"" .. os.date("%Y-%m-%d", t_release) .. "\" " .. |
michael@428 | 373 | "is not within the timerange \"" .. cfg["Assertion-GrantTime"] .. "\" " .. |
michael@428 | 374 | "of license configuration parameter \"Assertion-GrantTime\"") |
michael@428 | 375 | end |
michael@428 | 376 | end |
michael@428 | 377 | |
michael@428 | 378 | -- process "Assertion-InstanceAge" constraint |
michael@428 | 379 | if cfg["Assertion-InstanceAge"] ~= nil then |
michael@428 | 380 | integrity.util.debug(2, "checking: Assertion-InstanceAge: \"%s\"", cfg["Assertion-InstanceAge"]) |
michael@428 | 381 | |
michael@428 | 382 | -- determine maximum instance age in seconds |
michael@428 | 383 | local t_diff_max = cfg["Assertion-InstanceAge"] |
michael@428 | 384 | t_diff_max = 0 + util.rsubst(t_diff_max, "^(\\d+)([smhdw])$", function (t, unit) |
michael@428 | 385 | if unit == "s" then t = t * 1 |
michael@428 | 386 | elseif unit == "m" then t = t * 60 |
michael@428 | 387 | elseif unit == "h" then t = t * 60 * 60 |
michael@428 | 388 | elseif unit == "d" then t = t * 60 * 60 * 24 |
michael@428 | 389 | elseif unit == "w" then t = t * 60 * 60 * 24 * 7 |
michael@428 | 390 | end |
michael@428 | 391 | return t |
michael@428 | 392 | end) |
michael@428 | 393 | |
michael@428 | 394 | -- approach 1: determine install time via timestamp of UUID_REGISTRY |
michael@428 | 395 | local uuids = integrity.util.uuids() |
michael@428 | 396 | if uuids["UUID_REGISTRY"] == "" then |
michael@428 | 397 | return integrity.util.error(ctx, cfg, |
michael@428 | 398 | "failed to load UUID_REGISTRY") |
michael@428 | 399 | end |
michael@428 | 400 | txt = uuid.describe(uuids["UUID_REGISTRY"]) |
michael@428 | 401 | if txt == nil then |
michael@428 | 402 | return integrity.util.error(ctx, cfg, |
michael@428 | 403 | "failed to parse extracted UUID_REGISTRY string \"" .. uuids["UUID_REGISTRY"] .. "\" as an UUID") |
michael@428 | 404 | end |
michael@428 | 405 | local s, _, m = util.rmatch(txt, "(?s)^.*time:\\s+(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2}):(\\d{2}).*$") |
michael@428 | 406 | if s == nil then |
michael@428 | 407 | return integrity.util.error(ctx, cfg, |
michael@428 | 408 | "failed to extract timestamp from UUID_REGISTRY \"" .. uuids["UUID_REGISTRY"] .. "\"") |
michael@428 | 409 | end |
michael@428 | 410 | local t_install = os.time({ |
michael@428 | 411 | year = tonumber(m[1]), |
michael@428 | 412 | month = tonumber(m[2]), |
michael@428 | 413 | day = tonumber(m[3]), |
michael@428 | 414 | hour = tonumber(m[4]), |
michael@428 | 415 | min = tonumber(m[5]), |
michael@428 | 416 | sec = tonumber(m[6]) |
michael@428 | 417 | }) |
michael@428 | 418 | |
michael@428 | 419 | -- approach 2: determine install time via first install time of "openpkg" package |
michael@428 | 420 | local result = {} |
michael@428 | 421 | for _, line in ipairs(rpm.query( |
michael@428 | 422 | "Q:%|ORIGINTIME?{" .. |
michael@428 | 423 | "%{ORIGINTIME}" .. -- regular case: RPM 5 installed/updated with RPM 5 |
michael@428 | 424 | "}:{" .. |
michael@428 | 425 | "%|INSTALLTIME?{" .. |
michael@428 | 426 | "%{INSTALLTIME}" .. -- special case: RPM 5 installed initially with RPM 4 |
michael@428 | 427 | "}:{" .. |
michael@428 | 428 | "}|" .. |
michael@428 | 429 | "}|", false, "openpkg" |
michael@428 | 430 | )) do |
michael@428 | 431 | local s, _, m = util.rmatch(line, "(?s)^Q:(.+)$") |
michael@428 | 432 | if s ~= nil then |
michael@428 | 433 | table.insert(result, m[1]) |
michael@428 | 434 | end |
michael@428 | 435 | end |
michael@428 | 436 | if result[1] ~= nil then |
michael@428 | 437 | local n = tonumber(result[1]) |
michael@428 | 438 | if n > 0 then |
michael@428 | 439 | t_install = n |
michael@428 | 440 | end |
michael@428 | 441 | end |
michael@428 | 442 | |
michael@428 | 443 | -- check time difference |
michael@428 | 444 | local t_now = os.time() |
michael@428 | 445 | local t_diff = os.difftime(t_now, t_install) |
michael@428 | 446 | integrity.util.debug(3, "calc: %d - %d = %d", t_now, t_install, t_diff) |
michael@428 | 447 | if t_diff < 0 then |
michael@428 | 448 | return integrity.util.error(ctx, cfg, |
michael@428 | 449 | "current system time \"" .. t_now .. "\" is lower than " .. |
michael@428 | 450 | "instance installation time \"" .. t_install .. "\"") |
michael@428 | 451 | end |
michael@428 | 452 | integrity.util.debug(3, "require: %d <= %d", t_diff, t_diff_max) |
michael@428 | 453 | if t_diff > t_diff_max then |
michael@428 | 454 | return integrity.util.error(ctx, cfg, |
michael@428 | 455 | "instance age \"" .. t_diff .. "\" " .. |
michael@428 | 456 | "is greater than value \"" .. t_diff_max .. "\" (\"" .. cfg["Assertion-InstanceAge"] .. "\") " .. |
michael@428 | 457 | "of license configuration parameter \"Assertion-InstanceAge\"") |
michael@428 | 458 | end |
michael@428 | 459 | end |
michael@428 | 460 | |
michael@428 | 461 | -- process "Assertion-FromSourceOnTarget" constraint |
michael@428 | 462 | if cfg["Assertion-FromSourceOnTarget"] ~= nil then |
michael@428 | 463 | integrity.util.debug(2, "checking: Assertion-FromSourceOnTarget: \"%s\"", cfg["Assertion-FromSourceOnTarget"]) |
michael@428 | 464 | local hostname = rpm.hostname() |
michael@428 | 465 | for _, line in ipairs(rpm.query("Q:%{NAME}:%{BUILDHOST}", true, "*")) do |
michael@428 | 466 | local s, _, m = util.rmatch(line, "(?s)^Q:([^:]+):(.+)$") |
michael@428 | 467 | if s ~= nil then |
michael@428 | 468 | local name = m[1] |
michael@428 | 469 | local buildhost = m[2] |
michael@428 | 470 | integrity.util.debug(4, "info: name \"%s\", buildhost \"%s\"", name, buildhost) |
michael@428 | 471 | if not util.rmatch(name, "(?s)^gpg-.+$") and buildhost ~= "localhost" then |
michael@428 | 472 | if cfg["Assertion-FromSourceOnTarget"] == "yes" and buildhost ~= hostname then |
michael@428 | 473 | return integrity.util.error(ctx, cfg, |
michael@428 | 474 | "license-required \"build from source on target system only\" situation not met because " .. |
michael@428 | 475 | "package build host \"" .. buildhost .. "\" is not(!) equal to the package install host \"" .. hostname .. "\".") |
michael@428 | 476 | end |
michael@428 | 477 | if cfg["Assertion-FromSourceOnTarget"] == "no" and buildhost == hostname then |
michael@428 | 478 | return integrity.util.error(ctx, cfg, |
michael@428 | 479 | "license-required \"build binaries on separate build-host only\" situation not met because " .. |
michael@428 | 480 | "package build host \"" .. buildhost .. "\" is equal to the package install host \"" .. hostname .. "\".") |
michael@428 | 481 | end |
michael@428 | 482 | end |
michael@428 | 483 | end |
michael@428 | 484 | end |
michael@428 | 485 | end |
michael@428 | 486 | |
michael@428 | 487 | -- process "Assertion-PackageNames" constraints |
michael@428 | 488 | if cfg["Assertion-PackageNames"] ~= nil then |
michael@428 | 489 | integrity.util.debug(2, "checking: Assertion-PackageNames: \"%s\"", cfg["Assertion-PackageNames"]) |
michael@428 | 490 | |
michael@428 | 491 | -- query RPMDB for names of all installed packages |
michael@428 | 492 | local packages = {} |
michael@428 | 493 | for _, line in ipairs(rpm.query("Q:%{NAME}", true, "*")) do |
michael@428 | 494 | local s, _, m = util.rmatch(line, "(?s)^Q:(.+)$") |
michael@428 | 495 | if s ~= nil then |
michael@428 | 496 | table.insert(packages, m[1]) |
michael@428 | 497 | end |
michael@428 | 498 | end |
michael@428 | 499 | |
michael@428 | 500 | -- iterate over all constraints |
michael@428 | 501 | for _, constraint in |
michael@428 | 502 | ipairs( |
michael@428 | 503 | util.rsplit( |
michael@428 | 504 | util.rsubst( |
michael@428 | 505 | cfg["Assertion-PackageNames"], |
michael@428 | 506 | "(?s)^\\s*(.+?)\\s*$", "%1" |
michael@428 | 507 | ), |
michael@428 | 508 | "(?s)\\s+" |
michael@428 | 509 | ) |
michael@428 | 510 | ) do |
michael@428 | 511 | -- parse constraint |
michael@428 | 512 | local s, _, m = util.rmatch(constraint, "(?s)^(!?)([^:]+):(!?)(.+)$") |
michael@428 | 513 | if s == nil then |
michael@428 | 514 | return integrity.util.error(ctx, cfg, |
michael@428 | 515 | "invalid syntax in license configuration \"Assertion-PackageNames\" " .. |
michael@428 | 516 | "parameter: \"" .. constraint .. "\"") |
michael@428 | 517 | end |
michael@428 | 518 | local mode_negate = m[1] ~= "" |
michael@428 | 519 | local mode_regex = m[2] |
michael@428 | 520 | local package_negate = m[3] ~= "" |
michael@428 | 521 | local package_regex = m[4] |
michael@428 | 522 | -- apply the mode filter |
michael@428 | 523 | local mode_matches, _, _ = util.rmatch(ctx.rpm.mode, mode_regex); |
michael@428 | 524 | if (not mode_negate and mode_matches ~= nil) |
michael@428 | 525 | or ( mode_negate and mode_matches == nil) then |
michael@428 | 526 | -- apply the package filter to names of all installed packages |
michael@428 | 527 | for _, package in ipairs(packages) do |
michael@428 | 528 | if package_negate then |
michael@428 | 529 | integrity.util.debug(3, "require: \"%s\" !~ /%s/", package, package_regex) |
michael@428 | 530 | else |
michael@428 | 531 | integrity.util.debug(3, "require: \"%s\" ~~ /%s/", package, package_regex) |
michael@428 | 532 | end |
michael@428 | 533 | local package_matches, _, _ = util.rmatch(package, package_regex) |
michael@428 | 534 | if not ( (not package_negate and package_matches ~= nil) |
michael@428 | 535 | or ( package_negate and package_matches == nil)) then |
michael@428 | 536 | -- indicate integrity validation error |
michael@428 | 537 | return integrity.util.error(ctx, cfg, |
michael@428 | 538 | "installed package \"" .. package .. "\" " .. |
michael@428 | 539 | "under RPM run-time mode \"" .. ctx.rpm.mode .. "\" " .. |
michael@428 | 540 | "not covered by pattern \"" .. package_regex .. "\" " .. |
michael@428 | 541 | "of license configuration parameter \"Assertion-PackageNames\"") |
michael@428 | 542 | end |
michael@428 | 543 | end |
michael@428 | 544 | end |
michael@428 | 545 | end |
michael@428 | 546 | end |
michael@428 | 547 | |
michael@428 | 548 | -- process "Assertion-PackageReleaseAge" |
michael@428 | 549 | if cfg["Assertion-PackageReleaseAge"] ~= nil then |
michael@428 | 550 | integrity.util.debug(2, "checking: Assertion-PackageReleaseAge: \"%s[...]\"", string.sub(cfg["Assertion-PackageReleaseAge"], 1, 20)) |
michael@428 | 551 | |
michael@428 | 552 | -- parse constraint |
michael@428 | 553 | local constraint = cfg["Assertion-PackageReleaseAge"] |
michael@428 | 554 | local s, _, m = util.rmatch(constraint, "(?s)^([^:]+)%:([^:]+):([^\\s]+)\\s+(.+)$") |
michael@428 | 555 | if s == nil then |
michael@428 | 556 | return integrity.util.error(ctx, cfg, |
michael@428 | 557 | "invalid syntax in license configuration \"Assertion-PackageReleaseAge\" parameter") |
michael@428 | 558 | end |
michael@428 | 559 | local percent = m[1] / 100 |
michael@428 | 560 | local offset = m[2] |
michael@428 | 561 | local distregex = m[3] |
michael@428 | 562 | local spec = m[4] |
michael@428 | 563 | |
michael@428 | 564 | -- determine maximum release time difference (in seconds) |
michael@428 | 565 | local t_diff_max = 0 + util.rsubst(offset, "^(\\d+)([smhdw])$", function (t, unit) |
michael@428 | 566 | if unit == "s" then t = t * 1 |
michael@428 | 567 | elseif unit == "m" then t = t * 60 |
michael@428 | 568 | elseif unit == "h" then t = t * 60 * 60 |
michael@428 | 569 | elseif unit == "d" then t = t * 60 * 60 * 24 |
michael@428 | 570 | elseif unit == "w" then t = t * 60 * 60 * 24 * 7 |
michael@428 | 571 | end |
michael@428 | 572 | return t |
michael@428 | 573 | end) |
michael@428 | 574 | |
michael@428 | 575 | -- iterate over all package specifications to build release map |
michael@428 | 576 | local releases = {} |
michael@428 | 577 | for _, constraint in |
michael@428 | 578 | ipairs( |
michael@428 | 579 | util.rsplit( |
michael@428 | 580 | util.rsubst( |
michael@428 | 581 | spec, |
michael@428 | 582 | "(?s)^\\s*(.+?)\\s*$", "%1" |
michael@428 | 583 | ), |
michael@428 | 584 | "(?s)\\s+" |
michael@428 | 585 | ) |
michael@428 | 586 | ) do |
michael@428 | 587 | |
michael@428 | 588 | -- parse specification into package name and release constraint |
michael@428 | 589 | local s, _, m = util.rmatch(constraint, "(?s)^([^:]+):(.+)$") |
michael@428 | 590 | if s == nil then |
michael@428 | 591 | return integrity.util.error(ctx, cfg, |
michael@428 | 592 | "invalid syntax in license configuration \"Assertion-PackageReleaseAge\" " .. |
michael@428 | 593 | "parameter: \"" .. constraint .. "\"") |
michael@428 | 594 | end |
michael@428 | 595 | |
michael@428 | 596 | -- store result into release map |
michael@428 | 597 | releases[m[1]] = m[2] |
michael@428 | 598 | end |
michael@428 | 599 | |
michael@428 | 600 | -- query RPMDB for releases of all installed packages and decide |
michael@428 | 601 | -- whether the release time is inside or outside our constraint window |
michael@428 | 602 | local release_window_inside = 0 |
michael@428 | 603 | local release_window_outside = 0 |
michael@428 | 604 | local release_window_foreign = 0 |
michael@428 | 605 | local release_window_unknown = 0 |
michael@428 | 606 | for _, line in ipairs(rpm.query("Q:%{NAME}:%{RELEASE}:%{DISTRIBUTION}", true, "*")) do |
michael@428 | 607 | local s, _, m = util.rmatch(line, "(?s)^Q:([^:]+):(\\d\\d\\d\\d)(\\d\\d)(\\d\\d):(.+)$") |
michael@428 | 608 | if s ~= nil then |
michael@428 | 609 | -- parse query results |
michael@428 | 610 | local name = m[1] |
michael@428 | 611 | local t_release = os.time({ |
michael@428 | 612 | year = tonumber(m[2]), |
michael@428 | 613 | month = tonumber(m[3]), |
michael@428 | 614 | day = tonumber(m[4]), |
michael@428 | 615 | hour = 23, |
michael@428 | 616 | min = 59, |
michael@428 | 617 | sec = 59 |
michael@428 | 618 | }) |
michael@428 | 619 | local dist = m[5] |
michael@428 | 620 | |
michael@428 | 621 | -- only check files of the constrained distribution(s) |
michael@428 | 622 | if util.rmatch(dist, "(?s)" .. distregex) then |
michael@428 | 623 | |
michael@428 | 624 | -- determine minimum release constraint |
michael@428 | 625 | local t_release_min = releases[name] |
michael@428 | 626 | if t_release_min == nil then |
michael@428 | 627 | t_release_min = releases["*"] |
michael@428 | 628 | end |
michael@428 | 629 | if t_release_min == nil then |
michael@428 | 630 | t_release_min = os.time() |
michael@428 | 631 | else |
michael@428 | 632 | local s, _, m = util.rmatch(t_release_min, "^(?s)(\\d{4})(\\d{2})(\\d{2})$") |
michael@428 | 633 | t_release_min = os.time({ |
michael@428 | 634 | year = tonumber(m[1]), |
michael@428 | 635 | month = tonumber(m[2]), |
michael@428 | 636 | day = tonumber(m[3]), |
michael@428 | 637 | hour = 0, |
michael@428 | 638 | min = 0, |
michael@428 | 639 | sec = 0 |
michael@428 | 640 | }) |
michael@428 | 641 | end |
michael@428 | 642 | |
michael@428 | 643 | -- check time difference of package release |
michael@428 | 644 | local t_diff = os.difftime(t_release_min, t_release) |
michael@428 | 645 | integrity.util.debug(4, "calc: %d - %d = %d", t_release_min, t_release, t_diff) |
michael@428 | 646 | integrity.util.debug(4, "require: %d <= 0 or (%d > 0 and %d < %d)", t_diff, t_diff, t_diff, t_diff_max) |
michael@428 | 647 | if t_diff <= 0 or (t_diff > 0 and t_diff < t_diff_max) then |
michael@428 | 648 | release_window_inside = release_window_inside + 1 |
michael@428 | 649 | else |
michael@428 | 650 | release_window_outside = release_window_outside + 1 |
michael@428 | 651 | end |
michael@428 | 652 | else |
michael@428 | 653 | release_window_foreign = release_window_foreign + 1 |
michael@428 | 654 | end |
michael@428 | 655 | else |
michael@428 | 656 | release_window_unknown = release_window_unknown + 1 |
michael@428 | 657 | end |
michael@428 | 658 | end |
michael@428 | 659 | integrity.util.debug(3, "info: inside %d, outside %d, foreign %d, unknown %d", |
michael@428 | 660 | release_window_inside, release_window_outside, release_window_foreign, release_window_unknown) |
michael@428 | 661 | |
michael@428 | 662 | -- check validity of overall constraint |
michael@428 | 663 | local percent_inside = |
michael@428 | 664 | (release_window_inside / (release_window_inside + release_window_outside)) |
michael@428 | 665 | integrity.util.debug(3, "require: %d >= %d", percent_inside, percent) |
michael@428 | 666 | if percent_inside < percent then |
michael@428 | 667 | return integrity.util.error(ctx, cfg, |
michael@428 | 668 | "there are only " .. math.floor(percent_inside * 100) .. "% " .. |
michael@428 | 669 | "packages inside the release date constraint " .. |
michael@428 | 670 | "(expected a minimum of " .. math.floor(percent * 100) .. "%)") |
michael@428 | 671 | end |
michael@428 | 672 | end |
michael@428 | 673 | |
michael@428 | 674 | -- process "Assertion-Expression" constraint |
michael@428 | 675 | if cfg["Assertion-Expression"] ~= nil then |
michael@428 | 676 | integrity.util.debug(2, "checking: Assertion-Expression: \"%s\"", cfg["Assertion-Expression"]) |
michael@428 | 677 | |
michael@428 | 678 | -- expand special consytructs in expression |
michael@428 | 679 | local expr = cfg["Assertion-Expression"] |
michael@428 | 680 | expr = util.rsubst(expr, "(%\{[a-zA-Z_][a-zA-Z0-9_]+\})", function (str) |
michael@428 | 681 | return rpm.expand(str) |
michael@428 | 682 | end) |
michael@428 | 683 | expr = util.rsubst(expr, "\"((?:\\\\.|[^\"])+)\"\\s*~~\\s*/((?:\\\\.|[^/])+)/", function (str, regex) |
michael@428 | 684 | if util.rmatch(str, "(?s)" .. regex) ~= nil then |
michael@428 | 685 | return "true" |
michael@428 | 686 | else |
michael@428 | 687 | return "false" |
michael@428 | 688 | end |
michael@428 | 689 | end) |
michael@428 | 690 | |
michael@428 | 691 | -- evaluate expression |
michael@428 | 692 | integrity.util.debug(3, "evaluate: %s", expr) |
michael@428 | 693 | result = assert(loadstring(expr))() |
michael@428 | 694 | if type(result) ~= "boolean" then |
michael@428 | 695 | result = false |
michael@428 | 696 | end |
michael@428 | 697 | if not result then |
michael@428 | 698 | return integrity.util.error(ctx, cfg, |
michael@428 | 699 | "expression \"" .. cfg["Assertion-Expression"] .. "\" " .. |
michael@428 | 700 | "of license configuration parameter \"Assertion-Expression\"" .. |
michael@428 | 701 | "evaluated to false") |
michael@428 | 702 | end |
michael@428 | 703 | end |
michael@428 | 704 | |
michael@428 | 705 | -- indicate license integrity validation success |
michael@428 | 706 | return "OK" |
michael@428 | 707 | end |
michael@428 | 708 | |
michael@428 | 709 | - -- integrity processor utilities namespace |
michael@428 | 710 | integrity.util = {} |
michael@428 | 711 | |
michael@428 | 712 | - -- write debug information to stderr |
michael@428 | 713 | function integrity.util.debug(level_this, msg, ...) |
michael@428 | 714 | local level_min = os.getenv("OPENPKG_LICENSE_DEBUG") |
michael@428 | 715 | if level_min ~= nil then |
michael@428 | 716 | if type(level_min) == "string" then |
michael@428 | 717 | level_min = tonumber(level_min) |
michael@428 | 718 | end |
michael@428 | 719 | if type(level_min) ~= "number" then |
michael@428 | 720 | level_min = 0 |
michael@428 | 721 | end |
michael@428 | 722 | if level_this <= level_min then |
michael@428 | 723 | local output |
michael@428 | 724 | if type(msg) == "function" then |
michael@428 | 725 | output = msg(...) |
michael@428 | 726 | else |
michael@428 | 727 | output = string.format(msg, ...) |
michael@428 | 728 | end |
michael@428 | 729 | local prefix = "" |
michael@428 | 730 | local i = 1 |
michael@428 | 731 | while (i < level_this) do |
michael@428 | 732 | prefix = prefix .. " " |
michael@428 | 733 | i = i + 1 |
michael@428 | 734 | end |
michael@428 | 735 | io.stderr:write("rpm: DEBUG: " .. prefix .. output .. "\n") |
michael@428 | 736 | end |
michael@428 | 737 | end |
michael@428 | 738 | end |
michael@428 | 739 | |
michael@428 | 740 | - -- load OpenPKG instance UUIDs |
michael@428 | 741 | function integrity.util.uuids() |
michael@428 | 742 | local uuids = { |
michael@428 | 743 | UUID_REGISTRY = "", |
michael@428 | 744 | UUID_INSTANCE = "", |
michael@428 | 745 | UUID_PLATFORM = "" |
michael@428 | 746 | } |
michael@428 | 747 | local filename = rpm.expand("%{l_prefix}/etc/openpkg/uuid") |
michael@428 | 748 | local txt = rpm.slurp(filename) |
michael@428 | 749 | if txt ~= nil then |
michael@428 | 750 | for name, _ in pairs(uuids) do |
michael@428 | 751 | local s, _, m = util.rmatch(txt, "(?s)^.*" .. name .. "=\"([^\"\"]+)\".*$") |
michael@428 | 752 | if s ~= nil then |
michael@428 | 753 | uuids[name] = m[1] |
michael@428 | 754 | end |
michael@428 | 755 | end |
michael@428 | 756 | end |
michael@428 | 757 | return uuids |
michael@428 | 758 | end |
michael@428 | 759 | |
michael@428 | 760 | - -- report validation warning |
michael@428 | 761 | function integrity.util.warning(ctx, cfg, warning) |
michael@428 | 762 | -- return prominent warning message |
michael@428 | 763 | return |
michael@428 | 764 | "WARNING: OpenPKG run-time license check failed -- continue processing\n" .. |
michael@428 | 765 | "+-----------------------------------------------------------------------------+\n" .. |
michael@428 | 766 | "| Attention, the OpenPKG RPM run-time integrity checking facility encountered a\n" .. |
michael@428 | 767 | "| non-fatal problem during license checking, but allows processing to continue.\n" .. |
michael@428 | 768 | "| The particular warning reported by the OpenPKG license processor is:\n" .. |
michael@428 | 769 | "|\n" .. |
michael@428 | 770 | util.textwrap("| ", warning, 60, 70) .. |
michael@428 | 771 | "|\n" .. |
michael@428 | 772 | "| Notice: Operation of the OpenPKG Framework requires a valid license.\n" .. |
michael@428 | 773 | "| Go to http://openpkg.com/go/framework-license for more details, please.\n" .. |
michael@428 | 774 | "+-----------------------------------------------------------------------------+" |
michael@428 | 775 | end |
michael@428 | 776 | |
michael@428 | 777 | - -- report validation error |
michael@428 | 778 | function integrity.util.error(ctx, cfg, error) |
michael@428 | 779 | -- support conversion of errors into warnings |
michael@428 | 780 | if cfg["Assertion-ErrorToWarning"] ~= nil then |
michael@428 | 781 | if cfg["Assertion-ErrorToWarning"] == "yes" then |
michael@428 | 782 | return integrity.util.warning(ctx, cfg, error) |
michael@428 | 783 | end |
michael@428 | 784 | end |
michael@428 | 785 | |
michael@428 | 786 | -- return prominent error message |
michael@428 | 787 | return |
michael@428 | 788 | "ERROR: OpenPKG run-time license check failed -- stopping processing\n" .. |
michael@428 | 789 | "+-----------------------------------------------------------------------------+\n" .. |
michael@428 | 790 | "| Sorry, the OpenPKG RPM run-time integrity checking facility encountered a\n" .. |
michael@428 | 791 | "| fatal problem during license checking and stops processing immediately.\n" .. |
michael@428 | 792 | "| The particular error reported by the OpenPKG license processor is:\n" .. |
michael@428 | 793 | "|\n" .. |
michael@428 | 794 | util.textwrap("| ", error, 60, 70) .. |
michael@428 | 795 | "|\n" .. |
michael@428 | 796 | "| Notice: Operation of the OpenPKG Framework requires a valid license.\n" .. |
michael@428 | 797 | "| Go to http://openpkg.com/go/framework-license for more details, please.\n" .. |
michael@428 | 798 | "| Run \"openpkg man license\" for details about local license management.\n" .. |
michael@428 | 799 | "+-----------------------------------------------------------------------------+" |
michael@428 | 800 | end |
michael@428 | 801 | |
michael@428 | 802 | -----BEGIN PGP SIGNATURE----- |
michael@428 | 803 | Comment: OpenPKG GmbH <openpkg@openpkg.com> |
michael@428 | 804 | |
michael@428 | 805 | iEYEARECAAYFAk8BelcACgkQZwQuyWG3rjTL6QCeLTLVj4PTnd/E7mf+Sv4mgbZj |
michael@428 | 806 | 5J0AoMXrO4EimPSSCZSJ1TLW8f8GP+B5 |
michael@428 | 807 | =AVpf |
michael@428 | 808 | -----END PGP SIGNATURE----- |