nsswitch/winbindd_cm.c

ソースコードを見る。

データ構造

struct  dc_name_ip

関数

static NTSTATUS init_dc_connection_network (struct winbindd_domain *domain)
static void set_dc_type_and_flags (struct winbindd_domain *domain)
static BOOL get_dcs (TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, struct dc_name_ip **dcs, int *num_dcs)
static void msg_failed_to_go_online (int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
static void msg_try_to_go_online (int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
static BOOL fork_child_dc_connect (struct winbindd_domain *domain)
static void check_domain_online_handler (struct event_context *ctx, struct timed_event *te, const struct timeval *now, void *private_data)
static void calc_new_online_timeout_check (struct winbindd_domain *domain)
void set_domain_offline (struct winbindd_domain *domain)
static void set_domain_online (struct winbindd_domain *domain)
void set_domain_online_request (struct winbindd_domain *domain)
void winbind_add_failed_connection_entry (const struct winbindd_domain *domain, const char *server, NTSTATUS result)
static void cm_get_ipc_userpass (char **username, char **domain, char **password)
static BOOL get_dc_name_via_netlogon (const struct winbindd_domain *domain, fstring dcname, struct in_addr *dc_ip)
static NTSTATUS get_trust_creds (const struct winbindd_domain *domain, char **machine_password, char **machine_account, char **machine_krb5_principal)
 Helper function to assemble trust password and account name
static NTSTATUS cm_prepare_connection (const struct winbindd_domain *domain, const int sockfd, const char *controller, struct cli_state **cli, BOOL *retry)
static BOOL add_one_dc_unique (TALLOC_CTX *mem_ctx, const char *domain_name, const char *dcname, struct in_addr ip, struct dc_name_ip **dcs, int *num)
static BOOL add_sockaddr_to_array (TALLOC_CTX *mem_ctx, struct in_addr ip, uint16 port, struct sockaddr_in **addrs, int *num)
static void mailslot_name (struct in_addr dc_ip, fstring name)
static BOOL send_getdc_request (struct in_addr dc_ip, const char *domain_name, const DOM_SID *sid)
static BOOL receive_getdc_response (struct in_addr dc_ip, const char *domain_name, fstring dc_name)
static BOOL dcip_to_name (const struct winbindd_domain *domain, struct in_addr ip, fstring name)
static BOOL find_new_dc (TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, fstring dcname, struct sockaddr_in *addr, int *fd)
static NTSTATUS cm_open_connection (struct winbindd_domain *domain, struct winbindd_cm_conn *new_conn)
void invalidate_cm_connection (struct winbindd_cm_conn *conn)
void close_conns_after_fork (void)
static BOOL connection_ok (struct winbindd_domain *domain)
NTSTATUS init_dc_connection (struct winbindd_domain *domain)
static BOOL cm_get_schannel_dcinfo (struct winbindd_domain *domain, struct dcinfo **ppdc)
NTSTATUS cm_connect_sam (struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
NTSTATUS cm_connect_lsa (struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct rpc_pipe_client **cli, POLICY_HND *lsa_policy)
NTSTATUS cm_connect_netlogon (struct winbindd_domain *domain, struct rpc_pipe_client **cli)

変数

winbindd_methods reconnect_methods
BOOL override_logfile


関数

static NTSTATUS init_dc_connection_network ( struct winbindd_domain domain  )  [static]

winbindd_cm.c1543 行で定義されています。

参照先 cm_open_connection()winbindd_domain::connconnection_ok()winbindd_domain::initializedwinbindd_domain::internalinvalidate_cm_connection()resultset_dc_type_and_flags().

参照元 init_dc_connection().

01544 {
01545         NTSTATUS result;
01546 
01547         /* Internal connections never use the network. */
01548         if (domain->internal) {
01549                 domain->initialized = True;
01550                 return NT_STATUS_OK;
01551         }
01552 
01553         if (connection_ok(domain)) {
01554                 if (!domain->initialized) {
01555                         set_dc_type_and_flags(domain);
01556                 }
01557                 return NT_STATUS_OK;
01558         }
01559 
01560         invalidate_cm_connection(&domain->conn);
01561 
01562         result = cm_open_connection(domain, &domain->conn);
01563 
01564         if (NT_STATUS_IS_OK(result) && !domain->initialized) {
01565                 set_dc_type_and_flags(domain);
01566         }
01567 
01568         return result;
01569 }

static void set_dc_type_and_flags ( struct winbindd_domain domain  )  [static]

winbindd_cm.c1589 行で定義されています。

参照先 DS_DOMINFO_CTR::basicclicli_rpc_pipe_close()cli_rpc_pipe_open_noauth()connection_ok()rpc_pipe_client::domaindomain_nameDSROLE_PRIMARY_DOMAIN_INFO_BASIC::flagscli_state::mem_ctxnt_errstr()polresultrpccli_ds_getprimarydominfo()rpccli_lsa_open_policy()rpccli_lsa_open_policy2()rpccli_lsa_query_info_policy()rpccli_lsa_query_info_policy2()sid_copy()talloc_init().

参照元 init_dc_connection_network().

01590 {
01591         NTSTATUS                result;
01592         DS_DOMINFO_CTR          ctr;
01593         TALLOC_CTX              *mem_ctx = NULL;
01594         struct rpc_pipe_client  *cli;
01595         POLICY_HND pol;
01596 
01597         char *domain_name = NULL;
01598         char *dns_name = NULL;
01599         char *forest_name = NULL;       
01600         DOM_SID *dom_sid = NULL;        
01601 
01602         ZERO_STRUCT( ctr );
01603         
01604         if (!connection_ok(domain)) {
01605                 return;
01606         }
01607 
01608         DEBUG(5, ("set_dc_type_and_flags: domain %s\n", domain->name ));
01609 
01610         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
01611                                        &result);
01612 
01613         if (cli == NULL) {
01614                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
01615                           "PI_LSARPC_DS on domain %s: (%s)\n",
01616                           domain->name, nt_errstr(result)));
01617 
01618                 /* if this is just a non-AD domain we need to continue
01619                  * identifying so that we can in the end return with
01620                  * domain->initialized = True - gd */
01621 
01622                 goto no_lsarpc_ds;
01623         }
01624 
01625         result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
01626                                              DsRolePrimaryDomainInfoBasic,
01627                                              &ctr);
01628         cli_rpc_pipe_close(cli);
01629 
01630         if (!NT_STATUS_IS_OK(result)) {
01631                 DEBUG(5, ("set_dc_type_and_flags: rpccli_ds_getprimarydominfo "
01632                           "on domain %s failed: (%s)\n",
01633                           domain->name, nt_errstr(result)));
01634 
01635                 /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
01636                  * every opcode on the LSARPC_DS pipe, continue with
01637                  * no_lsarpc_ds mode here as well to get domain->initialized
01638                  * set - gd */
01639 
01640                 if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
01641                         goto no_lsarpc_ds;
01642                 }
01643 
01644                 return;
01645         }
01646         
01647         if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
01648             !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
01649                 domain->native_mode = True;
01650         } else {
01651                 domain->native_mode = False;
01652         }
01653 
01654 no_lsarpc_ds:
01655         cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
01656 
01657         if (cli == NULL) {
01658                 DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
01659                           "PI_LSARPC on domain %s: (%s)\n",
01660                           domain->name, nt_errstr(result)));
01661                 cli_rpc_pipe_close(cli);
01662                 return;
01663         }
01664 
01665         mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n",
01666                               domain->name);
01667         if (!mem_ctx) {
01668                 DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
01669                 cli_rpc_pipe_close(cli);
01670                 return;
01671         }
01672 
01673         result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
01674                                          SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
01675                 
01676         if (NT_STATUS_IS_OK(result)) {
01677                 /* This particular query is exactly what Win2k clients use 
01678                    to determine that the DC is active directory */
01679                 result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
01680                                                        12, &domain_name,
01681                                                        &dns_name, &forest_name,
01682                                                        NULL, &dom_sid);
01683         }
01684 
01685         if (NT_STATUS_IS_OK(result)) {
01686                 domain->active_directory = True;
01687 
01688                 if (domain_name)
01689                         fstrcpy(domain->name, domain_name);
01690 
01691                 if (dns_name)
01692                         fstrcpy(domain->alt_name, dns_name);
01693 
01694                 if ( forest_name )
01695                         fstrcpy(domain->forest_name, forest_name);              
01696 
01697                 if (dom_sid) 
01698                         sid_copy(&domain->sid, dom_sid);
01699         } else {
01700                 domain->active_directory = False;
01701 
01702                 result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
01703                                                 SEC_RIGHTS_MAXIMUM_ALLOWED,
01704                                                 &pol);
01705                         
01706                 if (!NT_STATUS_IS_OK(result))
01707                         goto done;
01708                         
01709                 result = rpccli_lsa_query_info_policy(cli, mem_ctx, 
01710                                                       &pol, 5, &domain_name, 
01711                                                       &dom_sid);
01712                         
01713                 if (NT_STATUS_IS_OK(result)) {
01714                         if (domain_name)
01715                                 fstrcpy(domain->name, domain_name);
01716 
01717                         if (dom_sid) 
01718                                 sid_copy(&domain->sid, dom_sid);
01719                 }
01720         }
01721 done:
01722 
01723         DEBUG(5, ("set_dc_type_and_flags: domain %s is %sin native mode.\n",
01724                   domain->name, domain->native_mode ? "" : "NOT "));
01725 
01726         DEBUG(5,("set_dc_type_and_flags: domain %s is %srunning active directory.\n",
01727                   domain->name, domain->active_directory ? "" : "NOT "));
01728 
01729         cli_rpc_pipe_close(cli);
01730         
01731         talloc_destroy(mem_ctx);
01732 
01733         domain->initialized = True;
01734 }

static BOOL get_dcs ( TALLOC_CTX mem_ctx,
const struct winbindd_domain domain,
struct dc_name_ip **  dcs,
int *  num_dcs 
) [static]

winbindd_cm.c1155 行で定義されています。

参照先 add_one_dc_unique()winbindd_domain::alt_nameget_dc_name()get_dc_name_via_netlogon()get_sorted_dc_list()lp_workgroup()winbindd_domain::nameSEC_ADSsitename_fetch()strequal().

参照元 find_new_dc()fork_child_dc_connect().

01157 {
01158         fstring dcname;
01159         struct  in_addr ip;
01160         struct  ip_service *ip_list = NULL;
01161         int     iplist_size = 0;
01162         int     i;
01163         BOOL    is_our_domain;
01164         enum security_types sec = (enum security_types)lp_security();
01165 
01166         is_our_domain = strequal(domain->name, lp_workgroup());
01167 
01168         if ( !is_our_domain 
01169                 && get_dc_name_via_netlogon(domain, dcname, &ip) 
01170                 && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
01171         {
01172                 DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
01173                            dcname, inet_ntoa(ip)));
01174                 return True;
01175         }
01176 
01177         if (sec == SEC_ADS) {
01178                 char *sitename = NULL;
01179 
01180                 /* We need to make sure we know the local site before
01181                    doing any DNS queries, as this will restrict the
01182                    get_sorted_dc_list() call below to only fetching
01183                    DNS records for the correct site. */
01184 
01185                 /* Find any DC to get the site record.
01186                    We deliberately don't care about the
01187                    return here. */
01188 
01189                 get_dc_name(domain->name, domain->alt_name, dcname, &ip);
01190 
01191                 sitename = sitename_fetch(domain->alt_name);
01192                 if (sitename) {
01193 
01194                         /* Do the site-specific AD dns lookup first. */
01195                         get_sorted_dc_list(domain->alt_name, sitename, &ip_list, &iplist_size, True);
01196 
01197                         for ( i=0; i<iplist_size; i++ ) {
01198                                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
01199                                                         ip_list[i].ip, dcs, num_dcs);
01200                         }
01201 
01202                         SAFE_FREE(ip_list);
01203                         SAFE_FREE(sitename);
01204                         iplist_size = 0;
01205                 }
01206 
01207                 /* Now we add DCs from the main AD dns lookup. */
01208                 get_sorted_dc_list(domain->alt_name, NULL, &ip_list, &iplist_size, True);
01209 
01210                 for ( i=0; i<iplist_size; i++ ) {
01211                         add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
01212                                                 ip_list[i].ip, dcs, num_dcs);
01213                 }
01214         }
01215 
01216         /* try standard netbios queries if no ADS */
01217 
01218         if (iplist_size==0) {
01219                 get_sorted_dc_list(domain->name, NULL, &ip_list, &iplist_size, False);
01220         }
01221 
01222         /* FIXME!! this is where we should re-insert the GETDC requests --jerry */
01223 
01224         /* now add to the dc array.  We'll wait until the last minute 
01225            to look up the name of the DC.  But we fill in the char* for 
01226            the ip now in to make the failed connection cache work */
01227 
01228         for ( i=0; i<iplist_size; i++ ) {
01229                 add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip), 
01230                         ip_list[i].ip, dcs, num_dcs);
01231         }
01232 
01233         SAFE_FREE( ip_list );
01234 
01235         return True;
01236 }

static void msg_failed_to_go_online ( int  msg_type,
struct process_id  src,
void *  buf,
size_t  len,
void *  private_data 
) [static]

winbindd_cm.c85 行で定義されています。

参照先 domain_list()winbindd_domain::internalwinbindd_domain::namewinbindd_domain::nextwinbindd_domain::onlinestrequal().

参照元 fork_child_dc_connect().

00087 {
00088         struct winbindd_domain *domain;
00089         const char *domainname = (const char *)buf;
00090 
00091         if (buf == NULL || len == 0) {
00092                 return;
00093         }
00094 
00095         DEBUG(5,("msg_fail_to_go_online: received for domain %s.\n", domainname));
00096 
00097         for (domain = domain_list(); domain; domain = domain->next) {
00098                 if (domain->internal) {
00099                         continue;
00100                 }
00101 
00102                 if (strequal(domain->name, domainname)) {
00103                         if (domain->online) {
00104                                 /* We're already online, ignore. */
00105                                 DEBUG(5,("msg_fail_to_go_online: domain %s "
00106                                         "already online.\n", domainname));
00107                                 continue;
00108                         }
00109 
00110                         /* Reschedule the online check. */
00111                         set_domain_offline(domain);
00112                         break;
00113                 }
00114         }
00115 }

static void msg_try_to_go_online ( int  msg_type,
struct process_id  src,
void *  buf,
size_t  len,
void *  private_data 
) [static]

winbindd_cm.c121 行で定義されています。

参照先 domain_list()winbindd_domain::internalwinbindd_domain::namewinbindd_domain::nextwinbindd_domain::onlinestrequal().

参照元 fork_child_dc_connect().

00123 {
00124         struct winbindd_domain *domain;
00125         const char *domainname = (const char *)buf;
00126 
00127         if (buf == NULL || len == 0) {
00128                 return;
00129         }
00130 
00131         DEBUG(5,("msg_try_to_go_online: received for domain %s.\n", domainname));
00132 
00133         for (domain = domain_list(); domain; domain = domain->next) {
00134                 if (domain->internal) {
00135                         continue;
00136                 }
00137 
00138                 if (strequal(domain->name, domainname)) {
00139 
00140                         if (domain->online) {
00141                                 /* We're already online, ignore. */
00142                                 DEBUG(5,("msg_try_to_go_online: domain %s "
00143                                         "already online.\n", domainname));
00144                                 continue;
00145                         }
00146 
00147                         /* This call takes care of setting the online
00148                            flag to true if we connected, or re-adding
00149                            the offline handler if false. Bypasses online
00150                            check so always does network calls. */
00151 
00152                         init_dc_connection_network(domain);
00153                         break;
00154                 }
00155         }
00156 }

static BOOL fork_child_dc_connect ( struct winbindd_domain domain  )  [static]

winbindd_cm.c164 行で定義されています。

参照先 CatchChild()close_conns_after_fork()dyn_LOGFILEBASEerrnoget_dcs()message_block()message_register()message_send_pid()message_unblock()msg_failed_to_go_online()msg_try_to_go_online()winbindd_domain::nameoverride_logfilepid_to_procid()pstr_sprintf()reopen_logs()strerror()sys_fork()sys_getpid()talloc_init()tdb_reopen_all().

参照元 check_domain_online_handler().

00165 {
00166         struct dc_name_ip *dcs = NULL;
00167         int num_dcs = 0;
00168         TALLOC_CTX *mem_ctx = NULL;
00169         pid_t child_pid;
00170         pid_t parent_pid = sys_getpid();
00171 
00172         /* Stop zombies */
00173         CatchChild();
00174 
00175         message_block();
00176 
00177         child_pid = sys_fork();
00178 
00179         if (child_pid == -1) {
00180                 DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno)));
00181                 message_unblock();
00182                 return False;
00183         }
00184 
00185         if (child_pid != 0) {
00186                 /* Parent */
00187                 message_register(MSG_WINBIND_TRY_TO_GO_ONLINE,
00188                                  msg_try_to_go_online, NULL);
00189                 message_register(MSG_WINBIND_FAILED_TO_GO_ONLINE,
00190                                  msg_failed_to_go_online, NULL);
00191                 message_unblock();
00192                 return True;
00193         }
00194 
00195         /* Child. */
00196 
00197         /* Leave messages blocked - we will never process one. */
00198 
00199         /* tdb needs special fork handling */
00200         if (tdb_reopen_all(1) == -1) {
00201                 DEBUG(0,("tdb_reopen_all failed.\n"));
00202                 _exit(0);
00203         }
00204 
00205         close_conns_after_fork();
00206 
00207         if (!override_logfile) {
00208                 pstring logfile;
00209                 pstr_sprintf(logfile, "%s/winbindd-dc-connect.log", dyn_LOGFILEBASE);
00210                 lp_set_logfile(logfile);
00211                 reopen_logs();
00212         }
00213 
00214         mem_ctx = talloc_init("fork_child_dc_connect");
00215         if (!mem_ctx) {
00216                 DEBUG(0,("talloc_init failed.\n"));
00217                 _exit(0);
00218         }
00219 
00220         if ((!get_dcs(mem_ctx, domain, &dcs, &num_dcs)) || (num_dcs == 0)) {
00221                 /* Still offline ? Can't find DC's. */
00222                 message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_FAILED_TO_GO_ONLINE,
00223                                 domain->name,
00224                                 strlen(domain->name)+1, False);
00225                 _exit(0);
00226         }
00227 
00228         /* We got a DC. Send a message to our parent to get it to
00229            try and do the same. */
00230 
00231         message_send_pid(pid_to_procid(parent_pid), MSG_WINBIND_TRY_TO_GO_ONLINE,
00232                                 domain->name,
00233                                 strlen(domain->name)+1, False);
00234         _exit(0);
00235 }

static void check_domain_online_handler ( struct event_context ctx,
struct timed_event te,
const struct timeval *  now,
void *  private_data 
) [static]

winbindd_cm.c241 行で定義されています。

参照先 winbindd_domain::check_online_eventfork_child_dc_connect()get_global_winbindd_state_offline()winbindd_domain::namewinbindd_domain::startupwinbindd_domain::startup_time.

参照元 set_domain_offline()set_domain_online_request().

00245 {
00246         struct winbindd_domain *domain =
00247                 (struct winbindd_domain *)private_data;
00248 
00249         DEBUG(10,("check_domain_online_handler: called for domain %s\n",
00250                 domain->name ));
00251 
00252         TALLOC_FREE(domain->check_online_event);
00253 
00254         /* Are we still in "startup" mode ? */
00255 
00256         if (domain->startup && (now->tv_sec > domain->startup_time + 30)) {
00257                 /* No longer in "startup" mode. */
00258                 DEBUG(10,("check_domain_online_handler: domain %s no longer in 'startup' mode.\n",
00259                         domain->name ));
00260                 domain->startup = False;
00261         }
00262 
00263         /* We've been told to stay offline, so stay
00264            that way. */
00265 
00266         if (get_global_winbindd_state_offline()) {
00267                 DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
00268                         domain->name ));
00269                 return;
00270         }
00271 
00272         /* Fork a child to test if it can contact a DC. 
00273            If it can then send ourselves a message to
00274            cause a reconnect. */
00275 
00276         fork_child_dc_connect(domain);
00277 }

static void calc_new_online_timeout_check ( struct winbindd_domain domain  )  [static]

winbindd_cm.c283 行で定義されています。

参照先 winbindd_domain::check_online_timeoutwinbindd_domain::startup.

参照元 set_domain_offline().

00284 {
00285         int wbc = lp_winbind_cache_time();
00286 
00287         if (domain->startup) {
00288                 domain->check_online_timeout = 10;
00289         } else if (domain->check_online_timeout < wbc) {
00290                 domain->check_online_timeout = wbc;
00291         }
00292 }

void set_domain_offline ( struct winbindd_domain domain  ) 

winbindd_cm.c299 行で定義されています。

参照先 calc_new_online_timeout_check()check_domain_online_handler()winbindd_domain::check_online_eventwinbindd_domain::check_online_timeoutevent_add_timed()get_global_winbindd_state_offline()winbindd_domain::initializedwinbindd_domain::internalwinbindd_domain::namewinbindd_domain::onlinesmb_panic()timeval_current_ofs()winbind_event_context().

参照元 child_msg_offline()cm_open_connection()winbind_msg_offline()winbindd_dual_pam_auth().

00300 {
00301         DEBUG(10,("set_domain_offline: called for domain %s\n",
00302                 domain->name ));
00303 
00304         TALLOC_FREE(domain->check_online_event);
00305 
00306         if (domain->internal) {
00307                 DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
00308                         domain->name ));
00309                 return;
00310         }
00311 
00312         domain->online = False;
00313 
00314         /* Offline domains are always initialized. They're
00315            re-initialized when they go back online. */
00316 
00317         domain->initialized = True;
00318 
00319         /* We only add the timeout handler that checks and
00320            allows us to go back online when we've not
00321            been told to remain offline. */
00322 
00323         if (get_global_winbindd_state_offline()) {
00324                 DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
00325                         domain->name ));
00326                 return;
00327         }
00328 
00329         /* If we're in statup mode, check again in 10 seconds, not in
00330            lp_winbind_cache_time() seconds (which is 5 mins by default). */
00331 
00332         calc_new_online_timeout_check(domain);
00333 
00334         domain->check_online_event = event_add_timed(winbind_event_context(),
00335                                                 NULL,
00336                                                 timeval_current_ofs(domain->check_online_timeout,0),
00337                                                 "check_domain_online_handler",
00338                                                 check_domain_online_handler,
00339                                                 domain);
00340 
00341         /* The above *has* to succeed for winbindd to work. */
00342         if (!domain->check_online_event) {
00343                 smb_panic("set_domain_offline: failed to add online handler.\n");
00344         }
00345 
00346         DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
00347                 domain->name ));
00348 }

static void set_domain_online ( struct winbindd_domain domain  )  [static]

winbindd_cm.c354 行で定義されています。

参照先 winbindd_domain::backendwinbindd_domain::check_online_eventwinbindd_domain::check_online_timeoutget_global_winbindd_state_offline()GetTimeOfDay()winbindd_domain::initializedwinbindd_domain::internalmessage_deregister()winbindd_domain::namewinbindd_domain::onlinereconnect_methodsset_event_dispatch_time()winbindd_domain::startupwinbind_event_context().

参照元 cm_open_connection().

00355 {
00356         struct timeval now;
00357 
00358         DEBUG(10,("set_domain_online: called for domain %s\n",
00359                 domain->name ));
00360 
00361         if (domain->internal) {
00362                 DEBUG(3,("set_domain_online: domain %s is internal - logic error.\n",
00363                         domain->name ));
00364                 return;
00365         }
00366 
00367         if (get_global_winbindd_state_offline()) {
00368                 DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
00369                         domain->name ));
00370                 return;
00371         }
00372 
00373         /* If we are waiting to get a krb5 ticket, trigger immediately. */
00374         GetTimeOfDay(&now);
00375         set_event_dispatch_time(winbind_event_context(),
00376                                 "krb5_ticket_gain_handler", now);
00377 
00378         /* Ok, we're out of any startup mode now... */
00379         domain->startup = False;
00380 
00381         if (domain->online == False) {
00382                 /* We were offline - now we're online. We default to
00383                    using the MS-RPC backend if we started offline,
00384                    and if we're going online for the first time we
00385                    should really re-initialize the backends and the
00386                    checks to see if we're talking to an AD or NT domain.
00387                 */
00388 
00389                 domain->initialized = False;
00390 
00391                 /* 'reconnect_methods' is the MS-RPC backend. */
00392                 if (domain->backend == &reconnect_methods) {
00393                         domain->backend = NULL;
00394                 }
00395         }
00396 
00397         /* Ensure we have no online timeout checks. */
00398         domain->check_online_timeout = 0;
00399         TALLOC_FREE(domain->check_online_event);
00400 
00401         /* Ensure we ignore any pending child messages. */
00402         message_deregister(MSG_WINBIND_TRY_TO_GO_ONLINE);
00403         message_deregister(MSG_WINBIND_FAILED_TO_GO_ONLINE);
00404 
00405         domain->online = True;
00406 }

void set_domain_online_request ( struct winbindd_domain domain  ) 

winbindd_cm.c412 行で定義されています。

参照先 check_domain_online_handler()winbindd_domain::check_online_eventevent_add_timed()get_global_winbindd_state_offline()GetTimeOfDay()winbindd_domain::nameset_event_dispatch_time()smb_panic()winbindd_domain::startupwinbindd_domain::startup_timetimeval_current_ofs()winbind_event_context().

参照元 child_msg_online()init_domain_list()winbind_msg_online().

00413 {
00414         struct timeval tev;
00415 
00416         DEBUG(10,("set_domain_online_request: called for domain %s\n",
00417                 domain->name ));
00418 
00419         if (get_global_winbindd_state_offline()) {
00420                 DEBUG(10,("set_domain_online_request: domain %s remaining globally offline\n",
00421                         domain->name ));
00422                 return;
00423         }
00424 
00425         /* We've been told it's safe to go online and
00426            try and connect to a DC. But I don't believe it
00427            because network manager seems to lie.
00428            Wait at least 5 seconds. Heuristics suck... */
00429 
00430         if (!domain->check_online_event) {
00431                 /* If we've come from being globally offline we
00432                    don't have a check online event handler set.
00433                    We need to add one now we're trying to go
00434                    back online. */
00435 
00436                 DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
00437                         domain->name ));
00438 
00439                 domain->check_online_event = event_add_timed(winbind_event_context(),
00440                                                                 NULL,
00441                                                                 timeval_current_ofs(5, 0),
00442                                                                 "check_domain_online_handler",
00443                                                                 check_domain_online_handler,
00444                                                                 domain);
00445 
00446                 /* The above *has* to succeed for winbindd to work. */
00447                 if (!domain->check_online_event) {
00448                         smb_panic("set_domain_online_request: failed to add online handler.\n");
00449                 }
00450         }
00451 
00452         GetTimeOfDay(&tev);
00453 
00454         /* Go into "startup" mode again. */
00455         domain->startup_time = tev.tv_sec;
00456         domain->startup = True;
00457 
00458         tev.tv_sec += 5;
00459 
00460         set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
00461 }

void winbind_add_failed_connection_entry ( const struct winbindd_domain domain,
const char *  server,
NTSTATUS  result 
)

winbindd_cm.c467 行で定義されています。

参照先 add_failed_connection_entry()winbindd_domain::alt_namewinbindd_domain::nameresultsaf_delete().

参照元 cm_open_connection()cm_prepare_connection()find_new_dc().

00470 {
00471         add_failed_connection_entry(domain->name, server, result);
00472         /* If this was the saf name for the last thing we talked to,
00473            remove it. */
00474         saf_delete(domain->name);
00475         if (*domain->alt_name) {
00476                 add_failed_connection_entry(domain->alt_name, server, result);
00477                 saf_delete(domain->alt_name);
00478         }
00479 }

static void cm_get_ipc_userpass ( char **  username,
char **  domain,
char **  password 
) [static]

winbindd_cm.c489 行で定義されています。

参照先 lp_workgroup()secrets_fetch()smb_xstrdup().

参照元 cm_prepare_connection().

00490 {
00491         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
00492         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
00493         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
00494         
00495         if (*username && **username) {
00496 
00497                 if (!*domain || !**domain)
00498                         *domain = smb_xstrdup(lp_workgroup());
00499                 
00500                 if (!*password || !**password)
00501                         *password = smb_xstrdup("");
00502 
00503                 DEBUG(3, ("cm_get_ipc_userpass: Retrieved auth-user from secrets.tdb [%s\\%s]\n", 
00504                           *domain, *username));
00505 
00506         } else {
00507                 DEBUG(3, ("cm_get_ipc_userpass: No auth-user defined\n"));
00508                 *username = smb_xstrdup("");
00509                 *domain = smb_xstrdup("");
00510                 *password = smb_xstrdup("");
00511         }
00512 }

static BOOL get_dc_name_via_netlogon ( const struct winbindd_domain domain,
fstring  dcname,
struct in_addr *  dc_ip 
) [static]

winbindd_cm.c514 行で定義されています。

参照先 rpc_pipe_client::clicli_set_timeout()cm_connect_netlogon()winbindd_domain::dcnamerpc_pipe_client::domaindos_errstr()find_our_domain()rpc_pipe_client::mem_ctxresolve_name()resultrpccli_netlogon_getanydcname()talloc_init().

参照元 get_dcs().

00516 {
00517         struct winbindd_domain *our_domain = NULL;
00518         struct rpc_pipe_client *netlogon_pipe = NULL;
00519         NTSTATUS result;
00520         WERROR werr;
00521         TALLOC_CTX *mem_ctx;
00522         unsigned int orig_timeout;
00523         fstring tmp;
00524         char *p;
00525 
00526         /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
00527          * moment.... */
00528 
00529         if (IS_DC) {
00530                 return False;
00531         }
00532 
00533         if (domain->primary) {
00534                 return False;
00535         }
00536 
00537         our_domain = find_our_domain();
00538 
00539         if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
00540                 return False;
00541         }
00542 
00543         result = cm_connect_netlogon(our_domain, &netlogon_pipe);
00544         if (!NT_STATUS_IS_OK(result)) {
00545                 talloc_destroy(mem_ctx);
00546                 return False;
00547         }
00548 
00549         /* This call can take a long time - allow the server to time out.
00550            35 seconds should do it. */
00551 
00552         orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
00553         
00554         werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
00555                                             domain->name, tmp);
00556 
00557         /* And restore our original timeout. */
00558         cli_set_timeout(netlogon_pipe->cli, orig_timeout);
00559 
00560         talloc_destroy(mem_ctx);
00561 
00562         if (!W_ERROR_IS_OK(werr)) {
00563                 DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
00564                            dos_errstr(werr)));
00565                 return False;
00566         }
00567 
00568         /* cli_netlogon_getanydcname gives us a name with \\ */
00569         p = tmp;
00570         if (*p == '\\') {
00571                 p+=1;
00572         }
00573         if (*p == '\\') {
00574                 p+=1;
00575         }
00576 
00577         fstrcpy(dcname, p);
00578 
00579         DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
00580 
00581         if (!resolve_name(dcname, dc_ip, 0x20)) {
00582                 return False;
00583         }
00584 
00585         return True;
00586 }

static NTSTATUS get_trust_creds ( const struct winbindd_domain domain,
char **  machine_password,
char **  machine_account,
char **  machine_krb5_principal 
) [static]

Helper function to assemble trust password and account name

winbindd_cm.c591 行で定義されています。

参照先 asprintf()rpc_pipe_client::domainget_trust_pw_clear()strupper_m().

参照元 cm_connect_sam()cm_prepare_connection().

00595 {
00596         const char *account_name;
00597 
00598         if (!get_trust_pw_clear(domain->name, machine_password,
00599                                 &account_name, NULL))
00600         {
00601                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
00602         }
00603 
00604         if ((machine_account != NULL) &&
00605             (asprintf(machine_account, "%s$", account_name) == -1))
00606         {
00607                 return NT_STATUS_NO_MEMORY;
00608         }
00609 
00610         /* For now assume our machine account only exists in our domain */
00611 
00612         if (machine_krb5_principal != NULL)
00613         {
00614                 if (asprintf(machine_krb5_principal, "%s$@%s",
00615                              account_name, lp_realm()) == -1)
00616                 {
00617                         return NT_STATUS_NO_MEMORY;
00618                 }
00619 
00620                 strupper_m(*machine_krb5_principal);
00621         }
00622 
00623         return NT_STATUS_OK;
00624 }

static NTSTATUS cm_prepare_connection ( const struct winbindd_domain domain,
const int  sockfd,
const char *  controller,
struct cli_state **  cli,
BOOL retry 
) [static]

winbindd_cm.c631 行で定義されています。

参照先 ads_errstr()ads_ntstatus()winbindd_domain::alt_nameclicli_init_creds()cli_initialise()cli_negprot()cli_nt_error()cli_send_tconX()cli_session_request()cli_session_setup()cli_session_setup_spnego()cli_setup_signing_state()cli_shutdown()cm_get_ipc_userpass()errnoget_trust_creds()global_mynameis_trusted_domain_situation()lp_workgroup()make_nmb_name()winbindd_domain::nament_errstr()PROTOCOL_NT1resultsaf_store()SEC_ADSsecrets_named_mutex()secrets_named_mutex_release()strerror()winbind_add_failed_connection_entry().

参照元 cm_open_connection().

00636 {
00637         char *machine_password = NULL;
00638         char *machine_krb5_principal = NULL;
00639         char *machine_account = NULL;
00640         char *ipc_username = NULL;
00641         char *ipc_domain = NULL;
00642         char *ipc_password = NULL;
00643 
00644         BOOL got_mutex;
00645 
00646         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00647 
00648         struct sockaddr peeraddr;
00649         socklen_t peeraddr_len;
00650 
00651         struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;
00652 
00653         DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
00654                 controller, domain->name ));
00655 
00656         *retry = True;
00657 
00658         got_mutex = secrets_named_mutex(controller,
00659                                         WINBIND_SERVER_MUTEX_WAIT_TIME);
00660 
00661         if (!got_mutex) {
00662                 DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
00663                          controller));
00664                 result = NT_STATUS_POSSIBLE_DEADLOCK;
00665                 goto done;
00666         }
00667 
00668         if ((*cli = cli_initialise()) == NULL) {
00669                 DEBUG(1, ("Could not cli_initialize\n"));
00670                 result = NT_STATUS_NO_MEMORY;
00671                 goto done;
00672         }
00673 
00674         (*cli)->timeout = 10000;        /* 10 seconds */
00675         (*cli)->fd = sockfd;
00676         fstrcpy((*cli)->desthost, controller);
00677         (*cli)->use_kerberos = True;
00678 
00679         peeraddr_len = sizeof(peeraddr);
00680 
00681         if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
00682             (peeraddr_len != sizeof(struct sockaddr_in)) ||
00683             (peeraddr_in->sin_family != PF_INET))
00684         {
00685                 DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
00686                 result = NT_STATUS_UNSUCCESSFUL;
00687                 goto done;
00688         }
00689 
00690         if (ntohs(peeraddr_in->sin_port) == 139) {
00691                 struct nmb_name calling;
00692                 struct nmb_name called;
00693 
00694                 make_nmb_name(&calling, global_myname(), 0x0);
00695                 make_nmb_name(&called, "*SMBSERVER", 0x20);
00696 
00697                 if (!cli_session_request(*cli, &calling, &called)) {
00698                         DEBUG(8, ("cli_session_request failed for %s\n",
00699                                   controller));
00700                         result = NT_STATUS_UNSUCCESSFUL;
00701                         goto done;
00702                 }
00703         }
00704 
00705         cli_setup_signing_state(*cli, Undefined);
00706 
00707         if (!cli_negprot(*cli)) {
00708                 DEBUG(1, ("cli_negprot failed\n"));
00709                 result = NT_STATUS_UNSUCCESSFUL;
00710                 goto done;
00711         }
00712 
00713         if (!is_trusted_domain_situation(domain->name) &&
00714             (*cli)->protocol >= PROTOCOL_NT1 &&
00715             (*cli)->capabilities & CAP_EXTENDED_SECURITY)
00716         {
00717                 ADS_STATUS ads_status;
00718 
00719                 result = get_trust_creds(domain, &machine_password,
00720                                          &machine_account,
00721                                          &machine_krb5_principal);
00722                 if (!NT_STATUS_IS_OK(result)) {
00723                         goto anon_fallback;
00724                 }
00725 
00726                 if (lp_security() == SEC_ADS) {
00727 
00728                         /* Try a krb5 session */
00729 
00730                         (*cli)->use_kerberos = True;
00731                         DEBUG(5, ("connecting to %s from %s with kerberos principal "
00732                                   "[%s] and realm [%s]\n", controller, global_myname(),
00733                                   machine_krb5_principal, domain->alt_name));
00734 
00735                         ads_status = cli_session_setup_spnego(*cli,
00736                                                               machine_krb5_principal, 
00737                                                               machine_password, 
00738                                                               lp_workgroup(),
00739                                                               domain->alt_name);
00740 
00741                         if (!ADS_ERR_OK(ads_status)) {
00742                                 DEBUG(4,("failed kerberos session setup with %s\n",
00743                                          ads_errstr(ads_status)));
00744                         }
00745 
00746                         result = ads_ntstatus(ads_status);
00747                         if (NT_STATUS_IS_OK(result)) {
00748                                 /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
00749                                 cli_init_creds(*cli, machine_account, domain->name, machine_password);
00750                                 goto session_setup_done;
00751                         }
00752                 }
00753 
00754                 /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
00755                 (*cli)->use_kerberos = False;
00756 
00757                 DEBUG(5, ("connecting to %s from %s with username "
00758                           "[%s]\\[%s]\n",  controller, global_myname(),
00759                           lp_workgroup(), machine_account));
00760 
00761                 ads_status = cli_session_setup_spnego(*cli,
00762                                                       machine_account, 
00763                                                       machine_password, 
00764                                                       lp_workgroup(),
00765                                                       NULL);
00766                 if (!ADS_ERR_OK(ads_status)) {
00767                         DEBUG(4, ("authenticated session setup failed with %s\n",
00768                                 ads_errstr(ads_status)));
00769                 }
00770 
00771                 result = ads_ntstatus(ads_status);
00772                 if (NT_STATUS_IS_OK(result)) {
00773                         /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
00774                         cli_init_creds(*cli, machine_account, domain->name, machine_password);
00775                         goto session_setup_done;
00776                 }
00777         }
00778 
00779         /* Fall back to non-kerberos session setup with auth_user */
00780 
00781         (*cli)->use_kerberos = False;
00782 
00783         cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
00784 
00785         if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
00786             (strlen(ipc_username) > 0)) {
00787 
00788                 /* Only try authenticated if we have a username */
00789 
00790                 DEBUG(5, ("connecting to %s from %s with username "
00791                           "[%s]\\[%s]\n",  controller, global_myname(),
00792                           ipc_domain, ipc_username));
00793 
00794                 if (NT_STATUS_IS_OK(cli_session_setup(
00795                                             *cli, ipc_username,
00796                                             ipc_password, strlen(ipc_password)+1,
00797                                             ipc_password, strlen(ipc_password)+1,
00798                                             ipc_domain))) {
00799                         /* Successful logon with given username. */
00800                         cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
00801                         goto session_setup_done;
00802                 } else {
00803                         DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
00804                                 ipc_domain, ipc_username ));
00805                 }
00806         }
00807 
00808  anon_fallback:
00809 
00810         /* Fall back to anonymous connection, this might fail later */
00811 
00812         if (NT_STATUS_IS_OK(cli_session_setup(*cli, "", NULL, 0,
00813                                               NULL, 0, ""))) {
00814                 DEBUG(5, ("Connected anonymously\n"));
00815                 cli_init_creds(*cli, "", "", "");
00816                 goto session_setup_done;
00817         }
00818 
00819         result = cli_nt_error(*cli);
00820 
00821         if (NT_STATUS_IS_OK(result))
00822                 result = NT_STATUS_UNSUCCESSFUL;
00823 
00824         /* We can't session setup */
00825 
00826         goto done;
00827 
00828  session_setup_done:
00829 
00830         /* cache the server name for later connections */
00831 
00832         saf_store( domain->name, (*cli)->desthost );
00833         if (domain->alt_name && (*cli)->use_kerberos) {
00834                 saf_store( domain->alt_name, (*cli)->desthost );
00835         }
00836 
00837         if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
00838 
00839                 result = cli_nt_error(*cli);
00840 
00841                 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
00842 
00843                 if (NT_STATUS_IS_OK(result))
00844                         result = NT_STATUS_UNSUCCESSFUL;
00845 
00846                 goto done;
00847         }
00848 
00849         secrets_named_mutex_release(controller);
00850         got_mutex = False;
00851         *retry = False;
00852 
00853         /* set the domain if empty; needed for schannel connections */
00854         if ( !*(*cli)->domain ) {
00855                 fstrcpy( (*cli)->domain, domain->name );
00856         }
00857 
00858         result = NT_STATUS_OK;
00859 
00860  done:
00861         if (got_mutex) {
00862                 secrets_named_mutex_release(controller);
00863         }
00864 
00865         SAFE_FREE(machine_account);
00866         SAFE_FREE(machine_password);
00867         SAFE_FREE(machine_krb5_principal);
00868         SAFE_FREE(ipc_username);
00869         SAFE_FREE(ipc_domain);
00870         SAFE_FREE(ipc_password);
00871 
00872         if (!NT_STATUS_IS_OK(result)) {
00873                 winbind_add_failed_connection_entry(domain, controller, result);
00874                 if ((*cli) != NULL) {
00875                         cli_shutdown(*cli);
00876                         *cli = NULL;
00877                 }
00878         }
00879 
00880         return result;
00881 }

static BOOL add_one_dc_unique ( TALLOC_CTX mem_ctx,
const char *  domain_name,
const char *  dcname,
struct in_addr  ip,
struct dc_name_ip **  dcs,
int *  num 
) [static]

winbindd_cm.c883 行で定義されています。

参照先 check_negative_conn_cache()name.

参照元 get_dcs().

00886 {
00887         if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) {
00888                 DEBUG(10, ("DC %s was in the negative conn cache\n", dcname));
00889                 return False;
00890         }
00891 
00892         *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1);
00893 
00894         if (*dcs == NULL)
00895                 return False;
00896 
00897         fstrcpy((*dcs)[*num].name, dcname);
00898         (*dcs)[*num].ip = ip;
00899         *num += 1;
00900         return True;
00901 }

static BOOL add_sockaddr_to_array ( TALLOC_CTX mem_ctx,
struct in_addr  ip,
uint16  port,
struct sockaddr_in **  addrs,
int *  num 
) [static]

winbindd_cm.c903 行で定義されています。

参照元 cm_open_connection()find_new_dc().

00906 {
00907         *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1);
00908 
00909         if (*addrs == NULL) {
00910                 *num = 0;
00911                 return False;
00912         }
00913 
00914         (*addrs)[*num].sin_family = PF_INET;
00915         putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip);
00916         (*addrs)[*num].sin_port = htons(port);
00917 
00918         *num += 1;
00919         return True;
00920 }

static void mailslot_name ( struct in_addr  dc_ip,
fstring  name 
) [static]

winbindd_cm.c922 行で定義されています。

参照先 fstr_sprintf().

参照元 receive_getdc_response()send_getdc_request().

00923 {
00924         fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
00925 }

static BOOL send_getdc_request ( struct in_addr  dc_ip,
const char *  domain_name,
const DOM_SID sid 
) [static]

winbindd_cm.c927 行で定義されています。

参照先 cli_send_mailslot()dos_PutUniCode()fstr_sprintf()global_mynamemailslot_name()sid_linearize()sid_size().

参照元 dcip_to_name().

00930 {
00931         pstring outbuf;
00932         char *p;
00933         fstring my_acct_name;
00934         fstring my_mailslot;
00935 
00936         mailslot_name(dc_ip, my_mailslot);
00937 
00938         memset(outbuf, '\0', sizeof(outbuf));
00939 
00940         p = outbuf;
00941 
00942         SCVAL(p, 0, SAMLOGON);
00943         p++;
00944 
00945         SCVAL(p, 0, 0); /* Count pointer ... */
00946         p++;
00947 
00948         SIVAL(p, 0, 0); /* The sender's token ... */
00949         p += 2;
00950 
00951         p += dos_PutUniCode(p, global_myname(),
00952                 sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
00953         fstr_sprintf(my_acct_name, "%s$", global_myname());
00954         p += dos_PutUniCode(p, my_acct_name,
00955                         sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
00956 
00957         if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
00958                 return False;
00959         }
00960 
00961         memcpy(p, my_mailslot, strlen(my_mailslot)+1);
00962         p += strlen(my_mailslot)+1;
00963 
00964         if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) {
00965                 return False;
00966         }
00967         SIVAL(p, 0, 0x80);
00968         p+=4;
00969 
00970         SIVAL(p, 0, sid_size(sid));
00971         p+=4;
00972 
00973         p = ALIGN4(p, outbuf);
00974 
00975         if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) {
00976                 return False;
00977         }
00978 
00979         if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
00980                 return False;
00981         }
00982 
00983         sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
00984         p += sid_size(sid);
00985 
00986         SIVAL(p, 0, 1);
00987         SSVAL(p, 4, 0xffff);
00988         SSVAL(p, 6, 0xffff);
00989         p+=8;
00990 
00991         return cli_send_mailslot(False, "\\MAILSLOT\\NET\\NTLOGON", 0,
00992                                  outbuf, PTR_DIFF(p, outbuf),
00993                                  global_myname(), 0, domain_name, 0x1c,
00994                                  dc_ip);
00995 }

static BOOL receive_getdc_response ( struct in_addr  dc_ip,
const char *  domain_name,
fstring  dc_name 
) [static]

winbindd_cm.c997 行で定義されています。

参照先 bufDGRAM_PACKETlenmailslot_name()packetpull_ucs2()receive_unexpected()skip_unibuf()strequal().

参照元 dcip_to_name().

01000 {
01001         struct packet_struct *packet;
01002         fstring my_mailslot;
01003         char *buf, *p;
01004         fstring dcname, user, domain;
01005         int len;
01006 
01007         mailslot_name(dc_ip, my_mailslot);
01008 
01009         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
01010 
01011         if (packet == NULL) {
01012                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
01013                 return False;
01014         }
01015 
01016         DEBUG(5, ("Received packet for %s\n", my_mailslot));
01017 
01018         buf = packet->packet.dgram.data;
01019         len = packet->packet.dgram.datasize;
01020 
01021         if (len < 70) {
01022                 /* 70 is a completely arbitrary value to make sure
01023                    the SVAL below does not read uninitialized memory */
01024                 DEBUG(3, ("GetDC got short response\n"));
01025                 return False;
01026         }
01027 
01028         /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
01029         p = buf+SVAL(buf, smb_vwv10);
01030 
01031         if (CVAL(p,0) != SAMLOGON_R) {
01032                 DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
01033                 return False;
01034         }
01035 
01036         p+=2;
01037         pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
01038                   STR_TERMINATE|STR_NOALIGN);
01039         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
01040         pull_ucs2(buf, user, p, sizeof(dcname), PTR_DIFF(buf+len, p),
01041                   STR_TERMINATE|STR_NOALIGN);
01042         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
01043         pull_ucs2(buf, domain, p, sizeof(dcname), PTR_DIFF(buf+len, p),
01044                   STR_TERMINATE|STR_NOALIGN);
01045         p = skip_unibuf(p, PTR_DIFF(buf+len, p));
01046 
01047         if (!strequal(domain, domain_name)) {
01048                 DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
01049                           domain_name, domain));
01050                 return False;
01051         }
01052 
01053         p = dcname;
01054         if (*p == '\\') p += 1;
01055         if (*p == '\\') p += 1;
01056 
01057         fstrcpy(dc_name, p);
01058 
01059         DEBUG(10, ("GetDC gave name %s for domain %s\n",
01060                    dc_name, domain));
01061 
01062         return True;
01063 }

static BOOL dcip_to_name ( const struct winbindd_domain domain,
struct in_addr  ip,
fstring  name 
) [static]

winbindd_cm.c1069 行で定義されています。

参照先 ads_closest_dc()ads_destroy()ads_init()ads_try_connect()winbindd_domain::alt_nameADS_STRUCT::authADS_STRUCT::configcreate_local_private_krb5_conf_for_domain()ADS_STRUCT::flagsip_service::ipADS_STRUCT::ldap_server_namewinbindd_domain::namenamecache_store()ip_service::portwinbindd_domain::primaryreceive_getdc_response()saf_store()SEC_ADSsend_getdc_request()winbindd_domain::sidsitename_fetch()smb_msleep().

参照元 cm_open_connection()find_new_dc().

01070 {
01071         struct ip_service ip_list;
01072 
01073         ip_list.ip = ip;
01074         ip_list.port = 0;
01075 
01076 #ifdef WITH_ADS
01077         /* For active directory servers, try to get the ldap server name.
01078            None of these failures should be considered critical for now */
01079 
01080         if (lp_security() == SEC_ADS) {
01081                 ADS_STRUCT *ads;
01082 
01083                 ads = ads_init(domain->alt_name, domain->name, NULL);
01084                 ads->auth.flags |= ADS_AUTH_NO_BIND;
01085 
01086                 if (ads_try_connect( ads, inet_ntoa(ip) ) )  {
01087                         /* We got a cldap packet. */
01088                         fstrcpy(name, ads->config.ldap_server_name);
01089                         namecache_store(name, 0x20, 1, &ip_list);
01090 
01091                         DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
01092 
01093                         if (domain->primary && (ads->config.flags & ADS_KDC)) {
01094                                 if (ads_closest_dc(ads)) {
01095                                         char *sitename = sitename_fetch(ads->config.realm);
01096 
01097                                         /* We're going to use this KDC for this realm/domain.
01098                                            If we are using sites, then force the krb5 libs
01099                                            to use this KDC. */
01100 
01101                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
01102                                                                         domain->name,
01103                                                                         sitename,
01104                                                                         ip);
01105 
01106                                         SAFE_FREE(sitename);
01107                                 } else {
01108                                         /* use an off site KDC */
01109                                         create_local_private_krb5_conf_for_domain(domain->alt_name,
01110                                                                         domain->name,
01111                                                                         NULL,
01112                                                                         ip);
01113                                 }
01114                                 /* Ensure we contact this DC also. */
01115                                 saf_store( domain->name, name);
01116                                 saf_store( domain->alt_name, name);
01117                         }
01118 
01119                         ads_destroy( &ads );
01120                         return True;
01121                 }
01122 
01123                 ads_destroy( &ads );
01124         }
01125 #endif
01126 
01127         /* try GETDC requests next */
01128         
01129         if (send_getdc_request(ip, domain->name, &domain->sid)) {
01130                 int i;
01131                 smb_msleep(100);
01132                 for (i=0; i<5; i++) {
01133                         if (receive_getdc_response(ip, domain->name, name)) {
01134                                 namecache_store(name, 0x20, 1, &ip_list);
01135                                 return True;
01136                         }
01137                         smb_msleep(500);
01138                 }
01139         }
01140 
01141         /* try node status request */
01142 
01143         if ( name_status_find(domain->name, 0x1c, 0x20, ip, name) ) {
01144                 namecache_store(name, 0x20, 1, &ip_list);
01145                 return True;
01146         }
01147         return False;
01148 }

static BOOL find_new_dc ( TALLOC_CTX mem_ctx,
const struct winbindd_domain domain,
fstring  dcname,
struct sockaddr_in *  addr,
int *  fd 
) [static]

winbindd_cm.c1238 行で定義されています。

参照先 add_sockaddr_to_array()add_string_to_array()dcip_to_name()errnoget_dcs()is_ipaddress()winbindd_domain::namenameopen_any_socket_out()strerror()winbind_add_failed_connection_entry().

参照元 cm_open_connection().

01241 {
01242         struct dc_name_ip *dcs = NULL;
01243         int num_dcs = 0;
01244 
01245         const char **dcnames = NULL;
01246         int num_dcnames = 0;
01247 
01248         struct sockaddr_in *addrs = NULL;
01249         int num_addrs = 0;
01250 
01251         int i, fd_index;
01252 
01253         *fd = -1;
01254 
01255  again:
01256         if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0))
01257                 return False;
01258 
01259         for (i=0; i<num_dcs; i++) {
01260 
01261                 if (!add_string_to_array(mem_ctx, dcs[i].name,
01262                                     &dcnames, &num_dcnames)) {
01263                         return False;
01264                 }
01265                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445,
01266                                       &addrs, &num_addrs)) {
01267                         return False;
01268                 }
01269 
01270                 if (!add_string_to_array(mem_ctx, dcs[i].name,
01271                                     &dcnames, &num_dcnames)) {
01272                         return False;
01273                 }
01274                 if (!add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139,
01275                                       &addrs, &num_addrs)) {
01276                         return False;
01277                 }
01278         }
01279 
01280         if ((num_dcnames == 0) || (num_dcnames != num_addrs))
01281                 return False;
01282 
01283         if ((addrs == NULL) || (dcnames == NULL))
01284                 return False;
01285 
01286         /* 5 second timeout. */
01287         if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) 
01288         {
01289                 for (i=0; i<num_dcs; i++) {
01290                         DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
01291                                 "domain %s address %s. Error was %s\n",
01292                                 domain->name, inet_ntoa(dcs[i].ip), strerror(errno) ));
01293                         winbind_add_failed_connection_entry(domain,
01294                                 dcs[i].name, NT_STATUS_UNSUCCESSFUL);
01295                 }
01296                 return False;
01297         }
01298 
01299         *addr = addrs[fd_index];
01300 
01301         if (*dcnames[fd_index] != '\0' && !is_ipaddress(dcnames[fd_index])) {
01302                 /* Ok, we've got a name for the DC */
01303                 fstrcpy(dcname, dcnames[fd_index]);
01304                 return True;
01305         }
01306 
01307         /* Try to figure out the name */
01308         if (dcip_to_name( domain, addr->sin_addr, dcname )) {
01309                 return True;
01310         }
01311 
01312         /* We can not continue without the DC's name */
01313         winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
01314                                     NT_STATUS_UNSUCCESSFUL);
01315 
01316         /* Throw away all arrays as we're doing this again. */
01317         TALLOC_FREE(dcs);
01318         num_dcs = 0;
01319 
01320         TALLOC_FREE(dcnames);
01321         num_dcnames = 0;
01322 
01323         TALLOC_FREE(addrs);
01324         num_addrs = 0;
01325 
01326         *fd = -1;
01327 
01328         goto again;
01329 }

static NTSTATUS cm_open_connection ( struct winbindd_domain domain,
struct winbindd_cm_conn new_conn 
) [static]

winbindd_cm.c1331 行で定義されています。

参照先 add_sockaddr_to_array()check_negative_conn_cache()winbindd_cm_conn::clicm_prepare_connection()winbindd_domain::dcaddrdcip_to_name()winbindd_domain::dcnamefdfind_new_dc()interpret_addr2()is_ipaddress()winbindd_domain::namewinbindd_domain::onlineopen_any_socket_out()resolve_name()resultsaf_fetch()set_domain_offline()set_domain_online()set_global_winbindd_state_offline()set_global_winbindd_state_online()talloc_init()winbind_add_failed_connection_entry().

参照元 init_dc_connection_network().

01333 {
01334         TALLOC_CTX *mem_ctx;
01335         NTSTATUS result;
01336         char *saf_servername = saf_fetch( domain->name );
01337         int retries;
01338 
01339         if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
01340                 SAFE_FREE(saf_servername);
01341                 set_domain_offline(domain);
01342                 return NT_STATUS_NO_MEMORY;
01343         }
01344 
01345         /* we have to check the server affinity cache here since 
01346            later we selecte a DC based on response time and not preference */
01347            
01348         /* Check the negative connection cache
01349            before talking to it. It going down may have
01350            triggered the reconnection. */
01351 
01352         if ( saf_servername && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, saf_servername))) {
01353 
01354                 DEBUG(10,("cm_open_connection: saf_servername is '%s' for domain %s\n",
01355                         saf_servername, domain->name ));
01356 
01357                 /* convert an ip address to a name */
01358                 if ( is_ipaddress( saf_servername ) ) {
01359                         fstring saf_name;
01360                         struct in_addr ip;
01361 
01362                         ip = *interpret_addr2( saf_servername );
01363                         if (dcip_to_name( domain, ip, saf_name )) {
01364                                 fstrcpy( domain->dcname, saf_name );
01365                         } else {
01366                                 winbind_add_failed_connection_entry(
01367                                         domain, saf_servername,
01368                                         NT_STATUS_UNSUCCESSFUL);
01369                         }
01370                 } else {
01371                         fstrcpy( domain->dcname, saf_servername );
01372                 }
01373 
01374                 SAFE_FREE( saf_servername );
01375         }
01376 
01377         for (retries = 0; retries < 3; retries++) {
01378 
01379                 int fd = -1;
01380                 BOOL retry = False;
01381 
01382                 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
01383 
01384                 DEBUG(10,("cm_open_connection: dcname is '%s' for domain %s\n",
01385                         domain->dcname, domain->name ));
01386 
01387                 if (*domain->dcname 
01388                         && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
01389                         && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
01390                 {
01391                         struct sockaddr_in *addrs = NULL;
01392                         int num_addrs = 0;
01393                         int dummy = 0;
01394 
01395                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs)) {
01396                                 set_domain_offline(domain);
01397                                 talloc_destroy(mem_ctx);
01398                                 return NT_STATUS_NO_MEMORY;
01399                         }
01400                         if (!add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs)) {
01401                                 set_domain_offline(domain);
01402                                 talloc_destroy(mem_ctx);
01403                                 return NT_STATUS_NO_MEMORY;
01404                         }
01405 
01406                         /* 5 second timeout. */
01407                         if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
01408                                 fd = -1;
01409                         }
01410                 }
01411 
01412                 if ((fd == -1) 
01413                         && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
01414                 {
01415                         /* This is the one place where we will
01416                            set the global winbindd offline state
01417                            to true, if a "WINBINDD_OFFLINE" entry
01418                            is found in the winbindd cache. */
01419                         set_global_winbindd_state_offline();
01420                         break;
01421                 }
01422 
01423                 new_conn->cli = NULL;
01424 
01425                 result = cm_prepare_connection(domain, fd, domain->dcname,
01426                         &new_conn->cli, &retry);
01427 
01428                 if (!retry)
01429                         break;
01430         }
01431 
01432         if (NT_STATUS_IS_OK(result)) {
01433                 if (domain->online == False) {
01434                         /* We're changing state from offline to online. */
01435                         set_global_winbindd_state_online();
01436                 }
01437                 set_domain_online(domain);
01438         } else {
01439                 /* Ensure we setup the retry handler. */
01440                 set_domain_offline(domain);
01441         }
01442 
01443         talloc_destroy(mem_ctx);
01444         return result;
01445 }

void invalidate_cm_connection ( struct winbindd_cm_conn conn  ) 

winbindd_cm.c1449 行で定義されています。

参照先 winbindd_cm_conn::clicli_rpc_pipe_close()cli_set_timeout()cli_shutdown()winbindd_cm_conn::lsa_pipewinbindd_cm_conn::netlogon_pipewinbindd_cm_conn::samr_pipe.

参照元 cm_connect_lsa()cm_connect_sam()init_dc_connection_network()query_user_list()winbindd_dual_check_machine_acct()winbindd_dual_pam_auth_crap()winbindd_dual_pam_auth_samlogon().

01450 {
01451         /* We're closing down a possibly dead
01452            connection. Don't have impossibly long (10s) timeouts. */
01453 
01454         if (conn->cli) {
01455                 cli_set_timeout(conn->cli, 1000); /* 1 second. */
01456         }
01457 
01458         if (conn->samr_pipe != NULL) {
01459                 if (!cli_rpc_pipe_close(conn->samr_pipe)) {
01460                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
01461                         if (conn->cli) {
01462                                 cli_set_timeout(conn->cli, 500);
01463                         }
01464                 }
01465                 conn->samr_pipe = NULL;
01466         }
01467 
01468         if (conn->lsa_pipe != NULL) {
01469                 if (!cli_rpc_pipe_close(conn->lsa_pipe)) {
01470                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
01471                         if (conn->cli) {
01472                                 cli_set_timeout(conn->cli, 500);
01473                         }
01474                 }
01475                 conn->lsa_pipe = NULL;
01476         }
01477 
01478         if (conn->netlogon_pipe != NULL) {
01479                 if (!cli_rpc_pipe_close(conn->netlogon_pipe)) {
01480                         /* Ok, it must be dead. Drop timeout to 0.5 sec. */
01481                         if (conn->cli) {
01482                                 cli_set_timeout(conn->cli, 500);
01483                         }
01484                 }
01485                 conn->netlogon_pipe = NULL;
01486         }
01487 
01488         if (conn->cli) {
01489                 cli_shutdown(conn->cli);
01490         }
01491 
01492         conn->cli = NULL;
01493 }

void close_conns_after_fork ( void   ) 

winbindd_cm.c1495 行で定義されています。

参照先 winbindd_cm_conn::cliwinbindd_domain::conndomain_list()cli_state::fdwinbindd_domain::next.

参照元 fork_child_dc_connect()fork_domain_child().

01496 {
01497         struct winbindd_domain *domain;
01498 
01499         for (domain = domain_list(); domain; domain = domain->next) {
01500                 if (domain->conn.cli == NULL)
01501                         continue;
01502 
01503                 if (domain->conn.cli->fd == -1)
01504                         continue;
01505 
01506                 close(domain->conn.cli->fd);
01507                 domain->conn.cli->fd = -1;
01508         }
01509 }

static BOOL connection_ok ( struct winbindd_domain domain  )  [static]

winbindd_cm.c1511 行で定義されています。

参照先 winbindd_cm_conn::cliwinbindd_domain::connwinbindd_domain::dcnamecli_state::fdcli_state::initialisedwinbindd_domain::namewinbindd_domain::online.

参照元 init_dc_connection_network()set_dc_type_and_flags().

01512 {
01513         if (domain->conn.cli == NULL) {
01514                 DEBUG(8, ("connection_ok: Connection to %s for domain %s has NULL "
01515                           "cli!\n", domain->dcname, domain->name));
01516                 return False;
01517         }
01518 
01519         if (!domain->conn.cli->initialised) {
01520                 DEBUG(3, ("connection_ok: Connection to %s for domain %s was never "
01521                           "initialised!\n", domain->dcname, domain->name));
01522                 return False;
01523         }
01524 
01525         if (domain->conn.cli->fd == -1) {
01526                 DEBUG(3, ("connection_ok: Connection to %s for domain %s has died or was "
01527                           "never started (fd == -1)\n", 
01528                           domain->dcname, domain->name));
01529                 return False;
01530         }
01531 
01532         if (domain->online == False) {
01533                 DEBUG(3, ("connection_ok: Domain %s is offline\n", domain->name));
01534                 return False;
01535         }
01536 
01537         return True;
01538 }

NTSTATUS init_dc_connection ( struct winbindd_domain domain  ) 

winbindd_cm.c1571 行で定義されています。

参照先 init_dc_connection_network()winbindd_domain::initializedwinbindd_domain::online.

参照元 cm_connect_lsa()cm_connect_netlogon()cm_connect_sam()find_domain_from_name()find_domain_from_sid()get_cache()init_child_recv()winbindd_dual_init_connection()winbindd_dual_pam_auth()winbindd_dual_pam_auth_kerberos().

01572 {
01573         if (domain->initialized && !domain->online) {
01574                 /* We check for online status elsewhere. */
01575                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
01576         }
01577 
01578         return init_dc_connection_network(domain);
01579 }

static BOOL cm_get_schannel_dcinfo ( struct winbindd_domain domain,
struct dcinfo **  ppdc 
) [static]

winbindd_cm.c1736 行で定義されています。

参照先 cm_connect_netlogon()rpc_pipe_client::domainresult.

参照元 cm_connect_lsa()cm_connect_sam().

01738 {
01739         NTSTATUS result;
01740         struct rpc_pipe_client *netlogon_pipe;
01741 
01742         if (lp_client_schannel() == False) {
01743                 return False;
01744         }
01745 
01746         result = cm_connect_netlogon(domain, &netlogon_pipe);
01747         if (!NT_STATUS_IS_OK(result)) {
01748                 return False;
01749         }
01750 
01751         /* Return a pointer to the struct dcinfo from the
01752            netlogon pipe. */
01753 
01754         *ppdc = domain->conn.netlogon_pipe->dc;
01755         return True;
01756 }

NTSTATUS cm_connect_sam ( struct winbindd_domain domain,
TALLOC_CTX mem_ctx,
struct rpc_pipe_client **  cli,
POLICY_HND sam_handle 
)

winbindd_cm.c1758 行で定義されています。

参照先 cliwinbindd_cm_conn::clicli_rpc_pipe_close()cli_rpc_pipe_open_noauth()cli_rpc_pipe_open_schannel_with_key()cli_rpc_pipe_open_spnego_ntlmssp()cm_get_schannel_dcinfo()cli_state::domaindcinfo::domaindomain_nameget_trust_creds()init_dc_connection()invalidate_cm_connection()nt_errstr()PIPE_AUTH_LEVEL_PRIVACYcli_state::pwdpwd_get_cleartext()resultrpccli_samr_connect()rpccli_samr_open_domain()winbindd_cm_conn::sam_connect_handlewinbindd_cm_conn::sam_domain_handlewinbindd_cm_conn::samr_pipecli_state::user_name.

参照元 enum_dom_groups()enum_local_groups()lookup_groupmem()lookup_usergroups()msrpc_lockout_policy()msrpc_lookup_useraliases()msrpc_password_policy()query_user()query_user_list()sequence_number()winbindd_dual_pam_auth_samlogon()winbindd_dual_pam_chauthtok()winbindd_dual_pam_chng_pswd_auth_crap().

01760 {
01761         struct winbindd_cm_conn *conn;
01762         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01763         fstring conn_pwd;
01764         struct dcinfo *p_dcinfo;
01765         char *machine_password = NULL;
01766         char *machine_account = NULL;
01767         char *domain_name = NULL;
01768 
01769         result = init_dc_connection(domain);
01770         if (!NT_STATUS_IS_OK(result)) {
01771                 return result;
01772         }
01773 
01774         conn = &domain->conn;
01775 
01776         if (conn->samr_pipe != NULL) {
01777                 goto done;
01778         }
01779 
01780         /*
01781          * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
01782          * sign and sealed pipe using the machine account password by
01783          * preference. If we can't - try schannel, if that fails, try
01784          * anonymous.
01785          */
01786 
01787         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
01788         if ((conn->cli->user_name[0] == '\0') ||
01789             (conn->cli->domain[0] == '\0') || 
01790             (conn_pwd[0] == '\0'))
01791         {
01792                 result = get_trust_creds(domain, &machine_password,
01793                                          &machine_account, NULL);
01794                 if (!NT_STATUS_IS_OK(result)) {
01795                         DEBUG(10, ("cm_connect_sam: No no user available for "
01796                                    "domain %s, trying schannel\n", conn->cli->domain));
01797                         goto schannel;
01798                 }
01799                 domain_name = domain->name;
01800         } else {
01801                 machine_password = SMB_STRDUP(conn_pwd);                
01802                 machine_account = SMB_STRDUP(conn->cli->user_name);
01803                 domain_name = conn->cli->domain;
01804         }
01805 
01806         if (!machine_password || !machine_account) {
01807                 result = NT_STATUS_NO_MEMORY;
01808                 goto done;
01809         }
01810 
01811         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
01812            authenticated SAMR pipe with sign & seal. */
01813         conn->samr_pipe =
01814                 cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
01815                                                  PIPE_AUTH_LEVEL_PRIVACY,
01816                                                  domain_name,
01817                                                  machine_account,
01818                                                  machine_password, &result);
01819 
01820         if (conn->samr_pipe == NULL) {
01821                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
01822                           "pipe for domain %s using NTLMSSP "
01823                           "authenticated pipe: user %s\\%s. Error was "
01824                           "%s\n", domain->name, domain_name,
01825                           machine_account, nt_errstr(result)));
01826                 goto schannel;
01827         }
01828 
01829         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
01830                   "domain %s using NTLMSSP authenticated "
01831                   "pipe: user %s\\%s\n", domain->name,
01832                   domain_name, machine_account));
01833 
01834         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
01835                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
01836                                      &conn->sam_connect_handle);
01837         if (NT_STATUS_IS_OK(result)) {
01838                 goto open_domain;
01839         }
01840         DEBUG(10,("cm_connect_sam: ntlmssp-sealed rpccli_samr_connect "
01841                   "failed for domain %s, error was %s. Trying schannel\n",
01842                   domain->name, nt_errstr(result) ));
01843         cli_rpc_pipe_close(conn->samr_pipe);
01844 
01845  schannel:
01846 
01847         /* Fall back to schannel if it's a W2K pre-SP1 box. */
01848 
01849         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
01850                 /* If this call fails - conn->cli can now be NULL ! */
01851                 DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
01852                            "for domain %s, trying anon\n", domain->name));
01853                 goto anonymous;
01854         }
01855         conn->samr_pipe = cli_rpc_pipe_open_schannel_with_key
01856                 (conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY,
01857                  domain->name, p_dcinfo, &result);
01858 
01859         if (conn->samr_pipe == NULL) {
01860                 DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
01861                           "domain %s using schannel. Error was %s\n",
01862                           domain->name, nt_errstr(result) ));
01863                 goto anonymous;
01864         }
01865         DEBUG(10,("cm_connect_sam: connected to SAMR pipe for domain %s using "
01866                   "schannel.\n", domain->name ));
01867 
01868         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
01869                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
01870                                      &conn->sam_connect_handle);
01871         if (NT_STATUS_IS_OK(result)) {
01872                 goto open_domain;
01873         }
01874         DEBUG(10,("cm_connect_sam: schannel-sealed rpccli_samr_connect failed "
01875                   "for domain %s, error was %s. Trying anonymous\n",
01876                   domain->name, nt_errstr(result) ));
01877         cli_rpc_pipe_close(conn->samr_pipe);
01878 
01879  anonymous:
01880 
01881         /* Finally fall back to anonymous. */
01882         conn->samr_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR,
01883                                                    &result);
01884 
01885         if (conn->samr_pipe == NULL) {
01886                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
01887                 goto done;
01888         }
01889 
01890         result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
01891                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
01892                                      &conn->sam_connect_handle);
01893         if (!NT_STATUS_IS_OK(result)) {
01894                 DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
01895                           "for domain %s Error was %s\n",
01896                           domain->name, nt_errstr(result) ));
01897                 goto done;
01898         }
01899 
01900  open_domain:
01901         result = rpccli_samr_open_domain(conn->samr_pipe,
01902                                          mem_ctx,
01903                                          &conn->sam_connect_handle,
01904                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
01905                                          &domain->sid,
01906                                          &conn->sam_domain_handle);
01907 
01908  done:
01909 
01910         if (!NT_STATUS_IS_OK(result)) {
01911                 invalidate_cm_connection(conn);
01912                 return result;
01913         }
01914 
01915         *cli = conn->samr_pipe;
01916         *sam_handle = conn->sam_domain_handle;
01917         SAFE_FREE(machine_password);
01918         SAFE_FREE(machine_account);
01919         return result;
01920 }

NTSTATUS cm_connect_lsa ( struct winbindd_domain domain,
TALLOC_CTX mem_ctx,
struct rpc_pipe_client **  cli,
POLICY_HND lsa_policy 
)

winbindd_cm.c1922 行で定義されています。

参照先 cliwinbindd_cm_conn::clicli_rpc_pipe_close()cli_rpc_pipe_open_noauth()cli_rpc_pipe_open_schannel_with_key()cli_rpc_pipe_open_spnego_ntlmssp()cm_get_schannel_dcinfo()cli_state::domaindcinfo::domaininit_dc_connection()invalidate_cm_connection()winbindd_cm_conn::lsa_pipewinbindd_cm_conn::lsa_policynt_errstr()PIPE_AUTH_LEVEL_PRIVACYcli_state::pwdpwd_get_cleartext()resultrpccli_lsa_open_policy()cli_state::user_name.

参照元 msrpc_name_to_sid()msrpc_rids_to_names()msrpc_sid_to_name()trusted_domains().

01924 {
01925         struct winbindd_cm_conn *conn;
01926         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
01927         fstring conn_pwd;
01928         struct dcinfo *p_dcinfo;
01929 
01930         result = init_dc_connection(domain);
01931         if (!NT_STATUS_IS_OK(result))
01932                 return result;
01933 
01934         conn = &domain->conn;
01935 
01936         if (conn->lsa_pipe != NULL) {
01937                 goto done;
01938         }
01939 
01940         pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
01941         if ((conn->cli->user_name[0] == '\0') ||
01942             (conn->cli->domain[0] == '\0') || 
01943             (conn_pwd[0] == '\0')) {
01944                 DEBUG(10, ("cm_connect_lsa: No no user available for "
01945                            "domain %s, trying schannel\n", conn->cli->domain));
01946                 goto schannel;
01947         }
01948 
01949         /* We have an authenticated connection. Use a NTLMSSP SPNEGO
01950          * authenticated LSA pipe with sign & seal. */
01951         conn->lsa_pipe = cli_rpc_pipe_open_spnego_ntlmssp
01952                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
01953                  conn->cli->domain, conn->cli->user_name, conn_pwd, &result);
01954 
01955         if (conn->lsa_pipe == NULL) {
01956                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
01957                           "domain %s using NTLMSSP authenticated pipe: user "
01958                           "%s\\%s. Error was %s. Trying schannel.\n",
01959                           domain->name, conn->cli->domain,
01960                           conn->cli->user_name, nt_errstr(result)));
01961                 goto schannel;
01962         }
01963 
01964         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
01965                   "NTLMSSP authenticated pipe: user %s\\%s\n",
01966                   domain->name, conn->cli->domain, conn->cli->user_name ));
01967 
01968         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
01969                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
01970                                         &conn->lsa_policy);
01971         if (NT_STATUS_IS_OK(result)) {
01972                 goto done;
01973         }
01974 
01975         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
01976                   "schannel\n"));
01977 
01978         cli_rpc_pipe_close(conn->lsa_pipe);
01979 
01980  schannel:
01981 
01982         /* Fall back to schannel if it's a W2K pre-SP1 box. */
01983 
01984         if (!cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
01985                 /* If this call fails - conn->cli can now be NULL ! */
01986                 DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
01987                            "for domain %s, trying anon\n", domain->name));
01988                 goto anonymous;
01989         }
01990         conn->lsa_pipe = cli_rpc_pipe_open_schannel_with_key
01991                 (conn->cli, PI_LSARPC, PIPE_AUTH_LEVEL_PRIVACY,
01992                  domain->name, p_dcinfo, &result);
01993 
01994         if (conn->lsa_pipe == NULL) {
01995                 DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
01996                           "domain %s using schannel. Error was %s\n",
01997                           domain->name, nt_errstr(result) ));
01998                 goto anonymous;
01999         }
02000         DEBUG(10,("cm_connect_lsa: connected to LSA pipe for domain %s using "
02001                   "schannel.\n", domain->name ));
02002 
02003         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
02004                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
02005                                         &conn->lsa_policy);
02006         if (NT_STATUS_IS_OK(result)) {
02007                 goto done;
02008         }
02009 
02010         DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
02011                   "anonymous\n"));
02012 
02013         cli_rpc_pipe_close(conn->lsa_pipe);
02014 
02015  anonymous:
02016 
02017         conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_LSARPC,
02018                                                   &result);
02019         if (conn->lsa_pipe == NULL) {
02020                 result = NT_STATUS_PIPE_NOT_AVAILABLE;
02021                 goto done;
02022         }
02023 
02024         result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
02025                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
02026                                         &conn->lsa_policy);
02027  done:
02028         if (!NT_STATUS_IS_OK(result)) {
02029                 invalidate_cm_connection(conn);
02030                 return result;
02031         }
02032 
02033         *cli = conn->lsa_pipe;
02034         *lsa_policy = conn->lsa_policy;
02035         return result;
02036 }

NTSTATUS cm_connect_netlogon ( struct winbindd_domain domain,
struct rpc_pipe_client **  cli 
)

winbindd_cm.c2043 行で定義されています。

参照先 winbindd_cm_conn::cliclicli_rpc_pipe_close()cli_rpc_pipe_open_noauth()cli_rpc_pipe_open_schannel_with_key()rpc_pipe_client::dcrpc_pipe_client::domainget_trust_pw_hash()global_mynameinit_dc_connection()winbindd_cm_conn::netlogon_pipent_errstr()PIPE_AUTH_LEVEL_PRIVACYresultrpccli_netlogon_setup_creds().

参照元 cm_get_schannel_dcinfo()get_dc_name_via_netlogon()trusted_domains()winbindd_dual_check_machine_acct()winbindd_dual_getdcname()winbindd_dual_pam_auth_crap()winbindd_dual_pam_auth_samlogon().

02045 {
02046         struct winbindd_cm_conn *conn;
02047         NTSTATUS result;
02048 
02049         uint32 neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
02050         uint8  mach_pwd[16];
02051         uint32  sec_chan_type;
02052         const char *account_name;
02053         struct rpc_pipe_client *netlogon_pipe = NULL;
02054 
02055         *cli = NULL;
02056 
02057         result = init_dc_connection(domain);
02058         if (!NT_STATUS_IS_OK(result)) {
02059                 return result;
02060         }
02061 
02062         conn = &domain->conn;
02063 
02064         if (conn->netlogon_pipe != NULL) {
02065                 *cli = conn->netlogon_pipe;
02066                 return NT_STATUS_OK;
02067         }
02068 
02069         netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
02070                                                  &result);
02071         if (netlogon_pipe == NULL) {
02072                 return result;
02073         }
02074 
02075         if ((!IS_DC) && (!domain->primary)) {
02076                 /* Clear the schannel request bit and drop down */
02077                 neg_flags &= ~NETLOGON_NEG_SCHANNEL;            
02078                 goto no_schannel;
02079         }
02080 
02081         if (lp_client_schannel() != False) {
02082                 neg_flags |= NETLOGON_NEG_SCHANNEL;
02083         }
02084 
02085         if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
02086                                &sec_chan_type))
02087         {
02088                 cli_rpc_pipe_close(netlogon_pipe);
02089                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
02090         }
02091 
02092         result = rpccli_netlogon_setup_creds(
02093                  netlogon_pipe,
02094                  domain->dcname, /* server name. */
02095                  domain->name,   /* domain name */
02096                  global_myname(), /* client name */
02097                  account_name,   /* machine account */
02098                  mach_pwd,       /* machine password */
02099                  sec_chan_type,  /* from get_trust_pw */
02100                  &neg_flags);
02101 
02102         if (!NT_STATUS_IS_OK(result)) {
02103                 cli_rpc_pipe_close(netlogon_pipe);
02104                 return result;
02105         }
02106 
02107         if ((lp_client_schannel() == True) &&
02108                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
02109                 DEBUG(3, ("Server did not offer schannel\n"));
02110                 cli_rpc_pipe_close(netlogon_pipe);
02111                 return NT_STATUS_ACCESS_DENIED;
02112         }
02113 
02114  no_schannel:
02115         if ((lp_client_schannel() == False) ||
02116                         ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
02117                 /* We're done - just keep the existing connection to NETLOGON
02118                  * open */
02119                 conn->netlogon_pipe = netlogon_pipe;
02120                 *cli = conn->netlogon_pipe;
02121                 return NT_STATUS_OK;
02122         }
02123 
02124         /* Using the credentials from the first pipe, open a signed and sealed
02125            second netlogon pipe. The session key is stored in the schannel
02126            part of the new pipe auth struct.
02127         */
02128 
02129         conn->netlogon_pipe =
02130                 cli_rpc_pipe_open_schannel_with_key(conn->cli,
02131                                                     PI_NETLOGON,
02132                                                     PIPE_AUTH_LEVEL_PRIVACY,
02133                                                     domain->name,
02134                                                     netlogon_pipe->dc,
02135                                                     &result);
02136 
02137         /* We can now close the initial netlogon pipe. */
02138         cli_rpc_pipe_close(netlogon_pipe);
02139 
02140         if (conn->netlogon_pipe == NULL) {
02141                 DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
02142                           "was %s\n", nt_errstr(result)));
02143                           
02144                 /* make sure we return something besides OK */
02145                 return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
02146         }
02147 
02148         *cli = conn->netlogon_pipe;
02149         return NT_STATUS_OK;
02150 }


変数

struct winbindd_methods reconnect_methods

winbindd_reconnect.c300 行で定義されています。

BOOL override_logfile

debug.c91 行で定義されています。


Sambaに対してSat Aug 29 21:23:57 2009に生成されました。  doxygen 1.4.7