nsswitch/winbindd_user.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Winbind daemon - user related functions
00005 
00006    Copyright (C) Tim Potter 2000
00007    Copyright (C) Jeremy Allison 2001.
00008    Copyright (C) Gerald (Jerry) Carter 2003.
00009    
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 #include "winbindd.h"
00027 
00028 #undef DBGC_CLASS
00029 #define DBGC_CLASS DBGC_WINBIND
00030 
00031 static BOOL fillup_pw_field(const char *lp_template, 
00032                             const char *username, 
00033                             const char *domname,
00034                             uid_t uid,
00035                             gid_t gid,
00036                             const char *in, 
00037                             fstring out)
00038 {
00039         char *templ;
00040 
00041         if (out == NULL)
00042                 return False;
00043 
00044         /* The substitution of %U and %D in the 'template 
00045            homedir' is done by talloc_sub_specified() below.
00046            If we have an in string (which means the value has already
00047            been set in the nss_info backend), then use that.
00048            Otherwise use the template value passed in. */
00049 
00050         if ( in && !strequal(in,"") && lp_security() == SEC_ADS ) {
00051                 templ = talloc_sub_specified(NULL, in, 
00052                                              username, domname,
00053                                      uid, gid);
00054         } else {
00055                 templ = talloc_sub_specified(NULL, lp_template, 
00056                                              username, domname,
00057                                              uid, gid);         
00058         }
00059                 
00060         if (!templ)
00061                 return False;
00062 
00063         safe_strcpy(out, templ, sizeof(fstring) - 1);
00064         TALLOC_FREE(templ);
00065                 
00066         return True;
00067         
00068 }
00069 /* Fill a pwent structure with information we have obtained */
00070 
00071 static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, 
00072                                 DOM_SID *user_sid, DOM_SID *group_sid,
00073                                 char *full_name, char *homedir, char *shell,
00074                                 struct winbindd_pw *pw)
00075 {
00076         fstring output_username;
00077         fstring sid_string;
00078         
00079         if (!pw || !dom_name || !user_name)
00080                 return False;
00081         
00082         /* Resolve the uid number */
00083 
00084         if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid))) {
00085                 DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid)));
00086                 return False;
00087         }
00088         
00089         /* Resolve the gid number */   
00090 
00091         if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid))) {
00092                 DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid)));
00093                 return False;
00094         }
00095 
00096         strlower_m(user_name);
00097 
00098         /* Username */
00099 
00100         fill_domain_username(output_username, dom_name, user_name, True); 
00101 
00102         safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
00103         
00104         /* Full name (gecos) */
00105         
00106         safe_strcpy(pw->pw_gecos, full_name, sizeof(pw->pw_gecos) - 1);
00107 
00108         /* Home directory and shell - use template config parameters.  The
00109            defaults are /tmp for the home directory and /bin/false for
00110            shell. */
00111         
00112         if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, 
00113                              pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir))
00114                 return False;
00115 
00116         if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, 
00117                              pw->pw_uid, pw->pw_gid, shell, pw->pw_shell))
00118                 return False;
00119 
00120         /* Password - set to "*" as we can't generate anything useful here.
00121            Authentication can be done using the pam_winbind module. */
00122 
00123         safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
00124 
00125         return True;
00126 }
00127 
00128 /* Wrapper for domain->methods->query_user, only on the parent->child pipe */
00129 
00130 enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain,
00131                                             struct winbindd_cli_state *state)
00132 {
00133         DOM_SID sid;
00134         WINBIND_USERINFO user_info;
00135         NTSTATUS status;
00136 
00137         /* Ensure null termination */
00138         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
00139 
00140         DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
00141                   state->request.data.sid));
00142 
00143         if (!string_to_sid(&sid, state->request.data.sid)) {
00144                 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
00145                 return WINBINDD_ERROR;
00146         }
00147 
00148         status = domain->methods->query_user(domain, state->mem_ctx,
00149                                              &sid, &user_info);
00150         if (!NT_STATUS_IS_OK(status)) {
00151                 DEBUG(1, ("error getting user info for sid %s\n",
00152                           sid_string_static(&sid)));
00153                 return WINBINDD_ERROR;
00154         }
00155 
00156         fstrcpy(state->response.data.user_info.acct_name, user_info.acct_name);
00157         fstrcpy(state->response.data.user_info.full_name, user_info.full_name);
00158         fstrcpy(state->response.data.user_info.homedir, user_info.homedir);
00159         fstrcpy(state->response.data.user_info.shell, user_info.shell);
00160         state->response.data.user_info.primary_gid = user_info.primary_gid;     
00161         if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid,
00162                                 &state->response.data.user_info.group_rid)) {
00163                 DEBUG(1, ("Could not extract group rid out of %s\n",
00164                           sid_string_static(&sid)));
00165                 return WINBINDD_ERROR;
00166         }
00167 
00168         return WINBINDD_OK;
00169 }
00170 
00171 struct getpwsid_state {
00172         struct winbindd_cli_state *state;
00173         struct winbindd_domain *domain;
00174         char *username;
00175         char *fullname;
00176         char *homedir;
00177         char *shell;
00178         DOM_SID user_sid;
00179         uid_t uid;
00180         DOM_SID group_sid;
00181         gid_t gid;
00182 };
00183 
00184 static void getpwsid_queryuser_recv(void *private_data, BOOL success,
00185                                     const char *acct_name,
00186                                     const char *full_name, 
00187                                     const char *homedir,
00188                                     const char *shell,
00189                                     uint32 gid,
00190                                     uint32 group_rid);
00191 static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid);
00192 static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid);
00193 
00194 static void winbindd_getpwsid(struct winbindd_cli_state *state,
00195                               const DOM_SID *sid)
00196 {
00197         struct getpwsid_state *s;
00198 
00199         s = TALLOC_ZERO_P(state->mem_ctx, struct getpwsid_state);
00200         if (s == NULL) {
00201                 DEBUG(0, ("talloc failed\n"));
00202                 goto error;
00203         }
00204 
00205         s->state = state;
00206         s->domain = find_domain_from_sid_noinit(sid);
00207         if (s->domain == NULL) {
00208                 DEBUG(3, ("Could not find domain for sid %s\n",
00209                           sid_string_static(sid)));
00210                 goto error;
00211         }
00212 
00213         sid_copy(&s->user_sid, sid);
00214 
00215         query_user_async(s->state->mem_ctx, s->domain, sid,
00216                          getpwsid_queryuser_recv, s);
00217         return;
00218 
00219  error:
00220         request_error(state);
00221 }
00222         
00223 static void getpwsid_queryuser_recv(void *private_data, BOOL success,
00224                                     const char *acct_name,
00225                                     const char *full_name, 
00226                                     const char *homedir,
00227                                     const char *shell,
00228                                     uint32 gid,
00229                                     uint32 group_rid)
00230 {
00231         fstring username;
00232         struct getpwsid_state *s =
00233                 talloc_get_type_abort(private_data, struct getpwsid_state);
00234 
00235         if (!success) {
00236                 DEBUG(5, ("Could not query domain %s SID %s\n", s->domain->name,
00237                           sid_string_static(&s->user_sid)));
00238                 request_error(s->state);
00239                 return;
00240         }
00241 
00242         fstrcpy( username, acct_name );
00243         strlower_m( username );
00244         s->username = talloc_strdup(s->state->mem_ctx, username);
00245 
00246         ws_name_replace( s->username, WB_REPLACE_CHAR );
00247          
00248         s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
00249         s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
00250         s->shell = talloc_strdup(s->state->mem_ctx, shell);
00251         s->gid = gid;   
00252         sid_copy(&s->group_sid, &s->domain->sid);
00253         sid_append_rid(&s->group_sid, group_rid);
00254 
00255         winbindd_sid2uid_async(s->state->mem_ctx, &s->user_sid,
00256                                getpwsid_sid2uid_recv, s);
00257 }
00258 
00259 static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid)
00260 {
00261         struct getpwsid_state *s =
00262                 talloc_get_type_abort(private_data, struct getpwsid_state);
00263 
00264         if (!success) {
00265                 DEBUG(5, ("Could not query uid for user %s\\%s\n",
00266                           s->domain->name, s->username));
00267                 request_error(s->state);
00268                 return;
00269         }
00270 
00271         s->uid = uid;
00272         winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid,
00273                                getpwsid_sid2gid_recv, s);
00274 }
00275 
00276 static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
00277 {
00278         struct getpwsid_state *s =
00279                 talloc_get_type_abort(private_data, struct getpwsid_state);
00280         struct winbindd_pw *pw;
00281         fstring output_username;
00282 
00283         /* allow the nss backend to override the primary group ID.
00284            If the gid has already been set, then keep it.
00285            This makes me feel dirty.  If the nss backend already
00286            gave us a gid, we don't really care whether the sid2gid()
00287            call worked or not.   --jerry  */
00288 
00289         if ( s->gid == (gid_t)-1 ) {
00290 
00291                 if (!success) {
00292                         DEBUG(5, ("Could not query gid for user %s\\%s\n",
00293                                   s->domain->name, s->username));
00294                         goto failed;
00295                 }
00296 
00297                 /* take what the sid2gid() call gave us */
00298                 s->gid = gid;
00299         }
00300 
00301         pw = &s->state->response.data.pw;
00302         pw->pw_uid = s->uid;
00303         pw->pw_gid = s->gid;
00304         fill_domain_username(output_username, s->domain->name, s->username, True); 
00305         safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
00306         safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1);
00307 
00308         if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, 
00309                              pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) {
00310                 DEBUG(5, ("Could not compose homedir\n"));
00311                 goto failed;
00312         }
00313 
00314         if (!fillup_pw_field(lp_template_shell(), s->username, s->domain->name, 
00315                              pw->pw_uid, pw->pw_gid, s->shell, pw->pw_shell)) {
00316                 DEBUG(5, ("Could not compose shell\n"));
00317                 goto failed;
00318         }
00319 
00320         /* Password - set to "*" as we can't generate anything useful here.
00321            Authentication can be done using the pam_winbind module. */
00322 
00323         safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
00324 
00325         request_ok(s->state);
00326         return;
00327 
00328  failed:
00329         request_error(s->state);
00330 }
00331 
00332 /* Return a password structure from a username.  */
00333 
00334 static void getpwnam_name2sid_recv(void *private_data, BOOL success,
00335                                    const DOM_SID *sid, enum lsa_SidType type);
00336 
00337 void winbindd_getpwnam(struct winbindd_cli_state *state)
00338 {
00339         struct winbindd_domain *domain;
00340         fstring domname, username;
00341 
00342         /* Ensure null termination */
00343         state->request.data.username[sizeof(state->request.data.username)-1]='\0';
00344 
00345         DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid,
00346                   state->request.data.username));
00347 
00348         ws_name_return( state->request.data.username, WB_REPLACE_CHAR );
00349 
00350         if (!parse_domain_user(state->request.data.username, domname,
00351                                username)) {
00352                 DEBUG(5, ("Could not parse domain user: %s\n",
00353                           state->request.data.username));
00354                 request_error(state);
00355                 return;
00356         }
00357         
00358         /* Get info for the domain */
00359 
00360         domain = find_domain_from_name(domname);
00361 
00362         if (domain == NULL) {
00363                 DEBUG(7, ("could not find domain entry for domain %s\n",
00364                           domname));
00365                 request_error(state);
00366                 return;
00367         }
00368 
00369         if ( strequal(domname, lp_workgroup()) && lp_winbind_trusted_domains_only() ) {
00370                 DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", 
00371                         domname, username));
00372                 request_error(state);
00373                 return;
00374         }       
00375 
00376         /* Get rid and name type from name.  The following costs 1 packet */
00377 
00378         winbindd_lookupname_async(state->mem_ctx, domname, username,
00379                                   getpwnam_name2sid_recv, state);
00380 }
00381 
00382 static void getpwnam_name2sid_recv(void *private_data, BOOL success,
00383                                    const DOM_SID *sid, enum lsa_SidType type)
00384 {
00385         struct winbindd_cli_state *state =
00386                 (struct winbindd_cli_state *)private_data;
00387 
00388         if (!success) {
00389                 DEBUG(5, ("Could not lookup name for user %s\n",
00390                           state->request.data.username));
00391                 request_error(state);
00392                 return;
00393         }
00394 
00395         if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
00396                 DEBUG(5, ("%s is not a user\n", state->request.data.username));
00397                 request_error(state);
00398                 return;
00399         }
00400 
00401         winbindd_getpwsid(state, sid);
00402 }
00403 
00404 static void getpwuid_recv(void *private_data, BOOL success, const char *sid)
00405 {
00406         struct winbindd_cli_state *state =
00407                 (struct winbindd_cli_state *)private_data;
00408         DOM_SID user_sid;
00409 
00410         if (!success) {
00411                 DEBUG(10,("uid2sid_recv: uid [%lu] to sid mapping failed\n.",
00412                           (unsigned long)(state->request.data.uid)));
00413                 request_error(state);
00414                 return;
00415         }
00416         
00417         DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n",
00418                   (unsigned long)(state->request.data.uid), sid));
00419 
00420         string_to_sid(&user_sid, sid);
00421         winbindd_getpwsid(state, &user_sid);
00422 }
00423 
00424 /* Return a password structure given a uid number */
00425 void winbindd_getpwuid(struct winbindd_cli_state *state)
00426 {
00427         DEBUG(3, ("[%5lu]: getpwuid %lu\n", (unsigned long)state->pid, 
00428                   (unsigned long)state->request.data.uid));
00429 
00430         /* always query idmap via the async interface */
00431         /* if this turns to be too slow we will add here a direct query to the cache */
00432         winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, getpwuid_recv, state);
00433 }
00434 
00435 /*
00436  * set/get/endpwent functions
00437  */
00438 
00439 /* Rewind file pointer for ntdom passwd database */
00440 
00441 static BOOL winbindd_setpwent_internal(struct winbindd_cli_state *state)
00442 {
00443         struct winbindd_domain *domain;
00444         
00445         DEBUG(3, ("[%5lu]: setpwent\n", (unsigned long)state->pid));
00446         
00447         /* Check user has enabled this */
00448         
00449         if (!lp_winbind_enum_users()) {
00450                 return False;
00451         }
00452 
00453         /* Free old static data if it exists */
00454         
00455         if (state->getpwent_state != NULL) {
00456                 free_getent_state(state->getpwent_state);
00457                 state->getpwent_state = NULL;
00458         }
00459 
00460 #if 0   /* JERRY */
00461         /* add any local users we have */
00462                 
00463         if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL )
00464                 return False;
00465                 
00466         ZERO_STRUCTP(domain_state);
00467 
00468         /* Add to list of open domains */
00469                 
00470         DLIST_ADD(state->getpwent_state, domain_state);
00471 #endif
00472         
00473         /* Create sam pipes for each domain we know about */
00474         
00475         for(domain = domain_list(); domain != NULL; domain = domain->next) {
00476                 struct getent_state *domain_state;
00477                 
00478                 
00479                 /* don't add our domaina if we are a PDC or if we 
00480                    are a member of a Samba domain */
00481                 
00482                 if ( (IS_DC || lp_winbind_trusted_domains_only())
00483                         && strequal(domain->name, lp_workgroup()) )
00484                 {
00485                         continue;
00486                 }
00487                                                 
00488                 /* Create a state record for this domain */
00489                 
00490                 if ((domain_state = SMB_MALLOC_P(struct getent_state)) == NULL) {
00491                         DEBUG(0, ("malloc failed\n"));
00492                         return False;
00493                 }
00494                 
00495                 ZERO_STRUCTP(domain_state);
00496 
00497                 fstrcpy(domain_state->domain_name, domain->name);
00498 
00499                 /* Add to list of open domains */
00500                 
00501                 DLIST_ADD(state->getpwent_state, domain_state);
00502         }
00503         
00504         state->getpwent_initialized = True;
00505         return True;
00506 }
00507 
00508 void winbindd_setpwent(struct winbindd_cli_state *state)
00509 {
00510         if (winbindd_setpwent_internal(state)) {
00511                 request_ok(state);
00512         } else {
00513                 request_error(state);
00514         }
00515 }
00516 
00517 /* Close file pointer to ntdom passwd database */
00518 
00519 void winbindd_endpwent(struct winbindd_cli_state *state)
00520 {
00521         DEBUG(3, ("[%5lu]: endpwent\n", (unsigned long)state->pid));
00522 
00523         free_getent_state(state->getpwent_state);    
00524         state->getpwent_initialized = False;
00525         state->getpwent_state = NULL;
00526         request_ok(state);
00527 }
00528 
00529 /* Get partial list of domain users for a domain.  We fill in the sam_entries,
00530    and num_sam_entries fields with domain user information.  The dispinfo_ndx
00531    field is incremented to the index of the next user to fetch.  Return True if
00532    some users were returned, False otherwise. */
00533 
00534 static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx)
00535 {
00536         NTSTATUS status;
00537         uint32 num_entries;
00538         WINBIND_USERINFO *info;
00539         struct getpwent_user *name_list = NULL;
00540         struct winbindd_domain *domain;
00541         struct winbindd_methods *methods;
00542         unsigned int i;
00543 
00544         if (ent->num_sam_entries)
00545                 return False;
00546 
00547         if (!(domain = find_domain_from_name(ent->domain_name))) {
00548                 DEBUG(3, ("no such domain %s in get_sam_user_entries\n",
00549                           ent->domain_name));
00550                 return False;
00551         }
00552 
00553         methods = domain->methods;
00554 
00555         /* Free any existing user info */
00556 
00557         SAFE_FREE(ent->sam_entries);
00558         ent->num_sam_entries = 0;
00559         
00560         /* Call query_user_list to get a list of usernames and user rids */
00561 
00562         num_entries = 0;
00563 
00564         status = methods->query_user_list(domain, mem_ctx, &num_entries, 
00565                                           &info);
00566                 
00567         if (!NT_STATUS_IS_OK(status)) {
00568                 DEBUG(10,("get_sam_user_entries: query_user_list failed with %s\n",
00569                         nt_errstr(status) ));
00570                 return False;
00571         }
00572 
00573         if (num_entries) {
00574                 name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries);
00575                 
00576                 if (!name_list) {
00577                         DEBUG(0,("get_sam_user_entries realloc failed.\n"));
00578                         return False;
00579                 }
00580         }
00581 
00582         for (i = 0; i < num_entries; i++) {
00583                 /* Store account name and gecos */
00584                 if (!info[i].acct_name) {
00585                         fstrcpy(name_list[ent->num_sam_entries + i].name, "");
00586                 } else {
00587                         fstrcpy(name_list[ent->num_sam_entries + i].name, 
00588                                 info[i].acct_name); 
00589                 }
00590                 if (!info[i].full_name) {
00591                         fstrcpy(name_list[ent->num_sam_entries + i].gecos, "");
00592                 } else {
00593                         fstrcpy(name_list[ent->num_sam_entries + i].gecos, 
00594                                 info[i].full_name); 
00595                 }
00596                 if (!info[i].homedir) {
00597                         fstrcpy(name_list[ent->num_sam_entries + i].homedir, "");
00598                 } else {
00599                         fstrcpy(name_list[ent->num_sam_entries + i].homedir, 
00600                                 info[i].homedir); 
00601                 }
00602                 if (!info[i].shell) {
00603                         fstrcpy(name_list[ent->num_sam_entries + i].shell, "");
00604                 } else {
00605                         fstrcpy(name_list[ent->num_sam_entries + i].shell, 
00606                                 info[i].shell); 
00607                 }
00608         
00609         
00610                 /* User and group ids */
00611                 sid_copy(&name_list[ent->num_sam_entries+i].user_sid,
00612                          &info[i].user_sid);
00613                 sid_copy(&name_list[ent->num_sam_entries+i].group_sid,
00614                          &info[i].group_sid);
00615         }
00616                 
00617         ent->num_sam_entries += num_entries;
00618         
00619         /* Fill in remaining fields */
00620         
00621         ent->sam_entries = name_list;
00622         ent->sam_entry_index = 0;
00623         return ent->num_sam_entries > 0;
00624 }
00625 
00626 /* Fetch next passwd entry from ntdom database */
00627 
00628 #define MAX_GETPWENT_USERS 500
00629 
00630 void winbindd_getpwent(struct winbindd_cli_state *state)
00631 {
00632         struct getent_state *ent;
00633         struct winbindd_pw *user_list;
00634         int num_users, user_list_ndx;
00635 
00636         DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)state->pid));
00637 
00638         /* Check user has enabled this */
00639 
00640         if (!lp_winbind_enum_users()) {
00641                 request_error(state);
00642                 return;
00643         }
00644 
00645         /* Allocate space for returning a chunk of users */
00646 
00647         num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries);
00648 
00649         if (num_users == 0) {
00650                 request_error(state);
00651                 return;
00652         }
00653         
00654         if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) {
00655                 request_error(state);
00656                 return;
00657         }
00658 
00659         memset(state->response.extra_data.data, 0, num_users * 
00660                sizeof(struct winbindd_pw));
00661 
00662         user_list = (struct winbindd_pw *)state->response.extra_data.data;
00663 
00664         if (!state->getpwent_initialized)
00665                 winbindd_setpwent_internal(state);
00666         
00667         if (!(ent = state->getpwent_state)) {
00668                 request_error(state);
00669                 return;
00670         }
00671 
00672         /* Start sending back users */
00673 
00674         for (user_list_ndx = 0; user_list_ndx < num_users; ) {
00675                 struct getpwent_user *name_list = NULL;
00676                 uint32 result;
00677 
00678                 /* Do we need to fetch another chunk of users? */
00679 
00680                 if (ent->num_sam_entries == ent->sam_entry_index) {
00681 
00682                         while(ent &&
00683                               !get_sam_user_entries(ent, state->mem_ctx)) {
00684                                 struct getent_state *next_ent;
00685 
00686                                 /* Free state information for this domain */
00687 
00688                                 SAFE_FREE(ent->sam_entries);
00689 
00690                                 next_ent = ent->next;
00691                                 DLIST_REMOVE(state->getpwent_state, ent);
00692 
00693                                 SAFE_FREE(ent);
00694                                 ent = next_ent;
00695                         }
00696  
00697                         /* No more domains */
00698 
00699                         if (!ent) 
00700                                 break;
00701                 }
00702 
00703                 name_list = (struct getpwent_user *)ent->sam_entries;
00704 
00705                 /* Lookup user info */
00706                 
00707                 result = winbindd_fill_pwent(
00708                         ent->domain_name, 
00709                         name_list[ent->sam_entry_index].name,
00710                         &name_list[ent->sam_entry_index].user_sid,
00711                         &name_list[ent->sam_entry_index].group_sid,
00712                         name_list[ent->sam_entry_index].gecos,
00713                         name_list[ent->sam_entry_index].homedir,
00714                         name_list[ent->sam_entry_index].shell,
00715                         &user_list[user_list_ndx]);
00716                 
00717                 /* Add user to return list */
00718                 
00719                 if (result) {
00720                                 
00721                         user_list_ndx++;
00722                         state->response.data.num_entries++;
00723                         state->response.length += 
00724                                 sizeof(struct winbindd_pw);
00725 
00726                 } else
00727                         DEBUG(1, ("could not lookup domain user %s\n",
00728                                   name_list[ent->sam_entry_index].name));
00729 
00730                 ent->sam_entry_index++;
00731                 
00732         }
00733 
00734         /* Out of domains */
00735 
00736         if (user_list_ndx > 0)
00737                 request_ok(state);
00738         else
00739                 request_error(state);
00740 }
00741 
00742 /* List domain users without mapping to unix ids */
00743 
00744 void winbindd_list_users(struct winbindd_cli_state *state)
00745 {
00746         struct winbindd_domain *domain;
00747         WINBIND_USERINFO *info;
00748         const char *which_domain;
00749         uint32 num_entries = 0, total_entries = 0;
00750         char *extra_data = NULL;
00751         int extra_data_len = 0;
00752         enum winbindd_result rv = WINBINDD_ERROR;
00753 
00754         DEBUG(3, ("[%5lu]: list users\n", (unsigned long)state->pid));
00755 
00756         /* Ensure null termination */
00757         state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';  
00758         which_domain = state->request.domain_name;
00759         
00760         /* Enumerate over trusted domains */
00761 
00762         for (domain = domain_list(); domain; domain = domain->next) {
00763                 NTSTATUS status;
00764                 struct winbindd_methods *methods;
00765                 unsigned int i;
00766                 
00767                 /* if we have a domain name restricting the request and this
00768                    one in the list doesn't match, then just bypass the remainder
00769                    of the loop */
00770                    
00771                 if ( *which_domain && !strequal(which_domain, domain->name) )
00772                         continue;
00773                         
00774                 methods = domain->methods;
00775 
00776                 /* Query display info */
00777                 status = methods->query_user_list(domain, state->mem_ctx, 
00778                                                   &num_entries, &info);
00779 
00780                 if (!NT_STATUS_IS_OK(status)) {
00781                         continue;
00782                 }
00783 
00784                 if (num_entries == 0)
00785                         continue;
00786 
00787                 /* Allocate some memory for extra data */
00788                 total_entries += num_entries;
00789                         
00790                 extra_data = (char *)SMB_REALLOC(
00791                         extra_data, sizeof(fstring) * total_entries);
00792                         
00793                 if (!extra_data) {
00794                         DEBUG(0,("failed to enlarge buffer!\n"));
00795                         goto done;
00796                 }
00797 
00798                 /* Pack user list into extra data fields */
00799                         
00800                 for (i = 0; i < num_entries; i++) {
00801                         fstring acct_name, name;
00802                         
00803                         if (!info[i].acct_name) {
00804                                 fstrcpy(acct_name, "");
00805                         } else {
00806                                 fstrcpy(acct_name, info[i].acct_name);
00807                         }
00808                         
00809                         fill_domain_username(name, domain->name, acct_name, True);
00810                         
00811                                 /* Append to extra data */
00812                         memcpy(&extra_data[extra_data_len], name, 
00813                                strlen(name));
00814                         extra_data_len += strlen(name);
00815                         extra_data[extra_data_len++] = ',';
00816                 }   
00817         }
00818 
00819         /* Assign extra_data fields in response structure */
00820 
00821         if (extra_data) {
00822                 extra_data[extra_data_len - 1] = '\0';
00823                 state->response.extra_data.data = extra_data;
00824                 state->response.length += extra_data_len;
00825         }
00826 
00827         /* No domains responded but that's still OK so don't return an
00828            error. */
00829 
00830         rv = WINBINDD_OK;
00831 
00832  done:
00833 
00834         if (rv == WINBINDD_OK)
00835                 request_ok(state);
00836         else
00837                 request_error(state);
00838 }

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