{
  "component-definition": {
    "uuid": "a9fbb439-f90a-4d68-9cd0-ff716bbcdef7",
    "metadata": {
      "title": "Debian 13 ISM Word-Count Enforcement Component Definition",
      "last-modified": "2026-09-16T00:00:00Z",
      "version": "1.0.0",
      "oscal-version": "1.1.2",
      "roles": [
        {
          "id": "system-administrator",
          "title": "System Administrator"
        },
        {
          "id": "system-security-officer",
          "title": "System Security Officer"
        }
      ],
      "parties": [
        {
          "uuid": "1b4346aa-044e-4e42-a524-53d40f60f879",
          "type": "organization",
          "name": "Platform Operations"
        }
      ],
      "responsible-parties": [
        {
          "role-id": "system-administrator",
          "party-uuids": [
            "1b4346aa-044e-4e42-a524-53d40f60f879"
          ]
        },
        {
          "role-id": "system-security-officer",
          "party-uuids": [
            "1b4346aa-044e-4e42-a524-53d40f60f879"
          ]
        }
      ],
      "remarks": "Theoretical component. It describes a configuration that satisfies the named controls when applied; it is not an assertion that any particular system is running it. An SSP leveraging this component must supply the implementation evidence for its own hosts.\n\nAssurance state is 'technically-tested': the configuration was applied to a clean Debian 13 install and verified end to end. It has NOT been independently assessed, and is not endorsed or accredited by the ACSC, NIST, or any assessment authority.",
      "document-ids": [
        {
          "scheme": "https://ns.oscalops.net/component-definitions",
          "identifier": "debian-13-pam-wordcount"
        }
      ],
      "props": [
        {
          "name": "assurance-state",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "technically-tested"
        },
        {
          "name": "assurance-authority",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "none; self-asserted by the contributing author"
        },
        {
          "name": "endorsement",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "none"
        },
        {
          "name": "publisher",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "library_component-definition contributors"
        },
        {
          "name": "publication-status",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "unpublished"
        },
        {
          "name": "artifact-slug",
          "ns": "https://ns.oscalops.net/component-definitions",
          "value": "debian-13-pam-wordcount"
        }
      ],
      "links": [
        {
          "href": "https://library.oscalops.net/component-definitions/debian-13-pam-wordcount/1.0.0/component-definition.json",
          "rel": "canonical",
          "text": "Reserved canonical URL; the registry is not yet published"
        }
      ]
    },
    "components": [
      {
        "uuid": "d5fd110b-962b-4b6f-b64e-b972c6d19567",
        "type": "software",
        "title": "Debian 13 ISM word-count enforcement (pam_ism_wordcount)",
        "description": "Enforces the ism-1558 minimum word count for passwords that are a sequence of words: at least 4 words on non-classified, OFFICIAL: Sensitive and PROTECTED systems, 5 on SECRET and 6 on TOP SECRET. Single-token passwords are passed through untouched, which is what lets ism-1558 and ism-2080 hold together.\n\nThe default implementation is pam_ism_wordcount.so, a purpose-built PAM module that counts whitespace-delimited words in one read-only, in-process pass. A pam_exec(8) shell equivalent is shipped as a fallback for hosts that cannot deploy a compiled module.\n\nDepends on debian-13-pwquality-base. The check reads the new password but never asks for it; pam_pwquality, earlier in the stack, obtains it. Without it pam-auth-update still gives pam_unix use_authtok, there is no token to use, and every password change fails: verified on a clean Debian 13 install. The apply script refuses to run without pam_pwquality in the stack.",
        "purpose": "Enforce the ISM word-count requirement for passphrases on local Debian accounts without imposing a complexity requirement on single-token passwords.",
        "props": [
          {
            "name": "os-distribution",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "debian"
          },
          {
            "name": "os-release",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "13"
          },
          {
            "name": "os-codename",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "trixie"
          },
          {
            "name": "setting",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "pam-auth-update:ism-wordcount-module"
          },
          {
            "name": "setting",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "pam-auth-update:ism-wordcount"
          },
          {
            "name": "setting",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "pam-module:pam_ism_wordcount.so"
          },
          {
            "name": "setting",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "file:/usr/local/sbin/ism-wordcount-check"
          },
          {
            "name": "setting",
            "ns": "https://ns.oscalops.net/component-definitions",
            "value": "file:/etc/security/ism-wordcount.conf"
          },
          {
            "name": "enforcement-mechanism",
            "ns": "https://ns.oscalops.net/component-definitions/debian-13-pam-wordcount",
            "value": "pam_ism_wordcount.so (in-process, default) or pam_exec.so running ism-wordcount-check (fallback)"
          },
          {
            "name": "dependency-posture",
            "ns": "https://ns.oscalops.net/component-definitions/debian-13-pam-wordcount",
            "value": "No packages beyond libpam-pwquality, libpwquality-tools and cracklib-runtime; pam_exec ships in libpam-modules. libpam-python and libpam-script were evaluated and rejected."
          },
          {
            "name": "pam-stack-priority",
            "ns": "https://ns.oscalops.net/component-definitions/debian-13-pam-wordcount",
            "value": "1020 (after pam_pwquality at 1024, ahead of pam_unix at 256)"
          },
          {
            "name": "additional-packages-required",
            "ns": "https://ns.oscalops.net/component-definitions/debian-13-pam-wordcount",
            "value": "none at runtime; building the module needs libpam0g-dev and a C compiler on a build host"
          }
        ],
        "links": [
          {
            "href": "#61822038-eb12-4200-95d7-2c99575d5195",
            "rel": "depends-on",
            "text": "pam_pwquality obtains the new password this check reads"
          }
        ],
        "responsible-roles": [
          {
            "role-id": "system-administrator",
            "party-uuids": [
              "1b4346aa-044e-4e42-a524-53d40f60f879"
            ]
          },
          {
            "role-id": "system-security-officer",
            "party-uuids": [
              "1b4346aa-044e-4e42-a524-53d40f60f879"
            ]
          }
        ],
        "control-implementations": [
          {
            "uuid": "46fa7608-c11c-4c78-9d84-e7b8652b6182",
            "source": "https://raw.githubusercontent.com/AustralianCyberSecurityCentre/ism-oscal/v2026.09.4/ISM_catalog.json",
            "description": "The ISM word-count requirement, as published in the ACSC ISM OSCAL catalogue release v2026.09.4.",
            "props": [
              {
                "name": "catalog-release",
                "ns": "https://ns.oscalops.net/component-definitions",
                "value": "v2026.09.4"
              },
              {
                "name": "catalog-authority",
                "ns": "https://ns.oscalops.net/component-definitions",
                "value": "Australian Cyber Security Centre"
              },
              {
                "name": "control-family",
                "ns": "https://ns.oscalops.net/component-definitions",
                "value": "Guidelines for system access > Credential management > Password strength"
              }
            ],
            "links": [
              {
                "href": "#36c41fd6-4e7c-4dbf-92bc-604bf58f40f1",
                "rel": "reference",
                "text": "Pinned ISM catalogue release"
              }
            ],
            "implemented-requirements": [
              {
                "uuid": "5fe1d36a-2dea-4167-a57c-e4358ead47d3",
                "control-id": "ism-1558",
                "description": "Partially implemented. This component enforces the word-count limb. Sequences, repeats and account-derived strings are rejected by debian-13-pam-pwquality; the provenance limbs are not enforced by any component.\n\nENFORCED, verified by behaviour through the PAM stack on all three applicability tiers: a password using a sequence of words must use at least 4 words on non-classified, OFFICIAL: Sensitive and PROTECTED systems, 5 on SECRET and 6 on TOP SECRET. This is implemented by pam_ism_wordcount.so, a purpose-built PAM module that counts whitespace-delimited words in a single read-only pass. It runs in-process, so the candidate never leaves the PAM process. A pam_exec(8) shell equivalent is shipped as a fallback for hosts that cannot deploy a compiled module; pam_exec ships in libpam-modules, so neither route requires an additional package.\n\nCrucially, the check applies ONLY to passwords that are a sequence of words. A single-token password is not one, so it is passed through untouched. That is what allows this control and ism-2080 to hold simultaneously; see the remarks for why a character-class module cannot.\n\nNOT ENFORCED: a sequence of categorised words, a real sentence in natural language, and song lyrics, quotes or other publicly available material all satisfy a word count while being exactly what this control prohibits. Verified: all three are still accepted. Determining whether words were randomly selected is not something any available module can do.",
                "props": [
                  {
                    "name": "implementation-status",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "partial"
                  },
                  {
                    "name": "applicability",
                    "ns": "https://cyber.gov.au/ns/ism/oscal/3.0",
                    "value": "NC"
                  },
                  {
                    "name": "applicability",
                    "ns": "https://cyber.gov.au/ns/ism/oscal/3.0",
                    "value": "OS"
                  },
                  {
                    "name": "applicability",
                    "ns": "https://cyber.gov.au/ns/ism/oscal/3.0",
                    "value": "P"
                  },
                  {
                    "name": "applicability",
                    "ns": "https://cyber.gov.au/ns/ism/oscal/3.0",
                    "value": "S"
                  },
                  {
                    "name": "applicability",
                    "ns": "https://cyber.gov.au/ns/ism/oscal/3.0",
                    "value": "TS"
                  },
                  {
                    "name": "correlates-nist-statement",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "ia-5.1_smt.h"
                  },
                  {
                    "name": "correlation-strength",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "narrower"
                  },
                  {
                    "name": "assessment-method",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "examine"
                  },
                  {
                    "name": "assessment-frequency",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "annual"
                  },
                  {
                    "name": "residual-risk",
                    "ns": "https://ns.oscalops.net/component-definitions",
                    "value": "Word count is enforced; randomness and provenance of the words are not. Natural-language sentences, lyrics and categorised word lists remain accepted."
                  }
                ],
                "links": [
                  {
                    "href": "#51799d81-e8a9-5fbe-a93c-3c77e3e85e2f",
                    "rel": "reference",
                    "text": "ism-1558 word-count check"
                  },
                  {
                    "href": "#4458d8f2-7275-50d0-bddc-1f1b5af4544e",
                    "rel": "reference",
                    "text": "pam-auth-update profile for the word-count check"
                  },
                  {
                    "href": "#4a83f138-8d1f-5580-afc6-afca5f91c3ef",
                    "rel": "reference",
                    "text": "pam_ism_wordcount source"
                  },
                  {
                    "href": "#0a472c7c-c5ba-5d12-81ca-13fa1b4ca2a7",
                    "rel": "reference",
                    "text": "pam-auth-update profile for the in-process module"
                  },
                  {
                    "href": "#1e0249c8-b96c-4bc8-a191-a2c0bd135f72",
                    "rel": "reference",
                    "text": "Verification script"
                  }
                ],
                "responsible-roles": [
                  {
                    "role-id": "system-security-officer",
                    "party-uuids": [
                      "1b4346aa-044e-4e42-a524-53d40f60f879"
                    ]
                  }
                ],
                "remarks": "Why not pam_passwdqc: it can enforce a word count, but passwdqc requires each min value to be no larger than the preceding one, so 'disabled' can only ever apply to the weakest character-class tiers. It can therefore never express 'reject all non-passphrases regardless of class'. Tested: under min=disabled,disabled,15,15,15 with passphrase=4 a two-word candidate is correctly rejected, but a 15-character single-token password is ALSO rejected -- which breaches ism-2080, since ism-1558 governs only passwords using a sequence of words. passwdqc's min is additionally an effective length rather than a raw character count, so it cannot assert the literal 'minimum of 15 characters' that ism-0421 states.\n\nThe pam_exec approach keys off word structure instead, which is what the control actually describes, and leaves single-token passwords alone.\n\nImplementation choice: a purpose-built C module is the default because it removes the only real exposure of the shell route, where expose_authtok passes the cleartext candidate across a pipe to a child process. The module reads PAM_AUTHTOK in-process and the candidate is never copied, logged, or passed to another process.\n\nC rather than Rust: the check is a single read-only pass counting whitespace transitions, with no allocation, no copying and no index arithmetic, so the memory-safety hazards C is criticised for are absent rather than merely managed. A Rust module would still require #[no_mangle] extern \"C\" and an unsafe read of a raw *const c_char from pam_get_item, placing unsafe code at exactly the point of risk, while adding a rustc build dependency and a much larger artefact. The source is 91 lines and compiles clean under -Wall -Wextra -Werror; the resulting object is roughly 15 kB and links only libpam and libc.\n\nAlternatives evaluated and rejected: libpam-python would also run in-process but depends on libpython3.13 and installs 11 packages including the full CPython standard library, linking a Python interpreter into sshd, login, sudo and cron; its Debian changelog records 'Fix CVE-2019-16729 again' in 2024, five years after the original. libpam-script uses the same external script model as pam_exec and so changes nothing.\n\nThe pam_exec fallback, where used, is hardened: pinned to type=password, ulimit -c 0 so a credential cannot reach a core file, umask 077, the shell read builtin rather than a command substitution so no second process holds the cleartext, and no branch that logs or passes the candidate as a command argument.\n\nResidual mitigation: pwqgen(1) or pwmake(1) generate passphrases so users never select words themselves, which is the only practical answer to the provenance limbs."
              }
            ]
          }
        ]
      }
    ],
    "back-matter": {
      "resources": [
        {
          "uuid": "51799d81-e8a9-5fbe-a93c-3c77e3e85e2f",
          "title": "ism-1558 word-count check",
          "description": "Invoked by pam_exec from the password stack. Enforces the minimum word count for passwords that are a sequence of words, and passes single-token passwords through so ism-2080 is not breached.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "shell-script"
            }
          ],
          "rlinks": [
            {
              "href": "scripts/ism-wordcount-check",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "ism-wordcount-check",
            "media-type": "text/plain",
            "value": "IyEvYmluL3NoCiMgaXNtLTE1NTggd29yZC1jb3VudCBjaGVjaywgaW52b2tlZCBieSBwYW1fZXhlYyg4KSBmcm9tIHRoZSBwYXNzd29yZCBzdGFjay4KIwojIGlzbS0xNTU4IGNvbnN0cmFpbnMgcGFzc3dvcmRzICJ1c2luZyBhIHNlcXVlbmNlIG9mIHdvcmRzIi4gQSBzaW5nbGUtdG9rZW4KIyBwYXNzd29yZCBpcyBub3QgYSB3b3JkIHNlcXVlbmNlLCBzbyB0aGUgcnVsZSBkb2VzIG5vdCBhcHBseSB0byBpdCAtLSBhbmQgdGhhdAojIGlzIHByZWNpc2VseSB3aGF0IGtlZXBzIGlzbS0yMDgwIChubyBjb21wbGV4aXR5IHJlcXVpcmVtZW50cyBpbXBvc2VkKSBpbnRhY3QuCiMgQSBjaGFyYWN0ZXItY2xhc3MtYmFzZWQgbW9kdWxlIHN1Y2ggYXMgcGFtX3Bhc3N3ZHFjIGNhbm5vdCBleHByZXNzIHRoaXMsCiMgYmVjYXVzZSBpdCBjYW4gb25seSBkaXNhYmxlIHdob2xlIGNvbXBsZXhpdHkgdGllcnMuCiMKIyBFeGl0IDAgYWNjZXB0cywgZXhpdCAxIHJlamVjdHMuIEludm9rZWQgYXM6CiMgICBwYXNzd29yZCByZXF1aXNpdGUgcGFtX2V4ZWMuc28gZXhwb3NlX2F1dGh0b2sgcXVpZXQgL3Vzci9sb2NhbC9zYmluL2lzbS13b3JkY291bnQtY2hlY2sKCiMgRGVmZW5jZSBpbiBkZXB0aCBhZ2FpbnN0IHRoZSBvbmUgcmVhbCBleHBvc3VyZSBoZXJlOiBwYW1fZXhlYyBoYW5kcyB0aGUKIyBjbGVhcnRleHQgY2FuZGlkYXRlIHRvIHRoaXMgc2NyaXB0IG9uIHN0ZGluLiBOb3RoaW5nIG1heSBvdXRsaXZlIHRoZSBwcm9jZXNzLgp1bGltaXQgLWMgMCAyPi9kZXYvbnVsbCB8fCB0cnVlCSMgbmV2ZXIgY29yZS1kdW1wIHdpdGggYSBjcmVkZW50aWFsIGluIG1lbW9yeQp1bWFzayAwNzcKClsgIiRQQU1fVFlQRSIgPSAicGFzc3dvcmQiIF0gfHwgZXhpdCAwCgpNSU5fV09SRFM9NApbIC1yIC9ldGMvc2VjdXJpdHkvaXNtLXdvcmRjb3VudC5jb25mIF0gJiYgLiAvZXRjL3NlY3VyaXR5L2lzbS13b3JkY291bnQuY29uZgoKIyByZWFkIGJ1aWx0aW4sIG5vdCAkKGNhdCk6IGEgY29tbWFuZCBzdWJzdGl0dXRpb24gd291bGQgZm9yayBhIHNlY29uZCBwcm9jZXNzCiMgdGhhdCBhbHNvIGhvbGRzIHRoZSBjbGVhcnRleHQuIHJlYWQga2VlcHMgaXQgaW4gdGhpcyBzaGVsbCBvbmx5LiBJdCByZXR1cm5zCiMgbm9uLXplcm8gYXQgRU9GIHdpdGhvdXQgYSB0cmFpbGluZyBuZXdsaW5lLCB3aGljaCBpcyB0aGUgbm9ybWFsIGNhc2UgaGVyZS4KSUZTPSByZWFkIC1yIHB3IHx8IHRydWUKCiMgUEFNIHJ1bnMgdGhlIHBhc3N3b3JkIHN0YWNrIHR3aWNlOiBhIHByZWxpbWluYXJ5IGNoZWNrIHdoZXJlIHRoZSBuZXcgdG9rZW4gaXMKIyBub3QgeWV0IHNldCwgdGhlbiB0aGUgdXBkYXRlLiBOb3RoaW5nIHRvIGluc3BlY3QgaW4gdGhlIGZpcnN0IHBhc3MuClsgLW4gIiRwdyIgXSB8fCBleGl0IDAKCnNldCAtZgkJIyBhIHBhc3N3b3JkIG11c3QgbmV2ZXIgYmUgZ2xvYi1leHBhbmRlZApzZXQgLS0gJHB3CSMgZGVsaWJlcmF0ZSBJRlMgd29yZCBzcGxpdHRpbmcKCiMgTm90IGEgc2VxdWVuY2Ugb2Ygd29yZHM6IGlzbS0xNTU4IGRvZXMgbm90IGFwcGx5LCBhbmQgaW1wb3NpbmcgYW55IGZ1cnRoZXIKIyByZXF1aXJlbWVudCBoZXJlIHdvdWxkIGJyZWFjaCBpc20tMjA4MC4KWyAkIyAtbGUgMSBdICYmIGV4aXQgMAoKWyAkIyAtZ2UgIiRNSU5fV09SRFMiIF0gJiYgZXhpdCAwCmV4aXQgMQoKIyBObyBicmFuY2ggYWJvdmUgbG9ncywgZWNob2VzLCBvciBwYXNzZXMgJHB3IGFzIGFuIGFyZ3VtZW50IHRvIGFueSBjb21tYW5kLgo="
          }
        },
        {
          "uuid": "4458d8f2-7275-50d0-bddc-1f1b5af4544e",
          "title": "pam-auth-update profile for the word-count check",
          "description": "Declarative PAM profile at priority 1020, so it stacks after pam_pwquality (1024) and length errors are reported first. Deploys to /usr/share/pam-configs/ism-wordcount.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "pam-config"
            }
          ],
          "rlinks": [
            {
              "href": "config/pam-configs/ism-wordcount",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "ism-wordcount.pam-config",
            "media-type": "text/plain",
            "value": "TmFtZTogSVNNIHdvcmQtY291bnQgZW5mb3JjZW1lbnQgZm9yIHBhc3NwaHJhc2VzCkRlZmF1bHQ6IHllcwpQcmlvcml0eTogMTAyMApQYXNzd29yZC1UeXBlOiBQcmltYXJ5ClBhc3N3b3JkOgoJcmVxdWlzaXRlCQkJcGFtX2V4ZWMuc28gdHlwZT1wYXNzd29yZCBleHBvc2VfYXV0aHRvayBxdWlldCAvdXNyL2xvY2FsL3NiaW4vaXNtLXdvcmRjb3VudC1jaGVjawpQYXNzd29yZC1Jbml0aWFsOgoJcmVxdWlzaXRlCQkJcGFtX2V4ZWMuc28gdHlwZT1wYXNzd29yZCBleHBvc2VfYXV0aHRvayBxdWlldCAvdXNyL2xvY2FsL3NiaW4vaXNtLXdvcmRjb3VudC1jaGVjawo="
          }
        },
        {
          "uuid": "4a83f138-8d1f-5580-afc6-afca5f91c3ef",
          "title": "pam_ism_wordcount source",
          "description": "The complete source of the word-count PAM module: 91 lines, single read-only pass, no allocation. Auditable in full.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "c-source"
            }
          ],
          "rlinks": [
            {
              "href": "src/pam_ism_wordcount.c",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "pam_ism_wordcount.c",
            "media-type": "text/plain",
            "value": "LyoKICogcGFtX2lzbV93b3JkY291bnQgLSBlbmZvcmNlIHRoZSBJU00gaXNtLTE1NTggbWluaW11bSB3b3JkIGNvdW50LgogKgogKiBpc20tMTU1OCBjb25zdHJhaW5zIHBhc3N3b3JkcyAidXNpbmcgYSBzZXF1ZW5jZSBvZiB3b3JkcyIuIEEgc2luZ2xlLXRva2VuCiAqIHBhc3N3b3JkIGlzIG5vdCBvbmUsIHNvIHRoZSBydWxlIGRvZXMgbm90IGFwcGx5IHRvIGl0IC0tIHdoaWNoIGlzIHdoYXQga2VlcHMKICogaXNtLTIwODAgKG5vIGNvbXBsZXhpdHkgcmVxdWlyZW1lbnRzIGltcG9zZWQpIGludGFjdC4gQSBjaGFyYWN0ZXItY2xhc3MgbW9kdWxlCiAqIHN1Y2ggYXMgcGFtX3Bhc3N3ZHFjIGNhbm5vdCBleHByZXNzIHRoaXMgZGlzdGluY3Rpb24uCiAqCiAqIFRoZSBlbnRpcmUgY2hlY2sgaXMgYSBzaW5nbGUgcGFzcyBvdmVyIHRoZSBjYW5kaWRhdGUgY291bnRpbmcgd2hpdGVzcGFjZQogKiB0cmFuc2l0aW9ucy4gVGhlcmUgaXMgbm8gYWxsb2NhdGlvbiwgbm8gY29weWluZywgbm8gYnVmZmVyIGFyaXRobWV0aWMgYW5kIG5vCiAqIHBhcnNpbmcsIHNvIHRoZSB1c3VhbCBtZW1vcnktc2FmZXR5IGhhemFyZHMgb2YgQyBhcmUgc2ltcGx5IG5vdCBwcmVzZW50IGhlcmUuCiAqIFRoZSBjYW5kaWRhdGUgaXMgbmV2ZXIgY29waWVkLCBsb2dnZWQsIG9yIHBhc3NlZCB0byBhbm90aGVyIHByb2Nlc3MuCiAqCiAqIFN0YWNrIHVzYWdlOgogKiAgIHBhc3N3b3JkIHJlcXVpc2l0ZSBwYW1faXNtX3dvcmRjb3VudC5zbyBtaW53b3Jkcz00CiAqCiAqIEJ1aWxkOgogKiAgIGNjIC1PMiAtV2FsbCAtV2V4dHJhIC1mUElDIC1zaGFyZWQgLW8gcGFtX2lzbV93b3JkY291bnQuc28gXAogKiAgICAgIHBhbV9pc21fd29yZGNvdW50LmMgLWxwYW0KICovCgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSA8c2VjdXJpdHkvcGFtX21vZHVsZXMuaD4KI2luY2x1ZGUgPHNlY3VyaXR5L3BhbV9leHQuaD4KCiNkZWZpbmUgREVGQVVMVF9NSU5fV09SRFMgNAoKLyogQ291bnQgd2hpdGVzcGFjZS1kZWxpbWl0ZWQgd29yZHMuIFJlYWQtb25seSwgc2luZ2xlIHBhc3MsIG5vIGFsbG9jYXRpb24uICovCnN0YXRpYyBpbnQgY291bnRfd29yZHMoY29uc3QgY2hhciAqcykKewoJaW50IHdvcmRzID0gMDsKCWludCBpbl93b3JkID0gMDsKCglmb3IgKDsgKnMgIT0gJ1wwJzsgcysrKSB7CgkJaWYgKGlzc3BhY2UoKHVuc2lnbmVkIGNoYXIpKnMpKSB7CgkJCWluX3dvcmQgPSAwOwoJCX0gZWxzZSBpZiAoIWluX3dvcmQpIHsKCQkJaW5fd29yZCA9IDE7CgkJCXdvcmRzKys7CgkJfQoJfQoJcmV0dXJuIHdvcmRzOwp9CgpzdGF0aWMgaW50IG1pbl93b3Jkc19mcm9tX2FyZ3MoaW50IGFyZ2MsIGNvbnN0IGNoYXIgKiphcmd2KQp7CglzdGF0aWMgY29uc3QgY2hhciBrZXlbXSA9ICJtaW53b3Jkcz0iOwoJaW50IGk7CgoJZm9yIChpID0gMDsgaSA8IGFyZ2M7IGkrKykgewoJCWlmIChzdHJuY21wKGFyZ3ZbaV0sIGtleSwgc2l6ZW9mKGtleSkgLSAxKSA9PSAwKSB7CgkJCWludCB2ID0gYXRvaShhcmd2W2ldICsgc2l6ZW9mKGtleSkgLSAxKTsKCQkJaWYgKHYgPiAwICYmIHYgPD0gNjQpCgkJCQlyZXR1cm4gdjsKCQl9Cgl9CglyZXR1cm4gREVGQVVMVF9NSU5fV09SRFM7Cn0KClBBTV9FWFRFUk4gaW50IHBhbV9zbV9jaGF1dGh0b2socGFtX2hhbmRsZV90ICpwYW1oLCBpbnQgZmxhZ3MsCgkJCQlpbnQgYXJnYywgY29uc3QgY2hhciAqKmFyZ3YpCnsKCWNvbnN0IHZvaWQgKml0ZW0gPSBOVUxMOwoJY29uc3QgY2hhciAqY2FuZGlkYXRlOwoJaW50IG1pbl93b3Jkcywgd29yZHM7CgoJLyogVGhlIHN0YWNrIHJ1bnMgdHdpY2UuIFRoZSBuZXcgdG9rZW4gb25seSBleGlzdHMgb24gdGhlIHVwZGF0ZSBwYXNzLiAqLwoJaWYgKCEoZmxhZ3MgJiBQQU1fVVBEQVRFX0FVVEhUT0spKQoJCXJldHVybiBQQU1fU1VDQ0VTUzsKCglpZiAocGFtX2dldF9pdGVtKHBhbWgsIFBBTV9BVVRIVE9LLCAmaXRlbSkgIT0gUEFNX1NVQ0NFU1MgfHwgaXRlbSA9PSBOVUxMKQoJCXJldHVybiBQQU1fU1VDQ0VTUzsJLyogYW5vdGhlciBtb2R1bGUgd2lsbCByZWplY3QgYW4gYWJzZW50IHRva2VuICovCgoJY2FuZGlkYXRlID0gKGNvbnN0IGNoYXIgKilpdGVtOwoJbWluX3dvcmRzID0gbWluX3dvcmRzX2Zyb21fYXJncyhhcmdjLCBhcmd2KTsKCXdvcmRzID0gY291bnRfd29yZHMoY2FuZGlkYXRlKTsKCgkvKiBOb3QgYSBzZXF1ZW5jZSBvZiB3b3JkczogaXNtLTE1NTggZG9lcyBub3QgZ292ZXJuIGl0LiBJbXBvc2luZyBhbnkKCSAqIGZ1cnRoZXIgcmVxdWlyZW1lbnQgaGVyZSB3b3VsZCBicmVhY2ggaXNtLTIwODAuICovCglpZiAod29yZHMgPD0gMSkKCQlyZXR1cm4gUEFNX1NVQ0NFU1M7CgoJaWYgKHdvcmRzID49IG1pbl93b3JkcykKCQlyZXR1cm4gUEFNX1NVQ0NFU1M7CgoJcGFtX2Vycm9yKHBhbWgsICJBIHBhc3NwaHJhc2UgbXVzdCB1c2UgYXQgbGVhc3QgJWQgd29yZHMuIiwgbWluX3dvcmRzKTsKCXJldHVybiBQQU1fQVVUSFRPS19FUlI7Cn0K"
          }
        },
        {
          "uuid": "5aa658a3-6616-54af-940f-cee3cb5f54ea",
          "title": "Build file for the word-count module",
          "description": "Builds with -Wall -Wextra -Werror. Intended to run on a build host so a hardened target needs no compiler.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "makefile"
            }
          ],
          "rlinks": [
            {
              "href": "src/Makefile",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "Makefile",
            "media-type": "text/plain",
            "value": "IyBCdWlsZCB0aGUgaXNtLTE1NTggd29yZC1jb3VudCBQQU0gbW9kdWxlLgojCiMgQnVpbGQgb24gYSBidWlsZCBob3N0IGFuZCBzaGlwIHRoZSByZXN1bHRpbmcgLnNvOyBhIGhhcmRlbmVkIHRhcmdldCBzaG91bGQgbm90CiMgbmVlZCBhIGNvbXBpbGVyLiBgbWFrZSBpbnN0YWxsYCBpcyBwcm92aWRlZCBmb3IgY29udmVuaWVuY2UgaW4gdGVzdCBlbnZpcm9ubWVudHMuCgpDQyAgICAgID89IGNjCkNGTEFHUyAgPz0gLU8yIC1XYWxsIC1XZXh0cmEgLVdlcnJvciAtZlBJQwpMRExJQlMgIDo9IC1scGFtCiMgUEFNIGxvb2tzIGZvciBtb2R1bGVzIHdoZXJlIGxpYnBhbS1tb2R1bGVzIGluc3RhbGxlZCBpdHMgb3duLiBEZWJpYW4ncyBwYW0ucGMKIyBkZWZpbmVzIG5vIHNlY3VyZWRpciwgc28gcGtnLWNvbmZpZyByZXR1cm5zIGFuIGVtcHR5IHZhbHVlOyBhc2sgZHBrZyBpbnN0ZWFkLgpTRUNESVIgID89ICQocGF0c3Vic3QgJS9wYW1fdW5peC5zbywlLCQoc2hlbGwgZHBrZyAtTCBsaWJwYW0tbW9kdWxlczokJChkcGtnIC0tcHJpbnQtYXJjaGl0ZWN0dXJlKSAyPi9kZXYvbnVsbCB8IGdyZXAgJy9zZWN1cml0eS9wYW1fdW5peFwuc28kJCcgfCBoZWFkIC1uIDEpKQoKTU9EVUxFICA6PSBwYW1faXNtX3dvcmRjb3VudC5zbwoKYWxsOiAkKE1PRFVMRSkKCiQoTU9EVUxFKTogcGFtX2lzbV93b3JkY291bnQuYwoJJChDQykgJChDRkxBR1MpIC1zaGFyZWQgLW8gJEAgJDwgJChMRExJQlMpCgppbnN0YWxsOiAkKE1PRFVMRSkKCUB0ZXN0IC1uICIkKFNFQ0RJUikiICYmIHRlc3QgLWYgIiQoU0VDRElSKS9wYW1fdW5peC5zbyIgfHwgXAoJCXsgZWNobyAiZXJyb3I6IFBBTSBtb2R1bGUgZGlyZWN0b3J5IG5vdCBmb3VuZDsgcGFzcyBTRUNESVI9PGRpcj4iID4mMjsgZXhpdCAxOyB9CglpbnN0YWxsIC1tIDA2NDQgJChNT0RVTEUpICQoU0VDRElSKS8kKE1PRFVMRSkKCmNsZWFuOgoJcm0gLWYgJChNT0RVTEUpCgouUEhPTlk6IGFsbCBpbnN0YWxsIGNsZWFuCg=="
          }
        },
        {
          "uuid": "0a472c7c-c5ba-5d12-81ca-13fa1b4ca2a7",
          "title": "pam-auth-update profile for the in-process module",
          "description": "Declarative PAM profile at priority 1020, stacking after pam_pwquality (1024). Deploys to /usr/share/pam-configs/ism-wordcount-module.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "pam-config"
            }
          ],
          "rlinks": [
            {
              "href": "config/pam-configs/ism-wordcount-module",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "ism-wordcount-module.pam-config",
            "media-type": "text/plain",
            "value": "TmFtZTogSVNNIHdvcmQtY291bnQgZW5mb3JjZW1lbnQgZm9yIHBhc3NwaHJhc2VzIChpbi1wcm9jZXNzIG1vZHVsZSkKRGVmYXVsdDogeWVzClByaW9yaXR5OiAxMDIwClBhc3N3b3JkLVR5cGU6IFByaW1hcnkKUGFzc3dvcmQ6CglyZXF1aXNpdGUJCQlwYW1faXNtX3dvcmRjb3VudC5zbyBtaW53b3Jkcz00ClBhc3N3b3JkLUluaXRpYWw6CglyZXF1aXNpdGUJCQlwYW1faXNtX3dvcmRjb3VudC5zbyBtaW53b3Jkcz00Cg=="
          }
        },
        {
          "uuid": "10936d19-4304-444c-8c1d-7e55f96ad553",
          "title": "Apply script",
          "description": "Installs the word-count module (or the pam_exec fallback) with the minimum word count for the system's ISM applicability. Refuses to run unless pam_pwquality is already in the password stack.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "shell-script"
            }
          ],
          "rlinks": [
            {
              "href": "scripts/apply-wordcount.sh",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "apply-wordcount.sh",
            "media-type": "text/plain",
            "value": "IyEvYmluL3NoCiMgQXBwbHkgaXNtLTE1NTggd29yZC1jb3VudCBlbmZvcmNlbWVudCB0byBhIERlYmlhbiAxMyAodHJpeGllKSBob3N0LgojCiMgVXNhZ2U6IGFwcGx5LXdvcmRjb3VudC5zaCA8TkN8T1N8UHxTfFRTPiBbbW9kdWxlfGV4ZWNdCiMKIyBUaGUgZmlyc3QgYXJndW1lbnQgaXMgdGhlIHN5c3RlbSdzIElTTSBhcHBsaWNhYmlsaXR5IGNvZGUsIHdoaWNoIHNldHMgdGhlCiMgbWluaW11bSB3b3JkIGNvdW50OiA0IG9uIE5DLCBPUyBhbmQgUCwgNSBvbiBTLCA2IG9uIFRTLgojCiMgVGhlIHNlY29uZCBzZWxlY3RzIHRoZSBpbXBsZW1lbnRhdGlvbjoKIyAgIG1vZHVsZSAgKGRlZmF1bHQpIHBhbV9pc21fd29yZGNvdW50LnNvIC0tIGluLXByb2Nlc3MsIHRoZSBjYW5kaWRhdGUgbmV2ZXIKIyAgICAgICAgICAgbGVhdmVzIHRoZSBQQU0gcHJvY2Vzcy4gTmVlZHMgdGhlIG1vZHVsZSBidWlsdDsgc2VlIHNyYy9NYWtlZmlsZS4KIyAgIGV4ZWMgICAgcGFtX2V4ZWMuc28gcnVubmluZyBhIHNoZWxsIGNoZWNrIC0tIG5vIGJ1aWxkIHN0ZXAsIGJ1dCB0aGUgY2xlYXJ0ZXh0CiMgICAgICAgICAgIGNhbmRpZGF0ZSBjcm9zc2VzIGEgcGlwZSB0byBhIGNoaWxkIHByb2Nlc3MuCiMKIyBSZXF1aXJlcyBkZWJpYW4tMTMtcHdxdWFsaXR5LWJhc2UgdG8gYmUgYXBwbGllZCBmaXJzdC4gVGhlIGNoZWNrIHJlYWRzIHRoZSBuZXcKIyBwYXNzd29yZCBidXQgbmV2ZXIgYXNrcyBmb3IgaXQ7IHBhbV9wd3F1YWxpdHksIGVhcmxpZXIgaW4gdGhlIHN0YWNrLCBpcyB3aGF0CiMgb2J0YWlucyBpdC4gV2l0aG91dCBzdWNoIGEgbW9kdWxlIHBhbS1hdXRoLXVwZGF0ZSBzdGlsbCBnaXZlcyBwYW1fdW5peAojIHVzZV9hdXRodG9rLCB0aGVyZSBpcyBubyB0b2tlbiB0byB1c2UsIGFuZCBldmVyeSBwYXNzd29yZCBjaGFuZ2UgZmFpbHMuCiMKIyBJZGVtcG90ZW50OiBzYWZlIHRvIHJlLXJ1bi4KCnNldCAtZXUKClVTQUdFPSJ1c2FnZTogJDAgPE5DfE9TfFB8U3xUUz4gW21vZHVsZXxleGVjXSIKCkFQUExJQ0FCSUxJVFk9JChwcmludGYgJyVzJyAiJHsxOi19IiB8IHRyICdbOmxvd2VyOl0nICdbOnVwcGVyOl0nKQpjYXNlICIkQVBQTElDQUJJTElUWSIgaW4KCU5DfE9TfFApIE1JTl9XT1JEUz00IDs7CglTKSAgICAgICBNSU5fV09SRFM9NSA7OwoJVFMpICAgICAgTUlOX1dPUkRTPTYgOzsKCSopICAgICAgIGVjaG8gIiRVU0FHRSIgPiYyOyBleGl0IDIgOzsKZXNhYwoKV09SRENPVU5UX01PREU9IiR7MjotbW9kdWxlfSIKY2FzZSAiJFdPUkRDT1VOVF9NT0RFIiBpbgoJbW9kdWxlfGV4ZWMpIDs7CgkqKSBlY2hvICIkVVNBR0UiID4mMjsgZXhpdCAyIDs7CmVzYWMKClsgIiQoaWQgLXUpIiAtZXEgMCBdIHx8IHsgZWNobyAiZXJyb3I6IG11c3QgcnVuIGFzIHJvb3QiID4mMjsgZXhpdCAxOyB9CgpCQVNFX0RJUj0iJChDRFBBVEg9IGNkIC0tICIkKGRpcm5hbWUgLS0gIiQwIikvLi4iICYmIHB3ZCkiCgpwYW1fc2VjdXJlZGlyKCkgewoJdW5peD0kKGRwa2cgLUwgImxpYnBhbS1tb2R1bGVzOiQoZHBrZyAtLXByaW50LWFyY2hpdGVjdHVyZSkiIDI+L2Rldi9udWxsIHwKCQlncmVwICcvc2VjdXJpdHkvcGFtX3VuaXhcLnNvJCcgfCBoZWFkIC1uIDEpCglbIC1uICIkdW5peCIgXSAmJiBbIC1mICIkdW5peCIgXSB8fCByZXR1cm4gMQoJZGlybmFtZSAiJHVuaXgiCn0KCiMgRUxGIG1hZ2ljLCBjbGFzcywgYnl0ZSBvcmRlciBhbmQgbWFjaGluZS4gQSBtb2R1bGUgUEFNIGNhbm5vdCBsb2FkIGlzIG90aGVyd2lzZQojIG9ubHkgZGlzY292ZXJlZCBhdCB0aGUgbmV4dCBwYXNzd29yZCBjaGFuZ2UsIGFzICJNb2R1bGUgaXMgdW5rbm93biIuCmVsZl9pZCgpIHsKCXsgb2QgLUFuIC10eDEgLU42ICIkMSIgJiYgb2QgLUFuIC10eDEgLWoxOCAtTjIgIiQxIjsgfSAyPi9kZXYvbnVsbCB8IHRyIC1kICcgXG4nCn0KCnVucmVzb2x2ZWRfbW9kdWxlcygpIHsKCWdyZXAgLXYgJ15bWzpzcGFjZTpdXSojJyAvZXRjL3BhbS5kL2NvbW1vbi1wYXNzd29yZCB8CgkJZ3JlcCAtb0UgJ1teXVs6c3BhY2U6XV0rXC5zbyhbWzpzcGFjZTpdXXwkKScgfCB0ciAtZCAnIFx0JyB8CgkJd2hpbGUgSUZTPSByZWFkIC1yIG1vZDsgZG8KCQkJY2FzZSAiJG1vZCIgaW4KCQkJCS8qKSBbIC1mICIkbW9kIiBdIHx8IGVjaG8gIiRtb2QiIDs7CgkJCQkqKSAgWyAtZiAiJFNFQ0RJUi8kbW9kIiBdIHx8IGVjaG8gIiRtb2QiIDs7CgkJCWVzYWMKCQlkb25lCn0KCiMgLS0tIFByZWZsaWdodDogbm90aGluZyB1cCB0byBoZXJlIG1vZGlmaWVzIHRoZSBob3N0IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClNFQ0RJUj0kKHBhbV9zZWN1cmVkaXIpIHx8IHsKCWVjaG8gImVycm9yOiBjYW5ub3QgbG9jYXRlIHRoZSBQQU0gbW9kdWxlIGRpcmVjdG9yeSAocGFtX3VuaXguc28gZnJvbSBsaWJwYW0tbW9kdWxlcykiID4mMgoJZXhpdCAxCn0KCmdyZXAgLXFFICdeW14jXSpwYW1fcHdxdWFsaXR5XC5zbycgL2V0Yy9wYW0uZC9jb21tb24tcGFzc3dvcmQgfHwgewoJZWNobyAiZXJyb3I6IHJlcXVpcmVzIGRlYmlhbi0xMy1wd3F1YWxpdHktYmFzZSwgYW5kIHBhbV9wd3F1YWxpdHkuc28gaXMgbm90IGluIC9ldGMvcGFtLmQvY29tbW9uLXBhc3N3b3JkLiIgPiYyCgllY2hvICIgICAgICAgV2l0aG91dCBhIG1vZHVsZSB0aGF0IG9idGFpbnMgdGhlIG5ldyBwYXNzd29yZCBhaGVhZCBvZiB0aGlzIGNoZWNrLCIgPiYyCgllY2hvICIgICAgICAgZXZlcnkgcGFzc3dvcmQgY2hhbmdlIGZhaWxzLiBBcHBseSBkZWJpYW4tMTMtcHdxdWFsaXR5LWJhc2UgZmlyc3QuIiA+JjIKCWV4aXQgMQp9CgojIHBhbV9pc21fd29yZGNvdW50LnNvIGlzIGV4Y2x1ZGVkOiB0aGlzIHJ1biByZXBsYWNlcyBpdCwgd2hpY2ggaXMgaG93IGEgaG9zdCBsZWZ0CiMgYnJva2VuIGJ5IGFuIGVhcmxpZXIgaW5zdGFsbCBpcyByZXBhaXJlZC4KTUlTU0lORz0kKHVucmVzb2x2ZWRfbW9kdWxlcyB8IGdyZXAgLXZ4ICdwYW1faXNtX3dvcmRjb3VudFwuc28nIHx8IHRydWUpClsgLXogIiRNSVNTSU5HIiBdIHx8IHsKCWVjaG8gImVycm9yOiAvZXRjL3BhbS5kL2NvbW1vbi1wYXNzd29yZCBhbHJlYWR5IG5hbWVzIG1vZHVsZXMgUEFNIGNhbm5vdCBmaW5kOiIgPiYyCglwcmludGYgJyAgICAgICAgICVzXG4nICRNSVNTSU5HID4mMgoJZWNobyAiICAgICAgIFJlZnVzaW5nIHRvIG1vZGlmeSBhIHBhc3N3b3JkIHN0YWNrIHRoYXQgaXMgYWxyZWFkeSBicm9rZW4uIiA+JjIKCWV4aXQgMQp9CgppZiBbICIkV09SRENPVU5UX01PREUiID0gIm1vZHVsZSIgXTsgdGhlbgoJTU9EVUxFPSIkQkFTRV9ESVIvc3JjL3BhbV9pc21fd29yZGNvdW50LnNvIgoJaWYgWyAhIC1mICIkTU9EVUxFIiBdOyB0aGVuCgkJY29tbWFuZCAtdiBjYyA+L2Rldi9udWxsIDI+JjEgfHwgewoJCQllY2hvICJlcnJvcjogcGFtX2lzbV93b3JkY291bnQuc28gaXMgbm90IGJ1aWx0IGFuZCBubyBjb21waWxlciBpcyBwcmVzZW50LiIgPiYyCgkJCWVjaG8gIiAgICAgICBCdWlsZCBpdCBvbiBhIGJ1aWxkIGhvc3Qgd2l0aCAnbWFrZSAtQyBzcmMnIGFuZCBzaGlwIHRoZSAuc28sIiA+JjIKCQkJZWNobyAiICAgICAgIG9yIHJlLXJ1biB3aXRoICdleGVjJyB0byB1c2UgdGhlIHBhbV9leGVjIGZhbGxiYWNrLiIgPiYyCgkJCWV4aXQgMQoJCX0KCQltYWtlIC1DICIkQkFTRV9ESVIvc3JjIiA+L2Rldi9udWxsCglmaQoJWyAiJChlbGZfaWQgIiRNT0RVTEUiKSIgPSAiJChlbGZfaWQgIiRTRUNESVIvcGFtX3VuaXguc28iKSIgXSB8fCB7CgkJZWNobyAiZXJyb3I6ICRNT0RVTEUgaXMgbm90IGJ1aWx0IGZvciB0aGlzIGhvc3QgKCQoZHBrZyAtLXByaW50LWFyY2hpdGVjdHVyZSkpLiIgPiYyCgkJZWNobyAiICAgICAgIFBBTSBjb3VsZCBub3QgbG9hZCBpdCwgYW5kIGV2ZXJ5IHBhc3N3b3JkIGNoYW5nZSB3b3VsZCBmYWlsLiIgPiYyCgkJZXhpdCAxCgl9CmZpCgojIFN3aXRjaGluZyBtb2RlcyByZW1vdmVzIHRoZSBvdGhlciBwcm9maWxlLCBzbyBvbmx5IG9uZSBlbmZvcmNlbWVudCBwYXRoIGlzIGxpdmUuCmVjaG8gIj09PiBpbnN0YWxsaW5nIHdvcmQtY291bnQgZW5mb3JjZW1lbnQgKCRXT1JEQ09VTlRfTU9ERSwgbWluaW11bSAkTUlOX1dPUkRTIHdvcmRzKSIKcm0gLWYgL3Vzci9zaGFyZS9wYW0tY29uZmlncy9pc20td29yZGNvdW50IC91c3Ivc2hhcmUvcGFtLWNvbmZpZ3MvaXNtLXdvcmRjb3VudC1tb2R1bGUKCmlmIFsgIiRXT1JEQ09VTlRfTU9ERSIgPSAibW9kdWxlIiBdOyB0aGVuCglpbnN0YWxsIC1tIDA2NDQgIiRNT0RVTEUiICIkU0VDRElSL3BhbV9pc21fd29yZGNvdW50LnNvIgoJc2VkICJzL21pbndvcmRzPTQvbWlud29yZHM9JE1JTl9XT1JEUy9nIiBcCgkJIiRCQVNFX0RJUi9jb25maWcvcGFtLWNvbmZpZ3MvaXNtLXdvcmRjb3VudC1tb2R1bGUiID4vdXNyL3NoYXJlL3BhbS1jb25maWdzL2lzbS13b3JkY291bnQtbW9kdWxlCgljaG1vZCAwNjQ0IC91c3Ivc2hhcmUvcGFtLWNvbmZpZ3MvaXNtLXdvcmRjb3VudC1tb2R1bGUKCVBST0ZJTEU9aXNtLXdvcmRjb3VudC1tb2R1bGUKZWxzZQoJaW5zdGFsbCAtbSAwNzU1ICIkQkFTRV9ESVIvc2NyaXB0cy9pc20td29yZGNvdW50LWNoZWNrIiAvdXNyL2xvY2FsL3NiaW4vaXNtLXdvcmRjb3VudC1jaGVjawoJcHJpbnRmICdNSU5fV09SRFM9JXNcbicgIiRNSU5fV09SRFMiID4vZXRjL3NlY3VyaXR5L2lzbS13b3JkY291bnQuY29uZgoJY2htb2QgMDY0NCAvZXRjL3NlY3VyaXR5L2lzbS13b3JkY291bnQuY29uZgoJaW5zdGFsbCAtbSAwNjQ0ICIkQkFTRV9ESVIvY29uZmlnL3BhbS1jb25maWdzL2lzbS13b3JkY291bnQiIC91c3Ivc2hhcmUvcGFtLWNvbmZpZ3MvaXNtLXdvcmRjb3VudAoJUFJPRklMRT1pc20td29yZGNvdW50CmZpCgplY2hvICI9PT4gZW5hYmxpbmcgJFBST0ZJTEUgaW4gdGhlIFBBTSBzdGFjayIKcGFtLWF1dGgtdXBkYXRlIC0tcGFja2FnZSAtLWVuYWJsZSAiJFBST0ZJTEUiCgojIFByZWZsaWdodCBlc3RhYmxpc2hlZCB0aGUgc3RhY2sgd2FzIHNvdW5kLCBzbyBhbnl0aGluZyB1bnJlc29sdmVkIG5vdyBpcyBvdXJzLgpNSVNTSU5HPSQodW5yZXNvbHZlZF9tb2R1bGVzKQpbIC16ICIkTUlTU0lORyIgXSB8fCB7CglwYW0tYXV0aC11cGRhdGUgLS1wYWNrYWdlIC0tcmVtb3ZlICIkUFJPRklMRSIKCWVjaG8gImVycm9yOiBhZnRlciBlbmFibGluZyAkUFJPRklMRSwgUEFNIGNhbm5vdCBmaW5kOiIgPiYyCglwcmludGYgJyAgICAgICAgICVzXG4nICRNSVNTSU5HID4mMgoJZWNobyAiICAgICAgICRQUk9GSUxFIGhhcyBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgc3RhY2sgYWdhaW4uIiA+JjIKCWV4aXQgMQp9CgplY2hvICI9PT4gYXBwbGllZC4gVmVyaWZ5IHdpdGg6IHNjcmlwdHMvdmVyaWZ5LXdvcmRjb3VudC5zaCAtLXdpdGgtdGVzdC1hY2NvdW50Igo="
          }
        },
        {
          "uuid": "1e0249c8-b96c-4bc8-a191-a2c0bd135f72",
          "title": "Verification script",
          "description": "Checks the dependency, wiring and module architecture; with --with-test-account, exercises the word count through a real password change on a throwaway account and reports ism-1558.",
          "props": [
            {
              "name": "artifact-type",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "shell-script"
            }
          ],
          "rlinks": [
            {
              "href": "scripts/verify-wordcount.sh",
              "media-type": "text/plain"
            }
          ],
          "base64": {
            "filename": "verify-wordcount.sh",
            "media-type": "text/plain",
            "value": "IyEvYmluL3NoCiMgVmVyaWZ5IGlzbS0xNTU4IHdvcmQtY291bnQgZW5mb3JjZW1lbnQgb24gYSBEZWJpYW4gMTMgKHRyaXhpZSkgaG9zdC4KIwojIEJ5IGRlZmF1bHQgb25seSB3aXJpbmcgaXMgaW5zcGVjdGVkLCBhbmQgbm8gYWNjb3VudCBpcyBjcmVhdGVkIG9yIG1vZGlmaWVkLCBzbwojIHRoaXMgaXMgc2FmZSBvbiBhIHByb2R1Y3Rpb24gaG9zdC4gVGhhdCBjYW5ub3Qgc2hvdyB0aGUgd29yZCBjb3VudCBpcyBlbmZvcmNlZCwKIyBzbyBubyBpc20tMTU1OCByZXN1bHQgaXMgcmVwb3J0ZWQgd2l0aG91dCAtLXdpdGgtdGVzdC1hY2NvdW50LCB3aGljaCBleGVyY2lzZXMKIyBpdCB0aHJvdWdoIGEgcmVhbCBwYXNzd29yZCBjaGFuZ2Ugb24gYSB0aHJvd2F3YXkgYWNjb3VudCBjcmVhdGVkIGFuZCBkZWxldGVkIGJ5CiMgdGhpcyBzY3JpcHQuCiMKIyBUZXN0IGNhbmRpZGF0ZXMgYXJlIGxvbmcgZW5vdWdoIGZvciBhbnkgYXBwbGljYWJpbGl0eSdzIG1pbmltdW0gbGVuZ3RoLCBzbyBhCiMgcmVqZWN0aW9uIGlzIGF0dHJpYnV0YWJsZSB0byB0aGUgd29yZCBjb3VudCBhbmQgbm90IHRvIGFub3RoZXIgY29tcG9uZW50J3MKIyBwb2xpY3kuCiMKIyBFeGl0IHN0YXR1czogMCBpZiBub3RoaW5nIEZBSUxzLCAxIG90aGVyd2lzZS4KCnNldCAtdQoKV0lUSF9URVNUX0FDQ09VTlQ9MApbICIkezE6LX0iID0gIi0td2l0aC10ZXN0LWFjY291bnQiIF0gJiYgV0lUSF9URVNUX0FDQ09VTlQ9MQoKUEFTU19DT1VOVD0wCkZBSUxfQ09VTlQ9MApQQVJUSUFMX0NPVU5UPTAKCnJlcG9ydCgpIHsKCWNhc2UgIiQxIiBpbgoJCVBBU1MpIFBBU1NfQ09VTlQ9JCgoUEFTU19DT1VOVCArIDEpKSA7OwoJCVBBUlRJQUwpIFBBUlRJQUxfQ09VTlQ9JCgoUEFSVElBTF9DT1VOVCArIDEpKSA7OwoJCSopIEZBSUxfQ09VTlQ9JCgoRkFJTF9DT1VOVCArIDEpKSA7OwoJZXNhYwoJcHJpbnRmICclLThzICUtMTNzICVzXG4nICIkMSIgIiQyIiAiJDMiCn0KCnBhbV9zZWN1cmVkaXIoKSB7Cgl1bml4PSQoZHBrZyAtTCAibGlicGFtLW1vZHVsZXM6JChkcGtnIC0tcHJpbnQtYXJjaGl0ZWN0dXJlKSIgMj4vZGV2L251bGwgfAoJCWdyZXAgJy9zZWN1cml0eS9wYW1fdW5peFwuc28kJyB8IGhlYWQgLW4gMSkKCVsgLW4gIiR1bml4IiBdICYmIFsgLWYgIiR1bml4IiBdIHx8IHJldHVybiAxCglkaXJuYW1lICIkdW5peCIKfQoKZWxmX2lkKCkgewoJeyBvZCAtQW4gLXR4MSAtTjYgIiQxIiAmJiBvZCAtQW4gLXR4MSAtajE4IC1OMiAiJDEiOyB9IDI+L2Rldi9udWxsIHwgdHIgLWQgJyBcbicKfQoKdW5yZXNvbHZlZF9tb2R1bGVzKCkgewoJZ3JlcCAtdiAnXltbOnNwYWNlOl1dKiMnIC9ldGMvcGFtLmQvY29tbW9uLXBhc3N3b3JkIHwKCQlncmVwIC1vRSAnW15dWzpzcGFjZTpdXStcLnNvKFtbOnNwYWNlOl1dfCQpJyB8IHRyIC1kICcgXHQnIHwKCQl3aGlsZSBJRlM9IHJlYWQgLXIgbW9kOyBkbwoJCQljYXNlICIkbW9kIiBpbgoJCQkJLyopIFsgLWYgIiRtb2QiIF0gfHwgZWNobyAiJG1vZCIgOzsKCQkJCSopICBbIC1mICIkU0VDRElSLyRtb2QiIF0gfHwgZWNobyAiJG1vZCIgOzsKCQkJZXNhYwoJCWRvbmUKfQoKU0VDRElSPSQocGFtX3NlY3VyZWRpcikgfHwgU0VDRElSPQpDSEVDSz0vdXNyL2xvY2FsL3NiaW4vaXNtLXdvcmRjb3VudC1jaGVjawpNSU5fV09SRFM9NAoKaWYgZ3JlcCAtcSAncGFtX2lzbV93b3JkY291bnRcLnNvJyAvZXRjL3BhbS5kL2NvbW1vbi1wYXNzd29yZDsgdGhlbgoJV0NfTU9ERT1tb2R1bGUKCU1JTl9XT1JEUz0kKHNlZCAtbiAncy8uKnBhbV9pc21fd29yZGNvdW50XC5zby4qbWlud29yZHM9XChbMC05XSpcKS4qL1wxL3AnIC9ldGMvcGFtLmQvY29tbW9uLXBhc3N3b3JkIHwgaGVhZCAtMSkKCTogIiR7TUlOX1dPUkRTOj00fSIKZWxpZiBncmVwIC1xICdwYW1fZXhlY1wuc28uKmlzbS13b3JkY291bnQtY2hlY2snIC9ldGMvcGFtLmQvY29tbW9uLXBhc3N3b3JkOyB0aGVuCglXQ19NT0RFPWV4ZWMKCVsgLXIgL2V0Yy9zZWN1cml0eS9pc20td29yZGNvdW50LmNvbmYgXSAmJiAuIC9ldGMvc2VjdXJpdHkvaXNtLXdvcmRjb3VudC5jb25mCmVsc2UKCVdDX01PREU9bm9uZQpmaQoKZWNobyAiTW9kZTogICAgICAgJFdDX01PREUiCmVjaG8gIk1pbiB3b3JkczogICRNSU5fV09SRFMiCmVjaG8KCiMgRGlzdGluY3Qgd29yZHMgd2l0aCBkaWdpdHMsIHNvIG5vIGRpY3Rpb25hcnksIHNlcXVlbmNlIG9yIHJlcGVhdCBydWxlIHJlamVjdHMKIyB0aGVtLCBhbmQgZXZlcnkgY2FuZGlkYXRlIGlzIGxvbmdlciB0aGFuIHRoZSBoaWdoZXN0IG1pbmltdW0gbGVuZ3RoICgyMCkuCnNob3J0X3NlcT0nJwppPTEKd2hpbGUgWyAiJGkiIC1sdCAiJE1JTl9XT1JEUyIgXTsgZG8KCXNob3J0X3NlcT0iJHtzaG9ydF9zZXF9b3R0ZXIke2l9bWFuZ28gIgoJaT0kKChpICsgMSkpCmRvbmUKZnVsbF9zZXE9IiR7c2hvcnRfc2VxfXF1aWx0cmF2ZW4iCnNpbmdsZV90b2tlbj12YXVsdG90dGVybWFuZ29xdWlsdHJhdmVuZmpvcmR6ZWJyYXBsaW50aAoKIyAtLS0gZGVwZW5kZW5jeSBhbmQgd2lyaW5nIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmlmIGdyZXAgLXFFICdeW14jXSpwYW1fcHdxdWFsaXR5XC5zbycgL2V0Yy9wYW0uZC9jb21tb24tcGFzc3dvcmQ7IHRoZW4KCXJlcG9ydCBQQVNTICJkZXBlbmRlbmN5IiAicGFtX3B3cXVhbGl0eS5zbyBvYnRhaW5zIHRoZSBuZXcgcGFzc3dvcmQgYWhlYWQgb2YgdGhlIHdvcmQtY291bnQgY2hlY2siCmVsc2UKCXJlcG9ydCBGQUlMICJkZXBlbmRlbmN5IiAicGFtX3B3cXVhbGl0eS5zbyBpcyBhYnNlbnQ7IHdpdGggbm90aGluZyB0byBvYnRhaW4gdGhlIG5ldyBwYXNzd29yZCwgZXZlcnkgcGFzc3dvcmQgY2hhbmdlIGZhaWxzIgpmaQoKY2FzZSAiJFdDX01PREUiIGluCgltb2R1bGUpCgkJaWYgWyAteiAiJFNFQ0RJUiIgXSB8fCBbICEgLWYgIiRTRUNESVIvcGFtX2lzbV93b3JkY291bnQuc28iIF07IHRoZW4KCQkJcmVwb3J0IEZBSUwgIm1vZHVsZSIgIndpcmVkIGJ1dCBub3QgaW5zdGFsbGVkIGluICR7U0VDRElSOi10aGUgUEFNIG1vZHVsZSBkaXJlY3Rvcnl9OyBwYXNzd29yZCBjaGFuZ2VzIHdpbGwgZmFpbCIKCQllbGlmIFsgIiQoZWxmX2lkICIkU0VDRElSL3BhbV9pc21fd29yZGNvdW50LnNvIikiICE9ICIkKGVsZl9pZCAiJFNFQ0RJUi9wYW1fdW5peC5zbyIpIiBdOyB0aGVuCgkJCXJlcG9ydCBGQUlMICJtb2R1bGUiICIkU0VDRElSL3BhbV9pc21fd29yZGNvdW50LnNvIGlzIG5vdCBidWlsdCBmb3IgdGhpcyBhcmNoaXRlY3R1cmUiCgkJZWxzZQoJCQlyZXBvcnQgUEFTUyAibW9kdWxlIiAicGFtX2lzbV93b3JkY291bnQuc28gd2lyZWQgd2l0aCBtaW53b3Jkcz0kTUlOX1dPUkRTIGFuZCBpbnN0YWxsZWQgaW4gJFNFQ0RJUiIKCQlmaQoJCTs7CglleGVjKQoJCVsgLXggIiRDSEVDSyIgXSAmJgoJCQlyZXBvcnQgUEFTUyAiZXhlYyIgInBhbV9leGVjIHdpcmVkIHRvICRDSEVDSyB3aXRoIE1JTl9XT1JEUz0kTUlOX1dPUkRTIiB8fAoJCQlyZXBvcnQgRkFJTCAiZXhlYyIgInBhbV9leGVjIHdpcmVkLCBidXQgJENIRUNLIGlzIG1pc3Npbmcgb3Igbm90IGV4ZWN1dGFibGUiCgkJOzsKCSopCgkJcmVwb3J0IEZBSUwgInBhbS1zdGFjayIgIm5vIHdvcmQtY291bnQgZW5mb3JjZW1lbnQgaXMgcHJlc2VudCBpbiAvZXRjL3BhbS5kL2NvbW1vbi1wYXNzd29yZCIKCQk7Owplc2FjCgppZiBbIC1uICIkU0VDRElSIiBdICYmIFsgLXogIiQodW5yZXNvbHZlZF9tb2R1bGVzKSIgXTsgdGhlbgoJcmVwb3J0IFBBU1MgInBhbS1zdGFjayIgImV2ZXJ5IG1vZHVsZSBpbiAvZXRjL3BhbS5kL2NvbW1vbi1wYXNzd29yZCByZXNvbHZlcyIKZWxzZQoJcmVwb3J0IEZBSUwgInBhbS1zdGFjayIgIlBBTSBjYW5ub3QgZmluZDogJChlY2hvICQodW5yZXNvbHZlZF9tb2R1bGVzKSk7IGV2ZXJ5IHBhc3N3b3JkIGNoYW5nZSB3aWxsIGZhaWwiCmZpCgojIC0tLSBpc20tMTU1OCA6IHdvcmQgY291bnQsIGJ5IGJlaGF2aW91ciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KaWYgWyAiJFdJVEhfVEVTVF9BQ0NPVU5UIiAtZXEgMSBdICYmIFsgIiRXQ19NT0RFIiAhPSAibm9uZSIgXTsgdGhlbgoJVEVTVF9VU0VSPSJpc213YyQkIgoJc2V0X3Bhc3N3b3JkKCkgeyBlY2hvICIkVEVTVF9VU0VSOiQxIiB8IGNocGFzc3dkID4vZGV2L251bGwgMj4mMTsgfQoJaWYgdXNlcmFkZCAtTSAtcyAvdXNyL3NiaW4vbm9sb2dpbiAiJFRFU1RfVVNFUiIgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCgkJU0lOR0xFPTAgU0hPUlQ9MCBGVUxMPTAKCQlzZXRfcGFzc3dvcmQgIiRzaW5nbGVfdG9rZW4iICYmIFNJTkdMRT0xCgkJc2V0X3Bhc3N3b3JkICIkc2hvcnRfc2VxIiAmJiBTSE9SVD0xCgkJc2V0X3Bhc3N3b3JkICIkZnVsbF9zZXEiICYmIEZVTEw9MQoJCXVzZXJkZWwgLWYgIiRURVNUX1VTRVIiID4vZGV2L251bGwgMj4mMQoJCWlmIFsgIiRTSU5HTEUiIC1lcSAxIF0gJiYgWyAiJFNIT1JUIiAtZXEgMCBdICYmIFsgIiRGVUxMIiAtZXEgMSBdOyB0aGVuCgkJCXJlcG9ydCBQQVJUSUFMICJpc20tMTU1OCIgXAoJCQkJIiQoKE1JTl9XT1JEUyAtIDEpKS13b3JkIHNlcXVlbmNlIHJlamVjdGVkLCAkTUlOX1dPUkRTIHdvcmRzIGFuZCBzaW5nbGUgdG9rZW5zIGFjY2VwdGVkICgkV0NfTU9ERSk7IHJhbmRvbW5lc3Mgb2Ygd29yZCBjaG9pY2UgaXMgbm90IGVuZm9yY2VkIgoJCWVsc2UKCQkJcmVwb3J0IEZBSUwgImlzbS0xNTU4IiBcCgkJCQkid29yZCBjb3VudCBub3QgZW5mb3JjZWQgYXMgY2xhaW1lZDogc2luZ2xlIHRva2VuICQoWyAkU0lOR0xFIC1lcSAxIF0gJiYgZWNobyBhY2NlcHRlZCB8fCBlY2hvIHJlamVjdGVkKSwgJCgoTUlOX1dPUkRTIC0gMSkpIHdvcmRzICQoWyAkU0hPUlQgLWVxIDEgXSAmJiBlY2hvIGFjY2VwdGVkIHx8IGVjaG8gcmVqZWN0ZWQpLCAkTUlOX1dPUkRTIHdvcmRzICQoWyAkRlVMTCAtZXEgMSBdICYmIGVjaG8gYWNjZXB0ZWQgfHwgZWNobyByZWplY3RlZCkiCgkJZmkKCWVsc2UKCQlyZXBvcnQgRkFJTCAiaXNtLTE1NTgiICJjb3VsZCBub3QgY3JlYXRlIGEgdGhyb3dhd2F5IGFjY291bnQgdG8gdGVzdCB3aXRoIgoJZmkKZWxpZiBbICIkV0NfTU9ERSIgIT0gIm5vbmUiIF07IHRoZW4KCWVjaG8gIihpc20tMTU1OCBub3QgYXNzZXNzZWQ6IHJlLXJ1biB3aXRoIC0td2l0aC10ZXN0LWFjY291bnQgdG8gZXhlcmNpc2UgdGhlIHdvcmQgY291bnQpIgpmaQoKZWNobwplY2hvICJwYXNzZWQ6ICRQQVNTX0NPVU5UICBwYXJ0aWFsOiAkUEFSVElBTF9DT1VOVCAgZmFpbGVkOiAkRkFJTF9DT1VOVCIKWyAiJEZBSUxfQ09VTlQiIC1lcSAwIF0gfHwgZXhpdCAxCg=="
          }
        },
        {
          "uuid": "36c41fd6-4e7c-4dbf-92bc-604bf58f40f1",
          "title": "ACSC ISM OSCAL catalogue v2026.09.4",
          "description": "Australian Cyber Security Centre Information Security Manual OSCAL catalogue, release v2026.09.4: the release this document's control identifiers resolve against.",
          "props": [
            {
              "name": "release-tag",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "v2026.09.4"
            },
            {
              "name": "sha256",
              "ns": "https://ns.oscalops.net/component-definitions",
              "value": "237ea09362b8449ed5c5ee85de4725a0468ee73d13af7cf61c26d4e6ac47f12d"
            }
          ],
          "rlinks": [
            {
              "href": "https://raw.githubusercontent.com/AustralianCyberSecurityCentre/ism-oscal/v2026.09.4/ISM_catalog.json",
              "media-type": "application/json"
            }
          ]
        },
        {
          "uuid": "61822038-eb12-4200-95d7-2c99575d5195",
          "title": "debian-13-pwquality-base component-definition",
          "description": "The component this one depends on: pam_pwquality obtains the new password that the word-count check reads.",
          "document-ids": [
            {
              "scheme": "https://ns.oscalops.net/component-definitions",
              "identifier": "debian-13-pwquality-base"
            }
          ],
          "rlinks": [
            {
              "href": "https://library.oscalops.net/component-definitions/debian-13-pwquality-base/1.0.0/component-definition.json",
              "media-type": "application/json"
            }
          ]
        }
      ]
    }
  }
}
