nsswitch/winbindd_util.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Winbind daemon for ntdom nss module
00005 
00006    Copyright (C) Tim Potter 2000-2001
00007    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
00008    
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 #include "winbindd.h"
00026 
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_WINBIND
00029 
00030 extern struct winbindd_methods cache_methods;
00031 extern struct winbindd_methods builtin_passdb_methods;
00032 extern struct winbindd_methods sam_passdb_methods;
00033 
00034 /**
00035  * @file winbindd_util.c
00036  *
00037  * Winbind daemon for NT domain authentication nss module.
00038  **/
00039 
00040 
00041 /* The list of trusted domains.  Note that the list can be deleted and
00042    recreated using the init_domain_list() function so pointers to
00043    individual winbindd_domain structures cannot be made.  Keep a copy of
00044    the domain name instead. */
00045 
00046 static struct winbindd_domain *_domain_list;
00047 
00048 /**
00049    When was the last scan of trusted domains done?
00050    
00051    0 == not ever
00052 */
00053 
00054 static time_t last_trustdom_scan;
00055 
00056 struct winbindd_domain *domain_list(void)
00057 {
00058         /* Initialise list */
00059 
00060         if ((!_domain_list) && (!init_domain_list())) {
00061                 smb_panic("Init_domain_list failed\n");
00062         }
00063 
00064         return _domain_list;
00065 }
00066 
00067 /* Free all entries in the trusted domain list */
00068 
00069 void free_domain_list(void)
00070 {
00071         struct winbindd_domain *domain = _domain_list;
00072 
00073         while(domain) {
00074                 struct winbindd_domain *next = domain->next;
00075                 
00076                 DLIST_REMOVE(_domain_list, domain);
00077                 SAFE_FREE(domain);
00078                 domain = next;
00079         }
00080 }
00081 
00082 static BOOL is_internal_domain(const DOM_SID *sid)
00083 {
00084         if (sid == NULL)
00085                 return False;
00086 
00087         if ( IS_DC )
00088                 return sid_check_is_builtin(sid);
00089 
00090         return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
00091 }
00092 
00093 static BOOL is_in_internal_domain(const DOM_SID *sid)
00094 {
00095         if (sid == NULL)
00096                 return False;
00097 
00098         if ( IS_DC )
00099                 return sid_check_is_in_builtin(sid);
00100 
00101         return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));
00102 }
00103 
00104 
00105 /* Add a trusted domain to our list of domains */
00106 static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
00107                                                   struct winbindd_methods *methods,
00108                                                   const DOM_SID *sid)
00109 {
00110         struct winbindd_domain *domain;
00111         const char *alternative_name = NULL;
00112         
00113         /* ignore alt_name if we are not in an AD domain */
00114         
00115         if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
00116                 alternative_name = alt_name;
00117         }
00118         
00119         /* We can't call domain_list() as this function is called from
00120            init_domain_list() and we'll get stuck in a loop. */
00121         for (domain = _domain_list; domain; domain = domain->next) {
00122                 if (strequal(domain_name, domain->name) ||
00123                     strequal(domain_name, domain->alt_name)) {
00124                         return domain;
00125                 }
00126                 if (alternative_name && *alternative_name) {
00127                         if (strequal(alternative_name, domain->name) ||
00128                             strequal(alternative_name, domain->alt_name)) {
00129                                 return domain;
00130                         }
00131                 }
00132                 if (sid) {
00133                         if (is_null_sid(sid)) {
00134                                 
00135                         } else if (sid_equal(sid, &domain->sid)) {
00136                                 return domain;
00137                         }
00138                 }
00139         }
00140         
00141         /* Create new domain entry */
00142 
00143         if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL)
00144                 return NULL;
00145 
00146         /* Fill in fields */
00147         
00148         ZERO_STRUCTP(domain);
00149 
00150         fstrcpy(domain->name, domain_name);
00151         if (alternative_name) {
00152                 fstrcpy(domain->alt_name, alternative_name);
00153         }
00154 
00155         domain->methods = methods;
00156         domain->backend = NULL;
00157         domain->internal = is_internal_domain(sid);
00158         domain->sequence_number = DOM_SEQUENCE_NONE;
00159         domain->last_seq_check = 0;
00160         domain->initialized = False;
00161         domain->online = is_internal_domain(sid);
00162         domain->check_online_timeout = 0;
00163         if (sid) {
00164                 sid_copy(&domain->sid, sid);
00165         }
00166         
00167         /* Link to domain list */
00168         DLIST_ADD(_domain_list, domain);
00169         
00170         DEBUG(2,("Added domain %s %s %s\n", 
00171                  domain->name, domain->alt_name,
00172                  &domain->sid?sid_string_static(&domain->sid):""));
00173         
00174         return domain;
00175 }
00176 
00177 /********************************************************************
00178   rescan our domains looking for new trusted domains
00179 ********************************************************************/
00180 
00181 struct trustdom_state {
00182         TALLOC_CTX *mem_ctx;
00183         struct winbindd_response *response;
00184 };
00185 
00186 static void trustdom_recv(void *private_data, BOOL success);
00187 
00188 static void add_trusted_domains( struct winbindd_domain *domain )
00189 {
00190         TALLOC_CTX *mem_ctx;
00191         struct winbindd_request *request;
00192         struct winbindd_response *response;
00193 
00194         struct trustdom_state *state;
00195 
00196         mem_ctx = talloc_init("add_trusted_domains");
00197         if (mem_ctx == NULL) {
00198                 DEBUG(0, ("talloc_init failed\n"));
00199                 return;
00200         }
00201 
00202         request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);
00203         response = TALLOC_P(mem_ctx, struct winbindd_response);
00204         state = TALLOC_P(mem_ctx, struct trustdom_state);
00205 
00206         if ((request == NULL) || (response == NULL) || (state == NULL)) {
00207                 DEBUG(0, ("talloc failed\n"));
00208                 talloc_destroy(mem_ctx);
00209                 return;
00210         }
00211 
00212         state->mem_ctx = mem_ctx;
00213         state->response = response;
00214 
00215         request->length = sizeof(*request);
00216         request->cmd = WINBINDD_LIST_TRUSTDOM;
00217 
00218         async_domain_request(mem_ctx, domain, request, response,
00219                              trustdom_recv, state);
00220 }
00221 
00222 static void trustdom_recv(void *private_data, BOOL success)
00223 {
00224         struct trustdom_state *state =
00225                 talloc_get_type_abort(private_data, struct trustdom_state);
00226         struct winbindd_response *response = state->response;
00227         char *p;
00228 
00229         if ((!success) || (response->result != WINBINDD_OK)) {
00230                 DEBUG(1, ("Could not receive trustdoms\n"));
00231                 talloc_destroy(state->mem_ctx);
00232                 return;
00233         }
00234 
00235         p = (char *)response->extra_data.data;
00236 
00237         while ((p != NULL) && (*p != '\0')) {
00238                 char *q, *sidstr, *alt_name;
00239                 DOM_SID sid;
00240 
00241                 alt_name = strchr(p, '\\');
00242                 if (alt_name == NULL) {
00243                         DEBUG(0, ("Got invalid trustdom response\n"));
00244                         break;
00245                 }
00246 
00247                 *alt_name = '\0';
00248                 alt_name += 1;
00249 
00250                 sidstr = strchr(alt_name, '\\');
00251                 if (sidstr == NULL) {
00252                         DEBUG(0, ("Got invalid trustdom response\n"));
00253                         break;
00254                 }
00255 
00256                 *sidstr = '\0';
00257                 sidstr += 1;
00258 
00259                 q = strchr(sidstr, '\n');
00260                 if (q != NULL)
00261                         *q = '\0';
00262 
00263                 if (!string_to_sid(&sid, sidstr)) {
00264                         /* Allow NULL sid for sibling domains */
00265                         if ( strcmp(sidstr,"S-0-0") == 0) {
00266                                 sid_copy( &sid, &global_sid_NULL);                              
00267                         } else {                                
00268                                 DEBUG(0, ("Got invalid trustdom response\n"));
00269                                 break;
00270                         }                       
00271                 }
00272 
00273                 if (find_domain_from_name_noinit(p) == NULL) {
00274                         struct winbindd_domain *domain;
00275                         char *alternate_name = NULL;
00276                         
00277                         /* use the real alt_name if we have one, else pass in NULL */
00278 
00279                         if ( !strequal( alt_name, "(null)" ) )
00280                                 alternate_name = alt_name;
00281 
00282                         domain = add_trusted_domain(p, alternate_name,
00283                                                     &cache_methods,
00284                                                     &sid);
00285                         setup_domain_child(domain, &domain->child, NULL);
00286                 }
00287                 p=q;
00288                 if (p != NULL)
00289                         p += 1;
00290         }
00291 
00292         SAFE_FREE(response->extra_data.data);
00293         talloc_destroy(state->mem_ctx);
00294 }
00295 
00296 /********************************************************************
00297  Periodically we need to refresh the trusted domain cache for smbd 
00298 ********************************************************************/
00299 
00300 void rescan_trusted_domains( void )
00301 {
00302         time_t now = time(NULL);
00303         
00304         /* see if the time has come... */
00305         
00306         if ((now >= last_trustdom_scan) &&
00307             ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
00308                 return;
00309                 
00310         /* this will only add new domains we didn't already know about */
00311         
00312         add_trusted_domains( find_our_domain() );
00313 
00314         last_trustdom_scan = now;
00315         
00316         return; 
00317 }
00318 
00319 struct init_child_state {
00320         TALLOC_CTX *mem_ctx;
00321         struct winbindd_domain *domain;
00322         struct winbindd_request *request;
00323         struct winbindd_response *response;
00324         void (*continuation)(void *private_data, BOOL success);
00325         void *private_data;
00326 };
00327 
00328 static void init_child_recv(void *private_data, BOOL success);
00329 static void init_child_getdc_recv(void *private_data, BOOL success);
00330 
00331 enum winbindd_result init_child_connection(struct winbindd_domain *domain,
00332                                            void (*continuation)(void *private_data,
00333                                                                 BOOL success),
00334                                            void *private_data)
00335 {
00336         TALLOC_CTX *mem_ctx;
00337         struct winbindd_request *request;
00338         struct winbindd_response *response;
00339         struct init_child_state *state;
00340         struct winbindd_domain *request_domain;
00341 
00342         mem_ctx = talloc_init("init_child_connection");
00343         if (mem_ctx == NULL) {
00344                 DEBUG(0, ("talloc_init failed\n"));
00345                 return WINBINDD_ERROR;
00346         }
00347 
00348         request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);
00349         response = TALLOC_P(mem_ctx, struct winbindd_response);
00350         state = TALLOC_P(mem_ctx, struct init_child_state);
00351 
00352         if ((request == NULL) || (response == NULL) || (state == NULL)) {
00353                 DEBUG(0, ("talloc failed\n"));
00354                 TALLOC_FREE(mem_ctx);
00355                 continuation(private_data, False);
00356                 return WINBINDD_ERROR;
00357         }
00358 
00359         request->length = sizeof(*request);
00360 
00361         state->mem_ctx = mem_ctx;
00362         state->domain = domain;
00363         state->request = request;
00364         state->response = response;
00365         state->continuation = continuation;
00366         state->private_data = private_data;
00367 
00368         if (IS_DC || domain->primary) {
00369                 /* The primary domain has to find the DC name itself */
00370                 request->cmd = WINBINDD_INIT_CONNECTION;
00371                 fstrcpy(request->domain_name, domain->name);
00372                 request->data.init_conn.is_primary = True;
00373                 fstrcpy(request->data.init_conn.dcname, "");
00374                 async_request(mem_ctx, &domain->child, request, response,
00375                               init_child_recv, state);
00376                 return WINBINDD_PENDING;
00377         }
00378 
00379         /* This is *not* the primary domain, let's ask our DC about a DC
00380          * name */
00381 
00382         request->cmd = WINBINDD_GETDCNAME;
00383         fstrcpy(request->domain_name, domain->name);
00384 
00385         request_domain = find_our_domain();
00386         
00387         async_domain_request(mem_ctx, request_domain, request, response,
00388                              init_child_getdc_recv, state);
00389         return WINBINDD_PENDING;
00390 }
00391 
00392 static void init_child_getdc_recv(void *private_data, BOOL success)
00393 {
00394         struct init_child_state *state =
00395                 talloc_get_type_abort(private_data, struct init_child_state);
00396         const char *dcname = "";
00397 
00398         DEBUG(10, ("Received getdcname response\n"));
00399 
00400         if (success && (state->response->result == WINBINDD_OK)) {
00401                 dcname = state->response->data.dc_name;
00402         }
00403 
00404         state->request->cmd = WINBINDD_INIT_CONNECTION;
00405         fstrcpy(state->request->domain_name, state->domain->name);
00406         state->request->data.init_conn.is_primary = False;
00407         fstrcpy(state->request->data.init_conn.dcname, dcname);
00408 
00409         async_request(state->mem_ctx, &state->domain->child,
00410                       state->request, state->response,
00411                       init_child_recv, state);
00412 }
00413 
00414 static void init_child_recv(void *private_data, BOOL success)
00415 {
00416         struct init_child_state *state =
00417                 talloc_get_type_abort(private_data, struct init_child_state);
00418 
00419         DEBUG(5, ("Received child initialization response for domain %s\n",
00420                   state->domain->name));
00421 
00422         if ((!success) || (state->response->result != WINBINDD_OK)) {
00423                 DEBUG(3, ("Could not init child\n"));
00424                 state->continuation(state->private_data, False);
00425                 talloc_destroy(state->mem_ctx);
00426                 return;
00427         }
00428 
00429         fstrcpy(state->domain->name,
00430                 state->response->data.domain_info.name);
00431         fstrcpy(state->domain->alt_name,
00432                 state->response->data.domain_info.alt_name);
00433         string_to_sid(&state->domain->sid,
00434                       state->response->data.domain_info.sid);
00435         state->domain->native_mode =
00436                 state->response->data.domain_info.native_mode;
00437         state->domain->active_directory =
00438                 state->response->data.domain_info.active_directory;
00439         state->domain->sequence_number =
00440                 state->response->data.domain_info.sequence_number;
00441 
00442         init_dc_connection(state->domain);
00443 
00444         if (state->continuation != NULL)
00445                 state->continuation(state->private_data, True);
00446         talloc_destroy(state->mem_ctx);
00447 }
00448 
00449 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
00450                                                    struct winbindd_cli_state *state)
00451 {
00452         /* Ensure null termination */
00453         state->request.domain_name
00454                 [sizeof(state->request.domain_name)-1]='\0';
00455         state->request.data.init_conn.dcname
00456                 [sizeof(state->request.data.init_conn.dcname)-1]='\0';
00457 
00458         if (strlen(state->request.data.init_conn.dcname) > 0) {
00459                 fstrcpy(domain->dcname, state->request.data.init_conn.dcname);
00460         }
00461 
00462         init_dc_connection(domain);
00463 
00464         if (!domain->initialized) {
00465                 /* If we return error here we can't do any cached authentication,
00466                    but we may be in disconnected mode and can't initialize correctly.
00467                    Do what the previous code did and just return without initialization,
00468                    once we go online we'll re-initialize.
00469                 */
00470                 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
00471                         "online = %d\n", domain->name, (int)domain->online ));
00472         }
00473 
00474         fstrcpy(state->response.data.domain_info.name, domain->name);
00475         fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name);
00476         fstrcpy(state->response.data.domain_info.sid,
00477                 sid_string_static(&domain->sid));
00478         
00479         state->response.data.domain_info.native_mode
00480                 = domain->native_mode;
00481         state->response.data.domain_info.active_directory
00482                 = domain->active_directory;
00483         state->response.data.domain_info.primary
00484                 = domain->primary;
00485         state->response.data.domain_info.sequence_number =
00486                 domain->sequence_number;
00487 
00488         return WINBINDD_OK;
00489 }
00490 
00491 /* Look up global info for the winbind daemon */
00492 BOOL init_domain_list(void)
00493 {
00494         struct winbindd_domain *domain;
00495         int role = lp_server_role();
00496 
00497         /* Free existing list */
00498         free_domain_list();
00499 
00500         /* Add ourselves as the first entry. */
00501 
00502         if ( role == ROLE_DOMAIN_MEMBER ) {
00503                 DOM_SID our_sid;
00504 
00505                 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
00506                         DEBUG(0, ("Could not fetch our SID - did we join?\n"));
00507                         return False;
00508                 }
00509         
00510                 domain = add_trusted_domain( lp_workgroup(), lp_realm(),
00511                                              &cache_methods, &our_sid);
00512                 domain->primary = True;
00513                 setup_domain_child(domain, &domain->child, NULL);
00514                 
00515                 /* Even in the parent winbindd we'll need to
00516                    talk to the DC, so try and see if we can
00517                    contact it. Theoretically this isn't neccessary
00518                    as the init_dc_connection() in init_child_recv()
00519                    will do this, but we can start detecting the DC
00520                    early here. */
00521                 set_domain_online_request(domain);
00522         }
00523 
00524         /* Local SAM */
00525 
00526         domain = add_trusted_domain(get_global_sam_name(), NULL,
00527                                     &sam_passdb_methods, get_global_sam_sid());
00528         if ( role != ROLE_DOMAIN_MEMBER ) {
00529                 domain->primary = True;
00530         }
00531         setup_domain_child(domain, &domain->child, NULL);
00532 
00533         /* BUILTIN domain */
00534 
00535         domain = add_trusted_domain("BUILTIN", NULL, &builtin_passdb_methods,
00536                                     &global_sid_Builtin);
00537         setup_domain_child(domain, &domain->child, NULL);
00538 
00539         return True;
00540 }
00541 
00542 /** 
00543  * Given a domain name, return the struct winbindd domain info for it 
00544  *
00545  * @note Do *not* pass lp_workgroup() to this function.  domain_list
00546  *       may modify it's value, and free that pointer.  Instead, our local
00547  *       domain may be found by calling find_our_domain().
00548  *       directly.
00549  *
00550  *
00551  * @return The domain structure for the named domain, if it is working.
00552  */
00553 
00554 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
00555 {
00556         struct winbindd_domain *domain;
00557 
00558         /* Search through list */
00559 
00560         for (domain = domain_list(); domain != NULL; domain = domain->next) {
00561                 if (strequal(domain_name, domain->name) ||
00562                     (domain->alt_name[0] &&
00563                      strequal(domain_name, domain->alt_name))) {
00564                         return domain;
00565                 }
00566         }
00567 
00568         /* Not found */
00569 
00570         return NULL;
00571 }
00572 
00573 struct winbindd_domain *find_domain_from_name(const char *domain_name)
00574 {
00575         struct winbindd_domain *domain;
00576 
00577         domain = find_domain_from_name_noinit(domain_name);
00578 
00579         if (domain == NULL)
00580                 return NULL;
00581 
00582         if (!domain->initialized)
00583                 init_dc_connection(domain);
00584 
00585         return domain;
00586 }
00587 
00588 /* Given a domain sid, return the struct winbindd domain info for it */
00589 
00590 struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid)
00591 {
00592         struct winbindd_domain *domain;
00593 
00594         /* Search through list */
00595 
00596         for (domain = domain_list(); domain != NULL; domain = domain->next) {
00597                 if (sid_compare_domain(sid, &domain->sid) == 0)
00598                         return domain;
00599         }
00600 
00601         /* Not found */
00602 
00603         return NULL;
00604 }
00605 
00606 /* Given a domain sid, return the struct winbindd domain info for it */
00607 
00608 struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
00609 {
00610         struct winbindd_domain *domain;
00611 
00612         domain = find_domain_from_sid_noinit(sid);
00613 
00614         if (domain == NULL)
00615                 return NULL;
00616 
00617         if (!domain->initialized)
00618                 init_dc_connection(domain);
00619 
00620         return domain;
00621 }
00622 
00623 struct winbindd_domain *find_our_domain(void)
00624 {
00625         struct winbindd_domain *domain;
00626 
00627         /* Search through list */
00628 
00629         for (domain = domain_list(); domain != NULL; domain = domain->next) {
00630                 if (domain->primary)
00631                         return domain;
00632         }
00633 
00634         smb_panic("Could not find our domain\n");
00635         return NULL;
00636 }
00637 
00638 struct winbindd_domain *find_root_domain(void)
00639 {
00640         struct winbindd_domain *ours = find_our_domain();       
00641         
00642         if ( !ours )
00643                 return NULL;
00644         
00645         if ( strlen(ours->forest_name) == 0 )
00646                 return NULL;
00647         
00648         return find_domain_from_name( ours->forest_name );
00649 }
00650 
00651 struct winbindd_domain *find_builtin_domain(void)
00652 {
00653         DOM_SID sid;
00654         struct winbindd_domain *domain;
00655 
00656         string_to_sid(&sid, "S-1-5-32");
00657         domain = find_domain_from_sid(&sid);
00658 
00659         if (domain == NULL)
00660                 smb_panic("Could not find BUILTIN domain\n");
00661 
00662         return domain;
00663 }
00664 
00665 /* Find the appropriate domain to lookup a name or SID */
00666 
00667 struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
00668 {
00669         /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
00670          * one to contact the external DC's. On member servers the internal
00671          * domains are different: These are part of the local SAM. */
00672 
00673         DEBUG(10, ("find_lookup_domain_from_sid(%s)\n",
00674                    sid_string_static(sid)));
00675 
00676         if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
00677                 DEBUG(10, ("calling find_domain_from_sid\n"));
00678                 return find_domain_from_sid(sid);
00679         }
00680 
00681         /* On a member server a query for SID or name can always go to our
00682          * primary DC. */
00683 
00684         DEBUG(10, ("calling find_our_domain\n"));
00685         return find_our_domain();
00686 }
00687 
00688 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
00689 {
00690         if (IS_DC || strequal(domain_name, "BUILTIN") ||
00691             strequal(domain_name, get_global_sam_name()))
00692                 return find_domain_from_name_noinit(domain_name);
00693 
00694         return find_our_domain();
00695 }
00696 
00697 /* Lookup a sid in a domain from a name */
00698 
00699 BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx,
00700                                  struct winbindd_domain *domain, 
00701                                  const char *domain_name,
00702                                  const char *name, DOM_SID *sid, 
00703                                  enum lsa_SidType *type)
00704 {
00705         NTSTATUS result;
00706 
00707         /* Lookup name */
00708         result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
00709 
00710         /* Return sid and type if lookup successful */
00711         if (!NT_STATUS_IS_OK(result)) {
00712                 *type = SID_NAME_UNKNOWN;
00713         }
00714 
00715         return NT_STATUS_IS_OK(result);
00716 }
00717 
00718 /**
00719  * @brief Lookup a name in a domain from a sid.
00720  *
00721  * @param sid Security ID you want to look up.
00722  * @param name On success, set to the name corresponding to @p sid.
00723  * @param dom_name On success, set to the 'domain name' corresponding to @p sid.
00724  * @param type On success, contains the type of name: alias, group or
00725  * user.
00726  * @retval True if the name exists, in which case @p name and @p type
00727  * are set, otherwise False.
00728  **/
00729 BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx,
00730                                  DOM_SID *sid,
00731                                  char **dom_name,
00732                                  char **name,
00733                                  enum lsa_SidType *type)
00734 {
00735         NTSTATUS result;
00736         struct winbindd_domain *domain;
00737 
00738         *dom_name = NULL;
00739         *name = NULL;
00740 
00741         domain = find_lookup_domain_from_sid(sid);
00742 
00743         if (!domain) {
00744                 DEBUG(1,("Can't find domain from sid\n"));
00745                 return False;
00746         }
00747 
00748         /* Lookup name */
00749 
00750         result = domain->methods->sid_to_name(domain, mem_ctx, sid, dom_name, name, type);
00751 
00752         /* Return name and type if successful */
00753         
00754         if (NT_STATUS_IS_OK(result)) {
00755                 return True;
00756         }
00757 
00758         *type = SID_NAME_UNKNOWN;
00759         
00760         return False;
00761 }
00762 
00763 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
00764 
00765 void free_getent_state(struct getent_state *state)
00766 {
00767         struct getent_state *temp;
00768 
00769         /* Iterate over state list */
00770 
00771         temp = state;
00772 
00773         while(temp != NULL) {
00774                 struct getent_state *next;
00775 
00776                 /* Free sam entries then list entry */
00777 
00778                 SAFE_FREE(state->sam_entries);
00779                 DLIST_REMOVE(state, state);
00780                 next = temp->next;
00781 
00782                 SAFE_FREE(temp);
00783                 temp = next;
00784         }
00785 }
00786 
00787 /* Is this a domain which we may assume no DOMAIN\ prefix? */
00788 
00789 static BOOL assume_domain(const char *domain)
00790 {
00791         /* never assume the domain on a standalone server */
00792 
00793         if ( lp_server_role() == ROLE_STANDALONE )
00794                 return False;
00795 
00796         /* domain member servers may possibly assume for the domain name */
00797 
00798         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
00799                 if ( !strequal(lp_workgroup(), domain) )
00800                         return False;
00801 
00802                 if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() )
00803                         return True;
00804         } 
00805 
00806         /* only left with a domain controller */
00807 
00808         if ( strequal(get_global_sam_name(), domain) )  {
00809                 return True;
00810         }
00811         
00812         return False;
00813 }
00814 
00815 /* Parse a string of the form DOMAIN\user into a domain and a user */
00816 
00817 BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
00818 {
00819         char *p = strchr(domuser,*lp_winbind_separator());
00820 
00821         if ( !p ) {
00822                 fstrcpy(user, domuser);
00823 
00824                 if ( assume_domain(lp_workgroup())) {
00825                         fstrcpy(domain, lp_workgroup());
00826                 } else {
00827                         return False;
00828                 }
00829         } else {
00830                 fstrcpy(user, p+1);
00831                 fstrcpy(domain, domuser);
00832                 domain[PTR_DIFF(p, domuser)] = 0;
00833         }
00834         
00835         strupper_m(domain);
00836         
00837         return True;
00838 }
00839 
00840 BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
00841                               char **domain, char **user)
00842 {
00843         fstring fstr_domain, fstr_user;
00844         if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
00845                 return False;
00846         }
00847         *domain = talloc_strdup(mem_ctx, fstr_domain);
00848         *user = talloc_strdup(mem_ctx, fstr_user);
00849         return ((*domain != NULL) && (*user != NULL));
00850 }
00851 
00852 /* Ensure an incoming username from NSS is fully qualified. Replace the
00853    incoming fstring with DOMAIN <separator> user. Returns the same
00854    values as parse_domain_user() but also replaces the incoming username.
00855    Used to ensure all names are fully qualified within winbindd.
00856    Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
00857    The protocol definitions of auth_crap, chng_pswd_auth_crap
00858    really should be changed to use this instead of doing things
00859    by hand. JRA. */
00860 
00861 BOOL canonicalize_username(fstring username_inout, fstring domain, fstring user)
00862 {
00863         if (!parse_domain_user(username_inout, domain, user)) {
00864                 return False;
00865         }
00866         slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
00867                  domain, *lp_winbind_separator(),
00868                  user);
00869         return True;
00870 }
00871 
00872 /*
00873     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
00874     'winbind separator' options.
00875     This means:
00876         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
00877         lp_workgroup()
00878 
00879     If we are a PDC or BDC, and this is for our domain, do likewise.
00880 
00881     Also, if omit DOMAIN if 'winbind trusted domains only = true', as the 
00882     username is then unqualified in unix
00883 
00884     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
00885 */
00886 void fill_domain_username(fstring name, const char *domain, const char *user, BOOL can_assume)
00887 {
00888         fstring tmp_user;
00889 
00890         fstrcpy(tmp_user, user);
00891         strlower_m(tmp_user);
00892 
00893         if (can_assume && assume_domain(domain)) {
00894                 strlcpy(name, tmp_user, sizeof(fstring));
00895         } else {
00896                 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
00897                          domain, *lp_winbind_separator(),
00898                          tmp_user);
00899         }
00900 }
00901 
00902 /*
00903  * Winbindd socket accessor functions
00904  */
00905 
00906 char *get_winbind_priv_pipe_dir(void) 
00907 {
00908         return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
00909 }
00910 
00911 /* Open the winbindd socket */
00912 
00913 static int _winbindd_socket = -1;
00914 static int _winbindd_priv_socket = -1;
00915 
00916 int open_winbindd_socket(void)
00917 {
00918         if (_winbindd_socket == -1) {
00919                 _winbindd_socket = create_pipe_sock(
00920                         WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755);
00921                 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
00922                            _winbindd_socket));
00923         }
00924 
00925         return _winbindd_socket;
00926 }
00927 
00928 int open_winbindd_priv_socket(void)
00929 {
00930         if (_winbindd_priv_socket == -1) {
00931                 _winbindd_priv_socket = create_pipe_sock(
00932                         get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
00933                 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
00934                            _winbindd_priv_socket));
00935         }
00936 
00937         return _winbindd_priv_socket;
00938 }
00939 
00940 /* Close the winbindd socket */
00941 
00942 void close_winbindd_socket(void)
00943 {
00944         if (_winbindd_socket != -1) {
00945                 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
00946                            _winbindd_socket));
00947                 close(_winbindd_socket);
00948                 _winbindd_socket = -1;
00949         }
00950         if (_winbindd_priv_socket != -1) {
00951                 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
00952                            _winbindd_priv_socket));
00953                 close(_winbindd_priv_socket);
00954                 _winbindd_priv_socket = -1;
00955         }
00956 }
00957 
00958 /*
00959  * Client list accessor functions
00960  */
00961 
00962 static struct winbindd_cli_state *_client_list;
00963 static int _num_clients;
00964 
00965 /* Return list of all connected clients */
00966 
00967 struct winbindd_cli_state *winbindd_client_list(void)
00968 {
00969         return _client_list;
00970 }
00971 
00972 /* Add a connection to the list */
00973 
00974 void winbindd_add_client(struct winbindd_cli_state *cli)
00975 {
00976         DLIST_ADD(_client_list, cli);
00977         _num_clients++;
00978 }
00979 
00980 /* Remove a client from the list */
00981 
00982 void winbindd_remove_client(struct winbindd_cli_state *cli)
00983 {
00984         DLIST_REMOVE(_client_list, cli);
00985         _num_clients--;
00986 }
00987 
00988 /* Close all open clients */
00989 
00990 void winbindd_kill_all_clients(void)
00991 {
00992         struct winbindd_cli_state *cl = winbindd_client_list();
00993 
00994         DEBUG(10, ("winbindd_kill_all_clients: going postal\n"));
00995 
00996         while (cl) {
00997                 struct winbindd_cli_state *next;
00998                 
00999                 next = cl->next;
01000                 winbindd_remove_client(cl);
01001                 cl = next;
01002         }
01003 }
01004 
01005 /* Return number of open clients */
01006 
01007 int winbindd_num_clients(void)
01008 {
01009         return _num_clients;
01010 }
01011 
01012 NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
01013                                   TALLOC_CTX *mem_ctx,
01014                                   const DOM_SID *user_sid,
01015                                   uint32 *p_num_groups, DOM_SID **user_sids)
01016 {
01017         NET_USER_INFO_3 *info3 = NULL;
01018         NTSTATUS status = NT_STATUS_NO_MEMORY;
01019         int i;
01020         size_t num_groups = 0;
01021         DOM_SID group_sid, primary_group;
01022         
01023         DEBUG(3,(": lookup_usergroups_cached\n"));
01024         
01025         *user_sids = NULL;
01026         num_groups = 0;
01027         *p_num_groups = 0;
01028 
01029         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
01030 
01031         if (info3 == NULL) {
01032                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
01033         }
01034 
01035         if (info3->num_groups == 0) {
01036                 TALLOC_FREE(info3);
01037                 return NT_STATUS_UNSUCCESSFUL;
01038         }
01039         
01040         /* always add the primary group to the sid array */
01041         sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
01042         
01043         if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
01044                 TALLOC_FREE(info3);
01045                 return NT_STATUS_NO_MEMORY;
01046         }
01047 
01048         for (i=0; i<info3->num_groups; i++) {
01049                 sid_copy(&group_sid, &info3->dom_sid.sid);
01050                 sid_append_rid(&group_sid, info3->gids[i].g_rid);
01051 
01052                 if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
01053                                  &num_groups)) {
01054                         TALLOC_FREE(info3);
01055                         return NT_STATUS_NO_MEMORY;
01056                 }
01057         }
01058 
01059         TALLOC_FREE(info3);
01060         *p_num_groups = num_groups;
01061         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
01062         
01063         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
01064 
01065         return status;
01066 }
01067 
01068 /*********************************************************************
01069  We use this to remove spaces from user and group names
01070 ********************************************************************/
01071 
01072 void ws_name_replace( char *name, char replace )
01073 {
01074         char replace_char[2] = { 0x0, 0x0 };
01075     
01076         if ( !lp_winbind_normalize_names() || (replace == '\0') ) 
01077                 return;
01078 
01079         replace_char[0] = replace;      
01080         all_string_sub( name, " ", replace_char, 0 );
01081 
01082         return; 
01083 }
01084 
01085 /*********************************************************************
01086  We use this to do the inverse of ws_name_replace()
01087 ********************************************************************/
01088 
01089 void ws_name_return( char *name, char replace )
01090 {
01091         char replace_char[2] = { 0x0, 0x0 };
01092     
01093         if ( !lp_winbind_normalize_names() || (replace == '\0') ) 
01094                 return;
01095         
01096         replace_char[0] = replace;      
01097         all_string_sub( name, replace_char, " ", 0 );
01098 
01099         return; 
01100 }

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