nsswitch/winbindd_rpc.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Winbind rpc backend functions
00005 
00006    Copyright (C) Tim Potter 2000-2001,2003
00007    Copyright (C) Andrew Tridgell 2001
00008    Copyright (C) Volker Lendecke 2005
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 
00032 /* Query display info for a domain.  This returns enough information plus a
00033    bit extra to give an overview of domain users for the User Manager
00034    application. */
00035 static NTSTATUS query_user_list(struct winbindd_domain *domain,
00036                                TALLOC_CTX *mem_ctx,
00037                                uint32 *num_entries, 
00038                                WINBIND_USERINFO **info)
00039 {
00040         NTSTATUS result;
00041         POLICY_HND dom_pol;
00042         unsigned int i, start_idx;
00043         uint32 loop_count;
00044         struct rpc_pipe_client *cli;
00045 
00046         DEBUG(3,("rpc: query_user_list\n"));
00047 
00048         *num_entries = 0;
00049         *info = NULL;
00050 
00051         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00052         if (!NT_STATUS_IS_OK(result))
00053                 return result;
00054 
00055         i = start_idx = 0;
00056         loop_count = 0;
00057 
00058         do {
00059                 TALLOC_CTX *ctx2;
00060                 uint32 num_dom_users, j;
00061                 uint32 max_entries, max_size;
00062                 SAM_DISPINFO_CTR ctr;
00063                 SAM_DISPINFO_1 info1;
00064 
00065                 ZERO_STRUCT( ctr );
00066                 ZERO_STRUCT( info1 );
00067                 ctr.sam.info1 = &info1;
00068         
00069                 if (!(ctx2 = talloc_init("winbindd enum_users")))
00070                         return NT_STATUS_NO_MEMORY;
00071 
00072                 /* this next bit is copied from net_user_list_internal() */
00073 
00074                 get_query_dispinfo_params(loop_count, &max_entries,
00075                                           &max_size);
00076 
00077                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
00078                                                     &start_idx, 1,
00079                                                     &num_dom_users,
00080                                                     max_entries, max_size,
00081                                                     &ctr);
00082 
00083                 loop_count++;
00084 
00085                 *num_entries += num_dom_users;
00086 
00087                 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
00088                                              *num_entries);
00089 
00090                 if (!(*info)) {
00091                         talloc_destroy(ctx2);
00092                         return NT_STATUS_NO_MEMORY;
00093                 }
00094 
00095                 for (j = 0; j < num_dom_users; i++, j++) {
00096                         fstring username, fullname;
00097                         uint32 rid = ctr.sam.info1->sam[j].rid_user;
00098                         
00099                         unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
00100                         unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
00101                         
00102                         (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
00103                         (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
00104                         (*info)[i].homedir = NULL;
00105                         (*info)[i].shell = NULL;
00106                         sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
00107                         
00108                         /* For the moment we set the primary group for
00109                            every user to be the Domain Users group.
00110                            There are serious problems with determining
00111                            the actual primary group for large domains.
00112                            This should really be made into a 'winbind
00113                            force group' smb.conf parameter or
00114                            something like that. */
00115                            
00116                         sid_compose(&(*info)[i].group_sid, &domain->sid, 
00117                                     DOMAIN_GROUP_RID_USERS);
00118                 }
00119 
00120                 talloc_destroy(ctx2);
00121 
00122         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
00123 
00124         return result;
00125 }
00126 
00127 /* list all domain groups */
00128 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
00129                                 TALLOC_CTX *mem_ctx,
00130                                 uint32 *num_entries, 
00131                                 struct acct_info **info)
00132 {
00133         POLICY_HND dom_pol;
00134         NTSTATUS status;
00135         uint32 start = 0;
00136         struct rpc_pipe_client *cli;
00137 
00138         *num_entries = 0;
00139         *info = NULL;
00140 
00141         DEBUG(3,("rpc: enum_dom_groups\n"));
00142 
00143         status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00144         if (!NT_STATUS_IS_OK(status))
00145                 return status;
00146 
00147         do {
00148                 struct acct_info *info2 = NULL;
00149                 uint32 count = 0;
00150                 TALLOC_CTX *mem_ctx2;
00151 
00152                 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
00153 
00154                 /* start is updated by this call. */
00155                 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
00156                                                      &start,
00157                                                      0xFFFF, /* buffer size? */
00158                                                      &info2, &count);
00159 
00160                 if (!NT_STATUS_IS_OK(status) && 
00161                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
00162                         talloc_destroy(mem_ctx2);
00163                         break;
00164                 }
00165 
00166                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
00167                                                struct acct_info,
00168                                                (*num_entries) + count);
00169                 if (! *info) {
00170                         talloc_destroy(mem_ctx2);
00171                         return NT_STATUS_NO_MEMORY;
00172                 }
00173 
00174                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
00175                 (*num_entries) += count;
00176                 talloc_destroy(mem_ctx2);
00177         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
00178 
00179         return NT_STATUS_OK;
00180 }
00181 
00182 /* List all domain groups */
00183 
00184 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
00185                                 TALLOC_CTX *mem_ctx,
00186                                 uint32 *num_entries, 
00187                                 struct acct_info **info)
00188 {
00189         POLICY_HND dom_pol;
00190         NTSTATUS result;
00191         struct rpc_pipe_client *cli;
00192 
00193         *num_entries = 0;
00194         *info = NULL;
00195 
00196         DEBUG(3,("rpc: enum_local_groups\n"));
00197 
00198         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00199         if (!NT_STATUS_IS_OK(result))
00200                 return result;
00201 
00202         do {
00203                 struct acct_info *info2 = NULL;
00204                 uint32 count = 0, start = *num_entries;
00205                 TALLOC_CTX *mem_ctx2;
00206 
00207                 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
00208 
00209                 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
00210                                                       &start, 0xFFFF, &info2,
00211                                                       &count);
00212                                           
00213                 if (!NT_STATUS_IS_OK(result) &&
00214                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) 
00215                 {
00216                         talloc_destroy(mem_ctx2);
00217                         return result;
00218                 }
00219 
00220                 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
00221                                                struct acct_info,
00222                                                (*num_entries) + count);
00223                 if (! *info) {
00224                         talloc_destroy(mem_ctx2);
00225                         return NT_STATUS_NO_MEMORY;
00226                 }
00227 
00228                 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
00229                 (*num_entries) += count;
00230                 talloc_destroy(mem_ctx2);
00231 
00232         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
00233 
00234         return NT_STATUS_OK;
00235 }
00236 
00237 /* convert a single name to a sid in a domain */
00238 NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
00239                             TALLOC_CTX *mem_ctx,
00240                             const char *domain_name,
00241                             const char *name,
00242                             DOM_SID *sid,
00243                             enum lsa_SidType *type)
00244 {
00245         NTSTATUS result;
00246         DOM_SID *sids = NULL;
00247         enum lsa_SidType *types = NULL;
00248         char *full_name = NULL;
00249         struct rpc_pipe_client *cli;
00250         POLICY_HND lsa_policy;
00251 
00252         if(name == NULL || *name=='\0') {
00253                 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
00254                 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
00255         } else {
00256                 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
00257                 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
00258         }
00259         if (!full_name) {
00260                 DEBUG(0, ("talloc_asprintf failed!\n"));
00261                 return NT_STATUS_NO_MEMORY;
00262         }
00263 
00264         ws_name_return( full_name, WB_REPLACE_CHAR );
00265 
00266         DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
00267 
00268         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
00269         if (!NT_STATUS_IS_OK(result))
00270                 return result;
00271 
00272         result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
00273                                          (const char**) &full_name, NULL, &sids, &types);
00274         
00275         if (!NT_STATUS_IS_OK(result))
00276                 return result;
00277 
00278         /* Return rid and type if lookup successful */
00279 
00280         sid_copy(sid, &sids[0]);
00281         *type = types[0];
00282 
00283         return NT_STATUS_OK;
00284 }
00285 
00286 /*
00287   convert a domain SID to a user or group name
00288 */
00289 NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
00290                             TALLOC_CTX *mem_ctx,
00291                             const DOM_SID *sid,
00292                             char **domain_name,
00293                             char **name,
00294                             enum lsa_SidType *type)
00295 {
00296         char **domains;
00297         char **names;
00298         enum lsa_SidType *types;
00299         NTSTATUS result;
00300         struct rpc_pipe_client *cli;
00301         POLICY_HND lsa_policy;
00302 
00303         DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
00304                         domain->name ));
00305 
00306         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
00307         if (!NT_STATUS_IS_OK(result))
00308                 return result;
00309 
00310         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
00311                                         1, sid, &domains, &names, &types);
00312         if (!NT_STATUS_IS_OK(result))
00313                 return result;
00314 
00315         *type = (enum lsa_SidType)types[0];
00316         *domain_name = domains[0];
00317         *name = names[0];
00318 
00319         ws_name_replace( *name, WB_REPLACE_CHAR );      
00320                 
00321         DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
00322         return NT_STATUS_OK;
00323 }
00324 
00325 NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
00326                              TALLOC_CTX *mem_ctx,
00327                              const DOM_SID *sid,
00328                              uint32 *rids,
00329                              size_t num_rids,
00330                              char **domain_name,
00331                              char ***names,
00332                              enum lsa_SidType **types)
00333 {
00334         char **domains;
00335         NTSTATUS result;
00336         struct rpc_pipe_client *cli;
00337         POLICY_HND lsa_policy;
00338         DOM_SID *sids;
00339         size_t i;
00340         char **ret_names;
00341 
00342         DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
00343 
00344         if (num_rids) {
00345                 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
00346                 if (sids == NULL) {
00347                         return NT_STATUS_NO_MEMORY;
00348                 }
00349         } else {
00350                 sids = NULL;
00351         }
00352 
00353         for (i=0; i<num_rids; i++) {
00354                 if (!sid_compose(&sids[i], sid, rids[i])) {
00355                         return NT_STATUS_INTERNAL_ERROR;
00356                 }
00357         }
00358 
00359         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
00360         if (!NT_STATUS_IS_OK(result)) {
00361                 return result;
00362         }
00363 
00364         result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
00365                                         num_rids, sids, &domains,
00366                                         names, types);
00367         if (!NT_STATUS_IS_OK(result) &&
00368             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
00369                 return result;
00370         }
00371 
00372         ret_names = *names;
00373         for (i=0; i<num_rids; i++) {
00374                 if ((*types)[i] != SID_NAME_UNKNOWN) {
00375                         ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
00376                         *domain_name = domains[i];
00377                 }
00378         }
00379 
00380         return result;
00381 }
00382 
00383 /* Lookup user information from a rid or username. */
00384 static NTSTATUS query_user(struct winbindd_domain *domain, 
00385                            TALLOC_CTX *mem_ctx, 
00386                            const DOM_SID *user_sid, 
00387                            WINBIND_USERINFO *user_info)
00388 {
00389         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00390         POLICY_HND dom_pol, user_pol;
00391         SAM_USERINFO_CTR *ctr;
00392         fstring sid_string;
00393         uint32 user_rid;
00394         NET_USER_INFO_3 *user;
00395         struct rpc_pipe_client *cli;
00396 
00397         DEBUG(3,("rpc: query_user sid=%s\n",
00398                  sid_to_string(sid_string, user_sid)));
00399 
00400         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
00401                 return NT_STATUS_UNSUCCESSFUL;
00402         
00403         /* try netsamlogon cache first */
00404                         
00405         if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
00406         {
00407                                 
00408                 DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
00409                         sid_string_static(user_sid)));
00410 
00411                 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
00412                 sid_compose(&user_info->group_sid, &domain->sid,
00413                             user->group_rid);
00414                                 
00415                 user_info->acct_name = unistr2_tdup(mem_ctx,
00416                                                     &user->uni_user_name);
00417                 user_info->full_name = unistr2_tdup(mem_ctx,
00418                                                     &user->uni_full_name);
00419                 
00420                 user_info->homedir = NULL;
00421                 user_info->shell = NULL;
00422                 user_info->primary_gid = (gid_t)-1;
00423                                                 
00424                 TALLOC_FREE(user);
00425                                 
00426                 return NT_STATUS_OK;
00427         }
00428         
00429         /* no cache; hit the wire */
00430                 
00431         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00432         if (!NT_STATUS_IS_OK(result))
00433                 return result;
00434 
00435         /* Get user handle */
00436         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
00437                                        SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
00438                                        &user_pol);
00439 
00440         if (!NT_STATUS_IS_OK(result))
00441                 return result;
00442 
00443         /* Get user info */
00444         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
00445                                             0x15, &ctr);
00446 
00447         rpccli_samr_close(cli, mem_ctx, &user_pol);
00448 
00449         if (!NT_STATUS_IS_OK(result))
00450                 return result;
00451 
00452         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
00453         sid_compose(&user_info->group_sid, &domain->sid,
00454                     ctr->info.id21->group_rid);
00455         user_info->acct_name = unistr2_tdup(mem_ctx, 
00456                                             &ctr->info.id21->uni_user_name);
00457         user_info->full_name = unistr2_tdup(mem_ctx, 
00458                                             &ctr->info.id21->uni_full_name);
00459         user_info->homedir = NULL;
00460         user_info->shell = NULL;
00461         user_info->primary_gid = (gid_t)-1;
00462 
00463         return NT_STATUS_OK;
00464 }                                   
00465 
00466 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
00467 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
00468                                   TALLOC_CTX *mem_ctx,
00469                                   const DOM_SID *user_sid,
00470                                   uint32 *num_groups, DOM_SID **user_grpsids)
00471 {
00472         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00473         POLICY_HND dom_pol, user_pol;
00474         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
00475         DOM_GID *user_groups;
00476         unsigned int i;
00477         fstring sid_string;
00478         uint32 user_rid;
00479         struct rpc_pipe_client *cli;
00480 
00481         DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
00482                  sid_to_string(sid_string, user_sid)));
00483 
00484         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
00485                 return NT_STATUS_UNSUCCESSFUL;
00486 
00487         *num_groups = 0;
00488         *user_grpsids = NULL;
00489 
00490         /* so lets see if we have a cached user_info_3 */
00491         result = lookup_usergroups_cached(domain, mem_ctx, user_sid, 
00492                                           num_groups, user_grpsids);
00493 
00494         if (NT_STATUS_IS_OK(result)) {
00495                 return NT_STATUS_OK;
00496         }
00497 
00498         /* no cache; hit the wire */
00499         
00500         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00501         if (!NT_STATUS_IS_OK(result))
00502                 return result;
00503 
00504         /* Get user handle */
00505         result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
00506                                         des_access, user_rid, &user_pol);
00507 
00508         if (!NT_STATUS_IS_OK(result))
00509                 return result;
00510 
00511         /* Query user rids */
00512         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, 
00513                                            num_groups, &user_groups);
00514 
00515         rpccli_samr_close(cli, mem_ctx, &user_pol);
00516 
00517         if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
00518                 return result;
00519 
00520         (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
00521         if (!(*user_grpsids))
00522                 return NT_STATUS_NO_MEMORY;
00523 
00524         for (i=0;i<(*num_groups);i++) {
00525                 sid_copy(&((*user_grpsids)[i]), &domain->sid);
00526                 sid_append_rid(&((*user_grpsids)[i]),
00527                                 user_groups[i].g_rid);
00528         }
00529         
00530         return NT_STATUS_OK;
00531 }
00532 
00533 NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
00534                                   TALLOC_CTX *mem_ctx,
00535                                   uint32 num_sids, const DOM_SID *sids,
00536                                   uint32 *num_aliases, uint32 **alias_rids)
00537 {
00538         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00539         POLICY_HND dom_pol;
00540         DOM_SID2 *query_sids;
00541         uint32 num_query_sids = 0;
00542         int i;
00543         struct rpc_pipe_client *cli;
00544         uint32 *alias_rids_query, num_aliases_query;
00545         int rangesize = MAX_SAM_ENTRIES_W2K;
00546         uint32 total_sids = 0;
00547         int num_queries = 1;
00548 
00549         *num_aliases = 0;
00550         *alias_rids = NULL;
00551 
00552         DEBUG(3,("rpc: lookup_useraliases\n"));
00553 
00554         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00555         if (!NT_STATUS_IS_OK(result))
00556                 return result;
00557 
00558         do {
00559                 /* prepare query */
00560 
00561                 num_query_sids = MIN(num_sids - total_sids, rangesize);
00562 
00563                 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n", 
00564                         num_queries, num_query_sids));  
00565 
00566                 if (num_query_sids) {
00567                         query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
00568                         if (query_sids == NULL) {
00569                                 return NT_STATUS_NO_MEMORY;
00570                         }
00571                 } else {
00572                         query_sids = NULL;
00573                 }
00574 
00575                 for (i=0; i<num_query_sids; i++) {
00576                         sid_copy(&query_sids[i].sid, &sids[total_sids++]);
00577                         query_sids[i].num_auths = query_sids[i].sid.num_auths;
00578                 }
00579 
00580                 /* do request */
00581 
00582                 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
00583                                                        num_query_sids, query_sids,
00584                                                        &num_aliases_query, 
00585                                                        &alias_rids_query);
00586 
00587                 if (!NT_STATUS_IS_OK(result)) {
00588                         *num_aliases = 0;
00589                         *alias_rids = NULL;
00590                         TALLOC_FREE(query_sids);
00591                         goto done;
00592                 }
00593 
00594                 /* process output */
00595 
00596                 for (i=0; i<num_aliases_query; i++) {
00597                         size_t na = *num_aliases;
00598                         if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i], 
00599                                                 alias_rids, &na)) {
00600                                 return NT_STATUS_NO_MEMORY;
00601                         }
00602                         *num_aliases = na;
00603                 }
00604 
00605                 TALLOC_FREE(query_sids);
00606 
00607                 num_queries++;
00608 
00609         } while (total_sids < num_sids);
00610 
00611  done:
00612         DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
00613                 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
00614 
00615         return result;
00616 }
00617 
00618 
00619 /* Lookup group membership given a rid.   */
00620 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
00621                                 TALLOC_CTX *mem_ctx,
00622                                 const DOM_SID *group_sid, uint32 *num_names, 
00623                                 DOM_SID **sid_mem, char ***names, 
00624                                 uint32 **name_types)
00625 {
00626         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00627         uint32 i, total_names = 0;
00628         POLICY_HND dom_pol, group_pol;
00629         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
00630         uint32 *rid_mem = NULL;
00631         uint32 group_rid;
00632         unsigned int j;
00633         fstring sid_string;
00634         struct rpc_pipe_client *cli;
00635         unsigned int orig_timeout;
00636 
00637         DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
00638                   sid_to_string(sid_string, group_sid)));
00639 
00640         if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
00641                 return NT_STATUS_UNSUCCESSFUL;
00642 
00643         *num_names = 0;
00644 
00645         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00646         if (!NT_STATUS_IS_OK(result))
00647                 return result;
00648 
00649         result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
00650                                         des_access, group_rid, &group_pol);
00651 
00652         if (!NT_STATUS_IS_OK(result))
00653                 return result;
00654 
00655         /* Step #1: Get a list of user rids that are the members of the
00656            group. */
00657 
00658         /* This call can take a long time - allow the server to time out.
00659            35 seconds should do it. */
00660 
00661         orig_timeout = cli_set_timeout(cli->cli, 35000);
00662 
00663         result = rpccli_samr_query_groupmem(cli, mem_ctx,
00664                                             &group_pol, num_names, &rid_mem,
00665                                             name_types);
00666 
00667         /* And restore our original timeout. */
00668         cli_set_timeout(cli->cli, orig_timeout);
00669 
00670         rpccli_samr_close(cli, mem_ctx, &group_pol);
00671 
00672         if (!NT_STATUS_IS_OK(result))
00673                 return result;
00674 
00675         if (!*num_names) {
00676                 names = NULL;
00677                 name_types = NULL;
00678                 sid_mem = NULL;
00679                 return NT_STATUS_OK;
00680         }
00681 
00682         /* Step #2: Convert list of rids into list of usernames.  Do this
00683            in bunches of ~1000 to avoid crashing NT4.  It looks like there
00684            is a buffer overflow or something like that lurking around
00685            somewhere. */
00686 
00687 #define MAX_LOOKUP_RIDS 900
00688 
00689         *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
00690         *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
00691         *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
00692 
00693         for (j=0;j<(*num_names);j++)
00694                 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
00695         
00696         if (*num_names>0 && (!*names || !*name_types))
00697                 return NT_STATUS_NO_MEMORY;
00698 
00699         for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
00700                 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
00701                 uint32 tmp_num_names = 0;
00702                 char **tmp_names = NULL;
00703                 uint32 *tmp_types = NULL;
00704 
00705                 /* Lookup a chunk of rids */
00706 
00707                 result = rpccli_samr_lookup_rids(cli, mem_ctx,
00708                                                  &dom_pol,
00709                                                  num_lookup_rids,
00710                                                  &rid_mem[i],
00711                                                  &tmp_num_names,
00712                                                  &tmp_names, &tmp_types);
00713 
00714                 /* see if we have a real error (and yes the
00715                    STATUS_SOME_UNMAPPED is the one returned from 2k) */
00716                 
00717                 if (!NT_STATUS_IS_OK(result) &&
00718                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
00719                         return result;
00720                         
00721                 /* Copy result into array.  The talloc system will take
00722                    care of freeing the temporary arrays later on. */
00723 
00724                 memcpy(&(*names)[i], tmp_names, sizeof(char *) * 
00725                        tmp_num_names);
00726 
00727                 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
00728                        tmp_num_names);
00729                 
00730                 total_names += tmp_num_names;
00731         }
00732 
00733         *num_names = total_names;
00734 
00735         return NT_STATUS_OK;
00736 }
00737 
00738 #ifdef HAVE_LDAP
00739 
00740 #include <ldap.h>
00741 
00742 static int get_ldap_seq(const char *server, int port, uint32 *seq)
00743 {
00744         int ret = -1;
00745         struct timeval to;
00746         const char *attrs[] = {"highestCommittedUSN", NULL};
00747         LDAPMessage *res = NULL;
00748         char **values = NULL;
00749         LDAP *ldp = NULL;
00750 
00751         *seq = DOM_SEQUENCE_NONE;
00752 
00753         /*
00754          * Parameterised (5) second timeout on open. This is needed as the
00755          * search timeout doesn't seem to apply to doing an open as well. JRA.
00756          */
00757 
00758         ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
00759         if (ldp == NULL)
00760                 return -1;
00761 
00762         /* Timeout if no response within 20 seconds. */
00763         to.tv_sec = 10;
00764         to.tv_usec = 0;
00765 
00766         if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
00767                            CONST_DISCARD(char **, attrs), 0, &to, &res))
00768                 goto done;
00769 
00770         if (ldap_count_entries(ldp, res) != 1)
00771                 goto done;
00772 
00773         values = ldap_get_values(ldp, res, "highestCommittedUSN");
00774         if (!values || !values[0])
00775                 goto done;
00776 
00777         *seq = atoi(values[0]);
00778         ret = 0;
00779 
00780   done:
00781 
00782         if (values)
00783                 ldap_value_free(values);
00784         if (res)
00785                 ldap_msgfree(res);
00786         if (ldp)
00787                 ldap_unbind(ldp);
00788         return ret;
00789 }
00790 
00791 /**********************************************************************
00792  Get the sequence number for a Windows AD native mode domain using
00793  LDAP queries. 
00794 **********************************************************************/
00795 
00796 static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
00797 {
00798         int ret = -1;
00799         fstring ipstr;
00800 
00801         fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
00802         if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
00803                 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
00804                           "number for Domain (%s) from DC (%s)\n", 
00805                         domain->name, ipstr));
00806         } 
00807         return ret;
00808 }
00809 
00810 #endif /* HAVE_LDAP */
00811 
00812 /* find the sequence number for a domain */
00813 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
00814 {
00815         TALLOC_CTX *mem_ctx;
00816         SAM_UNK_CTR ctr;
00817         NTSTATUS result;
00818         POLICY_HND dom_pol;
00819         BOOL got_seq_num = False;
00820         struct rpc_pipe_client *cli;
00821 
00822         DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
00823 
00824         *seq = DOM_SEQUENCE_NONE;
00825 
00826         if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
00827                 return NT_STATUS_NO_MEMORY;
00828 
00829 #ifdef HAVE_LDAP
00830         if ( domain->native_mode ) 
00831         {
00832                 int res;
00833 
00834                 DEBUG(8,("using get_ldap_seq() to retrieve the "
00835                          "sequence number\n"));
00836 
00837                 res =  get_ldap_sequence_number( domain, seq );
00838                 if (res == 0)
00839                 {                       
00840                         result = NT_STATUS_OK;
00841                         DEBUG(10,("domain_sequence_number: LDAP for "
00842                                   "domain %s is %u\n",
00843                                   domain->name, *seq));
00844                         goto done;
00845                 }
00846 
00847                 DEBUG(10,("domain_sequence_number: failed to get LDAP "
00848                           "sequence number for domain %s\n",
00849                           domain->name ));
00850         }
00851 #endif /* HAVE_LDAP */
00852 
00853         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00854         if (!NT_STATUS_IS_OK(result)) {
00855                 goto done;
00856         }
00857 
00858         /* Query domain info */
00859 
00860         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
00861 
00862         if (NT_STATUS_IS_OK(result)) {
00863                 *seq = ctr.info.inf8.seq_num;
00864                 got_seq_num = True;
00865                 goto seq_num;
00866         }
00867 
00868         /* retry with info-level 2 in case the dc does not support info-level 8
00869          * (like all older samba2 and samba3 dc's - Guenther */
00870 
00871         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
00872         
00873         if (NT_STATUS_IS_OK(result)) {
00874                 *seq = ctr.info.inf2.seq_num;
00875                 got_seq_num = True;
00876         }
00877 
00878  seq_num:
00879         if (got_seq_num) {
00880                 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
00881                           domain->name, (unsigned)*seq));
00882         } else {
00883                 DEBUG(10,("domain_sequence_number: failed to get sequence "
00884                           "number (%u) for domain %s\n",
00885                           (unsigned)*seq, domain->name ));
00886         }
00887 
00888   done:
00889 
00890         talloc_destroy(mem_ctx);
00891 
00892         return result;
00893 }
00894 
00895 /* get a list of trusted domains */
00896 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
00897                                 TALLOC_CTX *mem_ctx,
00898                                 uint32 *num_domains,
00899                                 char ***names,
00900                                 char ***alt_names,
00901                                 DOM_SID **dom_sids)
00902 {
00903         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00904         uint32 enum_ctx = 0;
00905         struct rpc_pipe_client *cli;
00906         POLICY_HND lsa_policy;
00907 
00908         DEBUG(3,("rpc: trusted_domains\n"));
00909 
00910         *num_domains = 0;
00911         *names = NULL;
00912         *alt_names = NULL;
00913         *dom_sids = NULL;
00914 
00915         result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
00916         if (!NT_STATUS_IS_OK(result))
00917                 return result;
00918 
00919         result = STATUS_MORE_ENTRIES;
00920 
00921         while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
00922                 uint32 start_idx, num;
00923                 char **tmp_names;
00924                 DOM_SID *tmp_sids;
00925                 int i;
00926 
00927                 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
00928                                                    &lsa_policy, &enum_ctx,
00929                                                    &num, &tmp_names,
00930                                                    &tmp_sids);
00931 
00932                 if (!NT_STATUS_IS_OK(result) &&
00933                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
00934                         break;
00935 
00936                 start_idx = *num_domains;
00937                 *num_domains += num;
00938                 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
00939                                               char *, *num_domains);
00940                 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
00941                                                  DOM_SID, *num_domains);
00942                 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
00943                                                  char *, *num_domains);
00944                 if ((*names == NULL) || (*dom_sids == NULL) ||
00945                     (*alt_names == NULL))
00946                         return NT_STATUS_NO_MEMORY;
00947 
00948                 for (i=0; i<num; i++) {
00949                         (*names)[start_idx+i] = tmp_names[i];
00950                         (*dom_sids)[start_idx+i] = tmp_sids[i];
00951                         (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
00952                 }
00953         }
00954         return result;
00955 }
00956 
00957 /* find the lockout policy for a domain */
00958 NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, 
00959                               TALLOC_CTX *mem_ctx,
00960                               SAM_UNK_INFO_12 *lockout_policy)
00961 {
00962         NTSTATUS result;
00963         struct rpc_pipe_client *cli;
00964         POLICY_HND dom_pol;
00965         SAM_UNK_CTR ctr;
00966 
00967         DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
00968 
00969         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
00970         if (!NT_STATUS_IS_OK(result)) {
00971                 goto done;
00972         }
00973 
00974         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
00975         if (!NT_STATUS_IS_OK(result)) {
00976                 goto done;
00977         }
00978 
00979         *lockout_policy = ctr.info.inf12;
00980 
00981         DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", 
00982                 ctr.info.inf12.bad_attempt_lockout));
00983 
00984   done:
00985 
00986         return result;
00987 }
00988 
00989 /* find the password policy for a domain */
00990 NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, 
00991                                TALLOC_CTX *mem_ctx,
00992                                SAM_UNK_INFO_1 *password_policy)
00993 {
00994         NTSTATUS result;
00995         struct rpc_pipe_client *cli;
00996         POLICY_HND dom_pol;
00997         SAM_UNK_CTR ctr;
00998 
00999         DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
01000 
01001         result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
01002         if (!NT_STATUS_IS_OK(result)) {
01003                 goto done;
01004         }
01005 
01006         result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
01007         if (!NT_STATUS_IS_OK(result)) {
01008                 goto done;
01009         }
01010 
01011         *password_policy = ctr.info.inf1;
01012 
01013         DEBUG(10,("msrpc_password_policy: min_length_password %d\n", 
01014                 ctr.info.inf1.min_length_password));
01015 
01016   done:
01017 
01018         return result;
01019 }
01020 
01021 
01022 /* the rpc backend methods are exposed via this structure */
01023 struct winbindd_methods msrpc_methods = {
01024         False,
01025         query_user_list,
01026         enum_dom_groups,
01027         enum_local_groups,
01028         msrpc_name_to_sid,
01029         msrpc_sid_to_name,
01030         msrpc_rids_to_names,
01031         query_user,
01032         lookup_usergroups,
01033         msrpc_lookup_useraliases,
01034         lookup_groupmem,
01035         sequence_number,
01036         msrpc_lockout_policy,
01037         msrpc_password_policy,
01038         trusted_domains,
01039 };

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