From 86039855759ce38e6074f956073199b0ccd29bdf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 26 May 2009 11:43:37 +1000 Subject: Add support for sendmsg() in socket_wrapper This is required because the deferred connect code skips the connect() until sending the packet, but unless we catch this call, the connect() never happens. Andrew Bartlett --- lib/socket_wrapper/socket_wrapper.c | 71 +++++++++++++++++++++++++++++++++++++ lib/socket_wrapper/socket_wrapper.h | 6 ++++ 2 files changed, 77 insertions(+) diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index d809d8a500..bd848f920b 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -118,6 +118,7 @@ #define real_setsockopt setsockopt #define real_recvfrom recvfrom #define real_sendto sendto +#define real_sendmsg sendmsg #define real_ioctl ioctl #define real_recv recv #define real_send send @@ -2064,6 +2065,76 @@ _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) return ret; } +_PUBLIC_ ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags) +{ + int ret; + uint8_t *buf; + off_t ofs = 0; + size_t i; + size_t remain; + + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_sendmsg(s, msg, flags); + } + + if (si->defer_connect) { + struct sockaddr_un un_addr; + int bcast = 0; + + if (si->bound == 0) { + ret = swrap_auto_bind(si, si->family); + if (ret == -1) return -1; + } + + ret = sockaddr_convert_to_un(si, si->peername, si->peername_len, + &un_addr, 0, &bcast); + if (ret == -1) return -1; + + ret = real_connect(s, (struct sockaddr *)&un_addr, + sizeof(un_addr)); + + /* to give better errors */ + if (ret == -1 && errno == ENOENT) { + errno = EHOSTUNREACH; + } + + if (ret == -1) { + return ret; + } + si->defer_connect = 0; + } + + ret = real_sendmsg(s, msg, flags); + remain = ret; + + /* we capture it as one single packet */ + buf = (uint8_t *)malloc(ret); + if (!buf) { + /* we just not capture the packet */ + errno = 0; + return ret; + } + + for (i=0; i < msg->msg_iovlen; i++) { + size_t this_time = MIN(remain, msg->msg_iov[i].iov_len); + memcpy(buf + ofs, + msg->msg_iov[i].iov_base, + this_time); + ofs += this_time; + remain -= this_time; + } + + swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); + free(buf); + if (ret == -1) { + swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); + } + + return ret; +} + int swrap_readv(int s, const struct iovec *vector, size_t count) { int ret; diff --git a/lib/socket_wrapper/socket_wrapper.h b/lib/socket_wrapper/socket_wrapper.h index b2d44769ff..56282e23b9 100644 --- a/lib/socket_wrapper/socket_wrapper.h +++ b/lib/socket_wrapper/socket_wrapper.h @@ -49,6 +49,7 @@ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *opt int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); +ssize_t swrap_sendmsg(int s, const struct msghdr *msg, int flags); int swrap_ioctl(int s, int req, void *ptr); ssize_t swrap_recv(int s, void *buf, size_t len, int flags); ssize_t swrap_send(int s, const void *buf, size_t len, int flags); @@ -108,6 +109,11 @@ int swrap_close(int); #endif #define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen) +#ifdef sendmsg +#undef sendmsg +#endif +#define sendmsg(s,msg,flags) swrap_sendmsg(s,msg,flags) + #ifdef ioctl #undef ioctl #endif -- cgit From 6ef65389fd2f2bdcafe840e0cd0221bb9f26bdfc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 26 May 2009 12:31:39 +1000 Subject: Don't use crossRef records to find our own domain A single AD server can only host a single domain, so don't stuff about with looking up our crossRef record in the cn=Partitions container. We instead trust that lp_realm() and lp_workgroup() works correctly. Andrew Bartlett --- source4/auth/auth.h | 8 +- source4/auth/ntlm/auth_sam.c | 144 ++++-------------- source4/auth/sam.c | 49 ++---- source4/cldap_server/netlogon.c | 116 +++------------ source4/kdc/config.mk | 4 +- source4/kdc/hdb-samba4.c | 207 +++++++++----------------- source4/kdc/kdc.h | 4 +- source4/kdc/pac-glue.c | 10 +- source4/nbt_server/dgram/netlogon.c | 21 +-- source4/param/loadparm.c | 1 + source4/param/param.h | 5 + source4/param/util.c | 17 +++ source4/rpc_server/config.mk | 3 +- source4/rpc_server/lsa/lsa_init.c | 69 ++------- source4/rpc_server/netlogon/dcerpc_netlogon.c | 82 ++++------ source4/rpc_server/samr/dcesrv_samr.c | 128 +++++----------- 16 files changed, 253 insertions(+), 615 deletions(-) diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 973102d842..f6d739325d 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -221,24 +221,26 @@ struct auth_critical_sizes { struct ldb_message; struct ldb_context; +struct ldb_dn; struct gensec_security; NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal); NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, uint32_t logon_parameters, + struct ldb_dn *domain_dn, struct ldb_message *msg, - struct ldb_message *msg_domain_ref, const char *logon_workstation, const char *name_for_logs, bool allow_domain_trust); struct auth_session_info *system_session(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, const char *netbios_name, + const char *domain_name, + struct ldb_dn *domain_dn, struct ldb_message *msg, - struct ldb_message *msg_domain_ref, DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key, - struct auth_serversupplied_info **_server_info); + struct auth_serversupplied_info **_server_info); NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, struct loadparm_context *lp_ctx, struct auth_session_info **_session_info) ; diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index e99d0e1f51..75ed3243d4 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -42,26 +42,12 @@ extern const char *domain_ref_attrs[]; static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, const char *account_name, - const char *domain_name, - struct ldb_message ***ret_msgs, - struct ldb_message ***ret_msgs_domain_ref) + struct ldb_dn *domain_dn, + struct ldb_message ***ret_msgs) { - struct ldb_message **msgs_tmp; struct ldb_message **msgs; - struct ldb_message **msgs_domain_ref; - struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); int ret; - int ret_domain; - - struct ldb_dn *domain_dn = NULL; - - if (domain_name) { - domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx, domain_name); - if (!domain_dn) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - } /* pull the user attributes */ ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, user_attrs, @@ -72,8 +58,8 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context * } if (ret == 0) { - DEBUG(3,("sam_search_user: Couldn't find user [%s\\%s] in samdb, under %s\n", - domain_name, account_name, ldb_dn_get_linearized(domain_dn))); + DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb, under %s\n", + account_name, ldb_dn_get_linearized(domain_dn))); return NT_STATUS_NO_SUCH_USER; } @@ -82,57 +68,7 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context * return NT_STATUS_INTERNAL_DB_CORRUPTION; } - if (!domain_dn) { - struct dom_sid *domain_sid; - - domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid"); - if (!domain_sid) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - /* find the domain's DN */ - ret = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_tmp, NULL, - "(&(objectSid=%s)(objectClass=domain))", - ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); - if (ret == -1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - if (ret == 0) { - DEBUG(3,("check_sam_security: Couldn't find domain_sid [%s] in passdb file.\n", - dom_sid_string(mem_ctx, domain_sid))); - return NT_STATUS_NO_SUCH_USER; - } - - if (ret > 1) { - DEBUG(0,("Found %d records matching domain_sid [%s]\n", - ret, dom_sid_string(mem_ctx, domain_sid))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - domain_dn = msgs_tmp[0]->dn; - } - - ret_domain = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &msgs_domain_ref, domain_ref_attrs, - "(nCName=%s)", ldb_dn_get_linearized(domain_dn)); - if (ret_domain == -1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - if (ret_domain == 0) { - DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", - ldb_dn_get_linearized(msgs_tmp[0]->dn))); - return NT_STATUS_NO_SUCH_USER; - } - - if (ret_domain > 1) { - DEBUG(0,("Found %d records matching domain [%s]\n", - ret_domain, ldb_dn_get_linearized(msgs_tmp[0]->dn))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - *ret_msgs = msgs; - *ret_msgs_domain_ref = msgs_domain_ref; return NT_STATUS_OK; } @@ -210,14 +146,13 @@ static NTSTATUS authsam_password_ok(struct auth_context *auth_context, static NTSTATUS authsam_authenticate(struct auth_context *auth_context, TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, + struct ldb_dn *domain_dn, struct ldb_message **msgs, - struct ldb_message **msgs_domain_ref, const struct auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { struct samr_Password *lm_pwd, *nt_pwd; NTSTATUS nt_status; - struct ldb_dn *domain_dn = samdb_result_dn(sam_ctx, mem_ctx, msgs_domain_ref[0], "nCName", NULL); uint16_t acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msgs[0], domain_dn); @@ -245,8 +180,8 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, nt_status = authsam_account_ok(mem_ctx, sam_ctx, user_info->logon_parameters, + domain_dn, msgs[0], - msgs_domain_ref[0], user_info->workstation_name, user_info->mapped.account_name, false); @@ -258,15 +193,14 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, - const char *domain, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; const char *account_name = user_info->mapped.account_name; struct ldb_message **msgs; - struct ldb_message **domain_ref_msgs; struct ldb_context *sam_ctx; + struct ldb_dn *domain_dn; DATA_BLOB user_sess_key, lm_sess_key; TALLOC_CTX *tmp_ctx; @@ -286,13 +220,19 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx return NT_STATUS_INVALID_SYSTEM_SERVICE; } - nt_status = authsam_search_account(tmp_ctx, sam_ctx, account_name, domain, &msgs, &domain_ref_msgs); + domain_dn = ldb_get_default_basedn(sam_ctx); + if (domain_dn == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_SUCH_DOMAIN; + } + + nt_status = authsam_search_account(tmp_ctx, sam_ctx, account_name, domain_dn, &msgs); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } - nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, sam_ctx, msgs, domain_ref_msgs, user_info, + nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, sam_ctx, domain_dn, msgs, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); @@ -300,7 +240,9 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx } nt_status = authsam_make_server_info(tmp_ctx, sam_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx), - msgs[0], domain_ref_msgs[0], + lp_sam_name(ctx->auth_ctx->lp_ctx), + domain_dn, + msgs[0], user_sess_key, lm_sess_key, server_info); if (!NT_STATUS_IS_OK(nt_status)) { @@ -325,14 +267,6 @@ static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx, return NT_STATUS_OK; } -static NTSTATUS authsam_ignoredomain_check_password(struct auth_method_context *ctx, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) -{ - return authsam_check_password_internals(ctx, mem_ctx, NULL, user_info, server_info); -} - /**************************************************************************** Check SAM security (above) but with a few extra checks. ****************************************************************************/ @@ -377,34 +311,6 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx, return NT_STATUS_NOT_IMPLEMENTED; } -/**************************************************************************** -Check SAM security (above) but with a few extra checks. -****************************************************************************/ -static NTSTATUS authsam_check_password(struct auth_method_context *ctx, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) -{ - const char *domain; - - /* check whether or not we service this domain/workgroup name */ - switch (lp_server_role(ctx->auth_ctx->lp_ctx)) { - case ROLE_STANDALONE: - case ROLE_DOMAIN_MEMBER: - domain = lp_netbios_name(ctx->auth_ctx->lp_ctx); - break; - - case ROLE_DOMAIN_CONTROLLER: - domain = lp_workgroup(ctx->auth_ctx->lp_ctx); - break; - - default: - return NT_STATUS_NO_SUCH_USER; - } - - return authsam_check_password_internals(ctx, mem_ctx, domain, user_info, server_info); -} - /* Used in the gensec_gssapi and gensec_krb5 server-side code, where the PAC isn't available */ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, @@ -417,9 +323,9 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, DATA_BLOB lm_sess_key = data_blob(NULL, 0); struct ldb_message **msgs; - struct ldb_message **msgs_domain_ref; struct ldb_context *sam_ctx; - + struct ldb_dn *domain_dn; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; @@ -433,14 +339,16 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, } nt_status = sam_get_results_principal(sam_ctx, tmp_ctx, principal, - &msgs, &msgs_domain_ref); + &domain_dn, &msgs); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } nt_status = authsam_make_server_info(tmp_ctx, sam_ctx, lp_netbios_name(auth_context->lp_ctx), - msgs[0], msgs_domain_ref[0], + lp_workgroup(auth_context->lp_ctx), + domain_dn, + msgs[0], user_sess_key, lm_sess_key, server_info); if (NT_STATUS_IS_OK(nt_status)) { @@ -454,7 +362,7 @@ static const struct auth_operations sam_ignoredomain_ops = { .name = "sam_ignoredomain", .get_challenge = auth_get_challenge_not_implemented, .want_check = authsam_ignoredomain_want_check, - .check_password = authsam_ignoredomain_check_password, + .check_password = authsam_check_password_internals, .get_server_info_principal = authsam_get_server_info_principal }; @@ -462,7 +370,7 @@ static const struct auth_operations sam_ops = { .name = "sam", .get_challenge = auth_get_challenge_not_implemented, .want_check = authsam_want_check, - .check_password = authsam_check_password, + .check_password = authsam_check_password_internals, .get_server_info_principal = authsam_get_server_info_principal }; diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 819bca0db0..ebdf1932af 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -139,21 +139,19 @@ static bool logon_hours_ok(struct ldb_message *msg, const char *name_for_logs) (ie not disabled, expired and the like). ****************************************************************************/ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, - struct ldb_context *sam_ctx, - uint32_t logon_parameters, - struct ldb_message *msg, - struct ldb_message *msg_domain_ref, - const char *logon_workstation, - const char *name_for_logs, - bool allow_domain_trust) + struct ldb_context *sam_ctx, + uint32_t logon_parameters, + struct ldb_dn *domain_dn, + struct ldb_message *msg, + const char *logon_workstation, + const char *name_for_logs, + bool allow_domain_trust) { uint16_t acct_flags; const char *workstation_list; NTTIME acct_expiry; NTTIME must_change_time; - struct ldb_dn *domain_dn = samdb_result_dn(sam_ctx, mem_ctx, msg_domain_ref, "nCName", ldb_dn_new(mem_ctx, sam_ctx, NULL)); - NTTIME now; DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs)); @@ -256,8 +254,9 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, const char *netbios_name, + const char *domain_name, + struct ldb_dn *domain_dn, struct ldb_message *msg, - struct ldb_message *msg_domain_ref, DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key, struct auth_serversupplied_info **_server_info) { @@ -269,7 +268,6 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte struct dom_sid **groupSIDs = NULL; struct dom_sid *account_sid; struct dom_sid *primary_group_sid; - struct ldb_dn *domain_dn; const char *str; struct ldb_dn *ncname; int i; @@ -327,7 +325,8 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->account_name = talloc_steal(server_info, samdb_result_string(msg, "sAMAccountName", NULL)); - server_info->domain_name = talloc_steal(server_info, samdb_result_string(msg_domain_ref, "nETBIOSName", NULL)); + server_info->domain_name = talloc_strdup(server_info, domain_name); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); str = samdb_result_string(msg, "displayName", ""); server_info->full_name = talloc_strdup(server_info, str); @@ -357,10 +356,6 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->acct_expiry = samdb_result_account_expires(msg); server_info->last_password_change = samdb_result_nttime(msg, "pwdLastSet", 0); - ncname = samdb_result_dn(sam_ctx, mem_ctx, msg_domain_ref, "nCName", NULL); - if (!ncname) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx, ncname, msg, "pwdLastSet"); @@ -371,8 +366,6 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->logon_count = samdb_result_uint(msg, "logonCount", 0); server_info->bad_password_count = samdb_result_uint(msg, "badPwdCount", 0); - domain_dn = samdb_result_dn(sam_ctx, mem_ctx, msg_domain_ref, "nCName", NULL); - server_info->acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn); @@ -388,34 +381,24 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte NTSTATUS sam_get_results_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *principal, - struct ldb_message ***msgs, - struct ldb_message ***msgs_domain_ref) + struct ldb_dn **domain_dn, + struct ldb_message ***msgs) { - struct ldb_dn *user_dn, *domain_dn; + struct ldb_dn *user_dn; NTSTATUS nt_status; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); int ret; - struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } - nt_status = crack_user_principal_name(sam_ctx, tmp_ctx, principal, &user_dn, &domain_dn); + nt_status = crack_user_principal_name(sam_ctx, tmp_ctx, principal, &user_dn, domain_dn); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } - /* grab domain info from the reference */ - ret = gendb_search(sam_ctx, tmp_ctx, partitions_basedn, msgs_domain_ref, domain_ref_attrs, - "(ncName=%s)", ldb_dn_get_linearized(domain_dn)); - - if (ret != 1) { - talloc_free(tmp_ctx); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - /* pull the user attributes */ ret = gendb_search_dn(sam_ctx, tmp_ctx, user_dn, msgs, user_attrs); if (ret != 1) { @@ -423,7 +406,7 @@ NTSTATUS sam_get_results_principal(struct ldb_context *sam_ctx, return NT_STATUS_INTERNAL_DB_CORRUPTION; } talloc_steal(mem_ctx, *msgs); - talloc_steal(mem_ctx, *msgs_domain_ref); + talloc_steal(mem_ctx, *domain_dn); talloc_free(tmp_ctx); return NT_STATUS_OK; diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index 33c0adc3b1..8a21ea55c9 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -53,10 +53,9 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, struct loadparm_context *lp_ctx, struct netlogon_samlogon_response *netlogon) { - const char *ref_attrs[] = {"nETBIOSName", "dnsRoot", "ncName", NULL}; const char *dom_attrs[] = {"objectGUID", NULL}; const char *none_attrs[] = {NULL}; - struct ldb_result *ref_res = NULL, *dom_res = NULL, *user_res = NULL; + struct ldb_result *dom_res = NULL, *user_res = NULL; int ret; const char **services = lp_server_services(lp_ctx); uint32_t server_type; @@ -69,94 +68,39 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, const char *server_site; const char *client_site; const char *pdc_ip; - struct ldb_dn *partitions_basedn; + struct ldb_dn *domain_dn = NULL; struct interface *ifaces; bool user_known; NTSTATUS status; - partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); - /* the domain has an optional trailing . */ if (domain && domain[strlen(domain)-1] == '.') { domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); } - if (domain) { - struct ldb_dn *dom_dn; - /* try and find the domain */ - - ret = ldb_search(sam_ctx, mem_ctx, &ref_res, - partitions_basedn, LDB_SCOPE_ONELEVEL, - ref_attrs, - "(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))", - ldb_binary_encode_string(mem_ctx, domain)); - - if (ret != LDB_SUCCESS) { - DEBUG(2,("Unable to find referece to '%s' in sam: %s\n", - domain, - ldb_errstring(sam_ctx))); - return NT_STATUS_NO_SUCH_DOMAIN; - } else if (ref_res->count == 1) { - dom_dn = ldb_msg_find_attr_as_dn(sam_ctx, mem_ctx, ref_res->msgs[0], "ncName"); - if (!dom_dn) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - ret = ldb_search(sam_ctx, mem_ctx, &dom_res, - dom_dn, LDB_SCOPE_BASE, dom_attrs, - "objectClass=domain"); - if (ret != LDB_SUCCESS) { - DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(dom_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, ldb_dn_get_linearized(dom_dn))); - return NT_STATUS_NO_SUCH_DOMAIN; - } - } else if (ref_res->count > 1) { - talloc_free(ref_res); - return NT_STATUS_NO_SUCH_DOMAIN; - } + if (domain && strcasecmp_m(domain, lp_realm(lp_ctx)) == 0) { + domain_dn = ldb_get_default_basedn(sam_ctx); } - if (netbios_domain) { - struct ldb_dn *dom_dn; - /* try and find the domain */ + if (netbios_domain && strcasecmp_m(domain, lp_sam_name(lp_ctx))) { + domain_dn = ldb_get_default_basedn(sam_ctx); + } - ret = ldb_search(sam_ctx, mem_ctx, &ref_res, - partitions_basedn, LDB_SCOPE_ONELEVEL, - ref_attrs, - "(&(objectClass=crossRef)(ncName=*)(nETBIOSName=%s))", - ldb_binary_encode_string(mem_ctx, netbios_domain)); - + if (domain_dn) { + ret = ldb_search(sam_ctx, mem_ctx, &dom_res, + domain_dn, LDB_SCOPE_BASE, dom_attrs, + "objectClass=domain"); if (ret != LDB_SUCCESS) { - DEBUG(2,("Unable to find referece to '%s' in sam: %s\n", - netbios_domain, - ldb_errstring(sam_ctx))); + DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; - } else if (ref_res->count == 1) { - dom_dn = ldb_msg_find_attr_as_dn(sam_ctx, mem_ctx, ref_res->msgs[0], "ncName"); - if (!dom_dn) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - ret = ldb_search(sam_ctx, mem_ctx, &dom_res, - dom_dn, LDB_SCOPE_BASE, dom_attrs, - "objectClass=domain"); - if (ret != LDB_SUCCESS) { - DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(dom_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, ldb_dn_get_linearized(dom_dn))); - return NT_STATUS_NO_SUCH_DOMAIN; - } - } else if (ref_res->count > 1) { - talloc_free(ref_res); + } + if (dom_res->count != 1) { + DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain, ldb_dn_get_linearized(domain_dn))); return NT_STATUS_NO_SUCH_DOMAIN; } } if ((dom_res == NULL || dom_res->count == 0) && (domain_guid || domain_sid)) { - ref_res = NULL; if (domain_guid) { struct GUID binary_guid; @@ -206,36 +150,17 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } else if (dom_res->count == 1) { - /* try and find the domain */ - ret = ldb_search(sam_ctx, mem_ctx, &ref_res, - partitions_basedn, LDB_SCOPE_ONELEVEL, - ref_attrs, - "(&(objectClass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(dom_res->msgs[0]->dn)); + /* Ok, now just check it is our domain */ - if (ret != LDB_SUCCESS) { - DEBUG(2,("Unable to find referece to '%s' in sam: %s\n", - ldb_dn_get_linearized(dom_res->msgs[0]->dn), - ldb_errstring(sam_ctx))); - return NT_STATUS_NO_SUCH_DOMAIN; - - } else if (ref_res->count != 1) { - DEBUG(2,("Unable to find referece to '%s' in sam\n", - ldb_dn_get_linearized(dom_res->msgs[0]->dn))); + if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), dom_res->msgs[0]->dn) != 0) { return NT_STATUS_NO_SUCH_DOMAIN; } } else if (dom_res->count > 1) { - talloc_free(ref_res); return NT_STATUS_NO_SUCH_DOMAIN; } } - if ((ref_res == NULL || ref_res->count == 0)) { - DEBUG(2,("Unable to find domain reference with name %s or GUID {%s}\n", domain, domain_guid)); - return NT_STATUS_NO_SUCH_DOMAIN; - } - if ((dom_res == NULL || dom_res->count == 0)) { DEBUG(2,("Unable to find domain with name %s or GUID {%s}\n", domain, domain_guid)); return NT_STATUS_NO_SUCH_DOMAIN; @@ -308,15 +233,14 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name(lp_ctx)); domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); - realm = samdb_result_string(ref_res->msgs[0], "dnsRoot", lp_realm(lp_ctx)); - dns_domain = samdb_result_string(ref_res->msgs[0], "dnsRoot", lp_realm(lp_ctx)); + realm = lp_realm(lp_ctx); + dns_domain = lp_realm(lp_ctx); pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", strlower_talloc(mem_ctx, lp_netbios_name(lp_ctx)), dns_domain); - flatname = samdb_result_string(ref_res->msgs[0], "nETBIOSName", - lp_workgroup(lp_ctx)); + flatname = lp_sam_name(lp_ctx); /* FIXME: Hardcoded site names */ server_site = "Default-First-Site-Name"; client_site = "Default-First-Site-Name"; diff --git a/source4/kdc/config.mk b/source4/kdc/config.mk index bd8a313316..03fa2db295 100644 --- a/source4/kdc/config.mk +++ b/source4/kdc/config.mk @@ -6,7 +6,7 @@ INIT_FUNCTION = server_service_kdc_init SUBSYSTEM = service PRIVATE_DEPENDENCIES = \ - HEIMDAL_KDC HDB_SAMBA4 + HEIMDAL_KDC HDB_SAMBA4 LIBSAMBA-HOSTCONFIG # End SUBSYSTEM KDC ####################### @@ -18,7 +18,7 @@ KDC_OBJ_FILES = $(addprefix $(kdcsrcdir)/, kdc.o kpasswdd.o) CFLAGS = -Iheimdal/kdc -Iheimdal/lib/hdb PRIVATE_DEPENDENCIES = \ LIBLDB auth_sam auth_sam_reply CREDENTIALS \ - HEIMDAL_HDB + HEIMDAL_HDB LIBSAMBA-HOSTCONFIG # End SUBSYSTEM KDC ####################### diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index daeed77975..1fdb744a84 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -1,6 +1,6 @@ /* * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd. - * Copyright (c) 2004, Andrew Bartlett . + * Copyright (c) 2004-2009, Andrew Bartlett . * Copyright (c) 2004, Stefan Metzmacher * All rights reserved. * @@ -62,12 +62,6 @@ enum trust_direction { OUTBOUND = LSA_TRUST_DIRECTION_OUTBOUND }; -static const char *realm_ref_attrs[] = { - "nCName", - "dnsRoot", - NULL -}; - static const char *trust_attrs[] = { "trustPartner", "trustAuthIncoming", @@ -491,32 +485,33 @@ out: */ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, TALLOC_CTX *mem_ctx, krb5_const_principal principal, - enum hdb_ldb_ent_type ent_type, + enum hdb_ldb_ent_type ent_type, + struct ldb_dn *realm_dn, struct ldb_message *msg, - struct ldb_message *realm_ref_msg, hdb_entry_ex *entry_ex) { unsigned int userAccountControl; int i; krb5_error_code ret = 0; krb5_boolean is_computer = FALSE; - const char *dnsdomain = ldb_msg_find_attr_as_string(realm_ref_msg, "dnsRoot", NULL); - char *realm = strupper_talloc(mem_ctx, dnsdomain); struct loadparm_context *lp_ctx = ldb_get_opaque((struct ldb_context *)db->hdb_db, "loadparm"); - struct ldb_dn *domain_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, - mem_ctx, - realm_ref_msg, - "nCName", - ldb_dn_new(mem_ctx, (struct ldb_context *)db->hdb_db, NULL)); + char *realm = strupper_talloc(mem_ctx, lp_realm(lp_ctx)); struct hdb_ldb_private *p; NTTIME acct_expiry; struct ldb_message_element *objectclasses; struct ldb_val computer_val; + const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); computer_val.data = discard_const_p(uint8_t,"computer"); computer_val.length = strlen((const char *)computer_val.data); + if (!samAccountName) { + krb5_set_error_string(context, "LDB_message2entry: no samAccountName present"); + ret = ENOENT; + goto out; + } + objectclasses = ldb_msg_find_element(msg, "objectClass"); if (objectclasses && ldb_msg_find_val(objectclasses, &computer_val)) { @@ -539,7 +534,12 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, p->entry_ex = entry_ex; p->iconv_convenience = lp_iconv_convenience(lp_ctx); - p->netbios_name = lp_netbios_name(lp_ctx); + p->lp_ctx = lp_ctx; + p->realm_dn = talloc_reference(p, realm_dn); + if (!p->realm_dn) { + ret = ENOMEM; + goto out; + } talloc_set_destructor(p, hdb_ldb_destructor); @@ -551,13 +551,6 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); if (ent_type == HDB_SAMBA4_ENT_TYPE_ANY && principal == NULL) { - const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); - if (!samAccountName) { - krb5_set_error_string(context, "LDB_message2entry: no samAccountName present"); - ret = ENOENT; - goto out; - } - samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); krb5_make_principal(context, &entry_ex->entry.principal, realm, samAccountName, NULL); } else { char *strdup_realm; @@ -584,6 +577,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, krb5_princ_set_realm(context, entry_ex->entry.principal, &strdup_realm); } + /* First try and figure out the flags based on the userAccountControl */ entry_ex->entry.flags = uf2HDBFlags(context, userAccountControl, ent_type); if (ent_type == HDB_SAMBA4_ENT_TYPE_KRBTGT) { @@ -593,6 +587,11 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, entry_ex->entry.flags.ok_as_delegate = 1; } + /* Windows 2008 seems to enforce this (very sensible) rule by + * default - don't allow offline attacks on a user's password + * by asking for a ticket to them as a service (encrypted with + * their probably patheticly insecure password) */ + if (lp_parm_bool(lp_ctx, NULL, "kdc", "require spn for service", true)) { if (!is_computer && !ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL)) { entry_ex->entry.flags.server = 0; @@ -618,22 +617,19 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, entry_ex->entry.valid_start = NULL; - acct_expiry = samdb_result_account_expires(msg); - if (acct_expiry == 0x7FFFFFFFFFFFFFFFULL) { + /* The account/password expiry only applies when the account is used as a + * client (ie password login), not when used as a server */ + if (ent_type == HDB_SAMBA4_ENT_TYPE_KRBTGT || ent_type == HDB_SAMBA4_ENT_TYPE_SERVER) { + /* Make very well sure we don't use this for a client, + * it could bypass the above password restrictions */ + entry_ex->entry.flags.client = 0; entry_ex->entry.valid_end = NULL; - } else { - entry_ex->entry.valid_end = malloc(sizeof(*entry_ex->entry.valid_end)); - if (entry_ex->entry.valid_end == NULL) { - ret = ENOMEM; - goto out; - } - *entry_ex->entry.valid_end = nt_time_to_unix(acct_expiry); - } + entry_ex->entry.pw_end = NULL; - if (ent_type != HDB_SAMBA4_ENT_TYPE_KRBTGT) { + } else { NTTIME must_change_time = samdb_result_force_password_change((struct ldb_context *)db->hdb_db, mem_ctx, - domain_dn, msg); + realm_dn, msg); if (must_change_time == 0x7FFFFFFFFFFFFFFFULL) { entry_ex->entry.pw_end = NULL; } else { @@ -644,8 +640,18 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, } *entry_ex->entry.pw_end = nt_time_to_unix(must_change_time); } - } else { - entry_ex->entry.pw_end = NULL; + + acct_expiry = samdb_result_account_expires(msg); + if (acct_expiry == 0x7FFFFFFFFFFFFFFFULL) { + entry_ex->entry.valid_end = NULL; + } else { + entry_ex->entry.valid_end = malloc(sizeof(*entry_ex->entry.valid_end)); + if (entry_ex->entry.valid_end == NULL) { + ret = ENOMEM; + goto out; + } + *entry_ex->entry.valid_end = nt_time_to_unix(acct_expiry); + } } entry_ex->entry.max_life = NULL; @@ -680,7 +686,6 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, p->msg = talloc_steal(p, msg); - p->realm_ref_msg = talloc_steal(p, realm_ref_msg); p->samdb = (struct ldb_context *)db->hdb_db; out: @@ -701,6 +706,7 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, struct loadparm_context *lp_ctx, TALLOC_CTX *mem_ctx, krb5_const_principal principal, enum trust_direction direction, + struct ldb_dn *realm_dn, struct ldb_message *msg, hdb_entry_ex *entry_ex) { @@ -725,7 +731,8 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, p->entry_ex = entry_ex; p->iconv_convenience = lp_iconv_convenience(lp_ctx); - p->netbios_name = lp_netbios_name(lp_ctx); + p->lp_ctx = lp_ctx; + p->realm_dn = realm_dn; talloc_set_destructor(p, hdb_ldb_destructor); @@ -869,7 +876,6 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, p->msg = talloc_steal(p, msg); - p->realm_ref_msg = NULL; p->samdb = (struct ldb_context *)db->hdb_db; out: @@ -988,40 +994,6 @@ static krb5_error_code LDB_lookup_trust(krb5_context context, struct ldb_context return 0; } -static krb5_error_code LDB_lookup_realm(krb5_context context, struct ldb_context *ldb_ctx, - TALLOC_CTX *mem_ctx, - const char *realm, - struct ldb_message ***pmsg) -{ - int ret; - struct ldb_result *cross_ref_res; - struct ldb_dn *partitions_basedn = samdb_partitions_dn(ldb_ctx, mem_ctx); - - ret = ldb_search(ldb_ctx, mem_ctx, &cross_ref_res, - partitions_basedn, LDB_SCOPE_SUBTREE, realm_ref_attrs, - "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", - realm, realm); - - if (ret != LDB_SUCCESS) { - DEBUG(3, ("Failed to search to lookup realm(%s): %s\n", realm, ldb_errstring(ldb_ctx))); - talloc_free(cross_ref_res); - return HDB_ERR_NOENTRY; - } else if (cross_ref_res->count == 0 || cross_ref_res->count > 1) { - DEBUG(3, ("Failed find a single entry for realm %s: got %d\n", realm, cross_ref_res->count)); - talloc_free(cross_ref_res); - return HDB_ERR_NOENTRY; - } - - if (pmsg) { - *pmsg = cross_ref_res->msgs; - talloc_steal(mem_ctx, cross_ref_res->msgs); - } - talloc_free(cross_ref_res); - - return 0; -} - - static krb5_error_code LDB_open(krb5_context context, HDB *db, int flags, mode_t mode) { if (db->hdb_master_key_set) { @@ -1060,9 +1032,9 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, hdb_entry_ex *entry_ex) { NTSTATUS nt_status; char *principal_string; + struct ldb_dn *realm_dn; krb5_error_code ret; struct ldb_message **msg = NULL; - struct ldb_message **realm_ref_msg = NULL; ret = krb5_unparse_name(context, principal, &principal_string); @@ -1072,7 +1044,7 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, nt_status = sam_get_results_principal((struct ldb_context *)db->hdb_db, mem_ctx, principal_string, - &msg, &realm_ref_msg); + &realm_dn, &msg); free(principal_string); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { return HDB_ERR_NOENTRY; @@ -1084,7 +1056,7 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_CLIENT, - msg[0], realm_ref_msg[0], entry_ex); + realm_dn, msg[0], entry_ex); return ret; } @@ -1096,10 +1068,9 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, { krb5_error_code ret; struct ldb_message **msg = NULL; - struct ldb_message **realm_ref_msg_1 = NULL; - struct ldb_message **realm_ref_msg_2 = NULL; - struct ldb_dn *realm_dn; + struct ldb_dn *realm_dn = ldb_get_default_basedn(db->hdb_db); const char *realm; + struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context); krb5_principal alloc_principal = NULL; if (principal->name.name_string.len != 2 @@ -1110,18 +1081,14 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, /* krbtgt case. Either us or a trusted realm */ - if ((LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, - mem_ctx, principal->realm, &realm_ref_msg_1) == 0) - && (LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, - mem_ctx, principal->name.name_string.val[1], &realm_ref_msg_2) == 0) - && (ldb_dn_compare(realm_ref_msg_1[0]->dn, realm_ref_msg_1[0]->dn) == 0)) { + if (lp_is_my_domain_or_realm(lp_ctx, principal->realm) + && lp_is_my_domain_or_realm(lp_ctx, principal->name.name_string.val[1])) { /* us */ /* Cludge, cludge cludge. If the realm part of krbtgt/realm, * is in our db, then direct the caller at our primary * krbtgt */ - const char *dnsdomain = ldb_msg_find_attr_as_string(realm_ref_msg_1[0], "dnsRoot", NULL); - char *realm_fixed = strupper_talloc(mem_ctx, dnsdomain); + char *realm_fixed = strupper_talloc(mem_ctx, lp_realm(lp_ctx)); if (!realm_fixed) { krb5_set_error_string(context, "strupper_talloc: out of memory"); return ENOMEM; @@ -1140,8 +1107,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, return ENOMEM; } principal = alloc_principal; - realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg_1[0], "nCName", NULL); - + ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, realm_dn, &msg); @@ -1154,7 +1120,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, - msg[0], realm_ref_msg_1[0], entry_ex); + realm_dn, msg[0], entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: self krbtgt message2entry failed"); } @@ -1163,7 +1129,6 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, } else { enum trust_direction direction = UNKNOWN; - struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context); /* Either an inbound or outbound trust */ if (strcasecmp(lp_realm(lp_ctx), principal->realm) == 0) { @@ -1192,7 +1157,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, ret = LDB_trust_message2entry(context, db, lp_ctx, mem_ctx, principal, direction, - msg[0], entry_ex); + realm_dn, msg[0], entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: trust_message2entry failed"); } @@ -1214,13 +1179,12 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, krb5_error_code ret; const char *realm; struct ldb_message **msg = NULL; - struct ldb_message **realm_ref_msg = NULL; - struct ldb_dn *partitions_basedn = samdb_partitions_dn(db->hdb_db, mem_ctx); + struct ldb_dn *realm_dn; if (principal->name.name_string.len >= 2) { /* 'normal server' case */ int ldb_ret; NTSTATUS nt_status; - struct ldb_dn *user_dn, *domain_dn; + struct ldb_dn *user_dn; char *principal_string; ret = krb5_unparse_name_flags(context, principal, @@ -1235,7 +1199,7 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, * referral instead */ nt_status = crack_service_principal_name((struct ldb_context *)db->hdb_db, mem_ctx, principal_string, - &user_dn, &domain_dn); + &user_dn, &realm_dn); free(principal_string); if (!NT_STATUS_IS_OK(nt_status)) { @@ -1249,28 +1213,13 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, return HDB_ERR_NOENTRY; } - ldb_ret = gendb_search((struct ldb_context *)db->hdb_db, - mem_ctx, partitions_basedn, &realm_ref_msg, realm_ref_attrs, - "ncName=%s", ldb_dn_get_linearized(domain_dn)); - - if (ldb_ret != 1) { - return HDB_ERR_NOENTRY; - } - } else { - struct ldb_dn *realm_dn; /* server as client principal case, but we must not lookup userPrincipalNames */ - + realm_dn = ldb_get_default_basedn((struct ldb_context *)db->hdb_db); realm = krb5_principal_get_realm(context, principal); - ret = LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, - mem_ctx, realm, &realm_ref_msg); - if (ret != 0) { - return HDB_ERR_NOENTRY; - } - - realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL); - + /* Check if it is our realm, otherwise give referall */ + ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_SERVER, realm_dn, &msg); @@ -1282,7 +1231,7 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_SERVER, - msg[0], realm_ref_msg[0], entry_ex); + realm_dn, msg[0], entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: message2entry failed"); } @@ -1342,7 +1291,7 @@ struct hdb_ldb_seq { int index; int count; struct ldb_message **msgs; - struct ldb_message **realm_ref_msgs; + struct ldb_dn *realm_dn; }; static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) @@ -1367,8 +1316,7 @@ static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hd if (priv->index < priv->count) { ret = LDB_message2entry(context, db, mem_ctx, NULL, HDB_SAMBA4_ENT_TYPE_ANY, - priv->msgs[priv->index++], - priv->realm_ref_msgs[0], entry); + priv->realm_dn, priv->msgs[priv->index++], entry); } else { ret = HDB_ERR_NOENTRY; } @@ -1389,9 +1337,7 @@ static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flag struct ldb_context *ldb_ctx = (struct ldb_context *)db->hdb_db; struct hdb_ldb_seq *priv = (struct hdb_ldb_seq *)db->hdb_dbc; char *realm; - struct ldb_dn *realm_dn = NULL; struct ldb_result *res = NULL; - struct ldb_message **realm_ref_msgs = NULL; krb5_error_code ret; TALLOC_CTX *mem_ctx; int lret; @@ -1410,7 +1356,7 @@ static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flag priv->ctx = ldb_ctx; priv->index = 0; priv->msgs = NULL; - priv->realm_ref_msgs = NULL; + priv->realm_dn = ldb_get_default_basedn(ldb_ctx); priv->count = 0; mem_ctx = talloc_named(priv, 0, "LDB_firstkey context"); @@ -1426,23 +1372,8 @@ static krb5_error_code LDB_firstkey(krb5_context context, HDB *db, unsigned flag return ret; } - ret = LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db, - mem_ctx, realm, &realm_ref_msgs); - - free(realm); - - if (ret != 0) { - talloc_free(priv); - krb5_warnx(context, "LDB_firstkey: could not find realm\n"); - return HDB_ERR_NOENTRY; - } - - realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msgs[0], "nCName", NULL); - - priv->realm_ref_msgs = talloc_steal(priv, realm_ref_msgs); - lret = ldb_search(ldb_ctx, priv, &res, - realm_dn, LDB_SCOPE_SUBTREE, user_attrs, + priv->realm_dn, LDB_SCOPE_SUBTREE, user_attrs, "(objectClass=user)"); if (lret != LDB_SUCCESS) { diff --git a/source4/kdc/kdc.h b/source4/kdc/kdc.h index 417f327a57..a281e1d9c9 100644 --- a/source4/kdc/kdc.h +++ b/source4/kdc/kdc.h @@ -55,8 +55,8 @@ struct kdc_server { struct hdb_ldb_private { struct ldb_context *samdb; struct smb_iconv_convenience *iconv_convenience; + struct loadparm_context *lp_ctx; struct ldb_message *msg; - struct ldb_message *realm_ref_msg; + struct ldb_dn *realm_dn; hdb_entry_ex *entry_ex; - const char *netbios_name; }; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 1a0df8e4a1..411e752c04 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -3,7 +3,7 @@ PAC Glue between Samba and the KDC - Copyright (C) Andrew Bartlett 2005 + Copyright (C) Andrew Bartlett 2005-2009 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "auth/auth_sam.h" #include "auth/auth_sam_reply.h" #include "kdc/kdc.h" +#include "param/param.h" struct krb5_dh_moduli; struct _krb5_krb_auth_data; @@ -127,9 +128,10 @@ krb5_error_code samba_kdc_get_pac(void *priv, } nt_status = authsam_make_server_info(mem_ctx, p->samdb, - p->netbios_name, + lp_netbios_name(p->lp_ctx), + lp_sam_name(p->lp_ctx), + p->realm_dn, p->msg, - p->realm_ref_msg, data_blob(NULL, 0), data_blob(NULL, 0), &server_info); @@ -274,8 +276,8 @@ krb5_error_code samba_kdc_check_client_access(void *priv, nt_status = authsam_account_ok(tmp_ctx, p->samdb, MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT, + p->realm_dn, p->msg, - p->realm_ref_msg, workstation, name, true); free(name); diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c index e5c82280e3..2ed37fde59 100644 --- a/source4/nbt_server/dgram/netlogon.c +++ b/source4/nbt_server/dgram/netlogon.c @@ -45,33 +45,22 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); struct nbt_netlogon_response_from_pdc *pdc; - const char *ref_attrs[] = {"nETBIOSName", NULL}; - struct ldb_message **ref_res; struct ldb_context *samctx; - struct ldb_dn *partitions_basedn; struct nbt_netlogon_response netlogon_response; - int ret; /* only answer getdc requests on the PDC or LOGON names */ if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) { return; } - samctx = iface->nbtsrv->sam_ctx; - - if (!samdb_is_pdc(samctx)) { + if (lp_server_role(iface->nbtsrv->task->lp_ctx) != ROLE_DOMAIN_CONTROLLER + || !samdb_is_pdc(samctx)) { DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n")); return; } - partitions_basedn = samdb_partitions_dn(samctx, packet); - - ret = gendb_search(samctx, packet, partitions_basedn, &ref_res, ref_attrs, - "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", - name->name); - - if (ret != 1) { - DEBUG(2,("Unable to find domain reference '%s' in sam\n", name->name)); + if (strcasecmp_m(name->name, lp_workgroup(iface->nbtsrv->task->lp_ctx)) != 0) { + DEBUG(5,("GetDC requested for a domian %s that we don't host\n", name->name)); return; } @@ -83,7 +72,7 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, pdc->command = NETLOGON_RESPONSE_FROM_PDC; pdc->pdc_name = lp_netbios_name(iface->nbtsrv->task->lp_ctx); pdc->unicode_pdc_name = pdc->pdc_name; - pdc->domain_name = samdb_result_string(ref_res[0], "nETBIOSName", name->name);; + pdc->domain_name = lp_workgroup(iface->nbtsrv->task->lp_ctx); pdc->nt_version = 1; pdc->lmnt_token = 0xFFFF; pdc->lm20_token = 0xFFFF; diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index d6f418e568..eeffe9874f 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -2725,3 +2725,4 @@ struct gensec_settings *lp_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_ settings->target_hostname = lp_parm_string(lp_ctx, NULL, "gensec", "target_hostname"); return settings; } + diff --git a/source4/param/param.h b/source4/param/param.h index 3d257be062..27bc32f9b9 100644 --- a/source4/param/param.h +++ b/source4/param/param.h @@ -362,6 +362,9 @@ int param_write(struct param_context *ctx, const char *fn); bool lp_is_mydomain(struct loadparm_context *lp_ctx, const char *domain); +bool lp_is_my_domain_or_realm(struct loadparm_context *lp_ctx, + const char *domain); + /** see if a string matches either our primary or one of our secondary netbios aliases. do a case insensitive match @@ -434,6 +437,8 @@ const char *lp_messaging_path(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *smb_iconv_convenience_init_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); +const char *lp_sam_name(struct loadparm_context *lp_ctx); + /* The following definitions come from lib/version.c */ const char *samba_version_string(void); diff --git a/source4/param/util.c b/source4/param/util.c index 3881107cbc..366c3f1d78 100644 --- a/source4/param/util.c +++ b/source4/param/util.c @@ -41,6 +41,13 @@ bool lp_is_mydomain(struct loadparm_context *lp_ctx, return strequal(lp_workgroup(lp_ctx), domain); } +bool lp_is_my_domain_or_realm(struct loadparm_context *lp_ctx, + const char *domain) +{ + return strequal(lp_workgroup(lp_ctx), domain) || + strequal(lp_realm(lp_ctx), domain); +} + /** see if a string matches either our primary or one of our secondary netbios aliases. do a case insensitive match @@ -296,3 +303,13 @@ struct smb_iconv_convenience *smb_iconv_convenience_init_lp(TALLOC_CTX *mem_ctx, } +const char *lp_sam_name(struct loadparm_context *lp_ctx) +{ + switch (lp_server_role(lp_ctx)) { + case ROLE_DOMAIN_CONTROLLER: + return lp_workgroup(lp_ctx); + default: + return lp_netbios_name(lp_ctx); + } +} + diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index d05b0a0c0d..dfc3d17bed 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -129,7 +129,8 @@ PRIVATE_DEPENDENCIES = \ DCERPC_COMMON \ SCHANNELDB \ NDR_NETLOGON \ - auth_sam + auth_sam \ + LIBSAMBA-HOSTCONFIG # End MODULE dcerpc_netlogon ################################################ diff --git a/source4/rpc_server/lsa/lsa_init.c b/source4/rpc_server/lsa/lsa_init.c index 8d8417109f..ae565a3ff1 100644 --- a/source4/rpc_server/lsa/lsa_init.c +++ b/source4/rpc_server/lsa/lsa_init.c @@ -26,7 +26,6 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ struct lsa_policy_state **_state) { struct lsa_policy_state *state; - struct ldb_dn *partitions_basedn; struct ldb_result *dom_res; const char *dom_attrs[] = { "objectSid", @@ -35,13 +34,7 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ "fSMORoleOwner", NULL }; - struct ldb_result *ref_res; - struct ldb_result *forest_ref_res; - const char *ref_attrs[] = { - "nETBIOSName", - "dnsRoot", - NULL - }; + char *p; int ret; state = talloc(mem_ctx, struct lsa_policy_state); @@ -55,11 +48,9 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_INVALID_SYSTEM_SERVICE; } - partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx); - /* work out the domain_dn - useful for so many calls its worth fetching here */ - state->domain_dn = samdb_base_dn(state->sam_ldb); + state->domain_dn = ldb_get_default_basedn(state->sam_ldb); if (!state->domain_dn) { return NT_STATUS_NO_MEMORY; } @@ -86,66 +77,30 @@ NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ } state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); - if (!state->domain_sid) { - return NT_STATUS_NO_SUCH_DOMAIN; - } state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0); talloc_free(dom_res); - ret = ldb_search(state->sam_ldb, state, &ref_res, - partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs, - "(&(objectclass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(state->domain_dn)); - - if (ret != LDB_SUCCESS) { - talloc_free(ref_res); - return NT_STATUS_INVALID_SYSTEM_SERVICE; - } - if (ref_res->count != 1) { - talloc_free(ref_res); - return NT_STATUS_NO_SUCH_DOMAIN; - } - - state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL); - if (!state->domain_name) { - talloc_free(ref_res); - return NT_STATUS_NO_SUCH_DOMAIN; - } - talloc_steal(state, state->domain_name); + state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); - state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL); + state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn); if (!state->domain_dns) { - talloc_free(ref_res); return NT_STATUS_NO_SUCH_DOMAIN; } - talloc_steal(state, state->domain_dns); - - talloc_free(ref_res); - - ret = ldb_search(state->sam_ldb, state, &forest_ref_res, - partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs, - "(&(objectclass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(state->forest_dn)); - - if (ret != LDB_SUCCESS) { - talloc_free(forest_ref_res); - return NT_STATUS_INVALID_SYSTEM_SERVICE; - } - if (forest_ref_res->count != 1) { - talloc_free(forest_ref_res); - return NT_STATUS_NO_SUCH_DOMAIN; + p = strchr(state->domain_dns, '/'); + if (p) { + *p = '\0'; } - state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL); + state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn); if (!state->forest_dns) { - talloc_free(forest_ref_res); return NT_STATUS_NO_SUCH_DOMAIN; } - talloc_steal(state, state->forest_dns); - - talloc_free(forest_ref_res); + p = strchr(state->forest_dns, '/'); + if (p) { + *p = '\0'; + } /* work out the builtin_dn - useful for so many calls its worth fetching here */ diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index b17ab86e26..51849fc52e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1010,8 +1010,9 @@ static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TAL fill in a netr_DomainTrustInfo from a ldb search result */ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, struct ldb_message *res, - struct ldb_message *ref_res, struct netr_DomainTrustInfo *info, bool is_local, bool is_trust_list) { @@ -1020,9 +1021,10 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension); info->trust_extension.length = 16; info->trust_extension.info->flags = - NETR_TRUST_FLAG_TREEROOT | + NETR_TRUST_FLAG_TREEROOT | NETR_TRUST_FLAG_IN_FOREST | NETR_TRUST_FLAG_PRIMARY; + info->trust_extension.info->parent_index = 0; /* should be index into array of parent */ info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */ @@ -1032,13 +1034,21 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ info->forest.string = NULL; } else { + char *p; /* TODO: we need a common function for pulling the forest */ - info->forest.string = samdb_result_string(ref_res, "dnsRoot", NULL); + info->forest.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx)); + if (!info->forest.string) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + p = strchr(info->forest.string, '/'); + if (p) { + *p = '\0'; + } } if (is_local) { - info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL); - info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL); + info->domainname.string = lp_sam_name(lp_ctx); + info->fulldomainname.string = lp_realm(lp_ctx); info->guid = samdb_result_guid(res, "objectGUID"); info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid"); } else { @@ -1064,13 +1074,11 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal const char * const attrs[] = { "objectSid", "objectGUID", "flatName", "securityIdentifier", "trustPartner", NULL }; - const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL }; struct ldb_context *sam_ctx; - struct ldb_message **res1, **res2, **ref_res; + struct ldb_message **res1, **res2; struct netr_DomainInfo1 *info1; - int ret, ret1, ret2, i; + int ret1, ret2, i; NTSTATUS status; - struct ldb_dn *partitions_basedn; const char *local_domain; @@ -1090,8 +1098,6 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal return NT_STATUS_INVALID_SYSTEM_SERVICE; } - partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); - /* we need to do two searches. The first will pull our primary domain and the second will pull any trusted domains. Our primary domain is also a "trusted" domain, so we need to @@ -1103,15 +1109,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal } /* try and find the domain */ - ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, - &ref_res, ref_attrs, - "(&(objectClass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(res1[0]->dn)); - if (ret != 1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - local_domain = samdb_result_string(ref_res[0], "nETBIOSName", NULL); + local_domain = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)"); if (ret2 == -1) { @@ -1128,21 +1126,21 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal info1->num_trusts); NT_STATUS_HAVE_NO_MEMORY(info1->trusts); - status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, + status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0], &info1->domaininfo, true, false); NT_STATUS_NOT_OK_RETURN(status); for (i=0;itrusts[i], + status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[i], &info1->trusts[i], false, true); NT_STATUS_NOT_OK_RETURN(status); } - status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], + status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0], &info1->trusts[i], true, true); NT_STATUS_NOT_OK_RETURN(status); - info1->dns_hostname.string = samdb_result_string(ref_res[0], "dnsRoot", NULL); + info1->dns_hostname.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx); info1->workstation_flags = NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE; info1->supported_enc_types = 0; /* w2008 gives this 0 */ @@ -1191,7 +1189,7 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA struct netr_DsRGetDCNameEx2 *r) { const char * const attrs[] = { "objectGUID", NULL }; - void *sam_ctx; + struct ldb_context *sam_ctx; struct ldb_message **res; struct ldb_dn *domain_dn; int ret; @@ -1206,21 +1204,19 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA /* Win7-beta will send the domain name in the form the user typed, so we have to cope with both the short and long form here */ - if (r->in.domain_name == NULL || strcasecmp(r->in.domain_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx)) == 0) { - r->in.domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); + if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx, + r->in.domain_name)) { + return WERR_NO_SUCH_DOMAIN; } - domain_dn = samdb_dns_domain_to_dn((struct ldb_context *)sam_ctx, - mem_ctx, - r->in.domain_name); + domain_dn = ldb_get_default_basedn(sam_ctx); if (domain_dn == NULL) { return WERR_DS_SERVICE_UNAVAILABLE; } - ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, + ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs); if (ret != 1) { - return WERR_NO_SUCH_DOMAIN; } info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo); @@ -1359,10 +1355,8 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce struct netr_DomainTrustList *trusts; void *sam_ctx; int ret; - struct ldb_message **dom_res, **ref_res; + struct ldb_message **dom_res; const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL }; - const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL }; - struct ldb_dn *partitions_basedn; ZERO_STRUCT(r->out); @@ -1371,9 +1365,6 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce return WERR_GENERAL_FAILURE; } - partitions_basedn = samdb_partitions_dn((struct ldb_context *)sam_ctx, - mem_ctx); - ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs); if (ret == -1) { @@ -1383,17 +1374,6 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce return WERR_GENERAL_FAILURE; } - ret = gendb_search((struct ldb_context *)sam_ctx, mem_ctx, - partitions_basedn, &ref_res, ref_attrs, - "(&(objectClass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(dom_res[0]->dn)); - if (ret == -1) { - return WERR_GENERAL_FAILURE; - } - if (ret != 1) { - return WERR_GENERAL_FAILURE; - } - trusts = talloc(mem_ctx, struct netr_DomainTrustList); W_ERROR_HAVE_NO_MEMORY(trusts); @@ -1406,8 +1386,8 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce /* TODO: add filtering by trust_flags, and correct trust_type and attributes */ - trusts->array[0].netbios_name = samdb_result_string(ref_res[0], "nETBIOSName", NULL); - trusts->array[0].dns_name = samdb_result_string(ref_res[0], "dnsRoot", NULL); + trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); + trusts->array[0].dns_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx); trusts->array[0].trust_flags = NETR_TRUST_FLAG_TREEROOT | NETR_TRUST_FLAG_IN_FOREST | diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index df23e11a67..fabc88d02d 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -273,11 +273,8 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL struct dcesrv_handle *h; struct dom_sid *sid; const char * const dom_attrs[] = { "objectSid", NULL}; - const char * const ref_attrs[] = { "ncName", NULL}; struct ldb_message **dom_msgs; - struct ldb_message **ref_msgs; int ret; - struct ldb_dn *partitions_basedn; *r->out.sid = NULL; @@ -289,27 +286,17 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_INVALID_PARAMETER; } - partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx); - if (strcasecmp(r->in.domain_name->string, "BUILTIN") == 0) { ret = gendb_search(c_state->sam_ctx, mem_ctx, NULL, &dom_msgs, dom_attrs, "(objectClass=builtinDomain)"); - } else { - ret = gendb_search(c_state->sam_ctx, - mem_ctx, partitions_basedn, &ref_msgs, ref_attrs, - "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", - ldb_binary_encode_string(mem_ctx, r->in.domain_name->string)); - if (ret != 1) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - - ret = gendb_search_dn(c_state->sam_ctx, mem_ctx, - samdb_result_dn(c_state->sam_ctx, mem_ctx, - ref_msgs[0], "ncName", NULL), + } else if (strcasecmp_m(r->in.domain_name->string, lp_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) { + ret = gendb_search_dn(c_state->sam_ctx, + mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs); + } else { + return NT_STATUS_NO_SUCH_DOMAIN; } - if (ret != 1) { return NT_STATUS_NO_SUCH_DOMAIN; } @@ -338,12 +325,7 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL struct samr_connect_state *c_state; struct dcesrv_handle *h; struct samr_SamArray *array; - int i, start_i, ret; - const char * const dom_attrs[] = { "cn", NULL}; - const char * const ref_attrs[] = { "nETBIOSName", NULL}; - struct ldb_result *dom_res; - struct ldb_result *ref_res; - struct ldb_dn *partitions_basedn; + int i, start_i; *r->out.resume_handle = 0; *r->out.sam = NULL; @@ -353,20 +335,11 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL c_state = h->data; - partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx); - - ret = ldb_search(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx), - LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))"); - if (ret != LDB_SUCCESS) { - DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - *r->out.resume_handle = dom_res->count; + *r->out.resume_handle = 2; start_i = *r->in.resume_handle; - if (start_i >= dom_res->count) { + if (start_i >= 2) { /* search past end of list is not an error for this call */ return NT_STATUS_OK; } @@ -379,27 +352,17 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL array->count = 0; array->entries = NULL; - array->entries = talloc_array(mem_ctx, struct samr_SamEntry, dom_res->count - start_i); + array->entries = talloc_array(mem_ctx, struct samr_SamEntry, 2 - start_i); if (array->entries == NULL) { return NT_STATUS_NO_MEMORY; } - for (i=0;icount-start_i;i++) { + for (i=0;i<2-start_i;i++) { array->entries[i].idx = start_i + i; - /* try and find the domain */ - ret = ldb_search(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn, - LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))", - ldb_dn_get_linearized(dom_res->msgs[i]->dn)); - - if (ret != LDB_SUCCESS) { - DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - if (ref_res->count == 1) { - array->entries[i].name.string = samdb_result_string(ref_res->msgs[0], "nETBIOSName", NULL); + if (i == 0) { + array->entries[i].name.string = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); } else { - array->entries[i].name.string = samdb_result_string(dom_res->msgs[i], "cn", NULL); + array->entries[i].name.string = "BUILTIN"; } } @@ -418,15 +381,11 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO struct samr_OpenDomain *r) { struct dcesrv_handle *h_conn, *h_domain; - const char *domain_name; struct samr_connect_state *c_state; struct samr_domain_state *d_state; const char * const dom_attrs[] = { "cn", NULL}; - const char * const ref_attrs[] = { "nETBIOSName", NULL}; struct ldb_message **dom_msgs; - struct ldb_message **ref_msgs; int ret; - struct ldb_dn *partitions_basedn; ZERO_STRUCTP(r->out.domain_handle); @@ -438,63 +397,44 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO return NT_STATUS_INVALID_PARAMETER; } - partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx); + d_state = talloc(c_state, struct samr_domain_state); + if (!d_state) { + return NT_STATUS_NO_MEMORY; + } + + d_state->domain_sid = talloc_steal(d_state, r->in.sid); + + if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) { + d_state->builtin = true; + d_state->domain_name = "BUILTIN"; + } else { + d_state->builtin = false; + d_state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); + } ret = gendb_search(c_state->sam_ctx, - mem_ctx, NULL, &dom_msgs, dom_attrs, - "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", + mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs, + "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid)); + if (ret == 0) { + talloc_free(d_state); return NT_STATUS_NO_SUCH_DOMAIN; } else if (ret > 1) { + talloc_free(d_state); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == -1) { + talloc_free(d_state); DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx))); return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else { - ret = gendb_search(c_state->sam_ctx, - mem_ctx, partitions_basedn, &ref_msgs, ref_attrs, - "(&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s))", - ldb_dn_get_linearized(dom_msgs[0]->dn)); - if (ret == 0) { - domain_name = ldb_msg_find_attr_as_string(dom_msgs[0], "cn", NULL); - if (domain_name == NULL) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - } else if (ret == 1) { - - domain_name = ldb_msg_find_attr_as_string(ref_msgs[0], "nETBIOSName", NULL); - if (domain_name == NULL) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - } else { - return NT_STATUS_NO_SUCH_DOMAIN; - } - } - - d_state = talloc(c_state, struct samr_domain_state); - if (!d_state) { - return NT_STATUS_NO_MEMORY; } + d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn); d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx); d_state->connect_state = talloc_reference(d_state, c_state); d_state->sam_ctx = c_state->sam_ctx; - d_state->domain_sid = dom_sid_dup(d_state, r->in.sid); - d_state->domain_name = talloc_strdup(d_state, domain_name); - d_state->domain_dn = ldb_dn_copy(d_state, dom_msgs[0]->dn); - if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) { - talloc_free(d_state); - return NT_STATUS_NO_MEMORY; - } d_state->access_mask = r->in.access_mask; - if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) { - d_state->builtin = true; - } else { - d_state->builtin = false; - } - d_state->lp_ctx = dce_call->conn->dce_ctx->lp_ctx; h_domain = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_DOMAIN); -- cgit