mirror of
https://github.com/samba-team/samba.git
synced 2025-02-19 21:57:57 +03:00
secrets system, and not the old system from Samba3. This allowed the code from auth_domain to be shared - we now only lookup the secrets.ldb in lib/credentials.c. In order to link the resultant binary, samdb_search() has been moved from deep inside rpc_server into lib/gendb.c, along with the existing gendb_search_v(). The vast majority of this patch is the simple rename that followed, (Depending on the whole SAMDB for just this function seemed pointless, and brought in futher dependencies, such as smbencrypt.c). Andrew Bartlett (This used to be commit e13c671619bd290a8b3cae8555cb281a9a185ee0)
285 lines
7.5 KiB
C
285 lines
7.5 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
|
|
endpoint server for the drsuapi pipe
|
|
DsCrackNames()
|
|
|
|
Copyright (C) Stefan Metzmacher 2004
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "librpc/gen_ndr/ndr_drsuapi.h"
|
|
#include "rpc_server/dcerpc_server.h"
|
|
#include "rpc_server/common/common.h"
|
|
#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
|
|
#include "lib/ldb/include/ldb.h"
|
|
|
|
static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
|
|
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
|
const char *name, struct drsuapi_DsNameInfo1 *info1)
|
|
{
|
|
int ret;
|
|
const char *domain_filter = NULL;
|
|
const char * const *domain_attrs;
|
|
struct ldb_message **domain_res = NULL;
|
|
const char *result_basedn = NULL;
|
|
const char *result_filter = NULL;
|
|
const char * const *result_attrs;
|
|
struct ldb_message **result_res = NULL;
|
|
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
|
|
info1->dns_domain_name = NULL;
|
|
info1->result_name = NULL;
|
|
|
|
if (!name) {
|
|
return WERR_INVALID_PARAM;
|
|
}
|
|
|
|
/* TODO: - fill the correct names in all cases!
|
|
* - handle format_flags
|
|
*/
|
|
|
|
/* here we need to set the domain_filter and/or the result_filter */
|
|
switch (format_offered) {
|
|
case DRSUAPI_DS_NAME_FORMAT_CANONICAL: {
|
|
char *str;
|
|
|
|
str = talloc_asprintf(mem_ctx, "%s/", lp_realm());
|
|
WERR_TALLOC_CHECK(str);
|
|
|
|
ret = strcasecmp(str, name);
|
|
talloc_free(str);
|
|
if (ret != 0) {
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
|
|
return WERR_OK;
|
|
}
|
|
|
|
domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=domainDNS)(name=%s))",
|
|
lp_workgroup());
|
|
WERR_TALLOC_CHECK(domain_filter);
|
|
|
|
break;
|
|
}
|
|
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
|
|
char *p;
|
|
char *domain;
|
|
const char *account = NULL;
|
|
|
|
domain = talloc_strdup(mem_ctx, name);
|
|
WERR_TALLOC_CHECK(domain);
|
|
|
|
p = strchr(domain, '\\');
|
|
if (!p) {
|
|
/* invalid input format */
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
|
|
return WERR_OK;
|
|
}
|
|
p[0] = '\0';
|
|
|
|
if (p[1]) {
|
|
account = &p[1];
|
|
}
|
|
|
|
domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=domainDNS)(name=%s))",
|
|
domain);
|
|
WERR_TALLOC_CHECK(domain_filter);
|
|
if (account) {
|
|
result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
|
|
account);
|
|
WERR_TALLOC_CHECK(result_filter);
|
|
}
|
|
|
|
talloc_free(domain);
|
|
break;
|
|
}
|
|
default: {
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
|
|
return WERR_OK;
|
|
}
|
|
}
|
|
|
|
/* 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[] = { "dn", "dnsDomain", NULL};
|
|
const char * const _result_attrs[] = { "dn", NULL};
|
|
|
|
domain_attrs = _domain_attrs;
|
|
result_attrs = _result_attrs;
|
|
break;
|
|
}
|
|
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
|
|
const char * const _domain_attrs[] = { "name", "dnsDomain", "dn", NULL};
|
|
const char * const _result_attrs[] = { "sAMAccountName", NULL};
|
|
|
|
domain_attrs = _domain_attrs;
|
|
result_attrs = _result_attrs;
|
|
break;
|
|
}
|
|
case DRSUAPI_DS_NAME_FORMAT_GUID: {
|
|
const char * const _domain_attrs[] = { "objectGUID", "dnsDomain", "dn", NULL};
|
|
const char * const _result_attrs[] = { "objectGUID", NULL};
|
|
|
|
domain_attrs = _domain_attrs;
|
|
result_attrs = _result_attrs;
|
|
break;
|
|
}
|
|
default:
|
|
return WERR_OK;
|
|
}
|
|
|
|
/* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
|
|
ret = gendb_search(b_state->sam_ctx, mem_ctx, NULL, &domain_res, domain_attrs,
|
|
"%s", domain_filter);
|
|
switch (ret) {
|
|
case 1:
|
|
break;
|
|
case 0:
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
|
|
return WERR_OK;
|
|
case -1:
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
|
|
return WERR_OK;
|
|
default:
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
|
|
return WERR_OK;
|
|
}
|
|
|
|
info1->dns_domain_name = samdb_result_string(domain_res[0], "dnsDomain", NULL);
|
|
WERR_TALLOC_CHECK(info1->dns_domain_name);
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
|
|
|
|
if (result_filter) {
|
|
result_basedn = samdb_result_string(domain_res[0], "dn", NULL);
|
|
|
|
ret = gendb_search(b_state->sam_ctx, mem_ctx, result_basedn, &result_res,
|
|
result_attrs, "%s", result_filter);
|
|
switch (ret) {
|
|
case 1:
|
|
break;
|
|
case 0:
|
|
return WERR_OK;
|
|
case -1:
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
|
|
return WERR_OK;
|
|
default:
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
|
|
return WERR_OK;
|
|
}
|
|
} else {
|
|
result_res = domain_res;
|
|
}
|
|
|
|
/* here we can use result_res[0] and domain_res[0] */
|
|
switch (format_desired) {
|
|
case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
|
|
info1->result_name = samdb_result_string(result_res[0], "dn", NULL);
|
|
WERR_TALLOC_CHECK(info1->result_name);
|
|
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_OK;
|
|
return WERR_OK;
|
|
}
|
|
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
|
|
const char *_dom;
|
|
const char *_acc = "";
|
|
|
|
_dom = samdb_result_string(domain_res[0], "name", NULL);
|
|
WERR_TALLOC_CHECK(_dom);
|
|
|
|
if (result_filter) {
|
|
_acc = samdb_result_string(result_res[0], "sAMAccountName", NULL);
|
|
WERR_TALLOC_CHECK(_acc);
|
|
}
|
|
|
|
info1->result_name = talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc);
|
|
WERR_TALLOC_CHECK(info1->result_name);
|
|
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_OK;
|
|
return WERR_OK;
|
|
}
|
|
case DRSUAPI_DS_NAME_FORMAT_GUID: {
|
|
const char *result;
|
|
|
|
result = samdb_result_string(result_res[0], "objectGUID", NULL);
|
|
WERR_TALLOC_CHECK(result);
|
|
|
|
info1->result_name = talloc_asprintf(mem_ctx, "{%s}", result);
|
|
WERR_TALLOC_CHECK(info1->result_name);
|
|
|
|
info1->status = DRSUAPI_DS_NAME_STATUS_OK;
|
|
return WERR_OK;
|
|
}
|
|
default:
|
|
return WERR_OK;
|
|
}
|
|
|
|
return WERR_INVALID_PARAM;
|
|
}
|
|
|
|
/*
|
|
drsuapi_DsCrackNames
|
|
*/
|
|
WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
|
struct drsuapi_DsCrackNames *r)
|
|
{
|
|
WERROR status;
|
|
struct drsuapi_bind_state *b_state;
|
|
struct dcesrv_handle *h;
|
|
|
|
r->out.level = r->in.level;
|
|
ZERO_STRUCT(r->out.ctr);
|
|
|
|
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
|
|
b_state = h->data;
|
|
|
|
switch (r->in.level) {
|
|
case 1: {
|
|
struct drsuapi_DsNameCtr1 *ctr1;
|
|
struct drsuapi_DsNameInfo1 *names;
|
|
int count;
|
|
int i;
|
|
|
|
ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
|
|
WERR_TALLOC_CHECK(ctr1);
|
|
|
|
count = r->in.req.req1.count;
|
|
names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
|
|
WERR_TALLOC_CHECK(names);
|
|
|
|
for (i=0; i < count; i++) {
|
|
status = DsCrackNameOneName(b_state, mem_ctx,
|
|
r->in.req.req1.format_flags,
|
|
r->in.req.req1.format_offered,
|
|
r->in.req.req1.format_desired,
|
|
r->in.req.req1.names[i].str,
|
|
&names[i]);
|
|
if (!W_ERROR_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
ctr1->count = count;
|
|
ctr1->array = names;
|
|
r->out.ctr.ctr1 = ctr1;
|
|
|
|
return WERR_OK;
|
|
}
|
|
}
|
|
|
|
return WERR_UNKNOWN_LEVEL;
|
|
}
|