Example #1
0
NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
				struct hdb_entry_ex *client,
				DATA_BLOB **_pac_blob)
{
	struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry);
	struct auth_user_info_dc *user_info_dc;
	DATA_BLOB *pac_blob;
	NTSTATUS nt_status;

	/* The user account may be set not to want the PAC */
	if ( ! samba_princ_needs_pac(client)) {
		*_pac_blob = NULL;
		return NT_STATUS_OK;
	}

	pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
	if (!pac_blob) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb,
					     lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx),
					     lpcfg_sam_name(p->kdc_db_ctx->lp_ctx),
					     p->realm_dn,
					     p->msg,
					     data_blob(NULL, 0),
					     data_blob(NULL, 0),
					     &user_info_dc);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0, ("Getting user info for PAC failed: %s\n",
			  nt_errstr(nt_status)));
		return nt_status;
	}

	nt_status = samba_get_logon_info_pac_blob(mem_ctx, user_info_dc, pac_blob);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0, ("Building PAC failed: %s\n",
			  nt_errstr(nt_status)));
		return nt_status;
	}

	*_pac_blob = pac_blob;
	return NT_STATUS_OK;
}
Example #2
0
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
				     struct lsa_policy_state **_state)
{
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0);
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* and the privilege database */
	state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
	if (state->pdb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	*_state = state;

	return NT_STATUS_OK;
}
Example #3
0
/*
  fill in the cldap netlogon union for a given version
*/
NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
					 TALLOC_CTX *mem_ctx,
					 const char *domain,
					 const char *netbios_domain,
					 struct dom_sid *domain_sid,
					 const char *domain_guid,
					 const char *user,
					 uint32_t acct_control,
					 const char *src_address,
					 uint32_t version,
					 struct loadparm_context *lp_ctx,
					 struct netlogon_samlogon_response *netlogon,
					 bool fill_on_blank_request)
{
	const char *dom_attrs[] = {"objectGUID", NULL};
	const char *none_attrs[] = {NULL};
	struct ldb_result *dom_res = NULL, *user_res = NULL;
	int ret;
	const char **services = lpcfg_server_services(lp_ctx);
	uint32_t server_type;
	const char *pdc_name;
	struct GUID domain_uuid;
	const char *dns_domain;
	const char *forest_domain;
	const char *pdc_dns_name;
	const char *flatname;
	const char *server_site;
	const char *client_site;
	const char *pdc_ip;
	struct ldb_dn *domain_dn = NULL;
	struct interface *ifaces;
	bool user_known, am_rodc;
	NTSTATUS status;

	/* the domain parameter could have an optional trailing "." */
	if (domain && domain[strlen(domain)-1] == '.') {
		domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1);
		NT_STATUS_HAVE_NO_MEMORY(domain);
	}

	/* Lookup using long or short domainname */
	if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) {
		domain_dn = ldb_get_default_basedn(sam_ctx);
	}
	if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) {
		domain_dn = ldb_get_default_basedn(sam_ctx);
	}
	if (domain_dn) {
		const char *domain_identifier = domain != NULL ? domain
							: netbios_domain;
		ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
				 domain_dn, LDB_SCOPE_BASE, dom_attrs,
				 "objectClass=domain");
		if (ret != LDB_SUCCESS) {
			DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
				 domain_identifier,
				 ldb_dn_get_linearized(domain_dn),
				 ldb_errstring(sam_ctx)));
			return NT_STATUS_NO_SUCH_DOMAIN;
		}
		if (dom_res->count != 1) {
			DEBUG(2,("Error finding domain '%s'/'%s' in sam\n",
				 domain_identifier,
				 ldb_dn_get_linearized(domain_dn)));
			return NT_STATUS_NO_SUCH_DOMAIN;
		}
	}

	/* Lookup using GUID or SID */
	if ((dom_res == NULL) && (domain_guid || domain_sid)) {
		if (domain_guid) {
			struct GUID binary_guid;
			struct ldb_val guid_val;

			/* By this means, we ensure we don't have funny stuff in the GUID */

			status = GUID_from_string(domain_guid, &binary_guid);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}

			/* And this gets the result into the binary format we want anyway */
			status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}
			ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
						 NULL, LDB_SCOPE_SUBTREE, 
						 dom_attrs, 
						 "(&(objectCategory=DomainDNS)(objectGUID=%s))", 
						 ldb_binary_encode(mem_ctx, guid_val));
		} else { /* domain_sid case */
			ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
					 NULL, LDB_SCOPE_SUBTREE,
					 dom_attrs,
					 "(&(objectCategory=DomainDNS)(objectSid=%s))",
					 dom_sid_string(mem_ctx, domain_sid));
		}
		
		if (ret != LDB_SUCCESS) {
			DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n",
				 domain_guid, dom_sid_string(mem_ctx, domain_sid),
				 ldb_errstring(sam_ctx)));
			return NT_STATUS_NO_SUCH_DOMAIN;
		} else if (dom_res->count == 1) {
			/* Ok, now just check it is our domain */
			if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx),
					   dom_res->msgs[0]->dn) != 0) {
				DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n",
					 domain_guid,
					 dom_sid_string(mem_ctx, domain_sid)));
				return NT_STATUS_NO_SUCH_DOMAIN;
			}
		} else {
			DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n",
				 domain_guid, dom_sid_string(mem_ctx, domain_sid)));
			return NT_STATUS_NO_SUCH_DOMAIN;
		}
	}

	if (dom_res == NULL && fill_on_blank_request) {
		/* blank inputs gives our domain - tested against
		   w2k8r2. Without this ADUC on Win7 won't start */
		domain_dn = ldb_get_default_basedn(sam_ctx);
		ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
				 domain_dn, LDB_SCOPE_BASE, dom_attrs,
				 "objectClass=domain");
		if (ret != LDB_SUCCESS) {
			DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
				 lpcfg_dnsdomain(lp_ctx),
				 ldb_dn_get_linearized(domain_dn),
				 ldb_errstring(sam_ctx)));
			return NT_STATUS_NO_SUCH_DOMAIN;
		}
	}

        if (dom_res == NULL) {
		DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n"));
		return NT_STATUS_NO_SUCH_DOMAIN;
	}

	/* work around different inputs for not-specified users */
	if (!user) {
		user = "";
	}

	/* Enquire about any valid username with just a CLDAP packet -
	 * if kerberos didn't also do this, the security folks would
	 * scream... */
	if (user[0]) {							\
		/* Only allow some bits to be enquired:  [MS-ATDS] 7.3.3.2 */
		if (acct_control == (uint32_t)-1) {
			acct_control = 0;
		}
		acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST);

		/* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */
		ret = ldb_search(sam_ctx, mem_ctx, &user_res,
					 dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, 
					 none_attrs, 
					 "(&(objectClass=user)(samAccountName=%s)"
					 "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
					 "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", 
					 ldb_binary_encode_string(mem_ctx, user),
					 UF_ACCOUNTDISABLE, ds_acb2uf(acct_control));
		if (ret != LDB_SUCCESS) {
			DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n",
				 user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
				 ldb_errstring(sam_ctx)));
			return NT_STATUS_NO_SUCH_USER;
		} else if (user_res->count == 1) {
			user_known = true;
		} else {
			user_known = false;
		}

	} else {
		user_known = true;
	}
		
	server_type      = 
		DS_SERVER_DS | DS_SERVER_TIMESERV |
		DS_SERVER_GOOD_TIMESERV;

	if (samdb_is_pdc(sam_ctx)) {
		server_type |= DS_SERVER_PDC;
	}

	if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) {
		server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6;
	}

	if (samdb_is_gc(sam_ctx)) {
		server_type |= DS_SERVER_GC;
	}

	if (str_list_check(services, "ldap")) {
		server_type |= DS_SERVER_LDAP;
	}

	if (str_list_check(services, "kdc")) {
		server_type |= DS_SERVER_KDC;
	}

	if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) {
		server_type |= DS_SERVER_WRITABLE;
	}

	pdc_name         = talloc_asprintf(mem_ctx, "\\\\%s",
					   lpcfg_netbios_name(lp_ctx));
	NT_STATUS_HAVE_NO_MEMORY(pdc_name);
	domain_uuid      = samdb_result_guid(dom_res->msgs[0], "objectGUID");
	dns_domain       = lpcfg_dnsdomain(lp_ctx);
	forest_domain    = samdb_forest_name(sam_ctx, mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(forest_domain);
	pdc_dns_name     = talloc_asprintf(mem_ctx, "%s.%s", 
					   strlower_talloc(mem_ctx, 
							   lpcfg_netbios_name(lp_ctx)),
					   dns_domain);
	NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name);
	flatname         = lpcfg_workgroup(lp_ctx);

	server_site      = samdb_server_site_name(sam_ctx, mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(server_site);
	client_site      = samdb_client_site_name(sam_ctx, mem_ctx,
						  src_address, NULL);
	NT_STATUS_HAVE_NO_MEMORY(client_site);
	if (strcasecmp(server_site, client_site) == 0) {
		server_type |= DS_SERVER_CLOSEST;
	}

	load_interface_list(mem_ctx, lp_ctx, &ifaces);
	if (src_address) {
		pdc_ip = iface_list_best_ip(ifaces, src_address);
	} else {
		pdc_ip = iface_list_first_v4(ifaces);
	}
	if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) {
		/* this matches windows behaviour */
		pdc_ip = "127.0.0.1";
	}

	ZERO_STRUCTP(netlogon);

	/* check if either of these bits is present */
	if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
		uint32_t extra_flags = 0;
		netlogon->ntver = NETLOGON_NT_VERSION_5EX;

		/* could check if the user exists */
		if (user_known) {
			netlogon->data.nt5_ex.command      = LOGON_SAM_LOGON_RESPONSE_EX;
		} else {
			netlogon->data.nt5_ex.command      = LOGON_SAM_LOGON_USER_UNKNOWN_EX;
		}
		netlogon->data.nt5_ex.pdc_name     = pdc_name;
		netlogon->data.nt5_ex.user_name    = user;
		netlogon->data.nt5_ex.domain_name  = flatname;
		netlogon->data.nt5_ex.domain_uuid  = domain_uuid;
		netlogon->data.nt5_ex.forest       = forest_domain;
		netlogon->data.nt5_ex.dns_domain   = dns_domain;
		netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name;
		netlogon->data.nt5_ex.server_site  = server_site;
		netlogon->data.nt5_ex.client_site  = client_site;
		if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) {
			/* note that this is always a IPV4 address */
			extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP;
			netlogon->data.nt5_ex.sockaddr.sockaddr_family    = 2;
			netlogon->data.nt5_ex.sockaddr.pdc_ip       = pdc_ip;
			netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8);
		}
		netlogon->data.nt5_ex.server_type  = server_type;
		netlogon->data.nt5_ex.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags;
		netlogon->data.nt5_ex.lmnt_token   = 0xFFFF;
		netlogon->data.nt5_ex.lm20_token   = 0xFFFF;

	} else if (version & NETLOGON_NT_VERSION_5) {
		netlogon->ntver = NETLOGON_NT_VERSION_5;

		/* could check if the user exists */
		if (user_known) {
			netlogon->data.nt5.command      = LOGON_SAM_LOGON_RESPONSE;
		} else {
			netlogon->data.nt5.command      = LOGON_SAM_LOGON_USER_UNKNOWN;
		}
		netlogon->data.nt5.pdc_name     = pdc_name;
		netlogon->data.nt5.user_name    = user;
		netlogon->data.nt5.domain_name  = flatname;
		netlogon->data.nt5.domain_uuid  = domain_uuid;
		netlogon->data.nt5.forest       = forest_domain;
		netlogon->data.nt5.dns_domain   = dns_domain;
		netlogon->data.nt5.pdc_dns_name = pdc_dns_name;
		netlogon->data.nt5.pdc_ip       = pdc_ip;
		netlogon->data.nt5.server_type  = server_type;
		netlogon->data.nt5.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5;
		netlogon->data.nt5.lmnt_token   = 0xFFFF;
		netlogon->data.nt5.lm20_token   = 0xFFFF;

	} else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ {
		netlogon->ntver = NETLOGON_NT_VERSION_1;
		/* could check if the user exists */
		if (user_known) {
			netlogon->data.nt4.command      = LOGON_SAM_LOGON_RESPONSE;
		} else {
			netlogon->data.nt4.command      = LOGON_SAM_LOGON_USER_UNKNOWN;
		}
		netlogon->data.nt4.pdc_name    = pdc_name;
		netlogon->data.nt4.user_name   = user;
		netlogon->data.nt4.domain_name = flatname;
		netlogon->data.nt4.nt_version  = NETLOGON_NT_VERSION_1;
		netlogon->data.nt4.lmnt_token  = 0xFFFF;
		netlogon->data.nt4.lm20_token  = 0xFFFF;
	}

	return NT_STATUS_OK;
}
Example #4
0
static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
						 TALLOC_CTX *mem_ctx,
						 const struct auth_usersupplied_info *user_info, 
						 struct auth_user_info_dc **user_info_dc)
{
	NTSTATUS nt_status;
	const char *account_name = user_info->mapped.account_name;
	struct ldb_message *msg;
	struct ldb_dn *domain_dn;
	DATA_BLOB user_sess_key, lm_sess_key;
	TALLOC_CTX *tmp_ctx;

	if (ctx->auth_ctx->sam_ctx == NULL) {
		DEBUG(0, ("No SAM available, cannot log in users\n"));
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	if (!account_name || !*account_name) {
		/* 'not for me' */
		return NT_STATUS_NOT_IMPLEMENTED;
	}

	tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
	if (domain_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_SUCH_DOMAIN;
	}

	nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, ctx->auth_ctx->sam_ctx, domain_dn, msg, user_info,
					 &user_sess_key, &lm_sess_key);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
					     lpcfg_sam_name(ctx->auth_ctx->lp_ctx),
					     domain_dn,
					     msg,
					     user_sess_key, lm_sess_key,
					     user_info_dc);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	talloc_steal(mem_ctx, *user_info_dc);
	talloc_free(tmp_ctx);

	return NT_STATUS_OK;
}
Example #5
0
static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
					      hdb_entry_ex *entry,
					      struct sockaddr *from_addr,
					      const char *original_client_name,
					      const char *auth_type,
					      int hdb_auth_status)
{
	struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
									struct samba_kdc_db_context);

	struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);

	/*
	 * Forcing this via the NTLM auth structure is not ideal, but
	 * it is the most practical option right now, and ensures the
	 * logs are consistent, even if some elements are always NULL.
	 */
	struct auth_usersupplied_info ui = {
		.mapped_state = true,
		.was_mapped = true,
		.client = {
			.account_name = original_client_name,
			.domain_name = NULL,
		},
		.service_description = "Kerberos KDC",
		.auth_description = "ENC-TS Pre-authentication",
		.password_type = auth_type
	};

	size_t sa_socklen = 0;

	switch (from_addr->sa_family) {
	case AF_INET:
		sa_socklen = sizeof(struct sockaddr_in);
		break;
#ifdef HAVE_IPV6
	case AF_INET6:
		sa_socklen = sizeof(struct sockaddr_in6);
		break;
#endif
	}

	switch (hdb_auth_status) {
	case HDB_AUTHZ_SUCCESS:
	{
		struct samba_kdc_entry *p = talloc_get_type(entry->ctx,
							    struct samba_kdc_entry);

		/*
		 * TODO: We could log the AS-REQ authorization success here as
		 * well.  However before we do that, we need to pass
		 * in the PAC here or re-calculate it.
		 */
		authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
						 domain_dn, true);
		break;
	}
	case HDB_AUTH_INVALID_SIGNATURE:
		break;
	case HDB_AUTH_CORRECT_PASSWORD:
	case HDB_AUTH_WRONG_PASSWORD:
	{
		TALLOC_CTX *frame = talloc_stackframe();
		struct samba_kdc_entry *p = talloc_get_type(entry->ctx,
							    struct samba_kdc_entry);
		struct dom_sid *sid
			= samdb_result_dom_sid(frame, p->msg, "objectSid");
		const char *account_name
			= ldb_msg_find_attr_as_string(p->msg, "sAMAccountName", NULL);
		const char *domain_name = lpcfg_sam_name(p->kdc_db_ctx->lp_ctx);
		struct tsocket_address *remote_host;
		NTSTATUS status;
		int ret;

		if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
			authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
			status = NT_STATUS_WRONG_PASSWORD;
		} else {
			status = NT_STATUS_OK;
		}

		ret = tsocket_address_bsd_from_sockaddr(frame, from_addr,
							sa_socklen,
							&remote_host);
		if (ret != 0) {
			ui.remote_host = NULL;
		} else {
			ui.remote_host = remote_host;
		}

		ui.mapped.account_name = account_name;
		ui.mapped.domain_name = domain_name;

		log_authentication_event(kdc_db_ctx->msg_ctx,
					 kdc_db_ctx->lp_ctx,
					 &ui,
					 status,
					 domain_name,
					 account_name,
					 NULL,
					 sid);
		TALLOC_FREE(frame);
		break;
	}
	case HDB_AUTH_CLIENT_UNKNOWN:
	{
		struct tsocket_address *remote_host;
		int ret;
		TALLOC_CTX *frame = talloc_stackframe();
		ret = tsocket_address_bsd_from_sockaddr(frame, from_addr,
							sa_socklen,
							&remote_host);
		if (ret != 0) {
			ui.remote_host = NULL;
		} else {
			ui.remote_host = remote_host;
		}

		log_authentication_event(kdc_db_ctx->msg_ctx,
					 kdc_db_ctx->lp_ctx,
					 &ui,
					 NT_STATUS_NO_SUCH_USER,
					 NULL, NULL,
					 NULL, NULL);
		TALLOC_FREE(frame);
		break;
	}
	}
	return 0;
}
Example #6
0
int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
				      char *pwd,
				      krb5_db_entry *db_entry)
{
	NTSTATUS status;
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	TALLOC_CTX *tmp_ctx;
	DATA_BLOB password;
	enum samPwdChangeReason reject_reason;
	struct samr_DomInfo1 *dominfo;
	const char *error_string = NULL;
	struct auth_user_info_dc *user_info_dc;
	struct samba_kdc_entry *p;
	krb5_error_code code = 0;

#ifdef DEBUG_PASSWORD
	DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd));
#endif

	tmp_ctx = talloc_named(ctx, 0, "mit_samba_kpasswd_change_password");
	if (tmp_ctx == NULL) {
		return ENOMEM;
	}

	p = (struct samba_kdc_entry *)db_entry->e_data;

	status = authsam_make_user_info_dc(tmp_ctx,
					   ctx->db_ctx->samdb,
					   lpcfg_netbios_name(ctx->db_ctx->lp_ctx),
					   lpcfg_sam_name(ctx->db_ctx->lp_ctx),
					   p->realm_dn,
					   p->msg,
					   data_blob(NULL, 0),
					   data_blob(NULL, 0),
					   &user_info_dc);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("authsam_make_user_info_dc failed: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	status = auth_generate_session_info(tmp_ctx,
					    ctx->db_ctx->lp_ctx,
					    ctx->db_ctx->samdb,
					    user_info_dc,
					    0, /* session_info_flags */
					    &ctx->session_info);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("auth_generate_session_info failed: %s\n",
			nt_errstr(status)));
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	/* password is expected as UTF16 */

	if (!convert_string_talloc(tmp_ctx, CH_UTF8, CH_UTF16,
				   pwd, strlen(pwd),
				   &password.data, &password.length)) {
		DEBUG(1,("convert_string_talloc failed\n"));
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	status = samdb_kpasswd_change_password(tmp_ctx,
					       ctx->db_ctx->lp_ctx,
					       ctx->db_ctx->ev_ctx,
					       ctx->db_ctx->samdb,
					       ctx->session_info,
					       &password,
					       &reject_reason,
					       &dominfo,
					       &error_string,
					       &result);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("samdb_kpasswd_change_password failed: %s\n",
			nt_errstr(status)));
		code = KADM5_PASS_Q_GENERIC;
		krb5_set_error_message(ctx->context, code, "%s", error_string);
		goto out;
	}

	if (!NT_STATUS_IS_OK(result)) {
		code = mit_samba_change_pwd_error(ctx->context,
						  result,
						  reject_reason,
						  dominfo);
	}

out:
	talloc_free(tmp_ctx);

	return code;
}
Example #7
0
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
				     TALLOC_CTX *mem_ctx,
				     uint32_t access_desired,
				     struct lsa_policy_state **_state)
{
	struct auth_session_info *session_info = dce_call->conn->auth_state.session_info;
	enum security_user_level security_level;
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc_zero(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state,
				       dce_call->event_ctx,
				       dce_call->conn->dce_ctx->lp_ctx,
				       dce_call->conn->auth_state.session_info,
				       dce_call->conn->remote_address,
				       0);
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* and the privilege database */
	state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
	if (state->pdb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
				state->domain_sid);
	if (state->sd == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;

	se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
	security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);

	security_level = security_session_user_level(session_info, NULL);
	if (security_level >= SECURITY_SYSTEM) {
		/*
		 * The security descriptor doesn't allow system,
		 * but we want to allow system via ncalrpc as root.
		 */
		state->access_mask = access_desired;
		if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
			state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
			state->access_mask |= LSA_POLICY_ALL_ACCESS;
		}
	} else {
		NTSTATUS status;

		status = se_access_check(state->sd,
					 session_info->security_token,
					 access_desired,
					 &state->access_mask);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
				 __func__,
				 (unsigned)access_desired,
				 (unsigned)state->access_mask,
				 nt_errstr(status)));
			return status;
		}
	}

	DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
		  __func__,
		 (unsigned)access_desired,
		 (unsigned)state->access_mask));

	*_state = state;

	return NT_STATUS_OK;
}
Example #8
0
static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
						 TALLOC_CTX *mem_ctx,
						 const struct auth_usersupplied_info *user_info, 
						 struct auth_user_info_dc **user_info_dc,
						 bool *authoritative)
{
	NTSTATUS nt_status;
	const char *account_name = user_info->mapped.account_name;
	struct ldb_message *msg;
	struct ldb_dn *domain_dn;
	DATA_BLOB user_sess_key, lm_sess_key;
	TALLOC_CTX *tmp_ctx;
	const char *p = NULL;

	if (ctx->auth_ctx->sam_ctx == NULL) {
		DEBUG(0, ("No SAM available, cannot log in users\n"));
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	if (!account_name || !*account_name) {
		/* 'not for me' */
		return NT_STATUS_NOT_IMPLEMENTED;
	}

	tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
	if (domain_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_SUCH_DOMAIN;
	}

	p = strchr_m(account_name, '@');
	if (p != NULL) {
		const char *nt4_domain = NULL;
		const char *nt4_account = NULL;
		bool is_my_domain = false;

		nt_status = crack_name_to_nt4_name(mem_ctx,
						   ctx->auth_ctx->sam_ctx,
						   /*
						    * DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON ?
						    */
						   DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
						   account_name,
						   &nt4_domain, &nt4_account);
		if (!NT_STATUS_IS_OK(nt_status)) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_SUCH_USER;
		}

		is_my_domain = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain);
		if (!is_my_domain) {
			/*
			 * This is a user within our forest,
			 * but in a different domain,
			 * we're not authoritative
			 */
			talloc_free(tmp_ctx);
			return NT_STATUS_NOT_IMPLEMENTED;
		}

		/*
		 * Let's use the NT4 account name for the lookup.
		 */
		account_name = nt4_account;
	}

	nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, ctx->auth_ctx->sam_ctx, domain_dn, msg, user_info,
					 &user_sess_key, &lm_sess_key, authoritative);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx,
					     lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
					     lpcfg_sam_name(ctx->auth_ctx->lp_ctx),
					     lpcfg_sam_dnsname(ctx->auth_ctx->lp_ctx),
					     domain_dn,
					     msg,
					     user_sess_key, lm_sess_key,
					     user_info_dc);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	talloc_steal(mem_ctx, *user_info_dc);
	talloc_free(tmp_ctx);

	return NT_STATUS_OK;
}