view build.rs @ 81:a8f4718fed5d

When dynamically linking against the wrong PAM, fail.
author Paul Fisher <paul@pfish.zone>
date Tue, 10 Jun 2025 01:16:39 -0400
parents 5aa1a010f1e8
children 73c3f8e3b49d
line wrap: on
line source

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

fn main() {
    if cfg!(feature = "link") {
        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")
            .allowlist_function("pam_get_authtok")
            .allowlist_function("pam_end")
            .dynamic_link_require_all(true)
            .default_macro_constant_type(MacroTypeVariation::Signed);

        let linux_builder = common_builder
            .clone()
            // This function is not available in OpenPAM.
            // We don't use it, but we include it so that if the user
            // tries to run this against the wrong PAM library, it fails.
            .allowlist_function("pam_start_confdir")
            .header_contents(
                "linux-pam.h",
                r#"
                #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.
            // We don't use it, but we include it so that if the user
            // tries to run this against the wrong PAM library, it fails.
            .allowlist_function("pam_setenv")
            .header_contents(
                "openpam.h",
                r#"
                #include <security/openpam.h>
                #include <security/pam_appl.h>
                #include <security/pam_constants.h>
                #include <security/pam_types.h>
                "#,
            );

        let (pam_impl, bindings) = {
            let bb = linux_builder.generate();
            bb.as_ref().unwrap();
            if let Ok(bindings) = bb {
                ("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();
    }
}