mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
Add lp Rust bindings
Signed-off-by: David Mulder <dmulder@samba.org> Reviewed-by: Alexander Bokovoy <ab@samba.org>
This commit is contained in:
parent
61a5dc11a7
commit
f0cbe4d5a2
18
docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml
Normal file
18
docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<samba:parameter name="himmelblaud hello enabled"
|
||||
context="G"
|
||||
type="boolean"
|
||||
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
||||
<description>
|
||||
|
||||
<para>This parameter controls Hello enrollment and authentication to
|
||||
Azure Entra ID. By default, it is disabled to prevent security risks,
|
||||
such as on hosts exposing the SSH port. Administrators should enable
|
||||
this setting only when Hello enrollment is appropriate for their
|
||||
environment.
|
||||
|
||||
</para>
|
||||
</description>
|
||||
|
||||
<value type="default">no</value>
|
||||
<value type="example">yes</value>
|
||||
</samba:parameter>
|
17
docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml
Normal file
17
docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<samba:parameter name="himmelblaud sfa fallback"
|
||||
context="G"
|
||||
type="boolean"
|
||||
xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
||||
<description>
|
||||
|
||||
<para>This parameter is designed to control whether Himmelblaud should fallback to
|
||||
Single Factor Authentication (SFA) if Multi-Factor Authentication (MFA) isn't
|
||||
available. This normally is possible during a short window during which MFA
|
||||
enrollment is available to a new user.
|
||||
|
||||
</para>
|
||||
</description>
|
||||
|
||||
<value type="default">no</value>
|
||||
<value type="example">yes</value>
|
||||
</samba:parameter>
|
@ -17,9 +17,11 @@ dbg = { workspace = true }
|
||||
[workspace]
|
||||
members = [
|
||||
"chelps", "dbg", "ntstatus_gen",
|
||||
"param",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
param = { path = "param" }
|
||||
dbg = { path = "dbg" }
|
||||
chelps = { path = "chelps" }
|
||||
ntstatus_gen = { path = "ntstatus_gen" }
|
||||
|
15
himmelblaud/param/Cargo.toml
Normal file
15
himmelblaud/param/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "param"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
chelps = { workspace = true }
|
||||
dbg.workspace = true
|
||||
ntstatus_gen.workspace = true
|
||||
paste = "1.0.15"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.69.4"
|
48
himmelblaud/param/build.rs
Normal file
48
himmelblaud/param/build.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let bindings = bindgen::Builder::default()
|
||||
.blocklist_function("qgcvt")
|
||||
.blocklist_function("qgcvt_r")
|
||||
.blocklist_function("qfcvt")
|
||||
.blocklist_function("qfcvt_r")
|
||||
.blocklist_function("qecvt")
|
||||
.blocklist_function("qecvt_r")
|
||||
.blocklist_function("strtold")
|
||||
.clang_arg("-Dbool=int")
|
||||
.clang_arg("-Doffset_t=loff_t")
|
||||
.clang_arg("-I../../bin/default")
|
||||
.clang_arg("-includestdint.h")
|
||||
.header("../../lib/param/param.h")
|
||||
.header("../../lib/param/loadparm.h")
|
||||
.header("../../source3/param/loadparm.h")
|
||||
.header("../../bin/default/lib/param/param_functions.h")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
println!(
|
||||
"cargo:rerun-if-changed=../../bin/default/lib/param/param_functions.h"
|
||||
);
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
|
||||
let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
src_dir.push("../../bin/default/source3");
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
src_dir.to_str().unwrap()
|
||||
);
|
||||
println!("cargo:rustc-link-lib=smbconf");
|
||||
|
||||
let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
src_dir.push("../../bin/default/lib/param");
|
||||
println!("cargo:rustc-link-lib=samba-hostconfig-private-samba");
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
src_dir.to_str().unwrap()
|
||||
);
|
||||
}
|
208
himmelblaud/param/src/lib.rs
Normal file
208
himmelblaud/param/src/lib.rs
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Parameter loading functions
|
||||
|
||||
Copyright (C) David Mulder 2024
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use chelps::{string_free, wrap_c_char, wrap_string};
|
||||
use dbg::{DBG_ERR, DBG_INFO, DBG_WARNING};
|
||||
use ntstatus_gen::NT_STATUS_UNSUCCESSFUL;
|
||||
use std::error::Error;
|
||||
use std::ffi::c_void;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
mod ffi {
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
}
|
||||
|
||||
pub struct LoadParm {
|
||||
lp: Arc<Mutex<*mut ffi::loadparm_context>>,
|
||||
}
|
||||
|
||||
macro_rules! lpcfg_str {
|
||||
($var:ident) => {
|
||||
paste::item! {
|
||||
pub fn $var (&self) -> Result<Option<String>, Box<dyn Error + '_>> {
|
||||
let lp = self.lp.lock()?;
|
||||
let val = unsafe { ffi::[< lpcfg_ $var >] (*lp) } ;
|
||||
unsafe { Ok(wrap_c_char(val)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! lpcfg_i32 {
|
||||
($var:ident) => {
|
||||
paste::item! {
|
||||
pub fn $var (&self) -> Result<i32, Box<dyn Error + '_>> {
|
||||
let lp = self.lp.lock()?;
|
||||
unsafe { Ok(ffi::[< lpcfg_ $var >] (*lp)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! lpcfg_bool {
|
||||
($var:ident) => {
|
||||
paste::item! {
|
||||
pub fn $var (&self) -> Result<bool, Box<dyn Error + '_>> {
|
||||
let lp = self.lp.lock()?;
|
||||
unsafe { Ok(ffi::[< lpcfg_ $var >] (*lp) != 0) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl LoadParm {
|
||||
pub fn new(configfile: Option<&str>) -> Result<Self, Box<dyn Error + '_>> {
|
||||
let lp = unsafe {
|
||||
match configfile {
|
||||
Some(configfile) => {
|
||||
let configfile_cstr = wrap_string(configfile);
|
||||
let lp = ffi::loadparm_init_global(0);
|
||||
if ffi::lpcfg_load(lp, configfile_cstr) != 1 {
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
string_free(configfile_cstr);
|
||||
lp
|
||||
}
|
||||
None => ffi::loadparm_init_global(1),
|
||||
}
|
||||
};
|
||||
Ok(LoadParm {
|
||||
lp: Arc::new(Mutex::new(lp)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn private_path(
|
||||
&self,
|
||||
name: &str,
|
||||
) -> Result<Option<String>, Box<dyn Error + '_>> {
|
||||
let lp = self.lp.lock()?;
|
||||
let path = unsafe {
|
||||
let name_cstr = wrap_string(name);
|
||||
let path =
|
||||
ffi::lpcfg_private_path(*lp as *mut c_void, *lp, name_cstr);
|
||||
string_free(name_cstr);
|
||||
path
|
||||
};
|
||||
unsafe { Ok(wrap_c_char(path)) }
|
||||
}
|
||||
|
||||
pub fn logfile(&self) -> Result<Option<String>, Box<dyn Error + '_>> {
|
||||
let lp = self.lp.lock()?;
|
||||
let logfile = unsafe {
|
||||
let lp_sub = ffi::lpcfg_noop_substitution();
|
||||
ffi::lpcfg_logfile(*lp, lp_sub, *lp as *mut c_void)
|
||||
};
|
||||
unsafe { Ok(wrap_c_char(logfile)) }
|
||||
}
|
||||
|
||||
pub fn idmap_range(
|
||||
&self,
|
||||
domain_name: &str,
|
||||
) -> Result<(u32, u32), Box<dyn Error + '_>> {
|
||||
if let Ok(Some(backend)) = self.idmap_backend(domain_name) {
|
||||
if backend != "upn" {
|
||||
DBG_ERR!("Backend '{}' is not supported for Entra ID", backend);
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
} else {
|
||||
DBG_WARNING!(
|
||||
"No idmap backend configured for domain '{}'",
|
||||
domain_name
|
||||
);
|
||||
DBG_INFO!("Falling back to default idmap configuration");
|
||||
return self.idmap_default_range();
|
||||
}
|
||||
let mut low: u32 = 0;
|
||||
let mut high: u32 = 0;
|
||||
let res = unsafe {
|
||||
let domain_name_cstr = wrap_string(domain_name);
|
||||
let res =
|
||||
ffi::lp_idmap_range(domain_name_cstr, &mut low, &mut high);
|
||||
string_free(domain_name_cstr);
|
||||
res
|
||||
};
|
||||
if res == 0 {
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
Ok((low, high))
|
||||
}
|
||||
|
||||
pub fn idmap_backend(
|
||||
&self,
|
||||
domain_name: &str,
|
||||
) -> Result<Option<String>, Box<dyn Error + '_>> {
|
||||
let backend = unsafe {
|
||||
let domain_name_cstr = wrap_string(domain_name);
|
||||
let backend = ffi::lp_idmap_backend(domain_name_cstr);
|
||||
string_free(domain_name_cstr);
|
||||
backend
|
||||
};
|
||||
unsafe { Ok(wrap_c_char(backend)) }
|
||||
}
|
||||
|
||||
pub fn idmap_default_range(
|
||||
&self,
|
||||
) -> Result<(u32, u32), Box<dyn Error + '_>> {
|
||||
if let Ok(Some(backend)) = self.idmap_default_backend() {
|
||||
if backend != "upn" {
|
||||
DBG_ERR!(
|
||||
"Default backend '{}' is not supported for Entra ID",
|
||||
backend
|
||||
);
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
} else {
|
||||
DBG_ERR!("No default idmap backend configured.");
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
let mut low: u32 = 0;
|
||||
let mut high: u32 = 0;
|
||||
let res = unsafe { ffi::lp_idmap_default_range(&mut low, &mut high) };
|
||||
if res == 0 {
|
||||
return Err(Box::new(NT_STATUS_UNSUCCESSFUL));
|
||||
}
|
||||
Ok((low, high))
|
||||
}
|
||||
|
||||
pub fn idmap_default_backend(
|
||||
&self,
|
||||
) -> Result<Option<String>, Box<dyn Error + '_>> {
|
||||
let backend = unsafe { ffi::lp_idmap_default_backend() };
|
||||
unsafe { Ok(wrap_c_char(backend)) }
|
||||
}
|
||||
|
||||
lpcfg_str!(realm);
|
||||
lpcfg_str!(winbindd_socket_directory);
|
||||
lpcfg_i32!(winbind_request_timeout);
|
||||
lpcfg_bool!(himmelblaud_sfa_fallback);
|
||||
lpcfg_bool!(himmelblaud_hello_enabled);
|
||||
lpcfg_str!(cache_directory);
|
||||
lpcfg_str!(template_homedir);
|
||||
lpcfg_str!(template_shell);
|
||||
}
|
||||
|
||||
unsafe impl Send for LoadParm {}
|
||||
unsafe impl Sync for LoadParm {}
|
@ -3165,6 +3165,14 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
|
||||
"acl claims evaluation",
|
||||
"AD DC only");
|
||||
|
||||
/* Set the default Himmelblaud globals */
|
||||
lpcfg_do_global_parameter(lp_ctx,
|
||||
"himmelblaud hello enabled",
|
||||
"false");
|
||||
lpcfg_do_global_parameter(lp_ctx,
|
||||
"himmelblaud sfa fallback",
|
||||
"false");
|
||||
|
||||
for (i = 0; parm_table[i].label; i++) {
|
||||
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
|
||||
lp_ctx->flags[i] |= FLAG_DEFAULT;
|
||||
|
@ -1004,6 +1004,10 @@ void loadparm_s3_init_globals(struct loadparm_context *lp_ctx,
|
||||
|
||||
Globals.acl_claims_evaluation = ACL_CLAIMS_EVALUATION_AD_DC_ONLY;
|
||||
|
||||
/* Set the default Himmelblaud globals */
|
||||
Globals.himmelblaud_hello_enabled = false;
|
||||
Globals.himmelblaud_sfa_fallback = false;
|
||||
|
||||
/* Now put back the settings that were set with lp_set_cmdline() */
|
||||
apply_lp_set_cmdline();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user