/** * Specifies default values for domain, workstation and realm * from the smb.conf configuration file * * @param cred Credentials structure to fill in */ _PUBLIC_ void cli_credentials_set_conf(struct cli_credentials *cred, struct loadparm_context *lp_ctx) { cli_credentials_set_username(cred, "", CRED_UNINITIALISED); if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED); } }
/** \details This function replaces network address from the binding strings returned by Exchange for the PR_EMS_AB_NETWORK_ADDRESS property and limit the binding strings scope to ncacn_ip_tcp. \param dce_call pointer to the session context \param r pointer to the NspiGetProps structure \return true on success, otherwise false */ bool mapiproxy_NspiGetProps(struct dcesrv_call_state *dce_call, struct NspiGetProps *r) { uint32_t i; uint32_t propID = -1; struct SPropTagArray *SPropTagArray = NULL; struct PropertyRow_r *Row; struct StringArray_r *slpstr; struct PropertyValue_r *lpProp; /* Sanity checks */ if (!r->out.ppRows) return false; if (!(*r->out.ppRows)->cValues) return false; /* Step 1. Find PR_EMS_AB_NETWORK_ADDRESS index */ propID = -1; SPropTagArray = r->in.pPropTags; for (i = 0; i < SPropTagArray->cValues; i++) { if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_NETWORK_ADDRESS) { propID = i; break; } } if (propID == -1) return false; /* Step 2. Retrieve the SLPSTRArray */ Row = *r->out.ppRows; lpProp = &Row->lpProps[propID]; if (!lpProp) return false; if (lpProp->ulPropTag != PR_EMS_AB_NETWORK_ADDRESS) return false; slpstr = &(lpProp->value.MVszA); /* Step 3. Modify Exchange binding strings and only return ncacn_ip_tcp */ slpstr->cValues = 1; slpstr->lppszA[0] = talloc_asprintf(dce_call, "ncacn_ip_tcp:%s.%s", lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx), lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx)); slpstr->lppszA[0] = strlower_talloc(dce_call, slpstr->lppszA[0]); return true; }
/** \details exchange_ds_rfr RfrGetNewDSA (0x0) function \param dce_call pointer to the session context \param mem_ctx pointer to the memory context \param r pointer to the RfrGetNewDSA request data \note We incorrectly assume input pUserDN is correct and available, but it is OK for now. \return MAPI_E_SUCCESS on success */ static enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct RfrGetNewDSA *r) { const char *netbiosname = NULL; const char *realm = NULL; char *fqdn = NULL; OC_DEBUG(5, "exchange_ds_rfr: RfrGetNewDSA (0x0)"); /* Step 0. Ensure incoming user is authenticated */ if (!dcesrv_call_authenticated(dce_call)) { OC_DEBUG(1, "No challenge requested by client, cannot authenticate"); r->out.ppszUnused = NULL; r->out.ppszServer = NULL; r->out.result = MAPI_E_LOGON_FAILED; return MAPI_E_LOGON_FAILED; } /* Step 1. We don't have load-balancing support yet, just return Samba FQDN name */ netbiosname = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx); realm = lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx); if (!netbiosname || !realm) { r->out.ppszUnused = NULL; r->out.ppszServer = NULL; r->out.result = MAPI_E_NO_SUPPORT; return MAPI_E_NO_SUPPORT; } fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm); r->out.ppszUnused = NULL; r->out.ppszServer = talloc_array(mem_ctx, const char *, 2); r->out.ppszServer[0] = strlower_talloc(mem_ctx, fqdn); r->out.ppszServer[1] = NULL; r->out.result = MAPI_E_SUCCESS; return MAPI_E_SUCCESS; }
static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, struct kdc_check_generic_kerberos *r) { struct PAC_Validate pac_validate; DATA_BLOB srv_sig; struct PAC_SIGNATURE_DATA kdc_sig; struct kdc_server *kdc = talloc_get_type(msg->private_data, struct kdc_server); krb5_kdc_configuration *kdc_config = (krb5_kdc_configuration *)kdc->private_data; enum ndr_err_code ndr_err; int ret; hdb_entry_ex ent; krb5_principal principal; /* There is no reply to this request */ r->out.generic_reply = data_blob(NULL, 0); ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg, &pac_validate, (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NT_STATUS_INVALID_PARAMETER; } if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) { /* We don't implement any other message types - such as certificate validation - yet */ return NT_STATUS_INVALID_PARAMETER; } if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength) || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) { return NT_STATUS_INVALID_PARAMETER; } srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data, pac_validate.ChecksumLength); ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal, lpcfg_realm(kdc->task->lp_ctx), "krbtgt", lpcfg_realm(kdc->task->lp_ctx), NULL); if (ret != 0) { return NT_STATUS_NO_MEMORY; } ret = kdc_config->db[0]->hdb_fetch_kvno(kdc->smb_krb5_context->krb5_context, kdc_config->db[0], principal, HDB_F_GET_KRBTGT | HDB_F_DECRYPT, 0, &ent); if (ret != 0) { hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); return NT_STATUS_LOGON_FAILURE; } kdc_sig.type = pac_validate.SignatureType; kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength], pac_validate.SignatureLength); ret = kdc_check_pac(kdc->smb_krb5_context->krb5_context, srv_sig, &kdc_sig, &ent); hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); if (ret != 0) { return NT_STATUS_LOGON_FAILURE; } return NT_STATUS_OK; }
static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) { struct gensec_gssapi_state *gensec_gssapi_state; krb5_error_code ret; #ifdef SAMBA4_USES_HEIMDAL const char *realm; #endif gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state); if (!gensec_gssapi_state) { return NT_STATUS_NO_MEMORY; } gensec_security->private_data = gensec_gssapi_state; gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT; /* TODO: Fill in channel bindings */ gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; gensec_gssapi_state->server_name = GSS_C_NO_NAME; gensec_gssapi_state->client_name = GSS_C_NO_NAME; gensec_gssapi_state->gss_want_flags = 0; gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY; if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) { gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG; } if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) { gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG; } if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", true)) { gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG; } if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) { gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG; } if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) { gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG; } if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG; } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG; gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG; } if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) { gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE; } gensec_gssapi_state->gss_got_flags = 0; switch (gensec_security->ops->auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: gensec_gssapi_state->gss_oid = gss_mech_spnego; break; case DCERPC_AUTH_TYPE_KRB5: default: gensec_gssapi_state->gss_oid = discard_const_p(void, gss_mech_krb5); break; } ret = smb_krb5_init_context(gensec_gssapi_state, gensec_security->settings->lp_ctx, &gensec_gssapi_state->smb_krb5_context); if (ret) { DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n", error_message(ret))); talloc_free(gensec_gssapi_state); return NT_STATUS_INTERNAL_ERROR; } gensec_gssapi_state->client_cred = NULL; gensec_gssapi_state->server_cred = NULL; gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL; gensec_gssapi_state->sasl = false; gensec_gssapi_state->sasl_state = STAGE_GSS_NEG; gensec_gssapi_state->sasl_protection = 0; gensec_gssapi_state->max_wrap_buf_size = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536); gensec_gssapi_state->gss_exchange_count = 0; gensec_gssapi_state->sig_size = 0; talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor); #ifdef SAMBA4_USES_HEIMDAL realm = lpcfg_realm(gensec_security->settings->lp_ctx); if (realm != NULL) { ret = gsskrb5_set_default_realm(realm); if (ret) { DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n")); talloc_free(gensec_gssapi_state); return NT_STATUS_INTERNAL_ERROR; } } /* don't do DNS lookups of any kind, it might/will fail for a netbios name */ ret = gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security->settings, "krb5", "set_dns_canonicalize", false)); if (ret) { DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n")); talloc_free(gensec_gssapi_state); return NT_STATUS_INTERNAL_ERROR; } #endif return NT_STATUS_OK; }
/* * do a domain join using DCERPC/SAMR calls * - connect to the LSA pipe, to try and find out information about the domain * - create a secondary connection to SAMR pipe * - do a samr_Connect to get a policy handle * - do a samr_LookupDomain to get the domain sid * - do a samr_OpenDomain to get a domain handle * - do a samr_CreateAccount to try and get a new account * * If that fails, do: * - do a samr_LookupNames to get the users rid * - do a samr_OpenUser to get a user handle * - potentially delete and recreate the user * - assert the account is of the right type with samrQueryUserInfo * * - call libnet_SetPassword_samr_handle to set the password, * and pass a samr_UserInfo21 struct to set full_name and the account flags * * - do some ADS specific things when we join as Domain Controller, * look at libnet_joinADSDomain() for the details */ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *r) { TALLOC_CTX *tmp_ctx; NTSTATUS status, cu_status; struct libnet_RpcConnect *connect_with_info; struct dcerpc_pipe *samr_pipe; struct samr_Connect sc; struct policy_handle p_handle; struct samr_OpenDomain od; struct policy_handle d_handle; struct samr_LookupNames ln; struct samr_Ids rids, types; struct samr_OpenUser ou; struct samr_CreateUser2 cu; struct policy_handle *u_handle = NULL; struct samr_QueryUserInfo qui; union samr_UserInfo *uinfo; struct samr_UserInfo21 u_info21; union libnet_SetPassword r2; struct samr_GetUserPwInfo pwp; struct samr_PwInfo info; struct lsa_String samr_account_name; uint32_t acct_flags, old_acct_flags; uint32_t rid, access_granted; int policy_min_pw_len = 0; struct dom_sid *account_sid = NULL; const char *password_str = NULL; r->out.error_string = NULL; r2.samr_handle.out.error_string = NULL; tmp_ctx = talloc_named(mem_ctx, 0, "libnet_Join temp context"); if (!tmp_ctx) { r->out.error_string = NULL; return NT_STATUS_NO_MEMORY; } u_handle = talloc(tmp_ctx, struct policy_handle); if (!u_handle) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } connect_with_info = talloc_zero(tmp_ctx, struct libnet_RpcConnect); if (!connect_with_info) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } /* prepare connect to the SAMR pipe of PDC */ if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { connect_with_info->in.binding = NULL; connect_with_info->in.name = r->in.domain_name; } else { connect_with_info->in.binding = r->in.binding; connect_with_info->in.name = NULL; } /* This level makes a connection to the LSA pipe on the way, * to get some useful bits of information about the domain */ connect_with_info->level = LIBNET_RPC_CONNECT_DC_INFO; connect_with_info->in.dcerpc_iface = &ndr_table_samr; /* establish the SAMR connection */ status = libnet_RpcConnect(ctx, tmp_ctx, connect_with_info); if (!NT_STATUS_IS_OK(status)) { if (r->in.binding) { r->out.error_string = talloc_asprintf(mem_ctx, "Connection to SAMR pipe of DC %s failed: %s", r->in.binding, connect_with_info->out.error_string); } else { r->out.error_string = talloc_asprintf(mem_ctx, "Connection to SAMR pipe of PDC for %s failed: %s", r->in.domain_name, connect_with_info->out.error_string); } talloc_free(tmp_ctx); return status; } samr_pipe = connect_with_info->out.dcerpc_pipe; status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe, connect_with_info->out.dcerpc_pipe->binding, &ndr_table_samr, ctx->cred, ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "SAMR bind failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* prepare samr_Connect */ ZERO_STRUCT(p_handle); sc.in.system_name = NULL; sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; sc.out.connect_handle = &p_handle; /* 2. do a samr_Connect to get a policy handle */ status = dcerpc_samr_Connect_r(samr_pipe->binding_handle, tmp_ctx, &sc); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) { status = sc.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_Connect failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* If this is a connection on ncacn_ip_tcp to Win2k3 SP1, we don't get back this useful info */ if (!connect_with_info->out.domain_name) { if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name); } else { /* Bugger, we just lost our way to automatically find the domain name */ connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lpcfg_workgroup(ctx->lp_ctx)); connect_with_info->out.realm = talloc_strdup(tmp_ctx, lpcfg_realm(ctx->lp_ctx)); } } /* Perhaps we didn't get a SID above, because we are against ncacn_ip_tcp */ if (!connect_with_info->out.domain_sid) { struct lsa_String name; struct samr_LookupDomain l; struct dom_sid2 *sid = NULL; name.string = connect_with_info->out.domain_name; l.in.connect_handle = &p_handle; l.in.domain_name = &name; l.out.sid = &sid; status = dcerpc_samr_LookupDomain_r(samr_pipe->binding_handle, tmp_ctx, &l); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(l.out.result)) { status = l.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "SAMR LookupDomain failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } connect_with_info->out.domain_sid = *l.out.sid; } /* prepare samr_OpenDomain */ ZERO_STRUCT(d_handle); od.in.connect_handle = &p_handle; od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; od.in.sid = connect_with_info->out.domain_sid; od.out.domain_handle = &d_handle; /* do a samr_OpenDomain to get a domain handle */ status = dcerpc_samr_OpenDomain_r(samr_pipe->binding_handle, tmp_ctx, &od); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) { status = od.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_OpenDomain for [%s] failed: %s", dom_sid_string(tmp_ctx, connect_with_info->out.domain_sid), nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* prepare samr_CreateUser2 */ ZERO_STRUCTP(u_handle); cu.in.domain_handle = &d_handle; cu.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; samr_account_name.string = r->in.account_name; cu.in.account_name = &samr_account_name; cu.in.acct_flags = r->in.acct_type; cu.out.user_handle = u_handle; cu.out.rid = &rid; cu.out.access_granted = &access_granted; /* do a samr_CreateUser2 to get an account handle, or an error */ cu_status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu); if (NT_STATUS_IS_OK(cu_status) && !NT_STATUS_IS_OK(cu.out.result)) { cu_status = cu.out.result; } status = cu_status; if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { /* prepare samr_LookupNames */ ln.in.domain_handle = &d_handle; ln.in.num_names = 1; ln.in.names = talloc_array(tmp_ctx, struct lsa_String, 1); ln.out.rids = &rids; ln.out.types = &types; if (!ln.in.names) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ln.in.names[0].string = r->in.account_name; /* 5. do a samr_LookupNames to get the users rid */ status = dcerpc_samr_LookupNames_r(samr_pipe->binding_handle, tmp_ctx, &ln); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) { status = ln.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* check if we got one RID for the user */ if (ln.out.rids->count != 1) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] returns %d RIDs", r->in.account_name, ln.out.rids->count); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; } /* prepare samr_OpenUser */ ZERO_STRUCTP(u_handle); ou.in.domain_handle = &d_handle; ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; ou.in.rid = ln.out.rids->ids[0]; rid = ou.in.rid; ou.out.user_handle = u_handle; /* 6. do a samr_OpenUser to get a user handle */ status = dcerpc_samr_OpenUser_r(samr_pipe->binding_handle, tmp_ctx, &ou); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) { status = ou.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_OpenUser for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } if (r->in.recreate_account) { struct samr_DeleteUser d; d.in.user_handle = u_handle; d.out.user_handle = u_handle; status = dcerpc_samr_DeleteUser_r(samr_pipe->binding_handle, mem_ctx, &d); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(d.out.result)) { status = d.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_DeleteUser (for recreate) of [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* We want to recreate, so delete and another samr_CreateUser2 */ /* &cu filled in above */ status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(cu.out.result)) { status = cu.out.result; } if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_CreateUser2 (recreate) for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } } } else if (!NT_STATUS_IS_OK(status)) {
bool lpcfg_is_my_domain_or_realm(struct loadparm_context *lp_ctx, const char *domain) { return strequal(lpcfg_workgroup(lp_ctx), domain) || strequal(lpcfg_realm(lp_ctx), domain); }
/** * Fill in credentials for the machine trust account, from the * secrets.ldb or passed in handle to secrets.tdb (perhaps in CTDB). * * This version is used in parts of the code that can link in the * CTDB dbwrap backend, by passing down the already open handle. * * @param cred Credentials structure to fill in * @param db_ctx dbwrap context for secrets.tdb * @retval NTSTATUS error detailing any failure */ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account_db_ctx(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct db_context *db_ctx) { NTSTATUS status; char *filter; char *error_string = NULL; const char *domain; bool secrets_tdb_password_more_recent; time_t secrets_tdb_lct = 0; char *secrets_tdb_password = NULL; char *secrets_tdb_old_password = NULL; uint32_t secrets_tdb_secure_channel_type = SEC_CHAN_NULL; char *keystr; char *keystr_upper = NULL; TALLOC_CTX *tmp_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb"); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } /* Bleh, nasty recursion issues: We are setting a machine * account here, so we don't want the 'pending' flag around * any more */ cred->machine_account_pending = false; /* We have to do this, as the fallback in * cli_credentials_set_secrets is to run as anonymous, so the domain is wiped */ domain = cli_credentials_get_domain(cred); if (db_ctx) { TDB_DATA dbuf; keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) { secrets_tdb_lct = IVAL(dbuf.dptr,0); } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status)) { secrets_tdb_password = (char *)dbuf.dptr; } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_PASSWORD_PREV, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status)) { secrets_tdb_old_password = (char *)dbuf.dptr; } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) { secrets_tdb_secure_channel_type = IVAL(dbuf.dptr,0); } } filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, domain); status = cli_credentials_set_secrets_lct(cred, lp_ctx, NULL, SECRETS_PRIMARY_DOMAIN_DN, filter, secrets_tdb_lct, secrets_tdb_password, &error_string); if (secrets_tdb_password == NULL) { secrets_tdb_password_more_recent = false; } else if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status) || NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, status)) { secrets_tdb_password_more_recent = true; } else if (secrets_tdb_lct > cli_credentials_get_password_last_changed_time(cred)) { secrets_tdb_password_more_recent = true; } else if (secrets_tdb_lct == cli_credentials_get_password_last_changed_time(cred)) { secrets_tdb_password_more_recent = strcmp(secrets_tdb_password, cli_credentials_get_password(cred)) != 0; } else { secrets_tdb_password_more_recent = false; } if (secrets_tdb_password_more_recent) { char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx)); cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED); cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED); cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); if (strequal(domain, lpcfg_workgroup(lp_ctx))) { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED); } cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); cli_credentials_set_password_last_changed_time(cred, secrets_tdb_lct); cli_credentials_set_secure_channel_type(cred, secrets_tdb_secure_channel_type); status = NT_STATUS_OK; } else if (!NT_STATUS_IS_OK(status)) { if (db_ctx) { error_string = talloc_asprintf(cred, "Failed to fetch machine account password for %s from both " "secrets.ldb (%s) and from %s", domain, error_string == NULL ? "error" : error_string, dbwrap_name(db_ctx)); } else { char *secrets_tdb_path; secrets_tdb_path = lpcfg_private_db_path(tmp_ctx, lp_ctx, "secrets"); if (secrets_tdb_path == NULL) { return NT_STATUS_NO_MEMORY; } error_string = talloc_asprintf(cred, "Failed to fetch machine account password from " "secrets.ldb: %s and failed to open %s", error_string == NULL ? "error" : error_string, secrets_tdb_path); } DEBUG(1, ("Could not find machine account in secrets database: %s: %s\n", error_string == NULL ? "error" : error_string, nt_errstr(status))); /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); } TALLOC_FREE(tmp_ctx); return status; }
krb5_error_code smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx, struct loadparm_context *lp_ctx, krb5_context *_krb5_context) { krb5_error_code ret; #ifdef SAMBA4_USES_HEIMDAL char **config_files; const char *config_file, *realm; #endif krb5_context krb5_ctx; initialize_krb5_error_table(); ret = krb5_init_context(&krb5_ctx); if (ret) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ret; } /* The MIT Kerberos build relies on using the system krb5.conf file. * If you really want to use another file please set KRB5_CONFIG * accordingly. */ #ifdef SAMBA4_USES_HEIMDAL config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf"); if (!config_file) { krb5_free_context(krb5_ctx); return ENOMEM; } /* Use our local krb5.conf file by default */ ret = krb5_prepend_config_files_default(config_file, &config_files); if (ret) { DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } ret = krb5_set_config_files(krb5_ctx, config_files); krb5_free_config_files(config_files); if (ret) { DEBUG(1,("krb5_set_config_files failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } realm = lpcfg_realm(lp_ctx); if (realm != NULL) { ret = krb5_set_default_realm(krb5_ctx, realm); if (ret) { DEBUG(1,("krb5_set_default_realm failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } } #endif *_krb5_context = krb5_ctx; return 0; }
const char *realm = NULL; OC_DEBUG(3, "exchange_ds_rfr: RfrGetFQDNFromLegacyDN (0x1)"); if (!dcesrv_call_authenticated(dce_call)) { OC_DEBUG(1, "No challenge requested by client, cannot authenticate"); failure: r->out.ppszServerFQDN = talloc_array(mem_ctx, const char *, 2); r->out.ppszServerFQDN[0] = NULL; r->out.result = MAPI_E_LOGON_FAILED; return MAPI_E_LOGON_FAILED; } netbiosname = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx); realm = lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx); if (!netbiosname || !realm) { goto failure; } fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm); r->out.ppszServerFQDN = talloc_array(mem_ctx, const char *, 2); r->out.ppszServerFQDN[0] = strlower_talloc(mem_ctx, fqdn); talloc_free(fqdn); r->out.result = MAPI_E_SUCCESS; return MAPI_E_SUCCESS; } /**