nsswitch/winbindd_misc.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Winbind daemon - miscellaneous other functions
00005 
00006    Copyright (C) Tim Potter      2000
00007    Copyright (C) Andrew Bartlett 2002
00008    
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 #include "winbindd.h"
00026 
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_WINBIND
00029 
00030 /* Check the machine account password is valid */
00031 
00032 void winbindd_check_machine_acct(struct winbindd_cli_state *state)
00033 {
00034         DEBUG(3, ("[%5lu]: check machine account\n",
00035                   (unsigned long)state->pid));
00036 
00037         sendto_domain(state, find_our_domain());
00038 }
00039 
00040 enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
00041                                                       struct winbindd_cli_state *state)
00042 {
00043         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00044         int num_retries = 0;
00045         struct winbindd_domain *contact_domain;
00046 
00047         DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
00048 
00049         /* Get trust account password */
00050 
00051  again:
00052 
00053         contact_domain = find_our_domain();
00054         
00055         /* This call does a cli_nt_setup_creds() which implicitly checks
00056            the trust account password. */
00057 
00058         invalidate_cm_connection(&contact_domain->conn);
00059 
00060         {
00061                 struct rpc_pipe_client *netlogon_pipe;
00062                 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
00063         }
00064 
00065         if (!NT_STATUS_IS_OK(result)) {
00066                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
00067                 goto done;
00068         }
00069 
00070         /* There is a race condition between fetching the trust account
00071            password and the periodic machine password change.  So it's 
00072            possible that the trust account password has been changed on us.  
00073            We are returned NT_STATUS_ACCESS_DENIED if this happens. */
00074 
00075 #define MAX_RETRIES 8
00076 
00077         if ((num_retries < MAX_RETRIES) && 
00078             NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
00079                 num_retries++;
00080                 goto again;
00081         }
00082 
00083         /* Pass back result code - zero for success, other values for
00084            specific failures. */
00085 
00086         DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?  
00087                   "good" : "bad"));
00088 
00089  done:
00090         state->response.data.auth.nt_status = NT_STATUS_V(result);
00091         fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
00092         fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
00093         state->response.data.auth.pam_error = nt_status_to_pam(result);
00094 
00095         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", 
00096                                                 state->response.data.auth.nt_status_string));
00097 
00098         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
00099 }
00100 
00101 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
00102 {
00103         DEBUG(3, ("[%5lu]: list trusted domains\n",
00104                   (unsigned long)state->pid));
00105 
00106         sendto_domain(state, find_our_domain());
00107 }
00108 
00109 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
00110                                                         struct winbindd_cli_state *state)
00111 {
00112         uint32 i, num_domains;
00113         char **names, **alt_names;
00114         DOM_SID *sids;
00115         int extra_data_len = 0;
00116         char *extra_data;
00117         NTSTATUS result;
00118         BOOL have_own_domain = False;
00119 
00120         DEBUG(3, ("[%5lu]: list trusted domains\n",
00121                   (unsigned long)state->pid));
00122 
00123         result = domain->methods->trusted_domains(domain, state->mem_ctx,
00124                                                   &num_domains, &names,
00125                                                   &alt_names, &sids);
00126 
00127         if (!NT_STATUS_IS_OK(result)) {
00128                 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
00129                         nt_errstr(result) ));
00130                 return WINBINDD_ERROR;
00131         }
00132 
00133         extra_data = talloc_strdup(state->mem_ctx, "");
00134 
00135         if (num_domains > 0)
00136                 extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s",
00137                                              names[0],
00138                                              alt_names[0] ? alt_names[0] : names[0],
00139                                              sid_string_static(&sids[0]));
00140 
00141         for (i=1; i<num_domains; i++)
00142                 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
00143                                              extra_data,
00144                                              names[i],
00145                                              alt_names[i] ? alt_names[i] : names[i],
00146                                              sid_string_static(&sids[i]));
00147         /* add our primary domain */
00148         
00149         for (i=0; i<num_domains; i++) {
00150                 if (strequal(names[i], domain->name)) {
00151                         have_own_domain = True;
00152                         break;
00153                 }
00154         }
00155 
00156         if (state->request.data.list_all_domains && !have_own_domain) {
00157                 extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
00158                                              extra_data,
00159                                              domain->name,
00160                                              domain->alt_name ? domain->alt_name : domain->name,
00161                                              sid_string_static(&domain->sid));
00162         }
00163 
00164         /* This is a bit excessive, but the extra data sooner or later will be
00165            talloc'ed */
00166 
00167         extra_data_len = 0;
00168         if (extra_data != NULL) {
00169                 extra_data_len = strlen(extra_data);
00170         }
00171 
00172         if (extra_data_len > 0) {
00173                 state->response.extra_data.data = SMB_STRDUP(extra_data);
00174                 state->response.length += extra_data_len+1;
00175         }
00176 
00177         return WINBINDD_OK;
00178 }
00179 
00180 void winbindd_getdcname(struct winbindd_cli_state *state)
00181 {
00182         state->request.domain_name
00183                 [sizeof(state->request.domain_name)-1] = '\0';
00184 
00185         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
00186                   state->request.domain_name));
00187 
00188         sendto_domain(state, find_our_domain());
00189 }
00190 
00191 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
00192                                              struct winbindd_cli_state *state)
00193 {
00194         fstring dcname_slash;
00195         char *p;
00196         struct rpc_pipe_client *netlogon_pipe;
00197         NTSTATUS result;
00198         WERROR werr;
00199         unsigned int orig_timeout;
00200 
00201         state->request.domain_name
00202                 [sizeof(state->request.domain_name)-1] = '\0';
00203 
00204         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
00205                   state->request.domain_name));
00206 
00207         result = cm_connect_netlogon(domain, &netlogon_pipe);
00208 
00209         if (!NT_STATUS_IS_OK(result)) {
00210                 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
00211                 return WINBINDD_ERROR;
00212         }
00213 
00214         /* This call can take a long time - allow the server to time out.
00215            35 seconds should do it. */
00216 
00217         orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
00218 
00219         werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx, domain->dcname,
00220                                             state->request.domain_name,
00221                                             dcname_slash);
00222         /* And restore our original timeout. */
00223         cli_set_timeout(netlogon_pipe->cli, orig_timeout);
00224 
00225         if (!W_ERROR_IS_OK(werr)) {
00226                 DEBUG(5, ("Error requesting DCname: %s\n", dos_errstr(werr)));
00227                 return WINBINDD_ERROR;
00228         }
00229 
00230         p = dcname_slash;
00231         if (*p == '\\') {
00232                 p+=1;
00233         }
00234         if (*p == '\\') {
00235                 p+=1;
00236         }
00237 
00238         fstrcpy(state->response.data.dc_name, p);
00239         return WINBINDD_OK;
00240 }
00241 
00242 struct sequence_state {
00243         TALLOC_CTX *mem_ctx;
00244         struct winbindd_cli_state *cli_state;
00245         struct winbindd_domain *domain;
00246         struct winbindd_request *request;
00247         struct winbindd_response *response;
00248         char *extra_data;
00249 };
00250 
00251 static void sequence_recv(void *private_data, BOOL success);
00252 
00253 void winbindd_show_sequence(struct winbindd_cli_state *state)
00254 {
00255         struct sequence_state *seq;
00256 
00257         /* Ensure null termination */
00258         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
00259 
00260         if (strlen(state->request.domain_name) > 0) {
00261                 struct winbindd_domain *domain;
00262                 domain = find_domain_from_name_noinit(
00263                         state->request.domain_name);
00264                 if (domain == NULL) {
00265                         request_error(state);
00266                         return;
00267                 }
00268                 sendto_domain(state, domain);
00269                 return;
00270         }
00271 
00272         /* Ask all domains in sequence, collect the results in sequence_recv */
00273 
00274         seq = TALLOC_P(state->mem_ctx, struct sequence_state);
00275         if (seq == NULL) {
00276                 DEBUG(0, ("talloc failed\n"));
00277                 request_error(state);
00278                 return;
00279         }
00280 
00281         seq->mem_ctx = state->mem_ctx;
00282         seq->cli_state = state;
00283         seq->domain = domain_list();
00284         if (seq->domain == NULL) {
00285                 DEBUG(0, ("domain list empty\n"));
00286                 request_error(state);
00287                 return;
00288         }
00289         seq->request = TALLOC_ZERO_P(state->mem_ctx,
00290                                      struct winbindd_request);
00291         seq->response = TALLOC_ZERO_P(state->mem_ctx,
00292                                       struct winbindd_response);
00293         seq->extra_data = talloc_strdup(state->mem_ctx, "");
00294 
00295         if ((seq->request == NULL) || (seq->response == NULL) ||
00296             (seq->extra_data == NULL)) {
00297                 DEBUG(0, ("talloc failed\n"));
00298                 request_error(state);
00299                 return;
00300         }
00301 
00302         seq->request->length = sizeof(*seq->request);
00303         seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
00304         fstrcpy(seq->request->domain_name, seq->domain->name);
00305 
00306         async_domain_request(state->mem_ctx, seq->domain,
00307                              seq->request, seq->response,
00308                              sequence_recv, seq);
00309 }
00310 
00311 static void sequence_recv(void *private_data, BOOL success)
00312 {
00313         struct sequence_state *state =
00314                 (struct sequence_state *)private_data;
00315         uint32 seq = DOM_SEQUENCE_NONE;
00316 
00317         if ((success) && (state->response->result == WINBINDD_OK))
00318                 seq = state->response->data.domain_info.sequence_number;
00319 
00320         if (seq == DOM_SEQUENCE_NONE) {
00321                 state->extra_data = talloc_asprintf(state->mem_ctx,
00322                                                     "%s%s : DISCONNECTED\n",
00323                                                     state->extra_data,
00324                                                     state->domain->name);
00325         } else {
00326                 state->extra_data = talloc_asprintf(state->mem_ctx,
00327                                                     "%s%s : %d\n",
00328                                                     state->extra_data,
00329                                                     state->domain->name, seq);
00330         }
00331 
00332         state->domain->sequence_number = seq;
00333 
00334         state->domain = state->domain->next;
00335 
00336         if (state->domain == NULL) {
00337                 struct winbindd_cli_state *cli_state = state->cli_state;
00338                 cli_state->response.length =
00339                         sizeof(cli_state->response) +
00340                         strlen(state->extra_data) + 1;
00341                 cli_state->response.extra_data.data =
00342                         SMB_STRDUP(state->extra_data);
00343                 request_ok(cli_state);
00344                 return;
00345         }
00346 
00347         /* Ask the next domain */
00348         fstrcpy(state->request->domain_name, state->domain->name);
00349         async_domain_request(state->mem_ctx, state->domain,
00350                              state->request, state->response,
00351                              sequence_recv, state);
00352 }
00353 
00354 /* This is the child-only version of --sequence. It only allows for a single
00355  * domain (ie "our" one) to be displayed. */
00356 
00357 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
00358                                                  struct winbindd_cli_state *state)
00359 {
00360         DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
00361 
00362         /* Ensure null termination */
00363         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
00364 
00365         domain->methods->sequence_number(domain, &domain->sequence_number);
00366 
00367         state->response.data.domain_info.sequence_number =
00368                 domain->sequence_number;
00369 
00370         return WINBINDD_OK;
00371 }
00372 
00373 struct domain_info_state {
00374         struct winbindd_domain *domain;
00375         struct winbindd_cli_state *cli_state;
00376 };
00377 
00378 static void domain_info_init_recv(void *private_data, BOOL success);
00379 
00380 void winbindd_domain_info(struct winbindd_cli_state *state)
00381 {
00382         struct winbindd_domain *domain;
00383 
00384         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
00385                   state->request.domain_name));
00386 
00387         domain = find_domain_from_name_noinit(state->request.domain_name);
00388 
00389         if (domain == NULL) {
00390                 DEBUG(3, ("Did not find domain [%s]\n",
00391                           state->request.domain_name));
00392                 request_error(state);
00393                 return;
00394         }
00395 
00396         if (!domain->initialized) {
00397                 struct domain_info_state *istate;
00398 
00399                 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
00400                 if (istate == NULL) {
00401                         DEBUG(0, ("talloc failed\n"));
00402                         request_error(state);
00403                         return;
00404                 }
00405 
00406                 istate->cli_state = state;
00407                 istate->domain = domain;
00408 
00409                 init_child_connection(domain, domain_info_init_recv, istate);
00410                                       
00411                 return;
00412         }
00413 
00414         fstrcpy(state->response.data.domain_info.name,
00415                 domain->name);
00416         fstrcpy(state->response.data.domain_info.alt_name,
00417                 domain->alt_name);
00418         fstrcpy(state->response.data.domain_info.sid,
00419                 sid_string_static(&domain->sid));
00420         
00421         state->response.data.domain_info.native_mode =
00422                 domain->native_mode;
00423         state->response.data.domain_info.active_directory =
00424                 domain->active_directory;
00425         state->response.data.domain_info.primary =
00426                 domain->primary;
00427         state->response.data.domain_info.sequence_number =
00428                 domain->sequence_number;
00429 
00430         request_ok(state);
00431 }
00432 
00433 static void domain_info_init_recv(void *private_data, BOOL success)
00434 {
00435         struct domain_info_state *istate =
00436                 (struct domain_info_state *)private_data;
00437         struct winbindd_cli_state *state = istate->cli_state;
00438         struct winbindd_domain *domain = istate->domain;
00439 
00440         DEBUG(10, ("Got back from child init: %d\n", success));
00441 
00442         if ((!success) || (!domain->initialized)) {
00443                 DEBUG(5, ("Could not init child for domain %s\n",
00444                           domain->name));
00445                 request_error(state);
00446                 return;
00447         }
00448 
00449         fstrcpy(state->response.data.domain_info.name,
00450                 domain->name);
00451         fstrcpy(state->response.data.domain_info.alt_name,
00452                 domain->alt_name);
00453         fstrcpy(state->response.data.domain_info.sid,
00454                 sid_string_static(&domain->sid));
00455         
00456         state->response.data.domain_info.native_mode =
00457                 domain->native_mode;
00458         state->response.data.domain_info.active_directory =
00459                 domain->active_directory;
00460         state->response.data.domain_info.primary =
00461                 domain->primary;
00462         state->response.data.domain_info.sequence_number =
00463                 domain->sequence_number;
00464 
00465         request_ok(state);
00466 }
00467 
00468 void winbindd_ping(struct winbindd_cli_state *state)
00469 {
00470         DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
00471         request_ok(state);
00472 }
00473 
00474 /* List various tidbits of information */
00475 
00476 void winbindd_info(struct winbindd_cli_state *state)
00477 {
00478 
00479         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
00480 
00481         state->response.data.info.winbind_separator = *lp_winbind_separator();
00482         fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
00483         request_ok(state);
00484 }
00485 
00486 /* Tell the client the current interface version */
00487 
00488 void winbindd_interface_version(struct winbindd_cli_state *state)
00489 {
00490         DEBUG(3, ("[%5lu]: request interface version\n",
00491                   (unsigned long)state->pid));
00492         
00493         state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
00494         request_ok(state);
00495 }
00496 
00497 /* What domain are we a member of? */
00498 
00499 void winbindd_domain_name(struct winbindd_cli_state *state)
00500 {
00501         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
00502         
00503         fstrcpy(state->response.data.domain_name, lp_workgroup());
00504         request_ok(state);
00505 }
00506 
00507 /* What's my name again? */
00508 
00509 void winbindd_netbios_name(struct winbindd_cli_state *state)
00510 {
00511         DEBUG(3, ("[%5lu]: request netbios name\n",
00512                   (unsigned long)state->pid));
00513         
00514         fstrcpy(state->response.data.netbios_name, global_myname());
00515         request_ok(state);
00516 }
00517 
00518 /* Where can I find the privilaged pipe? */
00519 
00520 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
00521 {
00522 
00523         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
00524                   (unsigned long)state->pid));
00525         
00526         state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
00527         if (!state->response.extra_data.data) {
00528                 DEBUG(0, ("malloc failed\n"));
00529                 request_error(state);
00530                 return;
00531         }
00532 
00533         /* must add one to length to copy the 0 for string termination */
00534         state->response.length +=
00535                 strlen((char *)state->response.extra_data.data) + 1;
00536 
00537         request_ok(state);
00538 }

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