mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
r12361: Add a new function: ldb_binary_encode_string()
This is for use on user-supplied arguments to printf style format strings which will become ldb filters. I have used it on LSA, SAMR and the auth/ code so far. Also add comments to cracknames code. Andrew Bartlett
This commit is contained in:
parent
e751d81414
commit
8308cf6e04
source
auth
dsdb/samdb
lib/ldb
rpc_server
@ -280,10 +280,11 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *
|
||||
const struct ldb_dn *domain_dn = NULL;
|
||||
|
||||
if (domain_name) {
|
||||
char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
|
||||
/* find the domain's DN */
|
||||
ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain_ref, domain_ref_attrs,
|
||||
"(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))",
|
||||
domain_name, domain_name);
|
||||
escaped_domain, escaped_domain);
|
||||
if (ret_domain == -1) {
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
@ -306,7 +307,7 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *
|
||||
/* pull the user attributes */
|
||||
ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, user_attrs,
|
||||
"(&(sAMAccountName=%s)(objectclass=user))",
|
||||
account_name);
|
||||
ldb_binary_encode_string(mem_ctx, account_name));
|
||||
if (ret == -1) {
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
@ -115,6 +115,11 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
|
||||
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* When cracking a ServicePrincipalName, many services may be served
|
||||
* by the host/ servicePrincipalName. The incoming query is for cifs/
|
||||
* but we translate it here, and search on host/. This is done after
|
||||
* the cifs/ entry has been searched for, making this a fallback */
|
||||
|
||||
static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
struct smb_krb5_context *smb_krb5_context,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
@ -185,6 +190,8 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c
|
||||
return wret;
|
||||
}
|
||||
|
||||
/* Subcase of CrackNames, for the userPrincipalName */
|
||||
|
||||
static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
struct smb_krb5_context *smb_krb5_context,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
@ -214,7 +221,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
realm = krb5_princ_realm(smb_krb5_context->krb5_context, principal);
|
||||
domain_filter = talloc_asprintf(mem_ctx,
|
||||
"(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))",
|
||||
*realm, *realm);
|
||||
ldb_binary_encode_string(mem_ctx, *realm),
|
||||
ldb_binary_encode_string(mem_ctx, *realm));
|
||||
ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short);
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, principal);
|
||||
|
||||
@ -225,7 +233,7 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
|
||||
/* This may need to be extended for more userPrincipalName variations */
|
||||
result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))",
|
||||
unparsed_name_short);
|
||||
ldb_binary_encode_string(mem_ctx, unparsed_name_short));
|
||||
if (!result_filter || !domain_filter) {
|
||||
free(unparsed_name_short);
|
||||
return WERR_NOMEM;
|
||||
@ -239,6 +247,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Crack a single 'name', from format_offered into format_desired, returning the result in info1 */
|
||||
|
||||
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
const char *name, struct drsuapi_DsNameInfo1 *info1)
|
||||
@ -284,7 +294,7 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
|
||||
domain_filter = talloc_asprintf(mem_ctx,
|
||||
"(&(&(&(dnsRoot=%s)(objectclass=crossRef)))(nETBIOSName=*)(ncName=*))",
|
||||
str);
|
||||
ldb_binary_encode_string(mem_ctx, str));
|
||||
WERR_TALLOC_CHECK(domain_filter);
|
||||
|
||||
break;
|
||||
@ -311,11 +321,11 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
|
||||
domain_filter = talloc_asprintf(mem_ctx,
|
||||
"(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
|
||||
domain);
|
||||
ldb_binary_encode_string(mem_ctx, domain));
|
||||
WERR_TALLOC_CHECK(domain_filter);
|
||||
if (account) {
|
||||
result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
|
||||
account);
|
||||
ldb_binary_encode_string(mem_ctx, account));
|
||||
WERR_TALLOC_CHECK(result_filter);
|
||||
}
|
||||
|
||||
@ -356,7 +366,8 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
domain_filter = NULL;
|
||||
|
||||
result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
|
||||
name, name);
|
||||
ldb_binary_encode_string(mem_ctx, name),
|
||||
ldb_binary_encode_string(mem_ctx, name));
|
||||
WERR_TALLOC_CHECK(result_filter);
|
||||
break;
|
||||
}
|
||||
@ -399,7 +410,7 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, principal);
|
||||
result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(userPrincipalName=%s))",
|
||||
unparsed_name);
|
||||
ldb_binary_encode_string(mem_ctx, unparsed_name));
|
||||
|
||||
free(unparsed_name);
|
||||
WERR_TALLOC_CHECK(result_filter);
|
||||
@ -408,6 +419,7 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
|
||||
krb5_principal principal;
|
||||
char *unparsed_name_short;
|
||||
char *service;
|
||||
ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, name, &principal);
|
||||
if (ret) {
|
||||
/* perhaps it's a principal with a realm, so return the right 'domain only' response */
|
||||
@ -437,13 +449,20 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
domain_filter = NULL;
|
||||
|
||||
ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short);
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, principal);
|
||||
if (ret) {
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, principal);
|
||||
return WERR_NOMEM;
|
||||
}
|
||||
|
||||
result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(servicePrincipalName=%s))",
|
||||
unparsed_name_short);
|
||||
service = principal->name.name_string.val[0];
|
||||
if ((principal->name.name_string.len == 2) && (strcasecmp(service, "host") == 0)) {
|
||||
result_filter = talloc_asprintf(mem_ctx, "(|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer)))",
|
||||
ldb_binary_encode_string(mem_ctx, unparsed_name_short),
|
||||
ldb_binary_encode_string(mem_ctx, principal->name.name_string.val[1]));
|
||||
} else {
|
||||
result_filter = talloc_asprintf(mem_ctx, "(&(servicePrincipalName=%s)(objectClass=user))",
|
||||
ldb_binary_encode_string(mem_ctx, unparsed_name_short));
|
||||
}
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, principal);
|
||||
free(unparsed_name_short);
|
||||
WERR_TALLOC_CHECK(result_filter);
|
||||
|
||||
@ -469,6 +488,10 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
info1);
|
||||
}
|
||||
|
||||
/* Subcase of CrackNames. It is possible to translate a LDAP-style DN
|
||||
* (FQDN_1779) into a canoical name without actually searching the
|
||||
* database */
|
||||
|
||||
static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_offered, uint32_t format_desired,
|
||||
const struct ldb_dn *name_dn, const char *name,
|
||||
@ -498,9 +521,15 @@ static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
|
||||
return WERR_OK;
|
||||
|
||||
}
|
||||
|
||||
/* Given a filter for the domain, and one for the result, perform the
|
||||
* ldb search. The format offered and desired flags change the
|
||||
* behaviours, including what attributes to return.
|
||||
*
|
||||
* The smb_krb5_context is required because we use the krb5 libs for principal parsing
|
||||
*/
|
||||
|
||||
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
struct smb_krb5_context *smb_krb5_context,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
@ -733,6 +762,10 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Given a user Principal Name (such as foo@bar.com),
|
||||
* return the user and domain DNs. This is used in the KDC to then
|
||||
* return the Keys and evaluate policy */
|
||||
|
||||
NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *user_principal_name,
|
||||
@ -792,6 +825,10 @@ NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
|
||||
}
|
||||
|
||||
/* Given a Service Principal Name (such as host/foo.bar.com@BAR.COM),
|
||||
* return the user and domain DNs. This is used in the KDC to then
|
||||
* return the Keys and evaluate policy */
|
||||
|
||||
NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *service_principal_name,
|
||||
|
@ -127,6 +127,19 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
encode a string as a RFC2254 binary string, escaping any
|
||||
non-printable or '\' characters. This routine is suitable for use
|
||||
in escaping user data in ldap filters.
|
||||
*/
|
||||
char *ldb_binary_encode_string(void *mem_ctx, const char *string)
|
||||
{
|
||||
struct ldb_val val;
|
||||
val.data = string;
|
||||
val.length = strlen(string);
|
||||
return ldb_binary_encode(mem_ctx, val);
|
||||
}
|
||||
|
||||
/* find the first matching wildcard */
|
||||
static char *ldb_parse_find_wildcard(char *value)
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ struct ldb_parse_tree {
|
||||
struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s);
|
||||
char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree);
|
||||
char *ldb_binary_encode(void *ctx, struct ldb_val val);
|
||||
|
||||
char *ldb_binary_encode_string(void *mem_ctx, const char *string);
|
||||
|
||||
/*
|
||||
functions for controlling attribute handling
|
||||
|
@ -579,7 +579,7 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL
|
||||
ret = gendb_search(trusted_domain_state->policy->sam_ldb,
|
||||
mem_ctx, policy_state->system_dn, &msgs, attrs,
|
||||
"(&(cn=%s)(objectclass=trustedDomain))",
|
||||
r->in.info->name.string);
|
||||
ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
|
||||
if (ret > 0) {
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
@ -740,7 +740,7 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
|
||||
ret = gendb_search(trusted_domain_state->policy->sam_ldb,
|
||||
mem_ctx, policy_state->system_dn, &msgs, attrs,
|
||||
"(&(flatname=%s)(objectclass=trustedDomain))",
|
||||
r->in.name.string);
|
||||
ldb_binary_encode_string(mem_ctx, r->in.name.string));
|
||||
if (ret == 0) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
@ -1709,7 +1709,7 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
name2 = talloc_asprintf(mem_ctx, "%s Secret", name);
|
||||
name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
|
||||
/* search for the secret record */
|
||||
ret = gendb_search(secret_state->sam_ldb,
|
||||
mem_ctx, policy_state->system_dn, &msgs, attrs,
|
||||
@ -1745,7 +1745,8 @@ static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
ret = gendb_search(secret_state->sam_ldb, mem_ctx,
|
||||
ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
|
||||
&msgs, attrs,
|
||||
"(&(cn=%s)(objectclass=secret))", name);
|
||||
"(&(cn=%s)(objectclass=secret))",
|
||||
ldb_binary_encode_string(mem_ctx, name));
|
||||
if (ret > 0) {
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
@ -1843,7 +1844,7 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
|
||||
ret = gendb_search(secret_state->sam_ldb,
|
||||
mem_ctx, policy_state->system_dn, &msgs, attrs,
|
||||
"(&(cn=%s Secret)(objectclass=secret))",
|
||||
name);
|
||||
ldb_binary_encode_string(mem_ctx, name));
|
||||
if (ret == 0) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
@ -1867,7 +1868,8 @@ static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *m
|
||||
ret = gendb_search(secret_state->sam_ldb, mem_ctx,
|
||||
ldb_dn_explode(mem_ctx, "cn=LSA Secrets"),
|
||||
&msgs, attrs,
|
||||
"(&(cn=%s)(objectclass=secret))", name);
|
||||
"(&(cn=%s)(objectclass=secret))",
|
||||
ldb_binary_encode_string(mem_ctx, name));
|
||||
if (ret == 0) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
@ -2496,7 +2498,7 @@ static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_
|
||||
name = p + 1;
|
||||
}
|
||||
|
||||
ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", name);
|
||||
ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
|
||||
if (ret == 1) {
|
||||
*sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
|
||||
if (*sid == NULL) {
|
||||
|
@ -186,7 +186,7 @@ static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
ret = gendb_search(c_state->sam_ctx,
|
||||
mem_ctx, NULL, &ref_msgs, ref_attrs,
|
||||
"(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
|
||||
r->in.domain_name->string);
|
||||
ldb_binary_encode_string(mem_ctx, r->in.domain_name->string));
|
||||
if (ret != 1) {
|
||||
return NT_STATUS_NO_SUCH_DOMAIN;
|
||||
}
|
||||
@ -537,7 +537,7 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
|
||||
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
|
||||
"sAMAccountName",
|
||||
"(&(sAMAccountName=%s)(objectclass=group))",
|
||||
groupname);
|
||||
ldb_binary_encode_string(mem_ctx, groupname));
|
||||
if (name != NULL) {
|
||||
return NT_STATUS_GROUP_EXISTS;
|
||||
}
|
||||
@ -741,7 +741,8 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
/* check if the user already exists */
|
||||
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
|
||||
"sAMAccountName",
|
||||
"(&(sAMAccountName=%s)(objectclass=user))", account_name);
|
||||
"(&(sAMAccountName=%s)(objectclass=user))",
|
||||
ldb_binary_encode_string(mem_ctx, account_name));
|
||||
if (name != NULL) {
|
||||
return NT_STATUS_USER_EXISTS;
|
||||
}
|
||||
@ -969,7 +970,7 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
|
||||
"sAMAccountName",
|
||||
"(sAMAccountName=%s)(objectclass=group))",
|
||||
alias_name);
|
||||
ldb_binary_encode_string(mem_ctx, alias_name));
|
||||
|
||||
if (name != NULL) {
|
||||
return NT_STATUS_ALIAS_EXISTS;
|
||||
@ -1251,7 +1252,8 @@ static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
r->out.types.ids[i] = SID_NAME_UNKNOWN;
|
||||
|
||||
count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
|
||||
"sAMAccountName=%s", r->in.names[i].string);
|
||||
"sAMAccountName=%s",
|
||||
ldb_binary_encode_string(mem_ctx, r->in.names[i].string));
|
||||
if (count != 1) {
|
||||
status = STATUS_SOME_UNMAPPED;
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user