static NTSTATUS check_trustdomain_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; fstring dc_name; struct sockaddr_storage dc_ss; if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_trustdomain_security: Critical variables not present. Failing.\n")); return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); /* * Check that the requested domain is not our own machine name or domain name. */ if( strequal(get_global_sam_name(), user_info->mapped.domain_name)) { DEBUG(3,("check_trustdomain_security: Requested domain [%s] was for this machine.\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } /* No point is bothering if this is not a trusted domain. This return makes "map to guest = bad user" work again. The logic is that if we know nothing about the domain, that user is not known to us and does not exist */ if ( !is_trusted_domain( user_info->mapped.domain_name ) ) return NT_STATUS_NOT_IMPLEMENTED; /* use get_dc_name() for consistency even through we know that it will be a netbios name */ if ( !get_dc_name(user_info->mapped.domain_name, NULL, dc_name, &dc_ss) ) { DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n", user_info->mapped.domain_name)); return NT_STATUS_NO_LOGON_SERVERS; } nt_status = domain_client_validate(mem_ctx, user_info, user_info->mapped.domain_name, (uchar *)auth_context->challenge.data, server_info, dc_name, &dc_ss); return nt_status; }
static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; const char *domain = lp_workgroup(); fstring dc_name; struct sockaddr_storage dc_ss; if ( lp_server_role() != ROLE_DOMAIN_MEMBER ) { DEBUG(0,("check_ntdomain_security: Configuration error! Cannot use " "ntdomain auth method when not a member of a domain.\n")); return NT_STATUS_NOT_IMPLEMENTED; } if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n")); return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); /* * Check that the requested domain is not our own machine name. * If it is, we should never check the PDC here, we use our own local * password file. */ if(strequal(get_global_sam_name(), user_info->mapped.domain_name)) { DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n")); return NT_STATUS_NOT_IMPLEMENTED; } /* we need our DC to send the net_sam_logon() request to */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) { DEBUG(5,("check_ntdomain_security: unable to locate a DC for domain %s\n", user_info->mapped.domain_name)); return NT_STATUS_NO_LOGON_SERVERS; } nt_status = domain_client_validate(mem_ctx, user_info, domain, (uchar *)auth_context->challenge.data, server_info, dc_name, &dc_ss); return nt_status; }
static NTSTATUS _idmap_adex_init(struct idmap_domain *dom) { ADS_STRUCT *ads = NULL; ADS_STATUS status; static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct dom_sid domain_sid; fstring dcname; struct sockaddr_storage ip; struct likewise_cell *lwcell; if (NT_STATUS_IS_OK(init_status)) return NT_STATUS_OK; /* Silently fail if we are not a member server in security = ads */ if ((lp_server_role() != ROLE_DOMAIN_MEMBER) || (lp_security() != SEC_ADS)) { init_status = NT_STATUS_INVALID_SERVER_STATE; BAIL_ON_NTSTATUS_ERROR(init_status); } /* fetch our domain SID first */ if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; BAIL_ON_NTSTATUS_ERROR(init_status); } /* reuse the same ticket cache as winbindd */ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); /* Establish a connection to a DC */ if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) { init_status = NT_STATUS_NO_MEMORY; BAIL_ON_NTSTATUS_ERROR(init_status); } ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); ads->auth.realm = SMB_STRDUP(lp_realm()); /* get the DC name here to setup the server affinity cache and local krb5.conf */ get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip); status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n", ads_errstr(status))); } init_status = ads_ntstatus(status); BAIL_ON_NTSTATUS_ERROR(init_status); /* Find out cell membership */ init_status = cell_locate_membership(ads); if (!NT_STATUS_IS_OK(init_status)) { DEBUG(0,("LWI: Fail to locate cell membership (%s).", nt_errstr(init_status))); goto done; } /* Fill in the cell information */ lwcell = cell_list_head(); init_status = cell_lookup_settings(lwcell); BAIL_ON_NTSTATUS_ERROR(init_status); /* Miscellaneous setup. E.g. set up the list of GC servers and domain list for our forest (does not actually connect). */ init_status = gc_init_list(); BAIL_ON_NTSTATUS_ERROR(init_status); init_status = domain_init_list(); BAIL_ON_NTSTATUS_ERROR(init_status); done: if (!NT_STATUS_IS_OK(init_status)) { DEBUG(1,("Likewise initialization failed (%s)\n", nt_errstr(init_status))); } /* cleanup */ if (!NT_STATUS_IS_OK(init_status)) { cell_list_destroy(); /* init_status stores the failure reason but we need to return success or else idmap_init() will drop us from the backend list */ return NT_STATUS_OK; } init_status = NT_STATUS_OK; return init_status; }
bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, char ***domain_names, uint32 *num_domains, DOM_SID **sids ) { struct policy_handle pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring dc_name; struct sockaddr_storage dc_ss; uint32 enum_ctx = 0; struct cli_state *cli = NULL; struct rpc_pipe_client *lsa_pipe; bool retry; struct lsa_DomainList dom_list; int i; *domain_names = NULL; *num_domains = 0; *sids = NULL; /* lookup a DC first */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) { DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n", domain)); return False; } /* setup the anonymous connection */ result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC", "", "", "", 0, Undefined, &retry); if ( !NT_STATUS_IS_OK(result) ) goto done; /* open the LSARPC_PIPE */ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &lsa_pipe); if (!NT_STATUS_IS_OK(result)) { goto done; } /* get a handle */ result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol); if ( !NT_STATUS_IS_OK(result) ) goto done; /* Lookup list of trusted domains */ result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx, &pol, &enum_ctx, &dom_list, (uint32_t)-1); if ( !NT_STATUS_IS_OK(result) ) goto done; *num_domains = dom_list.count; *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains); if (!*domain_names) { result = NT_STATUS_NO_MEMORY; goto done; } *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains); if (!*sids) { result = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i< *num_domains; i++) { (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string); (*sids)[i] = *dom_list.domains[i].sid; } done: /* cleanup */ if (cli) { DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n")); cli_shutdown( cli ); } return NT_STATUS_IS_OK(result); }
/* return our ads connections structure for a domain. We keep the connection open to make things faster */ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) { ADS_STRUCT *ads; ADS_STATUS status; fstring dc_name; struct sockaddr_storage dc_ss; DEBUG(10,("ads_cached_connection\n")); if (domain->private_data) { time_t expire; time_t now = time(NULL); /* check for a valid structure */ ads = (ADS_STRUCT *)domain->private_data; expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire); DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n", (uint32)expire-(uint32)now, (uint32) expire, (uint32) now)); if ( ads->config.realm && (expire > now)) { return ads; } else { /* we own this ADS_STRUCT so make sure it goes away */ DEBUG(7,("Deleting expired krb5 credential cache\n")); ads->is_mine = True; ads_destroy( &ads ); ads_kdestroy("MEMORY:winbind_ccache"); domain->private_data = NULL; } } /* we don't want this to affect the users ccache */ setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1); ads = ads_init(domain->alt_name, domain->name, NULL); if (!ads) { DEBUG(1,("ads_init for domain %s failed\n", domain->name)); return NULL; } /* the machine acct password might have change - fetch it every time */ SAFE_FREE(ads->auth.password); SAFE_FREE(ads->auth.realm); if ( IS_DC ) { if ( !pdb_get_trusteddom_pw( domain->name, &ads->auth.password, NULL, NULL ) ) { ads_destroy( &ads ); return NULL; } ads->auth.realm = SMB_STRDUP( ads->server.realm ); strupper_m( ads->auth.realm ); } else { struct winbindd_domain *our_domain = domain; ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); /* always give preference to the alt_name in our primary domain if possible */ if ( !domain->primary ) our_domain = find_our_domain(); if ( our_domain->alt_name[0] != '\0' ) { ads->auth.realm = SMB_STRDUP( our_domain->alt_name ); strupper_m( ads->auth.realm ); } else ads->auth.realm = SMB_STRDUP( lp_realm() ); } ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME; /* Setup the server affinity cache. We don't reaally care about the name. Just setup affinity and the KRB5_CONFIG file. */ get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ss ); status = ads_connect(ads); if (!ADS_ERR_OK(status) || !ads->config.realm) { DEBUG(1,("ads_connect for domain %s failed: %s\n", domain->name, ads_errstr(status))); ads_destroy(&ads); /* if we get ECONNREFUSED then it might be a NT4 server, fall back to MSRPC */ if (status.error_type == ENUM_ADS_ERROR_SYSTEM && status.err.rc == ECONNREFUSED) { /* 'reconnect_methods' is the MS-RPC backend. */ DEBUG(1,("Trying MSRPC methods\n")); domain->backend = &reconnect_methods; } return NULL; } /* set the flag that says we don't own the memory even though we do so that ads_destroy() won't destroy the structure we pass back by reference */ ads->is_mine = False; domain->private_data = (void *)ads; return ads; }
static bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, char ***domain_names, uint32 *num_domains, struct dom_sid **sids ) { struct policy_handle pol; NTSTATUS status, result; fstring dc_name; struct sockaddr_storage dc_ss; uint32 enum_ctx = 0; struct cli_state *cli = NULL; struct rpc_pipe_client *lsa_pipe = NULL; struct lsa_DomainList dom_list; int i; struct dcerpc_binding_handle *b = NULL; *domain_names = NULL; *num_domains = 0; *sids = NULL; /* lookup a DC first */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) { DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n", domain)); return False; } /* setup the anonymous connection */ status = cli_full_connection( &cli, lp_netbios_name(), dc_name, &dc_ss, 0, "IPC$", "IPC", "", "", "", 0, Undefined); if ( !NT_STATUS_IS_OK(status) ) goto done; /* open the LSARPC_PIPE */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; /* get a handle */ status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol); if ( !NT_STATUS_IS_OK(status) ) goto done; /* Lookup list of trusted domains */ status = dcerpc_lsa_EnumTrustDom(b, mem_ctx, &pol, &enum_ctx, &dom_list, (uint32_t)-1, &result); if ( !NT_STATUS_IS_OK(status) ) goto done; if (!NT_STATUS_IS_OK(result)) { status = result; goto done; } *num_domains = dom_list.count; *domain_names = talloc_zero_array(mem_ctx, char *, *num_domains); if (!*domain_names) { status = NT_STATUS_NO_MEMORY; goto done; } *sids = talloc_zero_array(mem_ctx, struct dom_sid, *num_domains); if (!*sids) { status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i< *num_domains; i++) { (*domain_names)[i] = discard_const_p(char, dom_list.domains[i].name.string); (*sids)[i] = *dom_list.domains[i].sid; } done: /* cleanup */ if (cli) { DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n")); cli_shutdown( cli ); } return NT_STATUS_IS_OK(status); }
NTSTATUS cell_connect(struct likewise_cell *c) { ADS_STRUCT *ads = NULL; ADS_STATUS ads_status; fstring dc_name; struct sockaddr_storage dcip; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; /* have to at least have the AD domain name */ if (!c->dns_domain) { nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; BAIL_ON_NTSTATUS_ERROR(nt_status); } /* clear out any old information */ if (c->conn) { ads_destroy(&c->conn); c->conn = NULL; } /* now setup the new connection */ ads = ads_init(c->dns_domain, NULL, NULL); BAIL_ON_PTR_ERROR(ads, nt_status); ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); ads->auth.realm = SMB_STRDUP(lp_realm()); /* Make the connection. We should already have an initial TGT using the machine creds */ if (cell_flags(c) & LWCELL_FLAG_GC_CELL) { ads_status = ads_connect_gc(ads); } else { /* Set up server affinity for normal cells and the client site name cache */ if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) { nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; BAIL_ON_NTSTATUS_ERROR(nt_status); } ads_status = ads_connect(ads); } c->conn = ads; nt_status = ads_ntstatus(ads_status); done: if (!NT_STATUS_IS_OK(nt_status)) { ads_destroy(&ads); c->conn = NULL; } return nt_status; }
BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, char ***domain_names, uint32 *num_domains, DOM_SID **sids ) { POLICY_HND pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring dc_name; struct in_addr dc_ip; uint32 enum_ctx = 0; struct cli_state *cli = NULL; struct rpc_pipe_client *lsa_pipe; BOOL retry; *domain_names = NULL; *num_domains = 0; *sids = NULL; /* lookup a DC first */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) { DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n", domain)); return False; } /* setup the anonymous connection */ result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", "", "", "", 0, Undefined, &retry); if ( !NT_STATUS_IS_OK(result) ) goto done; /* open the LSARPC_PIPE */ lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result ); if ( !lsa_pipe) { goto done; } /* get a handle */ result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, POLICY_VIEW_LOCAL_INFORMATION, &pol); if ( !NT_STATUS_IS_OK(result) ) goto done; /* Lookup list of trusted domains */ result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx, num_domains, domain_names, sids); if ( !NT_STATUS_IS_OK(result) ) goto done; done: /* cleanup */ if (cli) { DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n")); cli_shutdown( cli ); } return NT_STATUS_IS_OK(result); }
/** * @brief Establish a connection to a DC * * @param[out] adsp ADS_STRUCT that will be created * @param[in] target_realm Realm of domain to connect to * @param[in] target_dom_name 'workgroup' name of domain to connect to * @param[in] ldap_server DNS name of server to connect to * @param[in] password Our machine acount secret * @param[in] auth_realm Realm of local domain for creating krb token * @param[in] renewable Renewable ticket time * * @return ADS_STATUS */ static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp, const char *target_realm, const char *target_dom_name, const char *ldap_server, char *password, char *auth_realm, time_t renewable) { ADS_STRUCT *ads; ADS_STATUS status; struct sockaddr_storage dc_ss; fstring dc_name; if (auth_realm == NULL) { return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); } /* we don't want this to affect the users ccache */ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); ads = ads_init(target_realm, target_dom_name, ldap_server); if (!ads) { DEBUG(1,("ads_init for domain %s failed\n", target_dom_name)); return ADS_ERROR(LDAP_NO_MEMORY); } SAFE_FREE(ads->auth.password); SAFE_FREE(ads->auth.realm); ads->auth.renewable = renewable; ads->auth.password = password; ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP; ads->auth.realm = SMB_STRDUP(auth_realm); if (!strupper_m(ads->auth.realm)) { ads_destroy(&ads); return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR); } /* Setup the server affinity cache. We don't reaally care about the name. Just setup affinity and the KRB5_CONFIG file. */ get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss); status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(1,("ads_connect for domain %s failed: %s\n", target_dom_name, ads_errstr(status))); ads_destroy(&ads); return status; } /* set the flag that says we don't own the memory even though we do so that ads_destroy() won't destroy the structure we pass back by reference */ ads->is_mine = False; *adsp = ads; return status; }
NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u) { uint32 flags = 0x0; uint32 pdc_connection_status = 0x0; uint32 logon_attempts = 0x0; uint32 tc_status; fstring servername, domain, dc_name, dc_name2; struct in_addr dc_ip; /* this should be \\global_myname() */ unistr2_to_ascii(servername, &q_u->uni_server_name, sizeof(servername)); r_u->status = NT_STATUS_OK; tc_status = ERROR_NO_SUCH_DOMAIN; fstrcpy( dc_name, "" ); switch ( q_u->function_code ) { case NETLOGON_CONTROL_TC_QUERY: unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain)); if ( !is_trusted_domain( domain ) ) break; if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) { tc_status = ERROR_NO_LOGON_SERVERS; break; } fstr_sprintf( dc_name, "\\\\%s", dc_name2 ); tc_status = NO_ERROR; break; case NETLOGON_CONTROL_REDISCOVER: unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain)); if ( !is_trusted_domain( domain ) ) break; if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) { tc_status = ERROR_NO_LOGON_SERVERS; break; } fstr_sprintf( dc_name, "\\\\%s", dc_name2 ); tc_status = NO_ERROR; break; default: /* no idea what this should be */ DEBUG(0,("_net_logon_ctrl2: unimplemented function level [%d]\n", q_u->function_code)); } /* prepare the response */ init_net_r_logon_ctrl2( r_u, q_u->query_level, flags, pdc_connection_status, logon_attempts, tc_status, dc_name ); if (lp_server_role() == ROLE_DOMAIN_BDC) send_sync_message(); return r_u->status; }