Example #1
0
static WERROR cracknames(struct rpc_pipe_client *cli,
			 TALLOC_CTX *mem_ctx,
			 struct policy_handle *bind_handle,
			 enum drsuapi_DsNameFormat format_offered,
			 enum drsuapi_DsNameFormat format_desired,
			 int argc,
			 const char **argv,
			 union drsuapi_DsNameCtr *ctr)
{
	NTSTATUS status;
	WERROR werr;
	int i;
	uint32_t level = 1;
	union drsuapi_DsNameRequest req;
	uint32_t level_out;
	struct drsuapi_DsNameString *names;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	names = talloc_zero_array(mem_ctx, struct drsuapi_DsNameString, argc);
	W_ERROR_HAVE_NO_MEMORY(names);

	for (i=0; i<argc; i++) {
		names[i].str = argv[i];
	}

	req.req1.codepage	= 1252; /* german */
	req.req1.language	= 0x00000407; /* german */
	req.req1.count		= argc;
	req.req1.names		= names;
	req.req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
	req.req1.format_offered	= format_offered;
	req.req1.format_desired	= format_desired;

	status = dcerpc_drsuapi_DsCrackNames(b, mem_ctx,
					     bind_handle,
					     level,
					     &req,
					     &level_out,
					     ctr,
					     &werr);
	if (!NT_STATUS_IS_OK(status)) {
		return ntstatus_to_werror(status);
	}

	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	return WERR_OK;
}
Example #2
0
static NTSTATUS libnet_dssync_lookup_nc(TALLOC_CTX *mem_ctx,
					struct dssync_context *ctx)
{
	NTSTATUS status;
	WERROR werr;
	uint32_t level = 1;
	union drsuapi_DsNameRequest req;
	uint32_t level_out;
	struct drsuapi_DsNameString names[1];
	union drsuapi_DsNameCtr ctr;
	struct dcerpc_binding_handle *b = ctx->cli->binding_handle;

	names[0].str = talloc_asprintf(mem_ctx, "%s\\", ctx->domain_name);
	NT_STATUS_HAVE_NO_MEMORY(names[0].str);

	req.req1.codepage	= 1252; /* german */
	req.req1.language	= 0x00000407; /* german */
	req.req1.count		= 1;
	req.req1.names		= names;
	req.req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
	req.req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_UNKNOWN;
	req.req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;

	status = dcerpc_drsuapi_DsCrackNames(b, mem_ctx,
					     &ctx->bind_handle,
					     level,
					     &req,
					     &level_out,
					     &ctr,
					     &werr);
	if (!NT_STATUS_IS_OK(status)) {
		ctx->error_message = talloc_asprintf(ctx,
			"Failed to lookup DN for domain name: %s",
			get_friendly_nt_error_msg(status));
		return status;
	}

	if (!W_ERROR_IS_OK(werr)) {
		ctx->error_message = talloc_asprintf(ctx,
			"Failed to lookup DN for domain name: %s",
			get_friendly_werror_msg(werr));
		return werror_to_ntstatus(werr);
	}

	if (ctr.ctr1->count != 1) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	ctx->nc_dn = talloc_strdup(mem_ctx, ctr.ctr1->array[0].result_name);
	NT_STATUS_HAVE_NO_MEMORY(ctx->nc_dn);

	if (!ctx->dns_domain_name) {
		ctx->dns_domain_name = talloc_strdup_upper(mem_ctx,
			ctr.ctr1->array[0].dns_domain_name);
		NT_STATUS_HAVE_NO_MEMORY(ctx->dns_domain_name);
	}

	return NT_STATUS_OK;
}
Example #3
0
bool test_DsCrackNames(struct torture_context *tctx,
		       struct DsPrivate *priv)
{
	NTSTATUS status;
	const char *err_msg;
	struct drsuapi_DsCrackNames r;
	union drsuapi_DsNameRequest req;
	int32_t level_out;
	union drsuapi_DsNameCtr ctr;
	struct drsuapi_DsNameString names[1];
	const char *dns_domain;
	const char *nt4_domain;
	const char *FQDN_1779_name;
	struct ldb_context *ldb;
	struct ldb_dn *FQDN_1779_dn;
	struct ldb_dn *realm_dn;
	const char *realm_dn_str;
	const char *realm_canonical;
	const char *realm_canonical_ex;
	const char *user_principal_name;
	char *user_principal_name_short;
	const char *service_principal_name;
	const char *canonical_name;
	const char *canonical_ex_name;
	const char *dom_sid;
	const char *test_dc = torture_join_netbios_name(priv->join);
	struct dcerpc_pipe *p = priv->drs_pipe;
	TALLOC_CTX *mem_ctx = priv;

	ZERO_STRUCT(r);
	r.in.bind_handle		= &priv->bind_handle;
	r.in.level			= 1;
	r.in.req			= &req;
	r.in.req->req1.codepage		= 1252; /* german */
	r.in.req->req1.language		= 0x00000407; /* german */
	r.in.req->req1.count		= 1;
	r.in.req->req1.names		= names;
	r.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;

	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;

	r.out.level_out			= &level_out;
	r.out.ctr			= &ctr;

	dom_sid = dom_sid_string(mem_ctx, torture_join_sid(priv->join));
	
	names[0].str = dom_sid;

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	dns_domain = r.out.ctr->ctr1->array[0].dns_domain_name;
	nt4_domain = r.out.ctr->ctr1->array[0].result_name;

	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_GUID;

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	priv->domain_dns_name = r.out.ctr->ctr1->array[0].dns_domain_name;
	priv->domain_guid_str = r.out.ctr->ctr1->array[0].result_name;
	GUID_from_string(priv->domain_guid_str, &priv->domain_guid);

	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	ldb = ldb_init(mem_ctx, tctx->ev);
	
	realm_dn_str = r.out.ctr->ctr1->array[0].result_name;
	realm_dn =  ldb_dn_new(mem_ctx, ldb, realm_dn_str);
	realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn);

	if (strcmp(realm_canonical,
		   talloc_asprintf(mem_ctx, "%s/", dns_domain))!= 0) {
		err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical name failed: %s != %s!",
				          realm_canonical,
				          talloc_asprintf(mem_ctx, "%s/", dns_domain));
		torture_fail(tctx, err_msg);
	};

	realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn);

	if (strcmp(realm_canonical_ex, 
		   talloc_asprintf(mem_ctx, "%s\n", dns_domain))!= 0) {
		err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical ex name failed: %s != %s!",
				          realm_canonical,
				          talloc_asprintf(mem_ctx, "%s\n", dns_domain));
		torture_fail(tctx, err_msg);
	};

	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = nt4_domain;

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	priv->domain_obj_dn = 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_FQDN_1779;
	names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc);

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	FQDN_1779_name = r.out.ctr->ctr1->array[0].result_name;

	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID;
	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = priv->domain_guid_str;

	torture_comment(tctx, "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);
		}
		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
		torture_fail(tctx, err_msg);
	} else if (!W_ERROR_IS_OK(r.out.result)) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
		torture_fail(tctx, err_msg);
	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
					  r.out.ctr->ctr1->array[0].status);
		torture_fail(tctx, err_msg);
	}

	if (strcmp(priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name) != 0) {
		err_msg = talloc_asprintf(mem_ctx,
				"DsCrackNames failed to return same DNS name - expected %s got %s",
				priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name);
		torture_fail(tctx, err_msg);
	}

	FQDN_1779_dn = ldb_dn_new(mem_ctx, ldb, FQDN_1779_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);

	/* form up a user@DOMAIN */
	user_principal_name_short = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, nt4_domain);
	/* variable nt4_domain includs a trailing \ */
	user_principal_name_short[strlen(user_principal_name_short) - 1] = '\0';
	
	service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
	{
		
		struct {
			enum drsuapi_DsNameFormat format_offered;
			enum drsuapi_DsNameFormat format_desired;
			const char *comment;
			const char *str;
			const char *expected_str;
			const char *expected_dns;
			enum drsuapi_DsNameStatus status;
			enum drsuapi_DsNameStatus alternate_status;
			enum drsuapi_DsNameFlags flags;
			bool skip;
		} crack[] = {
			{
				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
				.str = user_principal_name,
				.expected_str = FQDN_1779_name,
				.status = DRSUAPI_DS_NAME_STATUS_OK
			},
			{
				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
				.str = user_principal_name_short,
				.expected_str = FQDN_1779_name,
				.status = DRSUAPI_DS_NAME_STATUS_OK
			},
			{
				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
Example #4
0
static bool test_DsCrackNamesMatrix(struct torture_context *tctx,
				    struct DsPrivate *priv, const char *dn,
				    const char *user_principal_name, const char *service_principal_name)
{
	NTSTATUS status;
	const char *err_msg;
	struct drsuapi_DsCrackNames r;
	union drsuapi_DsNameRequest req;
	int32_t level_out;
	union drsuapi_DsNameCtr ctr;
	struct dcerpc_pipe *p = priv->drs_pipe;
	TALLOC_CTX *mem_ctx = priv;

	enum drsuapi_DsNameFormat formats[] = {
		DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
		DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
		DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
		DRSUAPI_DS_NAME_FORMAT_DISPLAY,
		DRSUAPI_DS_NAME_FORMAT_GUID,
		DRSUAPI_DS_NAME_FORMAT_CANONICAL,
		DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
		DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
		DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
		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)];
	const char *n_from[ARRAY_SIZE(formats)];

	ZERO_STRUCT(r);
	r.in.bind_handle		= &priv->bind_handle;
	r.in.level			= 1;
	r.in.req			= &req;
	r.in.req->req1.codepage		= 1252; /* german */
	r.in.req->req1.language		= 0x00000407; /* german */
	r.in.req->req1.count		= 1;
	r.in.req->req1.names		= names;
	r.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;

	r.out.level_out			= &level_out;
	r.out.ctr			= &ctr;

	n_matrix[0][0] = dn;

	for (i = 0; i < ARRAY_SIZE(formats); i++) {
		r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
		r.in.req->req1.format_desired	= formats[i];
		names[0].str = dn;
		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);
			}
			err_msg = talloc_asprintf(mem_ctx,
					"testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
					names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
			torture_fail(tctx, err_msg);
		} else if (!W_ERROR_IS_OK(r.out.result)) {
			err_msg = talloc_asprintf(mem_ctx,
					"testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
			       names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, win_errstr(r.out.result));
			torture_fail(tctx, err_msg);
		}
			
		switch (formats[i]) {
		case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:	
			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) {
				err_msg = talloc_asprintf(mem_ctx,
						"Unexpected error (%d): This name lookup should fail",
						r.out.ctr->ctr1->array[0].status);
				torture_fail(tctx, err_msg);
			}
			torture_comment(tctx, __location__ ": (expected) error\n");
			break;
		case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
				err_msg = talloc_asprintf(mem_ctx,
						"Unexpected error (%d): This name lookup should fail",
						r.out.ctr->ctr1->array[0].status);
				torture_fail(tctx, err_msg);
			}
			torture_comment(tctx, __location__ ": (expected) error\n");
			break;
		case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:	/* should fail as we ask server to convert to Unknown format */
		case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:	
		case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:	
			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) {
				err_msg = talloc_asprintf(mem_ctx,
						"Unexpected error (%d): This name lookup should fail",
						r.out.ctr->ctr1->array[0].status);
				torture_fail(tctx, err_msg);
			}
			torture_comment(tctx, __location__ ": (expected) error\n");
			break;
		default:
			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
				err_msg = talloc_asprintf(mem_ctx,
						"DsCrackNames error: %d",
						r.out.ctr->ctr1->array[0].status);
				torture_fail(tctx, err_msg);
			}
			break;
		}

		switch (formats[i]) {
		case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
			n_from[i] = user_principal_name;
			break;
		case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:	
			n_from[i] = service_principal_name;
			break;
		case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
		case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:	
		case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:	
			n_from[i] = NULL;
			break;
		default:
			n_from[i] = r.out.ctr->ctr1->array[0].result_name;
			printf("%s\n", n_from[i]);
			break;
		}
	}

	for (i = 0; i < ARRAY_SIZE(formats); i++) {
		for (j = 0; j < ARRAY_SIZE(formats); j++) {
			r.in.req->req1.format_offered	= formats[i];
			r.in.req->req1.format_desired	= formats[j];
			if (!n_from[i]) {
				n_matrix[i][j] = NULL;
				continue;
			}
			names[0].str = n_from[i];
			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);
				}
				err_msg = talloc_asprintf(mem_ctx,
						"testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
						names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
				torture_fail(tctx, err_msg);
			} else if (!W_ERROR_IS_OK(r.out.result)) {
				err_msg = talloc_asprintf(mem_ctx,
						"testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
						names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired,
						win_errstr(r.out.result));
				torture_fail(tctx, err_msg);
			}
			
			if (r.out.ctr->ctr1->array[0].status == DRSUAPI_DS_NAME_STATUS_OK) {
				n_matrix[i][j] = r.out.ctr->ctr1->array[0].result_name;
			} else {
				n_matrix[i][j] = NULL;
			}
		}
	}

	for (i = 0; i < ARRAY_SIZE(formats); i++) {
		for (j = 0; j < ARRAY_SIZE(formats); j++) {
			if (n_matrix[i][j] == n_from[j]) {
				
			/* We don't have a from name for these yet (and we can't map to them to find it out) */
			} else if (n_matrix[i][j] == NULL && n_from[i] == NULL) {
				
			/* we can't map to these two */
			} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL) {
			} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) {
			} else if (n_matrix[i][j] == NULL && n_from[j] != NULL) {
				err_msg = talloc_asprintf(mem_ctx,
						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
						formats[i], formats[j], n_matrix[i][j], n_from[j]);
				torture_fail(tctx, err_msg);
			} else if (n_matrix[i][j] != NULL && n_from[j] == NULL) {
				err_msg = talloc_asprintf(mem_ctx,
						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
						formats[i], formats[j], n_matrix[i][j], n_from[j]);
				torture_fail(tctx, err_msg);
			} else if (strcmp(n_matrix[i][j], n_from[j]) != 0) {
				err_msg = talloc_asprintf(mem_ctx,
						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
						formats[i], formats[j], n_matrix[i][j], n_from[j]);
				torture_fail(tctx, err_msg);
			}
		}
	}

	return true;
}
Example #5
0
/*
 * complete a domain join, when joining to a AD domain:
 * 1.) connect and bind to the DRSUAPI pipe
 * 2.) do a DsCrackNames() to find the machine account dn
 * 3.) connect to LDAP
 * 4.) do an ldap search to find the "msDS-KeyVersionNumber" of the machine account
 * 5.) set the servicePrincipalName's of the machine account via LDAP, (maybe we should use DsWriteAccountSpn()...)
 * 6.) do a DsCrackNames() to find the domain dn
 * 7.) find out Site specific stuff, look at libnet_JoinSite() for details
 */
static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_JoinDomain *r)
{
	NTSTATUS status;

	TALLOC_CTX *tmp_ctx;

	const char *realm = r->out.realm;

	struct dcerpc_binding *samr_binding = r->out.samr_binding;

	struct dcerpc_pipe *drsuapi_pipe;
	struct dcerpc_binding *drsuapi_binding;
	struct drsuapi_DsBind r_drsuapi_bind;
	struct drsuapi_DsCrackNames r_crack_names;
	struct drsuapi_DsNameString names[1];
	struct policy_handle drsuapi_bind_handle;
	struct GUID drsuapi_bind_guid;

	struct ldb_context *remote_ldb;
	struct ldb_dn *account_dn;
	const char *account_dn_str;
	const char *remote_ldb_url;
	struct ldb_result *res;
	struct ldb_message *msg;

	int ret, rtn;

	const char * const attrs[] = {
		"msDS-KeyVersionNumber",
		"servicePrincipalName",
		"dNSHostName",
		"objectGUID",
		NULL,
	};

	r->out.error_string = NULL;
	
	/* We need to convert between a samAccountName and domain to a
	 * DN in the directory.  The correct way to do this is with
	 * DRSUAPI CrackNames */

	/* Fiddle with the bindings, so get to DRSUAPI on
	 * NCACN_IP_TCP, sealed */
	tmp_ctx = talloc_named(r, 0, "libnet_JoinADSDomain temp context");  
	if (!tmp_ctx) {
		r->out.error_string = NULL;
		return NT_STATUS_NO_MEMORY;
	}
	                                           
	drsuapi_binding = talloc(tmp_ctx, struct dcerpc_binding);
	if (!drsuapi_binding) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	*drsuapi_binding = *samr_binding;

	/* DRSUAPI is only available on IP_TCP, and locally on NCALRPC */
	if (drsuapi_binding->transport != NCALRPC) {
		drsuapi_binding->transport = NCACN_IP_TCP;
	}
	drsuapi_binding->endpoint = NULL;
	drsuapi_binding->flags |= DCERPC_SEAL;

	status = dcerpc_pipe_connect_b(tmp_ctx, 
				       &drsuapi_pipe,
				       drsuapi_binding,
				       &ndr_table_drsuapi,
				       ctx->cred, 
				       ctx->event_ctx,
				       ctx->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(r,
					"Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s",
					r->out.domain_name,
					nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}

	/* get a DRSUAPI pipe handle */
	GUID_from_string(DRSUAPI_DS_BIND_GUID, &drsuapi_bind_guid);

	r_drsuapi_bind.in.bind_guid = &drsuapi_bind_guid;
	r_drsuapi_bind.in.bind_info = NULL;
	r_drsuapi_bind.out.bind_handle = &drsuapi_bind_handle;

	status = dcerpc_drsuapi_DsBind(drsuapi_pipe, tmp_ctx, &r_drsuapi_bind);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsBind failed - %s", 
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsBind failed - %s", 
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsBind failed - %s", 
						  win_errstr(r_drsuapi_bind.out.result));
			talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Actually 'crack' the names */
	ZERO_STRUCT(r_crack_names);
	r_crack_names.in.bind_handle		= &drsuapi_bind_handle;
	r_crack_names.in.level			= 1;
	r_crack_names.in.req			= talloc(r, union drsuapi_DsNameRequest);
	if (!r_crack_names.in.req) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	r_crack_names.in.req->req1.codepage	= 1252; /* western european */
	r_crack_names.in.req->req1.language	= 0x00000407; /* german */
	r_crack_names.in.req->req1.count	= 1;
	r_crack_names.in.req->req1.names	= names;
	r_crack_names.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
	r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
	r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = dom_sid_string(tmp_ctx, r->out.account_sid);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	r_crack_names.out.ctr			= talloc(r, union drsuapi_DsNameCtr);
	r_crack_names.out.level_out		= talloc(r, int32_t);
	if (!r_crack_names.out.ctr || !r_crack_names.out.level_out) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  names[0].str,
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  names[0].str,
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (*r_crack_names.out.level_out != 1
		   || !r_crack_names.out.ctr->ctr1
		   || r_crack_names.out.ctr->ctr1->count != 1) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	} else if (r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr->ctr1->array[0].status);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (r_crack_names.out.ctr->ctr1->array[0].result_name == NULL) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Store the DN of our machine account. */
	account_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;

	/* Now we know the user's DN, open with LDAP, read and modify a few things */

	remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", 
					 drsuapi_binding->target_hostname);
	if (!remote_ldb_url) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	remote_ldb = ldb_wrap_connect(tmp_ctx, ctx->event_ctx, ctx->lp_ctx, 
				      remote_ldb_url, 
				      NULL, ctx->cred, 0, NULL);
	if (!remote_ldb) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	account_dn = ldb_dn_new(tmp_ctx, remote_ldb, account_dn_str);
	if (! ldb_dn_validate(account_dn)) {
		r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s",
						      account_dn_str);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* search for the user's record */
	ret = ldb_search(remote_ldb, tmp_ctx, &res,
			 account_dn, LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s",
						      account_dn_str, ldb_errstring(remote_ldb));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (res->count != 1) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries",
						      account_dn_str, res->count);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Prepare a new message, for the modify */
	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	msg->dn = res->msgs[0]->dn;

	{
		int i;
		const char *service_principal_name[6];
		const char *dns_host_name = strlower_talloc(tmp_ctx, 
							    talloc_asprintf(tmp_ctx, 
									    "%s.%s", 
									    r->in.netbios_name, 
									    realm));

		if (!dns_host_name) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		service_principal_name[0] = talloc_asprintf(tmp_ctx, "host/%s", dns_host_name);
		service_principal_name[1] = talloc_asprintf(tmp_ctx, "host/%s", strlower_talloc(tmp_ctx, r->in.netbios_name));
		service_principal_name[2] = talloc_asprintf(tmp_ctx, "host/%s/%s", dns_host_name, realm);
		service_principal_name[3] = talloc_asprintf(tmp_ctx, "host/%s/%s", strlower_talloc(tmp_ctx, r->in.netbios_name), realm);
		service_principal_name[4] = talloc_asprintf(tmp_ctx, "host/%s/%s", dns_host_name, r->out.domain_name);
		service_principal_name[5] = talloc_asprintf(tmp_ctx, "host/%s/%s", strlower_talloc(tmp_ctx, r->in.netbios_name), r->out.domain_name);
		
		for (i=0; i < ARRAY_SIZE(service_principal_name); i++) {
			if (!service_principal_name[i]) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
			rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "servicePrincipalName", service_principal_name[i]);
			if (rtn == -1) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
		}

		rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "dNSHostName", dns_host_name);
		if (rtn == -1) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		rtn = samdb_replace(remote_ldb, tmp_ctx, msg);
		if (rtn != 0) {
			r->out.error_string
				= talloc_asprintf(r, 
						  "Failed to replace entries on %s", 
						  ldb_dn_get_linearized(msg->dn));
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}
	}
				
	/* DsCrackNames to find out the DN of the domain. */
	r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
	r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = talloc_asprintf(tmp_ctx, "%s\\", r->out.domain_name);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  r->in.domain_name, 
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  r->in.domain_name, 
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (*r_crack_names.out.level_out != 1
		   || !r_crack_names.out.ctr->ctr1
		   || r_crack_names.out.ctr->ctr1->count != 1
		   || !r_crack_names.out.ctr->ctr1->array[0].result_name
		   || r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Store the account DN. */
	r->out.account_dn_str = account_dn_str;
	talloc_steal(r, account_dn_str);

	/* Store the domain DN. */
	r->out.domain_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;
	talloc_steal(r, r_crack_names.out.ctr->ctr1->array[0].result_name);

	/* Store the KVNO of the account, critical for some kerberos
	 * operations */
	r->out.kvno = ldb_msg_find_attr_as_uint(res->msgs[0], "msDS-KeyVersionNumber", 0);

	/* Store the account GUID. */
	r->out.account_guid = samdb_result_guid(res->msgs[0], "objectGUID");

	if (r->in.acct_type == ACB_SVRTRUST) {
		status = libnet_JoinSite(ctx, remote_ldb, r);
	}
	talloc_free(tmp_ctx);

	return status;
}