diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-10-13 04:24:49 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:39:45 -0500 |
commit | d96f706bb0a6b41eddec9d467ef3d5f31bee41ab (patch) | |
tree | 1f692464945004d30cf746b864fad54e88103b20 | |
parent | 4c188e0a1e55ead361a4236bd8d02e198e9296a0 (diff) | |
download | samba-d96f706bb0a6b41eddec9d467ef3d5f31bee41ab.tar.gz samba-d96f706bb0a6b41eddec9d467ef3d5f31bee41ab.tar.bz2 samba-d96f706bb0a6b41eddec9d467ef3d5f31bee41ab.zip |
r10953: Add a new function to form a canonicalName out of a DN to ldb_dn.c
Use this new function in the client and server for the CrackNames
case, where we particularly need it.
Andrew Bartlett
(This used to be commit 380037ee09ef8293bdb288d6c015e7c80f180a30)
-rw-r--r-- | source4/lib/ldb/common/ldb_dn.c | 55 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 2 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/drsuapi_cracknames.c | 154 | ||||
-rw-r--r-- | source4/torture/rpc/drsuapi_cracknames.c | 96 |
4 files changed, 210 insertions, 97 deletions
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index b497de142b..abe8985f9d 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -839,3 +839,58 @@ struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn) return rdn; } +static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) { + int i; + char *cracked = NULL; + for (i = dn->comp_num - 1 ; i >= 0; i--) { + if (strcasecmp(dn->components[i].name, "dc") != 0) { + break; + } + if (cracked) { + cracked = talloc_asprintf(mem_ctx, "%s.%s", dn->components[i].value.data, + cracked); + } else { + cracked = talloc_strdup(mem_ctx, dn->components[i].value.data); + } + if (!cracked) { + return NULL; + } + } + + /* Only domain components */ + if (i < 0) { + if (ex_format) { + cracked = talloc_asprintf(mem_ctx, "%s\n", cracked); + } else { + cracked = talloc_asprintf(mem_ctx, "%s/", cracked); + } + return cracked; + } + + for (; i > 0; i--) { + cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, + dn->components[i].value.data); + if (!cracked) { + return NULL; + } + } + + /* Last one */ + if (ex_format) { + cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked, + dn->components[i].value.data); + } else { + cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, + dn->components[i].value.data); + } + return cracked; +} + +char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) { + return ldb_dn_canonical(mem_ctx, dn, 0); + +} + +char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) { + return ldb_dn_canonical(mem_ctx, dn, 1); +} diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index fd3577a470..27313613ab 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -502,4 +502,6 @@ int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *rep char *ldb_timestring(void *mem_ctx, time_t t); time_t ldb_string_to_time(const char *s); +char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn); +char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn); #endif diff --git a/source4/rpc_server/drsuapi/drsuapi_cracknames.c b/source4/rpc_server/drsuapi/drsuapi_cracknames.c index 29ca1a4527..c1a6c19978 100644 --- a/source4/rpc_server/drsuapi/drsuapi_cracknames.c +++ b/source4/rpc_server/drsuapi/drsuapi_cracknames.c @@ -41,6 +41,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, const char *name, struct drsuapi_DsNameInfo1 *info1); +static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, + uint32_t format_offered, uint32_t format_desired, + const struct ldb_dn *name_dn, const char *name, + struct drsuapi_DsNameInfo1 *info1); + static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, TALLOC_CTX *mem_ctx, const char *alias_from, @@ -82,7 +87,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru mapping = talloc_strdup(mem_ctx, (const char *)spnmappings->values[i].data); if (!mapping) { - DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping", service_dn_str)); + DEBUG(1, ("LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping\n", service_dn_str)); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } @@ -90,7 +95,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru p = strchr(mapping, '='); if (!p) { - DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s", + DEBUG(1, ("ldb_search: dn: %s sPNMapping malformed: %s\n", service_dn_str, mapping)); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } @@ -109,7 +114,7 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru } } while (p); } - DEBUG(1, ("LDB_lookup_spn_alias: no alias for service %s applicable", alias_from)); + DEBUG(1, ("LDB_lookup_spn_alias: no alias for service %s applicable\n", alias_from)); return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } @@ -137,8 +142,9 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX } /* grab cifs/, http/ etc */ + + /* This is checked for in callers, but be safe */ if (principal->name.name_string.len < 2) { - DEBUG(5, ("could not find principal in DB, alias not applicable")); info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; } @@ -167,6 +173,7 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX return WERR_NOMEM; } + /* reform principal */ ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &new_princ); krb5_free_principal(smb_krb5_context->krb5_context, principal); @@ -175,7 +182,6 @@ static WERROR DsCrackNameSPNAlias(struct drsuapi_bind_state *b_state, TALLOC_CTX return WERR_NOMEM; } - /* reform principal */ wret = DsCrackNameOneName(b_state, mem_ctx, format_flags, format_offered, format_desired, new_princ, info1); free(new_princ); @@ -201,7 +207,7 @@ static WERROR DsCrackNameUPN(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem return WERR_OK; } - ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal); + ret = krb5_parse_name_mustrealm(smb_krb5_context->krb5_context, name, &principal); if (ret) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; @@ -349,6 +355,14 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX WERR_TALLOC_CHECK(result_filter); break; } + case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { + domain_filter = NULL; + + result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))", + name, name); + WERR_TALLOC_CHECK(result_filter); + break; + } case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: { struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name); @@ -398,11 +412,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX krb5_principal principal; char *unparsed_name_short; ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, name, &principal); - if (ret) { + if (ret || (principal->name.name_string.len < 2)) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; } - + domain_filter = NULL; ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short); @@ -424,6 +438,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX } } + + if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) { + return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired, + name_dn, name, info1); + } return DsCrackNameOneFilter(b_state, mem_ctx, smb_krb5_context, @@ -433,6 +452,38 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX info1); } +static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, + uint32_t format_offered, uint32_t format_desired, + const struct ldb_dn *name_dn, const char *name, + struct drsuapi_DsNameInfo1 *info1) +{ + char *cracked; + if (format_offered != DRSUAPI_DS_NAME_FORMAT_FQDN_1779) { + info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING; + return WERR_OK; + } + + switch (format_desired) { + case DRSUAPI_DS_NAME_FORMAT_CANONICAL: + cracked = ldb_dn_canonical_string(mem_ctx, name_dn); + break; + case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: + cracked = ldb_dn_canonical_ex_string(mem_ctx, name_dn); + break; + default: + info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING; + return WERR_OK; + } + info1->status = DRSUAPI_DS_NAME_STATUS_OK; + info1->result_name = cracked; + if (!cracked) { + return WERR_NOMEM; + } + + return WERR_OK; + +} + static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, @@ -449,32 +500,42 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT /* here we need to set the attrs lists for domain and result lookups */ switch (format_desired) { - case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: { - const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL}; - const char * const _result_attrs[] = { "distinguishedName", NULL}; - - domain_attrs = _domain_attrs; - result_attrs = _result_attrs; - break; - } - case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: { - const char * const _domain_attrs[] = { "ncName", "dnsRoot", "nETBIOSName", NULL}; - const char * const _result_attrs[] = { "sAMAccountName", "objectSid", NULL}; - - domain_attrs = _domain_attrs; - result_attrs = _result_attrs; - break; - } - case DRSUAPI_DS_NAME_FORMAT_GUID: { - const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL}; - const char * const _result_attrs[] = { "objectGUID", NULL}; - - domain_attrs = _domain_attrs; - result_attrs = _result_attrs; - break; - } - default: - return WERR_OK; + case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: + case DRSUAPI_DS_NAME_FORMAT_CANONICAL: + case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: { + const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL}; + const char * const _result_attrs[] = { NULL}; + + domain_attrs = _domain_attrs; + result_attrs = _result_attrs; + break; + } + case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: { + const char * const _domain_attrs[] = { "ncName", "dnsRoot", "nETBIOSName", NULL}; + const char * const _result_attrs[] = { "sAMAccountName", "objectSid", NULL}; + + domain_attrs = _domain_attrs; + result_attrs = _result_attrs; + break; + } + case DRSUAPI_DS_NAME_FORMAT_GUID: { + const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL}; + const char * const _result_attrs[] = { "objectGUID", NULL}; + + domain_attrs = _domain_attrs; + result_attrs = _result_attrs; + break; + } + case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { + const char * const _domain_attrs[] = { "ncName", "dnsRoot", NULL}; + const char * const _result_attrs[] = { "displayName", "samAccountName", NULL}; + + domain_attrs = _domain_attrs; + result_attrs = _result_attrs; + break; + } + default: + return WERR_OK; } if (domain_filter) { @@ -534,7 +595,8 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT format_flags, format_offered, format_desired, name, info1); } - break; + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; + return WERR_OK; case -1: info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; @@ -552,6 +614,16 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } + case DRSUAPI_DS_NAME_FORMAT_CANONICAL: + return DsCrackNameOneSyntactical(mem_ctx, + DRSUAPI_DS_NAME_FORMAT_FQDN_1779, + DRSUAPI_DS_NAME_FORMAT_CANONICAL, + result_res[0]->dn, name, info1); + case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: + return DsCrackNameOneSyntactical(mem_ctx, + DRSUAPI_DS_NAME_FORMAT_FQDN_1779, + DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX, + result_res[0]->dn, name, info1); case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: { const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result_res[0], "objectSid"); const char *_acc = "", *_dom = ""; @@ -616,6 +688,18 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } + case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { + info1->result_name = samdb_result_string(result_res[0], "displayName", NULL); + if (!info1->result_name) { + info1->result_name = samdb_result_string(result_res[0], "sAMAccountName", NULL); + } + if (!info1->result_name) { + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; + } else { + info1->status = DRSUAPI_DS_NAME_STATUS_OK; + } + return WERR_OK; + } default: return WERR_OK; } diff --git a/source4/torture/rpc/drsuapi_cracknames.c b/source4/torture/rpc/drsuapi_cracknames.c index 9ebeab2a8b..b37825d85c 100644 --- a/source4/torture/rpc/drsuapi_cracknames.c +++ b/source4/torture/rpc/drsuapi_cracknames.c @@ -25,6 +25,7 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_drsuapi.h" #include "torture/rpc/drsuapi.h" +#include "ldb/include/ldb.h" static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct DsPrivate *priv, const char *dn, @@ -35,7 +36,6 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NTSTATUS status; BOOL ret = True; struct drsuapi_DsCrackNames r; - struct drsuapi_DsNameString names[1]; enum drsuapi_DsNameFormat formats[] = { DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, @@ -48,6 +48,7 @@ static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY, DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN }; + struct drsuapi_DsNameString names[ARRAY_SIZE(formats)]; int i, j; const char *n_matrix[ARRAY_SIZE(formats)][ARRAY_SIZE(formats)]; @@ -208,6 +209,10 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *dns_domain; const char *nt4_domain; const char *FQDN_1779_name; + struct ldb_dn *FQDN_1779_dn; + struct ldb_dn *realm_dn; + const char *realm_canonical; + const char *realm_canonical_ex; const char *user_principal_name; const char *service_principal_name; const char *canonical_name; @@ -305,6 +310,27 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, if (!ret) { return ret; } + + realm_dn = ldb_dn_explode(mem_ctx, r.out.ctr.ctr1->array[0].result_name); + realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn); + + if (strcmp(realm_canonical, + talloc_asprintf(mem_ctx, "%s/", lp_realm()))!= 0) { + printf("local Round trip on canonical name failed: %s != %s!\n", + realm_canonical, + talloc_asprintf(mem_ctx, "%s/", lp_realm())); + return False; + }; + + realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn); + + if (strcmp(realm_canonical_ex, + talloc_asprintf(mem_ctx, "%s\n", lp_realm()))!= 0) { + printf("local Round trip on canonical ex name failed: %s != %s!\n", + realm_canonical, + talloc_asprintf(mem_ctx, "%s\n", lp_realm())); + return False; + }; r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; @@ -364,63 +390,10 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name; - r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; - r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL; - names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc); - - printf("testing DsCrackNames with name '%s' desired format:%d\n", - names[0].str, r.in.req.req1.format_desired); - - status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r); - if (!NT_STATUS_IS_OK(status)) { - const char *errstr = nt_errstr(status); - if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { - errstr = dcerpc_errstr(mem_ctx, p->last_fault_code); - } - printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr); - ret = False; - } else if (!W_ERROR_IS_OK(r.out.result)) { - printf("DsCrackNames failed - %s\n", win_errstr(r.out.result)); - ret = False; - } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { - printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status); - ret = False; - } + FQDN_1779_dn = ldb_dn_explode(mem_ctx, FQDN_1779_name); - if (!ret) { - return ret; - } - - canonical_name = r.out.ctr.ctr1->array[0].result_name; - - r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; - r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX; - names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc); - - printf("testing DsCrackNames with name '%s' desired format:%d\n", - names[0].str, r.in.req.req1.format_desired); - - status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r); - if (!NT_STATUS_IS_OK(status)) { - const char *errstr = nt_errstr(status); - if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { - errstr = dcerpc_errstr(mem_ctx, p->last_fault_code); - } - printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr); - ret = False; - } else if (!W_ERROR_IS_OK(r.out.result)) { - printf("DsCrackNames failed - %s\n", win_errstr(r.out.result)); - ret = False; - } else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { - printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status); - ret = False; - } - - if (!ret) { - return ret; - } - - canonical_ex_name = r.out.ctr.ctr1->array[0].result_name; + canonical_name = ldb_dn_canonical_string(mem_ctx, FQDN_1779_dn); + canonical_ex_name = ldb_dn_canonical_ex_string(mem_ctx, FQDN_1779_dn); user_principal_name = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain); service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc); @@ -714,15 +687,14 @@ BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, printf("DsCrackNames failed - %s\n", win_errstr(r.out.result)); ret = False; } else if (r.out.ctr.ctr1->array[0].status != crack[i].status) { - printf("DsCrackNames unexpected error %d, wanted %d on name: %s\n", + printf("DsCrackNames unexpected status %d, wanted %d on name: %s\n", r.out.ctr.ctr1->array[0].status, crack[i].status, crack[i].str); ret = False; - } - if (crack[i].expected_str - && (strcmp(r.out.ctr.ctr1->array[0].result_name, - crack[i].expected_str) != 0)) { + } else if (crack[i].expected_str + && (strcmp(r.out.ctr.ctr1->array[0].result_name, + crack[i].expected_str) != 0)) { printf("DsCrackNames failed - got %s, expected %s\n", r.out.ctr.ctr1->array[0].result_name, crack[i].expected_str); |