1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-11 16:58:40 +03:00

Add by-upn idmapping for Himmelblaud

Signed-off-by: David Mulder <dmulder@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
This commit is contained in:
David Mulder 2024-07-30 09:53:56 -06:00
parent f7edbf70d0
commit 92dca744e1
38 changed files with 4148 additions and 3 deletions

View File

@ -47,7 +47,7 @@ variables:
# Set this to the contents of bootstrap/sha1sum.txt
# which is generated by bootstrap/template.py --render
#
SAMBA_CI_CONTAINER_TAG: 8845099b492ab9888181df3e094e00ae8916ddb7
SAMBA_CI_CONTAINER_TAG: 2a20df752f162f9d1f617af785e463fa39944c6e
#
# We use the ubuntu2204 image as default as
# it matches what we have on atb-devel-224

View File

@ -84,6 +84,7 @@ PKGS = [
('libcap-dev', 'libcap-devel'),
('libacl1-dev', 'libacl-devel'),
('libattr1-dev', 'libattr-devel'),
('libutf8proc-dev', 'utf8proc-devel'),
# libNAME1-dev, NAME2-devel
('libpopt-dev', 'popt-devel'),

View File

@ -116,6 +116,7 @@ dnf install -y \
tar \
tracker-devel \
tree \
utf8proc-devel \
wget \
which \
xfsprogs-devel \

View File

@ -97,6 +97,7 @@ packages:
- tar
- tracker-devel
- tree
- utf8proc-devel
- wget
- which
- xfsprogs-devel

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtracker-sparql-2.0-dev \
libunwind-dev \
liburing-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtracker-sparql-2.0-dev
- libunwind-dev
- liburing-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtracker-sparql-2.0-dev \
libunwind-dev \
liburing-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtracker-sparql-2.0-dev
- libunwind-dev
- liburing-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -74,6 +74,7 @@ apt-get -y install \
libtasn1-dev \
libunwind-dev \
liburing-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -63,6 +63,7 @@ packages:
- libtasn1-dev
- libunwind-dev
- liburing-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -74,6 +74,7 @@ apt-get -y install \
libtasn1-dev \
libunwind-dev \
liburing-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -63,6 +63,7 @@ packages:
- libtasn1-dev
- libunwind-dev
- liburing-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -115,6 +115,7 @@ dnf install -y \
tar \
tracker-devel \
tree \
utf8proc-devel \
wget \
which \
xfsprogs-devel \

View File

@ -104,6 +104,7 @@ packages:
- tar
- tracker-devel
- tree
- utf8proc-devel
- wget
- which
- xfsprogs-devel

View File

@ -107,6 +107,7 @@ zypper --non-interactive install \
tar \
tracker-devel \
tree \
utf8proc-devel \
wget \
which \
xfsprogs-devel \

View File

@ -95,6 +95,7 @@ packages:
- tar
- tracker-devel
- tree
- utf8proc-devel
- wget
- which
- xfsprogs-devel

View File

@ -116,6 +116,7 @@ yum install -y \
tar \
tracker-devel \
tree \
utf8proc-devel \
wget \
which \
xfsprogs-devel \

View File

@ -98,6 +98,7 @@ packages:
- tar
- tracker-devel
- tree
- utf8proc-devel
- wget
- which
- xfsprogs-devel

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtasn1-dev \
libtracker-sparql-2.0-dev \
libunwind-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtasn1-dev
- libtracker-sparql-2.0-dev
- libunwind-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtasn1-dev \
libtracker-sparql-2.0-dev \
libunwind-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtasn1-dev
- libtracker-sparql-2.0-dev
- libunwind-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtasn1-dev \
libtracker-sparql-2.0-dev \
libunwind-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtasn1-dev
- libtracker-sparql-2.0-dev
- libunwind-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -75,6 +75,7 @@ apt-get -y install \
libtasn1-dev \
libunwind-dev \
liburing-dev \
libutf8proc-dev \
lmdb-utils \
locales \
lsb-release \

View File

@ -64,6 +64,7 @@ packages:
- libtasn1-dev
- libunwind-dev
- liburing-dev
- libutf8proc-dev
- lmdb-utils
- locales
- lsb-release

View File

@ -1 +1 @@
8845099b492ab9888181df3e094e00ae8916ddb7
2a20df752f162f9d1f617af785e463fa39944c6e

View File

@ -16,7 +16,8 @@ dbg = { workspace = true }
[workspace]
members = [
"chelps", "dbg", "ntstatus_gen",
"chelps", "dbg", "idmap",
"ntstatus_gen",
"param", "tdb",
]
@ -26,3 +27,4 @@ dbg = { path = "dbg" }
chelps = { path = "chelps" }
ntstatus_gen = { path = "ntstatus_gen" }
tdb = { path = "tdb" }
idmap = { path = "idmap" }

View File

@ -0,0 +1,15 @@
[package]
name = "idmap"
edition.workspace = true
license.workspace = true
homepage.workspace = true
version.workspace = true
[dependencies]
chelps.workspace = true
dbg.workspace = true
libc = "0.2.153"
[build-dependencies]
cc = "1.0.97"
bindgen = "0.69.4"

View File

@ -0,0 +1,32 @@
use std::env;
use std::path::Path;
use std::path::PathBuf;
fn main() {
cc::Build::new()
.file("src/sss_idmap.c")
.file("src/sss_idmap_conv.c")
.file("src/murmurhash3.c")
.include(Path::new("../../bin/default/include"))
.warnings(false)
.compile("sss_idmap");
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")
.header("src/sss_idmap.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
println!("cargo:rustc-link-lib=utf8proc");
}

View File

@ -0,0 +1,227 @@
/*
Himmelblaud
ID-mapping library
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 dbg::DBG_ERR;
use std::ffi::CString;
use std::fmt;
use std::ptr;
use std::sync::{Arc, Mutex};
mod ffi {
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
#[derive(PartialEq, Eq)]
pub struct IdmapError(u32);
pub const IDMAP_SUCCESS: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_SUCCESS);
pub const IDMAP_NOT_IMPLEMENTED: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_NOT_IMPLEMENTED);
pub const IDMAP_ERROR: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_ERROR);
pub const IDMAP_OUT_OF_MEMORY: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_OUT_OF_MEMORY);
pub const IDMAP_NO_DOMAIN: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_NO_DOMAIN);
pub const IDMAP_CONTEXT_INVALID: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_CONTEXT_INVALID);
pub const IDMAP_SID_INVALID: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_SID_INVALID);
pub const IDMAP_SID_UNKNOWN: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_SID_UNKNOWN);
pub const IDMAP_NO_RANGE: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_NO_RANGE);
pub const IDMAP_BUILTIN_SID: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_BUILTIN_SID);
pub const IDMAP_OUT_OF_SLICES: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_OUT_OF_SLICES);
pub const IDMAP_COLLISION: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_COLLISION);
pub const IDMAP_EXTERNAL: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_EXTERNAL);
pub const IDMAP_NAME_UNKNOWN: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_NAME_UNKNOWN);
pub const IDMAP_NO_REVERSE: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_NO_REVERSE);
pub const IDMAP_ERR_LAST: IdmapError =
IdmapError(ffi::idmap_error_code_IDMAP_ERR_LAST);
impl fmt::Display for IdmapError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IdmapError({:#x})", self.0)
}
}
impl fmt::Debug for IdmapError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IdmapError({:#x})", self.0)
}
}
impl std::error::Error for IdmapError {}
pub struct Idmap {
ctx: Arc<Mutex<*mut ffi::sss_idmap_ctx>>,
}
impl Idmap {
pub fn new() -> Result<Idmap, IdmapError> {
let mut ctx = ptr::null_mut();
unsafe {
match IdmapError(ffi::sss_idmap_init(
None,
ptr::null_mut(),
None,
&mut ctx,
)) {
IDMAP_SUCCESS => Ok(Idmap {
ctx: Arc::new(Mutex::new(ctx)),
}),
e => Err(e),
}
}
}
pub fn add_gen_domain(
&mut self,
domain_name: &str,
tenant_id: &str,
range: (u32, u32),
) -> Result<(), IdmapError> {
let ctx = self.ctx.lock().map_err(|e| {
DBG_ERR!("Failed obtaining write lock on sss_idmap_ctx: {}", e);
IDMAP_ERROR
})?;
let domain_name_cstr =
CString::new(domain_name).map_err(|_| IDMAP_OUT_OF_MEMORY)?;
let tenant_id_cstr =
CString::new(tenant_id).map_err(|_| IDMAP_OUT_OF_MEMORY)?;
let mut idmap_range = ffi::sss_idmap_range {
min: range.0,
max: range.1,
};
unsafe {
match IdmapError(ffi::sss_idmap_add_gen_domain_ex(
*ctx,
domain_name_cstr.as_ptr(),
tenant_id_cstr.as_ptr(),
&mut idmap_range,
ptr::null_mut(),
None,
None,
ptr::null_mut(),
0,
false,
)) {
IDMAP_SUCCESS => Ok(()),
e => Err(e),
}
}
}
pub fn gen_to_unix(
&self,
tenant_id: &str,
input: &str,
) -> Result<u32, IdmapError> {
let ctx = self.ctx.lock().map_err(|e| {
DBG_ERR!("Failed obtaining write lock on sss_idmap_ctx: {}", e);
IDMAP_ERROR
})?;
let tenant_id_cstr =
CString::new(tenant_id).map_err(|_| IDMAP_OUT_OF_MEMORY)?;
let input_cstr = CString::new(input.to_lowercase())
.map_err(|_| IDMAP_OUT_OF_MEMORY)?;
unsafe {
let mut id: u32 = 0;
match IdmapError(ffi::sss_idmap_gen_to_unix(
*ctx,
tenant_id_cstr.as_ptr(),
input_cstr.as_ptr(),
&mut id,
)) {
IDMAP_SUCCESS => Ok(id),
e => Err(e),
}
}
}
}
impl Drop for Idmap {
fn drop(&mut self) {
match self.ctx.lock() {
Ok(ctx) => unsafe {
let _ = ffi::sss_idmap_free(*ctx);
},
Err(e) => {
DBG_ERR!(
"Failed obtaining write lock on sss_idmap_ctx during drop: {}",
e
);
}
}
}
}
unsafe impl Send for Idmap {}
unsafe impl Sync for Idmap {}
#[cfg(test)]
mod tests {
use crate::Idmap;
use std::collections::HashMap;
pub const DEFAULT_IDMAP_RANGE: (u32, u32) = (200000, 2000200000);
#[test]
fn sssd_idmapping() {
let domain = "contoso.onmicrosoft.com";
let tenant_id = "d7af6c1b-0497-40fe-9d17-07e6b0f8332e";
let mut idmap = Idmap::new().expect("Idmap initialization failed");
idmap
.add_gen_domain(domain, tenant_id, DEFAULT_IDMAP_RANGE)
.expect("Failed initializing test domain idmapping");
// Verify we always get the same mapping for various users
let mut usermap: HashMap<String, u32> = HashMap::new();
usermap.insert("tux@contoso.onmicrosoft.com".to_string(), 1912749799);
usermap.insert("admin@contoso.onmicrosoft.com".to_string(), 297515919);
usermap.insert("dave@contoso.onmicrosoft.com".to_string(), 132631922);
usermap.insert("joe@contoso.onmicrosoft.com".to_string(), 361591965);
usermap.insert("georg@contoso.onmicrosoft.com".to_string(), 866887005);
for (username, expected_uid) in &usermap {
let uid = idmap.gen_to_unix(tenant_id, username).expect(&format!(
"Failed converting username {} to uid",
username
));
assert_eq!(
uid, *expected_uid,
"Uid for {} did not match",
username
);
}
}
}

View File

@ -0,0 +1,114 @@
/* This file is based on the public domain MurmurHash3 from Austin Appleby:
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
*
* We use only the 32 bit variant because the 2 produce different result while
* we need to produce the same result regardless of the architecture as
* clients can be both 64 or 32 bit at the same time.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "murmurhash3.h"
#include "util.h"
static uint32_t rotl(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
}
/* slower than original but is endian neutral and handles platforms that
* do only aligned reads */
__attribute__((always_inline))
static inline uint32_t getblock(const uint8_t *p, int i)
{
uint32_t r;
size_t size = sizeof(uint32_t);
memcpy(&r, &p[i * size], size);
return le32toh(r);
}
/*
* Finalization mix - force all bits of a hash block to avalanche
*/
__attribute__((always_inline))
static inline uint32_t fmix(uint32_t h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
uint32_t murmurhash3(const char *key, int len, uint32_t seed)
{
const uint8_t *blocks;
const uint8_t *tail;
int nblocks;
uint32_t h1;
uint32_t k1;
uint32_t c1;
uint32_t c2;
int i;
blocks = (const uint8_t *)key;
nblocks = len / 4;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
/* body */
for (i = 0; i < nblocks; i++) {
k1 = getblock(blocks, i);
k1 *= c1;
k1 = rotl(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = rotl(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
/* tail */
tail = (const uint8_t *)key + nblocks * 4;
k1 = 0;
switch (len & 3) {
case 3:
k1 ^= tail[2] << 16;
SSS_ATTRIBUTE_FALLTHROUGH;
case 2:
k1 ^= tail[1] << 8;
SSS_ATTRIBUTE_FALLTHROUGH;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = rotl(k1, 15);
k1 *= c2;
h1 ^= k1;
break;
default:
break;
}
/* finalization */
h1 ^= len;
h1 = fmix(h1);
return h1;
}

View File

@ -0,0 +1,21 @@
/* This file is based on the public domain MurmurHash3 from Austin Appleby:
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
*
* We use only the 32 bit variant because the 2 produce different result while
* we need to produce the same result regardless of the architecture as
* clients can be both 64 or 32 bit at the same time.
*/
#ifndef _SHARED_MURMURHASH3_H_
#define _SHARED_MURMURHASH3_H_
/* CAUTION:
* This file is also used in sss_client (pam, nss). Therefore it have to be
* minimalist and cannot include DEBUG macros or header file util.h.
*/
#include <stdint.h>
uint32_t murmurhash3(const char *key, int len, uint32_t seed);
#endif /* _SHARED_MURMURHASH3_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,570 @@
/*
SSSD
ID-mapping library - conversion utilities
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2012 Red Hat
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/>.
*/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include "sss_idmap.h"
#include "sss_idmap_private.h"
//#include "util/util.h"
//#include "util/sss_endian.h"
#include "util.h"
#define SID_ID_AUTHS 6
#define SID_SUB_AUTHS 15
struct sss_dom_sid {
uint8_t sid_rev_num;
int8_t num_auths; /* [range(0,15)] */
uint8_t id_auth[SID_ID_AUTHS]; /* highest order byte has index 0 */
uint32_t sub_auths[SID_SUB_AUTHS]; /* host byte-order */
};
enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx,
const uint8_t *bin_sid,
size_t length,
struct sss_dom_sid **_dom_sid)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid;
size_t i = 0;
size_t p = 0;
uint32_t val;
CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
if (length > sizeof(struct sss_dom_sid)) return IDMAP_SID_INVALID;
dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt);
if (dom_sid == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(dom_sid, 0, sizeof(struct sss_dom_sid));
/* Safely copy in the SID revision number */
dom_sid->sid_rev_num = (uint8_t) *(bin_sid + p);
p++;
/* Safely copy in the number of sub auth values */
dom_sid->num_auths = (uint8_t) *(bin_sid + p);
p++;
/* Make sure we aren't being told to read more bin_sid
* than can fit in the structure
*/
if (dom_sid->num_auths > SID_SUB_AUTHS) {
err = IDMAP_SID_INVALID;
goto done;
}
/* Safely copy in the id_auth values */
for (i = 0; i < SID_ID_AUTHS; i++) {
dom_sid->id_auth[i] = (uint8_t) *(bin_sid + p);
p++;
}
/* Safely copy in the sub_auths values */
for (i = 0; i < dom_sid->num_auths; i++) {
/* SID sub auth values in Active Directory are stored little-endian,
* we store them in host order */
SAFEALIGN_COPY_UINT32(&val, bin_sid + p, &p);
dom_sid->sub_auths[i] = le32toh(val);
}
*_dom_sid = dom_sid;
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
ctx->free_func(dom_sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_dom_sid_to_bin_sid(struct sss_idmap_ctx *ctx,
struct sss_dom_sid *dom_sid,
uint8_t **_bin_sid,
size_t *_length)
{
enum idmap_error_code err;
uint8_t *bin_sid;
size_t length;
size_t i = 0;
size_t p = 0;
uint32_t val;
CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
if (dom_sid->num_auths > SID_SUB_AUTHS) {
return IDMAP_SID_INVALID;
}
length = 2 + SID_ID_AUTHS + dom_sid->num_auths * 4;
bin_sid = ctx->alloc_func(length, ctx->alloc_pvt);
if (bin_sid == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
bin_sid[p] = dom_sid->sid_rev_num;
p++;
bin_sid[p] = dom_sid->num_auths;
p++;
for (i = 0; i < SID_ID_AUTHS; i++) {
bin_sid[p] = dom_sid->id_auth[i];
p++;
}
for (i = 0; i < dom_sid->num_auths; i++) {
if (p + sizeof(uint32_t) > length) {
err = IDMAP_SID_INVALID;
goto done;
}
val = htole32(dom_sid->sub_auths[i]);
SAFEALIGN_COPY_UINT32(bin_sid + p, &val, &p);
}
*_bin_sid = bin_sid;
*_length = length;
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
ctx->free_func(bin_sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx,
struct sss_dom_sid *dom_sid,
char **_sid)
{
enum idmap_error_code err;
char *sid_buf;
size_t sid_buf_len;
char *p;
int nc;
int8_t i;
uint32_t id_auth_val = 0;
if (dom_sid->num_auths > SID_SUB_AUTHS) {
return IDMAP_SID_INVALID;
}
sid_buf_len = 25 + dom_sid->num_auths * 11;
sid_buf = ctx->alloc_func(sid_buf_len, ctx->alloc_pvt);
if (sid_buf == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(sid_buf, 0, sid_buf_len);
/* Only 32bits are used for the string representation */
id_auth_val = (dom_sid->id_auth[2] << 24) +
(dom_sid->id_auth[3] << 16) +
(dom_sid->id_auth[4] << 8) +
(dom_sid->id_auth[5]);
nc = snprintf(sid_buf, sid_buf_len, "S-%u-%lu", dom_sid->sid_rev_num,
(unsigned long) id_auth_val);
if (nc < 0 || nc >= sid_buf_len) {
err = IDMAP_SID_INVALID;
goto done;
}
/* Loop through the sub-auths, if any, prepending a hyphen
* for each one.
*/
p = sid_buf;
for (i = 0; i < dom_sid->num_auths ; i++) {
p += nc;
sid_buf_len -= nc;
nc = snprintf(p, sid_buf_len, "-%lu",
(unsigned long) dom_sid->sub_auths[i]);
if (nc < 0 || nc >= sid_buf_len) {
err = IDMAP_SID_INVALID;
goto done;
}
}
*_sid = sid_buf;
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
ctx->free_func(sid_buf, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx,
const char *sid,
struct sss_dom_sid **_dom_sid)
{
enum idmap_error_code err;
unsigned long ul;
char *r;
char *end;
struct sss_dom_sid *dom_sid;
CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
if (sid == NULL || (sid[0] != 'S' && sid[0] != 's') || sid[1] != '-') {
return IDMAP_SID_INVALID;
}
dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt);
if (dom_sid == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(dom_sid, 0, sizeof(struct sss_dom_sid));
if (!isdigit(sid[2])) {
err = IDMAP_SID_INVALID;
goto done;
}
errno = 0;
ul = strtoul(sid + 2, &r, 10);
if (errno != 0 || r == NULL || *r != '-' || ul > UINT8_MAX) {
err = IDMAP_SID_INVALID;
goto done;
}
dom_sid->sid_rev_num = (uint8_t) ul;
r++;
if (!isdigit(*r)) {
err = IDMAP_SID_INVALID;
goto done;
}
errno = 0;
ul = strtoul(r, &r, 10);
if (errno != 0 || r == NULL || ul > UINT32_MAX) {
err = IDMAP_SID_INVALID;
goto done;
}
/* id_auth in the string should always be <2^32 in decimal */
/* store values in the same order as the binary representation */
dom_sid->id_auth[0] = 0;
dom_sid->id_auth[1] = 0;
dom_sid->id_auth[2] = (ul & 0xff000000) >> 24;
dom_sid->id_auth[3] = (ul & 0x00ff0000) >> 16;
dom_sid->id_auth[4] = (ul & 0x0000ff00) >> 8;
dom_sid->id_auth[5] = (ul & 0x000000ff);
if (*r == '\0') {
/* no sub auths given */
err = IDMAP_SUCCESS;
goto done;
}
if (*r != '-') {
err = IDMAP_SID_INVALID;
goto done;
}
do {
if (dom_sid->num_auths >= SID_SUB_AUTHS) {
err = IDMAP_SID_INVALID;
goto done;
}
r++;
if (!isdigit(*r)) {
err = IDMAP_SID_INVALID;
goto done;
}
errno = 0;
ul = strtoul(r, &end, 10);
if (errno != 0 || ul > UINT32_MAX || end == NULL ||
(*end != '\0' && *end != '-')) {
err = IDMAP_SID_INVALID;
goto done;
}
dom_sid->sub_auths[dom_sid->num_auths++] = ul;
r = end;
} while (*r != '\0');
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
ctx->free_func(dom_sid, ctx->alloc_pvt);
} else {
*_dom_sid = dom_sid;
}
return err;
}
enum idmap_error_code sss_idmap_sid_to_bin_sid(struct sss_idmap_ctx *ctx,
const char *sid,
uint8_t **_bin_sid,
size_t *_length)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
size_t length;
uint8_t *bin_sid = NULL;
err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_bin_sid(ctx, dom_sid, &bin_sid, &length);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_length = length;
*_bin_sid = bin_sid;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(bin_sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_bin_sid_to_sid(struct sss_idmap_ctx *ctx,
const uint8_t *bin_sid,
size_t length,
char **_sid)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
char *sid = NULL;
err = sss_idmap_bin_sid_to_dom_sid(ctx, bin_sid, length, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_sid = sid;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_sid_to_smb_sid(struct sss_idmap_ctx *ctx,
const char *sid,
struct dom_sid **_smb_sid)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
struct dom_sid *smb_sid = NULL;
err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_smb_sid(ctx, dom_sid, &smb_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_smb_sid = smb_sid;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(smb_sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_smb_sid_to_sid(struct sss_idmap_ctx *ctx,
struct dom_sid *smb_sid,
char **_sid)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
char *sid = NULL;
err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_sid, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_sid = sid;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_dom_sid_to_smb_sid(struct sss_idmap_ctx *ctx,
struct sss_dom_sid *dom_sid,
struct dom_sid **_smb_sid)
{
struct dom_sid *smb_sid;
size_t c;
smb_sid = ctx->alloc_func(sizeof(struct dom_sid), ctx->alloc_pvt);
if (smb_sid == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(smb_sid, 0, sizeof(struct dom_sid));
smb_sid->sid_rev_num = dom_sid->sid_rev_num;
smb_sid->num_auths = dom_sid->num_auths;
for (c = 0; c < SID_ID_AUTHS; c++) {
smb_sid->id_auth[c] = dom_sid->id_auth[c];
}
for (c = 0; c < SID_SUB_AUTHS; c++) {
smb_sid->sub_auths[c] = dom_sid->sub_auths[c];
}
*_smb_sid = smb_sid;
return IDMAP_SUCCESS;
}
enum idmap_error_code sss_idmap_smb_sid_to_dom_sid(struct sss_idmap_ctx *ctx,
struct dom_sid *smb_sid,
struct sss_dom_sid **_dom_sid)
{
struct sss_dom_sid *dom_sid;
size_t c;
dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt);
if (dom_sid == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(dom_sid, 0, sizeof(struct sss_dom_sid));
dom_sid->sid_rev_num = smb_sid->sid_rev_num;
dom_sid->num_auths = smb_sid->num_auths;
for (c = 0; c < SID_ID_AUTHS; c++) {
dom_sid->id_auth[c] = smb_sid->id_auth[c];
}
for (c = 0; c < SID_SUB_AUTHS; c++) {
dom_sid->sub_auths[c] = smb_sid->sub_auths[c];
}
*_dom_sid = dom_sid;
return IDMAP_SUCCESS;
}
enum idmap_error_code sss_idmap_bin_sid_to_smb_sid(struct sss_idmap_ctx *ctx,
const uint8_t *bin_sid,
size_t length,
struct dom_sid **_smb_sid)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
struct dom_sid *smb_sid = NULL;
err = sss_idmap_bin_sid_to_dom_sid(ctx, bin_sid, length, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_smb_sid(ctx, dom_sid, &smb_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_smb_sid = smb_sid;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(smb_sid, ctx->alloc_pvt);
}
return err;
}
enum idmap_error_code sss_idmap_smb_sid_to_bin_sid(struct sss_idmap_ctx *ctx,
struct dom_sid *smb_sid,
uint8_t **_bin_sid,
size_t *_length)
{
enum idmap_error_code err;
struct sss_dom_sid *dom_sid = NULL;
uint8_t *bin_sid = NULL;
size_t length;
err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_sid, &dom_sid);
if (err != IDMAP_SUCCESS) {
goto done;
}
err = sss_idmap_dom_sid_to_bin_sid(ctx, dom_sid, &bin_sid, &length);
if (err != IDMAP_SUCCESS) {
goto done;
}
*_bin_sid = bin_sid;
*_length = length;
err = IDMAP_SUCCESS;
done:
ctx->free_func(dom_sid, ctx->alloc_pvt);
if (err != IDMAP_SUCCESS) {
ctx->free_func(bin_sid, ctx->alloc_pvt);
}
return err;
}

View File

@ -0,0 +1,84 @@
/*
SSSD
ID-mapping library - private headers
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2012 Red Hat
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/>.
*/
#ifndef SSS_IDMAP_PRIVATE_H_
#define SSS_IDMAP_PRIVATE_H_
#define SSS_IDMAP_DEFAULT_LOWER 200000
#define SSS_IDMAP_DEFAULT_UPPER 2000200000
#define SSS_IDMAP_DEFAULT_RANGESIZE 200000
#define SSS_IDMAP_DEFAULT_AUTORID false
#define SSS_IDMAP_DEFAULT_EXTRA_SLICE_INIT 10
#define CHECK_IDMAP_CTX(ctx, ret) do { \
if (ctx == NULL || ctx->alloc_func == NULL || ctx->free_func == NULL) { \
return ret; \
} \
} while(0)
struct sss_idmap_opts {
/* true if autorid compatibility mode is used */
bool autorid_mode;
/* smallest available id (for all domains) */
id_t idmap_lower;
/* highest available id (for all domains) */
id_t idmap_upper;
/* number of available UIDs (for single domain) */
id_t rangesize;
/* maximal number of secondary slices */
int extra_slice_init;
};
struct sss_idmap_ctx {
idmap_alloc_func *alloc_func;
void *alloc_pvt;
idmap_free_func *free_func;
struct sss_idmap_opts idmap_opts;
struct idmap_domain_info *idmap_domain_info;
};
/* This is a copy of the definition in the samba gen_ndr/security.h header
* file. We use it here to be able to offer conversions form struct dom_sid to
* string or binary representation since those are not made available by
* public samba libraries.
*
* If the definition ever changes on the samba side we have to adopt the
* change. But chances are very low that this will ever happen since e.g. this
* struct is also defined in public documentation from Microsoft. See e.g.
* section 2.4.2.3 of "[MS-DTYP]: Windows Data Types"
* http://msdn.microsoft.com/en-us/library/cc230364(v=prot.10)
*/
struct dom_sid {
uint8_t sid_rev_num;
int8_t num_auths;
uint8_t id_auth[6];
uint32_t sub_auths[15];
};
#endif /* SSS_IDMAP_PRIVATE_H_ */

View File

@ -0,0 +1,46 @@
/*
Himmelblaud
ID-mapping library utils
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/>.
*/
#ifndef _UTILS_H
#define _UTILS_H
#include <string.h>
#include <stdint.h>
static inline void
safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter)
{
memcpy(dest, src, n);
if (counter) {
*counter += n;
}
}
#define SAFEALIGN_COPY_UINT32(dest, src, pctr) \
safealign_memcpy(dest, src, sizeof(uint32_t), pctr)
#if defined(__GNUC__) && __GNUC__ >= 7
#define SSS_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough))
#else
#define SSS_ATTRIBUTE_FALLTHROUGH
#endif
#endif /* _UTILS_H */