1
0
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:
Andrew Bartlett 2005-12-19 07:07:11 +00:00 committed by Gerald (Jerry) Carter
parent e751d81414
commit 8308cf6e04
6 changed files with 82 additions and 27 deletions
source
auth
dsdb/samdb
lib/ldb
common
include
rpc_server

View File

@ -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;
}

View File

@ -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,

View File

@ -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)
{

View File

@ -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

View File

@ -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) {

View File

@ -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;