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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }