server: Change attribute values to bytes

This commit is contained in:
Valentin Tolmer 2022-08-07 17:43:46 +02:00 committed by nitnelave
parent 3acc448048
commit 697a64991d
6 changed files with 110 additions and 99 deletions

14
Cargo.lock generated
View file

@ -2009,14 +2009,14 @@ dependencies = [
]
[[package]]
name = "ldap3_server"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7873d5bd5baabdb77aa2d8a762bf8b1136f9f90cc90f44639b4c0d4486281dcb"
name = "ldap3_proto"
version = "0.2.3"
source = "git+https://github.com/nitnelave/ldap3_server/?rev=7b50b2b82c383f5f70e02e11072bb916629ed2bc#7b50b2b82c383f5f70e02e11072bb916629ed2bc"
dependencies = [
"bytes",
"lber",
"tokio-util 0.6.10",
"tokio-util 0.7.3",
"tracing",
]
[[package]]
@ -2120,7 +2120,7 @@ dependencies = [
"juniper",
"juniper_actix",
"jwt",
"ldap3_server",
"ldap3_proto",
"lettre",
"lldap_auth",
"log",
@ -2144,7 +2144,7 @@ dependencies = [
"tokio",
"tokio-rustls 0.23.4",
"tokio-stream",
"tokio-util 0.6.10",
"tokio-util 0.7.3",
"tracing",
"tracing-actix-web",
"tracing-attributes",

View file

@ -7,3 +7,8 @@ members = [
]
default-members = ["server"]
# Remove once https://github.com/kanidm/ldap3_proto/pull/8 is merged.
[patch.crates-io.ldap3_proto]
git = 'https://github.com/nitnelave/ldap3_server/'
rev = '7b50b2b82c383f5f70e02e11072bb916629ed2bc'

View file

@ -27,7 +27,7 @@ itertools = "0.10.1"
juniper = "0.15.10"
juniper_actix = "0.4.0"
jwt = "0.13"
ldap3_server = "=0.1.11"
ldap3_proto = "*"
log = "*"
orion = "0.16"
rustls = "0.20"
@ -39,7 +39,7 @@ thiserror = "*"
time = "0.2"
tokio-rustls = "0.23"
tokio-stream = "*"
tokio-util = "0.6.3"
tokio-util = "0.7.3"
tracing = "*"
tracing-actix-web = "0.4.0-beta.7"
tracing-attributes = "^0.1.21"
@ -104,7 +104,7 @@ version = "*"
[dependencies.tokio]
features = ["full"]
version = "1.13.1"
version = "1.17"
[dependencies.uuid]
features = ["v3"]

View file

@ -126,6 +126,11 @@ impl From<&JpegPhoto> for String {
}
impl JpegPhoto {
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
#[cfg(test)]
pub fn for_tests() -> Self {
use image::{ImageOutputFormat, Rgb, RgbImage};
let img = RgbImage::from_fn(32, 32, |x, y| {

View file

@ -10,7 +10,7 @@ use crate::{
};
use anyhow::{bail, Context, Result};
use itertools::Itertools;
use ldap3_server::proto::{
use ldap3_proto::proto::{
LdapBindCred, LdapBindRequest, LdapBindResponse, LdapExtendedRequest, LdapExtendedResponse,
LdapFilter, LdapOp, LdapPartialAttribute, LdapPasswordModifyRequest, LdapResult,
LdapResultCode, LdapSearchRequest, LdapSearchResultEntry, LdapSearchScope,
@ -154,22 +154,22 @@ fn get_user_attribute(
base_dn_str: &str,
groups: Option<&[GroupDetails]>,
ignored_user_attributes: &[String],
) -> Result<Option<Vec<String>>> {
) -> Result<Option<Vec<Vec<u8>>>> {
let attribute = attribute.to_ascii_lowercase();
Ok(Some(match attribute.as_str() {
"objectclass" => vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string(),
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec(),
],
// dn is always returned as part of the base response.
"dn" | "distinguishedname" => return Ok(None),
"uid" => vec![user.user_id.to_string()],
"entryuuid" => vec![user.uuid.to_string()],
"mail" => vec![user.email.clone()],
"givenname" => vec![user.first_name.clone()],
"sn" => vec![user.last_name.clone()],
"uid" => vec![user.user_id.to_string().into_bytes()],
"entryuuid" => vec![user.uuid.to_string().into_bytes()],
"mail" => vec![user.email.clone().into_bytes()],
"givenname" => vec![user.first_name.clone().into_bytes()],
"sn" => vec![user.last_name.clone().into_bytes()],
"memberof" => groups
.into_iter()
.flatten()
@ -178,10 +178,11 @@ fn get_user_attribute(
"uid={},ou=groups,{}",
&id_and_name.display_name, base_dn_str
)
.into_bytes()
})
.collect(),
"cn" | "displayname" => vec![user.display_name.clone()],
"createtimestamp" | "modifytimestamp" => vec![user.creation_date.to_rfc3339()],
"cn" | "displayname" => vec![user.display_name.clone().into_bytes()],
"createtimestamp" | "modifytimestamp" => vec![user.creation_date.to_rfc3339().into_bytes()],
"1.1" => return Ok(None),
// We ignore the operational attribute wildcard.
"+" => return Ok(None),
@ -279,19 +280,19 @@ fn get_group_attribute(
attribute: &str,
user_filter: &Option<&UserId>,
ignored_group_attributes: &[String],
) -> Result<Option<Vec<String>>> {
) -> Result<Option<Vec<Vec<u8>>>> {
let attribute = attribute.to_ascii_lowercase();
Ok(Some(match attribute.as_str() {
"objectclass" => vec!["groupOfUniqueNames".to_string()],
"objectclass" => vec![b"groupOfUniqueNames".to_vec()],
// Always returned as part of the base response.
"dn" | "distinguishedname" => return Ok(None),
"cn" | "uid" => vec![group.display_name.clone()],
"entryuuid" => vec![group.uuid.to_string()],
"cn" | "uid" => vec![group.display_name.clone().into_bytes()],
"entryuuid" => vec![group.uuid.to_string().into_bytes()],
"member" | "uniquemember" => group
.users
.iter()
.filter(|u| user_filter.map(|f| *u == f).unwrap_or(true))
.map(|u| format!("uid={},ou=people,{}", u, base_dn_str))
.map(|u| format!("uid={},ou=people,{}", u, base_dn_str).into_bytes())
.collect(),
"1.1" => return Ok(None),
// We ignore the operational attribute wildcard
@ -418,27 +419,27 @@ fn root_dse_response(base_dn: &str) -> LdapOp {
attributes: vec![
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec!["top".to_string()],
vals: vec![b"top".to_vec()],
},
LdapPartialAttribute {
atype: "vendorName".to_string(),
vals: vec!["LLDAP".to_string()],
vals: vec![b"LLDAP".to_vec()],
},
LdapPartialAttribute {
atype: "vendorVersion".to_string(),
vals: vec!["lldap_0.2.0".to_string()],
vals: vec![b"lldap_0.2.0".to_vec()],
},
LdapPartialAttribute {
atype: "supportedLDAPVersion".to_string(),
vals: vec!["3".to_string()],
vals: vec![b"3".to_vec()],
},
LdapPartialAttribute {
atype: "supportedExtension".to_string(),
vals: vec!["1.3.6.1.4.1.4203.1.11.1".to_string()],
vals: vec![b"1.3.6.1.4.1.4203.1.11.1".to_vec()],
},
LdapPartialAttribute {
atype: "defaultnamingcontext".to_string(),
vals: vec![base_dn.to_string()],
vals: vec![base_dn.to_string().into_bytes()],
},
],
})
@ -1032,7 +1033,7 @@ mod tests {
};
use async_trait::async_trait;
use chrono::TimeZone;
use ldap3_server::proto::{LdapDerefAliases, LdapSearchScope};
use ldap3_proto::proto::{LdapDerefAliases, LdapSearchScope};
use mockall::predicate::eq;
use std::collections::HashSet;
use tokio;
@ -1314,7 +1315,7 @@ mod tests {
dn: "uid=bob,ou=people,dc=example,dc=com".to_string(),
attributes: vec![LdapPartialAttribute {
atype: "memberOf".to_string(),
vals: vec!["uid=rockstars,ou=groups,dc=example,dc=com".to_string()]
vals: vec![b"uid=rockstars,ou=groups,dc=example,dc=com".to_vec()]
}],
}),
make_search_success(),
@ -1491,39 +1492,39 @@ mod tests {
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string()
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec()
]
},
LdapPartialAttribute {
atype: "uid".to_string(),
vals: vec!["bob_1".to_string()]
vals: vec![b"bob_1".to_vec()]
},
LdapPartialAttribute {
atype: "mail".to_string(),
vals: vec!["bob@bobmail.bob".to_string()]
vals: vec![b"bob@bobmail.bob".to_vec()]
},
LdapPartialAttribute {
atype: "givenName".to_string(),
vals: vec!["Bôb".to_string()]
vals: vec!["Bôb".to_string().into_bytes()]
},
LdapPartialAttribute {
atype: "sn".to_string(),
vals: vec!["Böbberson".to_string()]
vals: vec!["Böbberson".to_string().into_bytes()]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["Bôb Böbberson".to_string()]
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
},
LdapPartialAttribute {
atype: "createTimestamp".to_string(),
vals: vec!["1970-01-01T00:00:00+00:00".to_string()]
vals: vec![b"1970-01-01T00:00:00+00:00".to_vec()]
},
LdapPartialAttribute {
atype: "entryUuid".to_string(),
vals: vec!["698e1d5f-7a40-3151-8745-b9b8a37839da".to_string()]
vals: vec![b"698e1d5f-7a40-3151-8745-b9b8a37839da".to_vec()]
},
],
}),
@ -1533,39 +1534,39 @@ mod tests {
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string()
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec()
]
},
LdapPartialAttribute {
atype: "uid".to_string(),
vals: vec!["jim".to_string()]
vals: vec![b"jim".to_vec()]
},
LdapPartialAttribute {
atype: "mail".to_string(),
vals: vec!["jim@cricket.jim".to_string()]
vals: vec![b"jim@cricket.jim".to_vec()]
},
LdapPartialAttribute {
atype: "givenName".to_string(),
vals: vec!["Jim".to_string()]
vals: vec![b"Jim".to_vec()]
},
LdapPartialAttribute {
atype: "sn".to_string(),
vals: vec!["Cricket".to_string()]
vals: vec![b"Cricket".to_vec()]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["Jimminy Cricket".to_string()]
vals: vec![b"Jimminy Cricket".to_vec()]
},
LdapPartialAttribute {
atype: "createTimestamp".to_string(),
vals: vec!["2014-07-08T09:10:11+00:00".to_string()]
vals: vec![b"2014-07-08T09:10:11+00:00".to_vec()]
},
LdapPartialAttribute {
atype: "entryUuid".to_string(),
vals: vec!["04ac75e0-2900-3e21-926c-2f732c26b3fc".to_string()]
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()]
},
],
}),
@ -1612,22 +1613,22 @@ mod tests {
attributes: vec![
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec!["groupOfUniqueNames".to_string(),]
vals: vec![b"groupOfUniqueNames".to_vec(),]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["group_1".to_string()]
vals: vec![b"group_1".to_vec()]
},
LdapPartialAttribute {
atype: "uniqueMember".to_string(),
vals: vec![
"uid=bob,ou=people,dc=example,dc=com".to_string(),
"uid=john,ou=people,dc=example,dc=com".to_string(),
b"uid=bob,ou=people,dc=example,dc=com".to_vec(),
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
]
},
LdapPartialAttribute {
atype: "entryUuid".to_string(),
vals: vec!["04ac75e0-2900-3e21-926c-2f732c26b3fc".to_string()],
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
},
],
}),
@ -1636,19 +1637,19 @@ mod tests {
attributes: vec![
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec!["groupOfUniqueNames".to_string(),]
vals: vec![b"groupOfUniqueNames".to_vec(),]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["BestGroup".to_string()]
vals: vec![b"BestGroup".to_vec()]
},
LdapPartialAttribute {
atype: "uniqueMember".to_string(),
vals: vec!["uid=john,ou=people,dc=example,dc=com".to_string()]
vals: vec![b"uid=john,ou=people,dc=example,dc=com".to_vec()]
},
LdapPartialAttribute {
atype: "entryUuid".to_string(),
vals: vec!["04ac75e0-2900-3e21-926c-2f732c26b3fc".to_string()],
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
},
],
}),
@ -1750,7 +1751,7 @@ mod tests {
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
attributes: vec![LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["group_1".to_string()]
vals: vec![b"group_1".to_vec()]
},],
}),
make_search_success(),
@ -1826,7 +1827,7 @@ mod tests {
"ou=groups,dc=example,dc=com",
LdapFilter::And(vec![LdapFilter::Substring(
"whatever".to_string(),
ldap3_server::proto::LdapSubstringFilter::default(),
ldap3_proto::proto::LdapSubstringFilter::default(),
)]),
vec!["cn"],
);
@ -1970,10 +1971,10 @@ mod tests {
attributes: vec![LdapPartialAttribute {
atype: "objectclass".to_string(),
vals: vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string()
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec()
]
},]
}),
@ -2025,15 +2026,15 @@ mod tests {
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string()
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec()
]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["Bôb Böbberson".to_string()]
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
},
],
}),
@ -2042,11 +2043,11 @@ mod tests {
attributes: vec![
LdapPartialAttribute {
atype: "objectClass".to_string(),
vals: vec!["groupOfUniqueNames".to_string(),]
vals: vec![b"groupOfUniqueNames".to_vec(),]
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["group_1".to_string()]
vals: vec![b"group_1".to_vec()]
},
],
}),
@ -2098,35 +2099,35 @@ mod tests {
LdapPartialAttribute {
atype: "objectclass".to_string(),
vals: vec![
"inetOrgPerson".to_string(),
"posixAccount".to_string(),
"mailAccount".to_string(),
"person".to_string(),
b"inetOrgPerson".to_vec(),
b"posixAccount".to_vec(),
b"mailAccount".to_vec(),
b"person".to_vec(),
],
},
LdapPartialAttribute {
atype: "uid".to_string(),
vals: vec!["bob_1".to_string()],
vals: vec![b"bob_1".to_vec()],
},
LdapPartialAttribute {
atype: "mail".to_string(),
vals: vec!["bob@bobmail.bob".to_string()],
vals: vec![b"bob@bobmail.bob".to_vec()],
},
LdapPartialAttribute {
atype: "givenname".to_string(),
vals: vec!["Bôb".to_string()],
vals: vec!["Bôb".to_string().into_bytes()],
},
LdapPartialAttribute {
atype: "sn".to_string(),
vals: vec!["Böbberson".to_string()],
vals: vec!["Böbberson".to_string().into_bytes()],
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["Bôb Böbberson".to_string()],
vals: vec!["Bôb Böbberson".to_string().into_bytes()],
},
LdapPartialAttribute {
atype: "createtimestamp".to_string(),
vals: vec![chrono::Utc.timestamp(0, 0).to_rfc3339()],
vals: vec![chrono::Utc.timestamp(0, 0).to_rfc3339().into_bytes()],
},
],
}),
@ -2136,30 +2137,30 @@ mod tests {
attributes: vec![
LdapPartialAttribute {
atype: "objectclass".to_string(),
vals: vec!["groupOfUniqueNames".to_string()],
vals: vec![b"groupOfUniqueNames".to_vec()],
},
// UID
LdapPartialAttribute {
atype: "uid".to_string(),
vals: vec!["group_1".to_string()],
vals: vec![b"group_1".to_vec()],
},
LdapPartialAttribute {
atype: "cn".to_string(),
vals: vec!["group_1".to_string()],
vals: vec![b"group_1".to_vec()],
},
//member / uniquemember : "uid={},ou=people,{}"
LdapPartialAttribute {
atype: "member".to_string(),
vals: vec![
"uid=bob,ou=people,dc=example,dc=com".to_string(),
"uid=john,ou=people,dc=example,dc=com".to_string(),
b"uid=bob,ou=people,dc=example,dc=com".to_vec(),
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
],
},
LdapPartialAttribute {
atype: "uniquemember".to_string(),
vals: vec![
"uid=bob,ou=people,dc=example,dc=com".to_string(),
"uid=john,ou=people,dc=example,dc=com".to_string(),
b"uid=bob,ou=people,dc=example,dc=com".to_vec(),
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
],
},
],
@ -2234,7 +2235,7 @@ mod tests {
let request = make_user_search_request(
LdapFilter::Substring(
"uid".to_string(),
ldap3_server::proto::LdapSubstringFilter::default(),
ldap3_proto::proto::LdapSubstringFilter::default(),
),
vec!["objectClass"],
);

View file

@ -9,7 +9,7 @@ use actix_rt::net::TcpStream;
use actix_server::ServerBuilder;
use actix_service::{fn_service, ServiceFactoryExt};
use anyhow::{Context, Result};
use ldap3_server::{proto::LdapMsg, LdapCodec};
use ldap3_proto::{proto::LdapMsg, LdapCodec};
use tokio_rustls::TlsAcceptor as RustlsTlsAcceptor;
use tokio_util::codec::{FramedRead, FramedWrite};
use tracing::{debug, error, info, instrument};