view build.rs @ 100:3f11b8d30f63

Implement environment variable management. This actually wires up the environment variable handling to libpam, so that applications and modules can manage the environment through the authentication process.
author Paul Fisher <paul@pfish.zone>
date Tue, 24 Jun 2025 17:08:01 -0400
parents efe2f5f8b5b2
children
line wrap: on
line source

use bindgen::MacroTypeVariation;
use std::env;
use std::path::PathBuf;

fn main() {
    if cfg!(feature = "link") {
        println!("cargo::rustc-link-lib=pam");
        println!("cargo::rustc-check-cfg=cfg(pam_impl, values(\"linux-pam\",\"openpam\"))");
        let common_builder = bindgen::Builder::default()
            .merge_extern_blocks(true)
            .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
            .blocklist_type("pam_handle")
            .blocklist_type("pam_conv")
            .allowlist_var(".*")
            .allowlist_function("pam_start")
            .allowlist_function("pam_[gs]et_item")
            .allowlist_function("pam_get_(user|authtok)")
            .allowlist_function("pam_end")
            .allowlist_function("pam_strerror")
            .allowlist_function("pam_authenticate")
            .allowlist_function("pam_chauthtok")
            .allowlist_function("pam_acct_mgmt")
            .allowlist_function("pam_(ge|pu)tenv(list)?")
            .default_macro_constant_type(MacroTypeVariation::Unsigned);

        let linux_builder = common_builder
            .clone()
            // This function is not available in OpenPAM.
            // That means if somebody tries to run a binary compiled for
            // Linux-PAM against a different impl, it will fail.
            .allowlist_function("pam_syslog")
            .header_contents(
                "linux-pam.h",
                r#"
                #include <syslog.h> // for log levels
                #include <security/_pam_types.h>
                #include <security/pam_appl.h>
                #include <security/pam_ext.h>
                #include <security/pam_modules.h>
                "#,
            );
        let openpam_builder = common_builder
            .clone()
            // This function is not available in Linux-PAM.
            // That means if somebody tries to run a binary compiled for
            // OpenPAM against a different impl, it will fail.
            .allowlist_function("openpam_log")
            .header_contents(
                "openpam.h",
                r#"
                #include <security/pam_types.h>
                #include <security/openpam.h>
                #include <security/pam_appl.h>
                #include <security/pam_constants.h>
                "#,
            );

        let (pam_impl, bindings) = {
            if let Ok(bindings) = linux_builder.generate() {
                ("linux-pam", bindings)
            } else if let Ok(bindings) = openpam_builder.generate() {
                ("openpam", bindings)
            } else {
                panic!("unrecognized PAM implementation")
            }
        };
        println!("cargo::rustc-cfg=pam_impl={pam_impl:?}");
        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
        bindings
            .write_to_file(out_path.join("bindings.rs"))
            .unwrap();
    }
}