mirror of
https://github.com/samba-team/samba.git
synced 2025-01-10 01:18: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]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"chelps", "dbg", "ntstatus_gen",
|
"chelps", "dbg", "ntstatus_gen",
|
||||||
|
"param",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
param = { path = "param" }
|
||||||
dbg = { path = "dbg" }
|
dbg = { path = "dbg" }
|
||||||
chelps = { path = "chelps" }
|
chelps = { path = "chelps" }
|
||||||
ntstatus_gen = { path = "ntstatus_gen" }
|
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",
|
"acl claims evaluation",
|
||||||
"AD DC only");
|
"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++) {
|
for (i = 0; parm_table[i].label; i++) {
|
||||||
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
|
if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
|
||||||
lp_ctx->flags[i] |= FLAG_DEFAULT;
|
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;
|
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() */
|
/* Now put back the settings that were set with lp_set_cmdline() */
|
||||||
apply_lp_set_cmdline();
|
apply_lp_set_cmdline();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user