root/source3/winbindd/winbindd_misc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. winbindd_check_machine_acct
  2. winbindd_dual_check_machine_acct
  3. get_ent_type_string
  4. winbindd_list_ent
  5. listent_recv
  6. get_trust_type
  7. get_trust_type_string
  8. trust_is_inbound
  9. trust_is_outbound
  10. trust_is_transitive
  11. winbindd_list_trusted_domains
  12. winbindd_dual_list_trusted_domains
  13. winbindd_getdcname
  14. winbindd_dual_getdcname
  15. winbindd_show_sequence
  16. sequence_recv
  17. winbindd_dual_show_sequence
  18. winbindd_domain_info
  19. domain_info_init_recv
  20. winbindd_ping
  21. winbindd_info
  22. winbindd_interface_version
  23. winbindd_domain_name
  24. winbindd_netbios_name
  25. winbindd_priv_pipe_dir

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Winbind daemon - miscellaneous other functions
   5 
   6    Copyright (C) Tim Potter      2000
   7    Copyright (C) Andrew Bartlett 2002
   8    
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 #include "winbindd.h"
  25 
  26 #undef DBGC_CLASS
  27 #define DBGC_CLASS DBGC_WINBIND
  28 
  29 /* Check the machine account password is valid */
  30 
  31 void winbindd_check_machine_acct(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
  32 {
  33         DEBUG(3, ("[%5lu]: check machine account\n",
  34                   (unsigned long)state->pid));
  35 
  36         sendto_domain(state, find_our_domain());
  37 }
  38 
  39 enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *domain,
     /* [<][>][^][v][top][bottom][index][help] */
  40                                                       struct winbindd_cli_state *state)
  41 {
  42         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
  43         int num_retries = 0;
  44         struct winbindd_domain *contact_domain;
  45 
  46         DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
  47 
  48         /* Get trust account password */
  49 
  50  again:
  51 
  52         contact_domain = find_our_domain();
  53         
  54         /* This call does a cli_nt_setup_creds() which implicitly checks
  55            the trust account password. */
  56 
  57         invalidate_cm_connection(&contact_domain->conn);
  58 
  59         {
  60                 struct rpc_pipe_client *netlogon_pipe;
  61                 result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
  62         }
  63 
  64         if (!NT_STATUS_IS_OK(result)) {
  65                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
  66                 goto done;
  67         }
  68 
  69         /* There is a race condition between fetching the trust account
  70            password and the periodic machine password change.  So it's 
  71            possible that the trust account password has been changed on us.  
  72            We are returned NT_STATUS_ACCESS_DENIED if this happens. */
  73 
  74 #define MAX_RETRIES 8
  75 
  76         if ((num_retries < MAX_RETRIES) && 
  77             NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
  78                 num_retries++;
  79                 goto again;
  80         }
  81 
  82         /* Pass back result code - zero for success, other values for
  83            specific failures. */
  84 
  85         DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ?  
  86                   "good" : "bad"));
  87 
  88  done:
  89         set_auth_errors(&state->response, result);
  90 
  91         DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", 
  92                                                 state->response.data.auth.nt_status_string));
  93 
  94         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
  95 }
  96 
  97 /* Helpers for listing user and group names */
  98 
  99 const char *ent_type_strings[] = {"users", 
 100                                   "groups"};
 101 
 102 static const char *get_ent_type_string(enum ent_type type)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         return ent_type_strings[type];
 105 }
 106 
 107 struct listent_state {
 108         TALLOC_CTX *mem_ctx;
 109         struct winbindd_cli_state *cli_state;
 110         enum ent_type type;
 111         int domain_count;
 112         char *extra_data;
 113         uint32_t extra_data_len;
 114 };
 115 
 116 static void listent_recv(void *private_data, bool success, fstring dom_name,
 117                          char *extra_data);
 118 
 119 /* List domain users/groups without mapping to unix ids */
 120 void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type)
     /* [<][>][^][v][top][bottom][index][help] */
 121 {
 122         struct winbindd_domain *domain;
 123         const char *which_domain;
 124         struct listent_state *ent_state;
 125 
 126         DEBUG(3, ("[%5lu]: list %s\n", (unsigned long)state->pid, 
 127               get_ent_type_string(type)));
 128 
 129         /* Ensure null termination */
 130         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';  
 131         which_domain = state->request.domain_name;
 132         
 133         /* Initialize listent_state */
 134         ent_state = TALLOC_P(state->mem_ctx, struct listent_state);
 135         if (ent_state == NULL) {
 136                 DEBUG(0, ("talloc failed\n"));
 137                 request_error(state);
 138                 return;
 139         }
 140 
 141         ent_state->mem_ctx = state->mem_ctx;
 142         ent_state->cli_state = state;
 143         ent_state->type = type;
 144         ent_state->domain_count = 0;
 145         ent_state->extra_data = NULL;
 146         ent_state->extra_data_len = 0;
 147 
 148         /* Must count the full list of expected domains before we request data
 149          * from any of them.  Otherwise it's possible for a connection to the
 150          * first domain to fail, call listent_recv(), and return to the
 151          * client without checking any other domains. */
 152         for (domain = domain_list(); domain; domain = domain->next) {
 153                 /* if we have a domain name restricting the request and this
 154                    one in the list doesn't match, then just bypass the remainder
 155                    of the loop */
 156                 if ( *which_domain && !strequal(which_domain, domain->name) )
 157                         continue;
 158 
 159                 ent_state->domain_count++;
 160         }
 161 
 162         /* Make sure we're enumerating at least one domain */
 163         if (!ent_state->domain_count) {
 164                 request_ok(state);
 165                 return;
 166         }
 167 
 168         /* Enumerate list of trusted domains and request user/group list from
 169          * each */
 170         for (domain = domain_list(); domain; domain = domain->next) {
 171                 if ( *which_domain && !strequal(which_domain, domain->name) )
 172                         continue;
 173 
 174                 winbindd_listent_async(state->mem_ctx, domain, 
 175                                           listent_recv, ent_state, type);
 176         }
 177 }
 178 
 179 static void listent_recv(void *private_data, bool success, fstring dom_name,
     /* [<][>][^][v][top][bottom][index][help] */
 180                          char *extra_data)
 181 {
 182         /* extra_data comes to us as a '\0' terminated string of comma
 183            separated users or groups */
 184         struct listent_state *state = talloc_get_type_abort(
 185                 private_data, struct listent_state);
 186 
 187         /* Append users/groups from one domain onto the whole list */
 188         if (extra_data) {
 189                 DEBUG(5, ("listent_recv: %s returned %s.\n", 
 190                       dom_name, get_ent_type_string(state->type)));
 191                 if (!state->extra_data)
 192                         state->extra_data = talloc_asprintf(state->mem_ctx,
 193                                                             "%s", extra_data);
 194                 else
 195                         state->extra_data = talloc_asprintf_append(
 196                                                             state->extra_data,
 197                                                             ",%s", extra_data);
 198                 /* Add one for the '\0' and each additional ',' */
 199                 state->extra_data_len += strlen(extra_data) + 1;
 200         }
 201         else {
 202                 DEBUG(5, ("listent_recv: %s returned no %s.\n", 
 203                       dom_name, get_ent_type_string(state->type)));
 204         }
 205 
 206         if (--state->domain_count)
 207                 /* Still waiting for some child domains to return */
 208                 return;
 209 
 210         /* Return list of all users/groups to the client */
 211         if (state->extra_data) {
 212                 state->cli_state->response.extra_data.data = 
 213                         SMB_STRDUP(state->extra_data);
 214                 state->cli_state->response.length += state->extra_data_len;
 215         }
 216 
 217         request_ok(state->cli_state);
 218 }       
 219 
 220 /* Constants and helper functions for determining domain trust types */
 221 
 222 enum trust_type {
 223         EXTERNAL = 0,
 224         FOREST,
 225         IN_FOREST,
 226         NONE,
 227 };
 228 
 229 const char *trust_type_strings[] = {"External", 
 230                                     "Forest", 
 231                                     "In Forest",
 232                                     "None"};
 233 
 234 static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236         if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)   
 237                 return EXTERNAL;
 238         else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)
 239                 return FOREST;
 240         else if (((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) == NETR_TRUST_FLAG_IN_FOREST) &&
 241             ((domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) == 0x0))
 242                 return IN_FOREST;
 243         return NONE;    
 244 }
 245 
 246 static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 247 {
 248         return trust_type_strings[get_trust_type(domain)];
 249 }
 250 
 251 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 252 {
 253         return (domain->trust_flags == 0x0) ||
 254             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
 255             NETR_TRUST_FLAG_IN_FOREST) ||                       
 256             ((domain->trust_flags & NETR_TRUST_FLAG_INBOUND) ==
 257             NETR_TRUST_FLAG_INBOUND);           
 258 }
 259 
 260 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 261 {
 262         return (domain->trust_flags == 0x0) ||
 263             ((domain->trust_flags & NETR_TRUST_FLAG_IN_FOREST) ==
 264             NETR_TRUST_FLAG_IN_FOREST) ||                       
 265             ((domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) ==
 266             NETR_TRUST_FLAG_OUTBOUND);          
 267 }
 268 
 269 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 270 {
 271         if ((domain->trust_attribs == NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE) ||         
 272             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ||
 273             (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL))
 274                 return False;
 275         return True;
 276 }
 277 
 278 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280         struct winbindd_tdc_domain *dom_list = NULL;
 281         struct winbindd_tdc_domain *d = NULL;
 282         size_t num_domains = 0;
 283         int extra_data_len = 0;
 284         char *extra_data = NULL;
 285         int i = 0;
 286         
 287         DEBUG(3, ("[%5lu]: list trusted domains\n",
 288                   (unsigned long)state->pid));
 289 
 290         if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
 291                 request_error(state);   
 292                 goto done;
 293         }
 294 
 295         for ( i = 0; i < num_domains; i++ ) {
 296                 struct winbindd_domain *domain;
 297                 bool is_online = true;          
 298 
 299                 d = &dom_list[i];
 300                 domain = find_domain_from_name_noinit(d->domain_name);
 301                 if (domain) {
 302                         is_online = domain->online;
 303                 }
 304 
 305                 if ( !extra_data ) {
 306                         extra_data = talloc_asprintf(state->mem_ctx, 
 307                                                      "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
 308                                                      d->domain_name,
 309                                                      d->dns_name ? d->dns_name : d->domain_name,
 310                                                      sid_string_talloc(state->mem_ctx, &d->sid),
 311                                                      get_trust_type_string(d),
 312                                                      trust_is_transitive(d) ? "Yes" : "No",
 313                                                      trust_is_inbound(d) ? "Yes" : "No",
 314                                                      trust_is_outbound(d) ? "Yes" : "No",
 315                                                      is_online ? "Online" : "Offline" );
 316                 } else {
 317                         extra_data = talloc_asprintf(state->mem_ctx, 
 318                                                      "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
 319                                                      extra_data,
 320                                                      d->domain_name,
 321                                                      d->dns_name ? d->dns_name : d->domain_name,
 322                                                      sid_string_talloc(state->mem_ctx, &d->sid),
 323                                                      get_trust_type_string(d),
 324                                                      trust_is_transitive(d) ? "Yes" : "No",
 325                                                      trust_is_inbound(d) ? "Yes" : "No",
 326                                                      trust_is_outbound(d) ? "Yes" : "No",
 327                                                      is_online ? "Online" : "Offline" );
 328                 }
 329         }
 330         
 331         extra_data_len = 0;
 332         if (extra_data != NULL) {
 333                 extra_data_len = strlen(extra_data);
 334         }
 335 
 336         if (extra_data_len > 0) {
 337                 state->response.extra_data.data = SMB_STRDUP(extra_data);
 338                 state->response.length += extra_data_len+1;
 339         }
 340 
 341         request_ok(state);      
 342 done:
 343         TALLOC_FREE( dom_list );
 344         TALLOC_FREE( extra_data );      
 345 }
 346 
 347 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 348                                                         struct winbindd_cli_state *state)
 349 {
 350         uint32 i, num_domains;
 351         char **names, **alt_names;
 352         DOM_SID *sids;
 353         int extra_data_len = 0;
 354         char *extra_data;
 355         NTSTATUS result;
 356         bool have_own_domain = False;
 357 
 358         DEBUG(3, ("[%5lu]: list trusted domains\n",
 359                   (unsigned long)state->pid));
 360 
 361         result = domain->methods->trusted_domains(domain, state->mem_ctx,
 362                                                   &num_domains, &names,
 363                                                   &alt_names, &sids);
 364 
 365         if (!NT_STATUS_IS_OK(result)) {
 366                 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
 367                         nt_errstr(result) ));
 368                 return WINBINDD_ERROR;
 369         }
 370 
 371         extra_data = talloc_strdup(state->mem_ctx, "");
 372 
 373         if (num_domains > 0)
 374                 extra_data = talloc_asprintf(
 375                         state->mem_ctx, "%s\\%s\\%s",
 376                         names[0], alt_names[0] ? alt_names[0] : names[0],
 377                         sid_string_talloc(state->mem_ctx, &sids[0]));
 378 
 379         for (i=1; i<num_domains; i++)
 380                 extra_data = talloc_asprintf(
 381                         state->mem_ctx, "%s\n%s\\%s\\%s",
 382                         extra_data, names[i],
 383                         alt_names[i] ? alt_names[i] : names[i],
 384                         sid_string_talloc(state->mem_ctx, &sids[i]));
 385 
 386         /* add our primary domain */
 387         
 388         for (i=0; i<num_domains; i++) {
 389                 if (strequal(names[i], domain->name)) {
 390                         have_own_domain = True;
 391                         break;
 392                 }
 393         }
 394 
 395         if (state->request.data.list_all_domains && !have_own_domain) {
 396                 extra_data = talloc_asprintf(
 397                         state->mem_ctx, "%s\n%s\\%s\\%s",
 398                         extra_data, domain->name,
 399                         domain->alt_name ? domain->alt_name : domain->name,
 400                         sid_string_talloc(state->mem_ctx, &domain->sid));
 401         }
 402 
 403         /* This is a bit excessive, but the extra data sooner or later will be
 404            talloc'ed */
 405 
 406         extra_data_len = 0;
 407         if (extra_data != NULL) {
 408                 extra_data_len = strlen(extra_data);
 409         }
 410 
 411         if (extra_data_len > 0) {
 412                 state->response.extra_data.data = SMB_STRDUP(extra_data);
 413                 state->response.length += extra_data_len+1;
 414         }
 415 
 416         return WINBINDD_OK;
 417 }
 418 
 419 void winbindd_getdcname(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 420 {
 421         struct winbindd_domain *domain;
 422 
 423         state->request.domain_name
 424                 [sizeof(state->request.domain_name)-1] = '\0';
 425 
 426         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
 427                   state->request.domain_name));
 428 
 429         domain = find_domain_from_name_noinit(state->request.domain_name);
 430         if (domain && domain->internal) {
 431                 fstrcpy(state->response.data.dc_name, global_myname());
 432                 request_ok(state);      
 433                 return;
 434         }
 435 
 436         sendto_domain(state, find_our_domain());
 437 }
 438 
 439 enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 440                                              struct winbindd_cli_state *state)
 441 {
 442         const char *dcname_slash = NULL;
 443         const char *p;
 444         struct rpc_pipe_client *netlogon_pipe;
 445         NTSTATUS result;
 446         WERROR werr;
 447         unsigned int orig_timeout;
 448         struct winbindd_domain *req_domain;
 449 
 450         state->request.domain_name
 451                 [sizeof(state->request.domain_name)-1] = '\0';
 452 
 453         DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
 454                   state->request.domain_name));
 455 
 456         result = cm_connect_netlogon(domain, &netlogon_pipe);
 457 
 458         if (!NT_STATUS_IS_OK(result)) {
 459                 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
 460                 return WINBINDD_ERROR;
 461         }
 462 
 463         /* This call can take a long time - allow the server to time out.
 464            35 seconds should do it. */
 465 
 466         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
 467 
 468         req_domain = find_domain_from_name_noinit(state->request.domain_name);
 469         if (req_domain == domain) {
 470                 result = rpccli_netr_GetDcName(netlogon_pipe,
 471                                                state->mem_ctx,
 472                                                domain->dcname,
 473                                                state->request.domain_name,
 474                                                &dcname_slash,
 475                                                &werr);
 476         } else {
 477                 result = rpccli_netr_GetAnyDCName(netlogon_pipe,
 478                                                   state->mem_ctx,
 479                                                   domain->dcname,
 480                                                   state->request.domain_name,
 481                                                   &dcname_slash,
 482                                                   &werr);
 483         }
 484         /* And restore our original timeout. */
 485         rpccli_set_timeout(netlogon_pipe, orig_timeout);
 486 
 487         if (!NT_STATUS_IS_OK(result)) {
 488                 DEBUG(5,("Error requesting DCname for domain %s: %s\n",
 489                         state->request.domain_name, nt_errstr(result)));
 490                 return WINBINDD_ERROR;
 491         }
 492 
 493         if (!W_ERROR_IS_OK(werr)) {
 494                 DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
 495                         state->request.domain_name, win_errstr(werr)));
 496                 return WINBINDD_ERROR;
 497         }
 498 
 499         p = dcname_slash;
 500         if (*p == '\\') {
 501                 p+=1;
 502         }
 503         if (*p == '\\') {
 504                 p+=1;
 505         }
 506 
 507         fstrcpy(state->response.data.dc_name, p);
 508         return WINBINDD_OK;
 509 }
 510 
 511 struct sequence_state {
 512         TALLOC_CTX *mem_ctx;
 513         struct winbindd_cli_state *cli_state;
 514         struct winbindd_domain *domain;
 515         struct winbindd_request *request;
 516         struct winbindd_response *response;
 517         char *extra_data;
 518 };
 519 
 520 static void sequence_recv(void *private_data, bool success);
 521 
 522 void winbindd_show_sequence(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 523 {
 524         struct sequence_state *seq;
 525 
 526         /* Ensure null termination */
 527         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
 528 
 529         if (strlen(state->request.domain_name) > 0) {
 530                 struct winbindd_domain *domain;
 531                 domain = find_domain_from_name_noinit(
 532                         state->request.domain_name);
 533                 if (domain == NULL) {
 534                         request_error(state);
 535                         return;
 536                 }
 537                 sendto_domain(state, domain);
 538                 return;
 539         }
 540 
 541         /* Ask all domains in sequence, collect the results in sequence_recv */
 542 
 543         seq = TALLOC_P(state->mem_ctx, struct sequence_state);
 544         if (seq == NULL) {
 545                 DEBUG(0, ("talloc failed\n"));
 546                 request_error(state);
 547                 return;
 548         }
 549 
 550         seq->mem_ctx = state->mem_ctx;
 551         seq->cli_state = state;
 552         seq->domain = domain_list();
 553         if (seq->domain == NULL) {
 554                 DEBUG(0, ("domain list empty\n"));
 555                 request_error(state);
 556                 return;
 557         }
 558         seq->request = TALLOC_ZERO_P(state->mem_ctx,
 559                                      struct winbindd_request);
 560         seq->response = TALLOC_ZERO_P(state->mem_ctx,
 561                                       struct winbindd_response);
 562         seq->extra_data = talloc_strdup(state->mem_ctx, "");
 563 
 564         if ((seq->request == NULL) || (seq->response == NULL) ||
 565             (seq->extra_data == NULL)) {
 566                 DEBUG(0, ("talloc failed\n"));
 567                 request_error(state);
 568                 return;
 569         }
 570 
 571         seq->request->length = sizeof(*seq->request);
 572         seq->request->cmd = WINBINDD_SHOW_SEQUENCE;
 573         fstrcpy(seq->request->domain_name, seq->domain->name);
 574 
 575         async_domain_request(state->mem_ctx, seq->domain,
 576                              seq->request, seq->response,
 577                              sequence_recv, seq);
 578 }
 579 
 580 static void sequence_recv(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 581 {
 582         struct sequence_state *state =
 583                 (struct sequence_state *)private_data;
 584         uint32 seq = DOM_SEQUENCE_NONE;
 585 
 586         if ((success) && (state->response->result == WINBINDD_OK))
 587                 seq = state->response->data.sequence_number;
 588 
 589         if (seq == DOM_SEQUENCE_NONE) {
 590                 state->extra_data = talloc_asprintf(state->mem_ctx,
 591                                                     "%s%s : DISCONNECTED\n",
 592                                                     state->extra_data,
 593                                                     state->domain->name);
 594         } else {
 595                 state->extra_data = talloc_asprintf(state->mem_ctx,
 596                                                     "%s%s : %d\n",
 597                                                     state->extra_data,
 598                                                     state->domain->name, seq);
 599         }
 600 
 601         state->domain->sequence_number = seq;
 602 
 603         state->domain = state->domain->next;
 604 
 605         if (state->domain == NULL) {
 606                 struct winbindd_cli_state *cli_state = state->cli_state;
 607                 cli_state->response.length =
 608                         sizeof(cli_state->response) +
 609                         strlen(state->extra_data) + 1;
 610                 cli_state->response.extra_data.data =
 611                         SMB_STRDUP(state->extra_data);
 612                 request_ok(cli_state);
 613                 return;
 614         }
 615 
 616         /* Ask the next domain */
 617         fstrcpy(state->request->domain_name, state->domain->name);
 618         async_domain_request(state->mem_ctx, state->domain,
 619                              state->request, state->response,
 620                              sequence_recv, state);
 621 }
 622 
 623 /* This is the child-only version of --sequence. It only allows for a single
 624  * domain (ie "our" one) to be displayed. */
 625 
 626 enum winbindd_result winbindd_dual_show_sequence(struct winbindd_domain *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 627                                                  struct winbindd_cli_state *state)
 628 {
 629         DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid));
 630 
 631         /* Ensure null termination */
 632         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
 633 
 634         domain->methods->sequence_number(domain, &domain->sequence_number);
 635 
 636         state->response.data.sequence_number =
 637                 domain->sequence_number;
 638 
 639         return WINBINDD_OK;
 640 }
 641 
 642 struct domain_info_state {
 643         struct winbindd_domain *domain;
 644         struct winbindd_cli_state *cli_state;
 645 };
 646 
 647 static void domain_info_init_recv(void *private_data, bool success);
 648 
 649 void winbindd_domain_info(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 650 {
 651         struct winbindd_domain *domain;
 652 
 653         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)state->pid,
 654                   state->request.domain_name));
 655 
 656         domain = find_domain_from_name_noinit(state->request.domain_name);
 657 
 658         if (domain == NULL) {
 659                 DEBUG(3, ("Did not find domain [%s]\n",
 660                           state->request.domain_name));
 661                 request_error(state);
 662                 return;
 663         }
 664 
 665         if (!domain->initialized) {
 666                 struct domain_info_state *istate;
 667 
 668                 istate = TALLOC_P(state->mem_ctx, struct domain_info_state);
 669                 if (istate == NULL) {
 670                         DEBUG(0, ("talloc failed\n"));
 671                         request_error(state);
 672                         return;
 673                 }
 674 
 675                 istate->cli_state = state;
 676                 istate->domain = domain;
 677 
 678                 init_child_connection(domain, domain_info_init_recv, istate);
 679                                       
 680                 return;
 681         }
 682 
 683         fstrcpy(state->response.data.domain_info.name,
 684                 domain->name);
 685         fstrcpy(state->response.data.domain_info.alt_name,
 686                 domain->alt_name);
 687         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
 688         
 689         state->response.data.domain_info.native_mode =
 690                 domain->native_mode;
 691         state->response.data.domain_info.active_directory =
 692                 domain->active_directory;
 693         state->response.data.domain_info.primary =
 694                 domain->primary;
 695 
 696         request_ok(state);
 697 }
 698 
 699 static void domain_info_init_recv(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 700 {
 701         struct domain_info_state *istate =
 702                 (struct domain_info_state *)private_data;
 703         struct winbindd_cli_state *state = istate->cli_state;
 704         struct winbindd_domain *domain = istate->domain;
 705 
 706         DEBUG(10, ("Got back from child init: %d\n", success));
 707 
 708         if ((!success) || (!domain->initialized)) {
 709                 DEBUG(5, ("Could not init child for domain %s\n",
 710                           domain->name));
 711                 request_error(state);
 712                 return;
 713         }
 714 
 715         fstrcpy(state->response.data.domain_info.name,
 716                 domain->name);
 717         fstrcpy(state->response.data.domain_info.alt_name,
 718                 domain->alt_name);
 719         sid_to_fstring(state->response.data.domain_info.sid, &domain->sid);
 720         
 721         state->response.data.domain_info.native_mode =
 722                 domain->native_mode;
 723         state->response.data.domain_info.active_directory =
 724                 domain->active_directory;
 725         state->response.data.domain_info.primary =
 726                 domain->primary;
 727 
 728         request_ok(state);
 729 }
 730 
 731 void winbindd_ping(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 732 {
 733         DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
 734         request_ok(state);
 735 }
 736 
 737 /* List various tidbits of information */
 738 
 739 void winbindd_info(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 740 {
 741 
 742         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
 743 
 744         state->response.data.info.winbind_separator = *lp_winbind_separator();
 745         fstrcpy(state->response.data.info.samba_version, samba_version_string());
 746         request_ok(state);
 747 }
 748 
 749 /* Tell the client the current interface version */
 750 
 751 void winbindd_interface_version(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 752 {
 753         DEBUG(3, ("[%5lu]: request interface version\n",
 754                   (unsigned long)state->pid));
 755         
 756         state->response.data.interface_version = WINBIND_INTERFACE_VERSION;
 757         request_ok(state);
 758 }
 759 
 760 /* What domain are we a member of? */
 761 
 762 void winbindd_domain_name(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 763 {
 764         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
 765         
 766         fstrcpy(state->response.data.domain_name, lp_workgroup());
 767         request_ok(state);
 768 }
 769 
 770 /* What's my name again? */
 771 
 772 void winbindd_netbios_name(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 773 {
 774         DEBUG(3, ("[%5lu]: request netbios name\n",
 775                   (unsigned long)state->pid));
 776         
 777         fstrcpy(state->response.data.netbios_name, global_myname());
 778         request_ok(state);
 779 }
 780 
 781 /* Where can I find the privilaged pipe? */
 782 
 783 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 784 {
 785 
 786         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
 787                   (unsigned long)state->pid));
 788         
 789         state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
 790         if (!state->response.extra_data.data) {
 791                 DEBUG(0, ("malloc failed\n"));
 792                 request_error(state);
 793                 return;
 794         }
 795 
 796         /* must add one to length to copy the 0 for string termination */
 797         state->response.length +=
 798                 strlen((char *)state->response.extra_data.data) + 1;
 799 
 800         request_ok(state);
 801 }
 802 

/* [<][>][^][v][top][bottom][index][help] */