nsswitch/winbindd_async.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Async helpers for blocking functions
00005 
00006    Copyright (C) Volker Lendecke 2005
00007    Copyright (C) Gerald Carter 2006
00008    
00009    The helpers always consist of three functions: 
00010 
00011    * A request setup function that takes the necessary parameters together
00012      with a continuation function that is to be called upon completion
00013 
00014    * A private continuation function that is internal only. This is to be
00015      called by the lower-level functions in do_async(). Its only task is to
00016      properly call the continuation function named above.
00017 
00018    * A worker function that is called inside the appropriate child process.
00019 
00020    This program is free software; you can redistribute it and/or modify
00021    it under the terms of the GNU General Public License as published by
00022    the Free Software Foundation; either version 2 of the License, or
00023    (at your option) any later version.
00024    
00025    This program is distributed in the hope that it will be useful,
00026    but WITHOUT ANY WARRANTY; without even the implied warranty of
00027    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028    GNU General Public License for more details.
00029    
00030    You should have received a copy of the GNU General Public License
00031    along with this program; if not, write to the Free Software
00032    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00033 */
00034 
00035 #include "includes.h"
00036 #include "winbindd.h"
00037 
00038 #undef DBGC_CLASS
00039 #define DBGC_CLASS DBGC_WINBIND
00040 
00041 struct do_async_state {
00042         TALLOC_CTX *mem_ctx;
00043         struct winbindd_request request;
00044         struct winbindd_response response;
00045         void (*cont)(TALLOC_CTX *mem_ctx,
00046                      BOOL success,
00047                      struct winbindd_response *response,
00048                      void *c, void *private_data);
00049         void *c, *private_data;
00050 };
00051 
00052 static void do_async_recv(void *private_data, BOOL success)
00053 {
00054         struct do_async_state *state =
00055                 talloc_get_type_abort(private_data, struct do_async_state);
00056 
00057         state->cont(state->mem_ctx, success, &state->response,
00058                     state->c, state->private_data);
00059 }
00060 
00061 static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
00062                      const struct winbindd_request *request,
00063                      void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
00064                                   struct winbindd_response *response,
00065                                   void *c, void *private_data),
00066                      void *c, void *private_data)
00067 {
00068         struct do_async_state *state;
00069 
00070         state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
00071         if (state == NULL) {
00072                 DEBUG(0, ("talloc failed\n"));
00073                 cont(mem_ctx, False, NULL, c, private_data);
00074                 return;
00075         }
00076 
00077         state->mem_ctx = mem_ctx;
00078         state->request = *request;
00079         state->request.length = sizeof(state->request);
00080         state->cont = cont;
00081         state->c = c;
00082         state->private_data = private_data;
00083 
00084         async_request(mem_ctx, child, &state->request,
00085                       &state->response, do_async_recv, state);
00086 }
00087 
00088 void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
00089                      const struct winbindd_request *request,
00090                      void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
00091                                   struct winbindd_response *response,
00092                                   void *c, void *private_data),
00093                      void *c, void *private_data)
00094 {
00095         struct do_async_state *state;
00096 
00097         state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
00098         if (state == NULL) {
00099                 DEBUG(0, ("talloc failed\n"));
00100                 cont(mem_ctx, False, NULL, c, private_data);
00101                 return;
00102         }
00103 
00104         state->mem_ctx = mem_ctx;
00105         state->request = *request;
00106         state->request.length = sizeof(state->request);
00107         state->cont = cont;
00108         state->c = c;
00109         state->private_data = private_data;
00110 
00111         async_domain_request(mem_ctx, domain, &state->request,
00112                              &state->response, do_async_recv, state);
00113 }
00114 
00115 static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
00116                                    struct winbindd_response *response,
00117                                    void *c, void *private_data)
00118 {
00119         void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
00120 
00121         if (!success) {
00122                 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
00123                 cont(private_data, False);
00124                 return;
00125         }
00126 
00127         if (response->result != WINBINDD_OK) {
00128                 DEBUG(5, ("idmap_set_mapping returned an error\n"));
00129                 cont(private_data, False);
00130                 return;
00131         }
00132 
00133         cont(private_data, True);
00134 }
00135 
00136 void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map,
00137                              void (*cont)(void *private_data, BOOL success),
00138                              void *private_data)
00139 {
00140         struct winbindd_request request;
00141         ZERO_STRUCT(request);
00142         request.cmd = WINBINDD_DUAL_SET_MAPPING;
00143         request.data.dual_idmapset.id = map->xid.id;
00144         request.data.dual_idmapset.type = map->xid.type;
00145         sid_to_string(request.data.dual_idmapset.sid, map->sid);
00146 
00147         do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv,
00148                  (void *)cont, private_data);
00149 }
00150 
00151 enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain,
00152                                             struct winbindd_cli_state *state)
00153 {
00154         struct id_map map;
00155         DOM_SID sid;
00156         NTSTATUS result;
00157 
00158         DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
00159 
00160         if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
00161                 return WINBINDD_ERROR;
00162 
00163         map.sid = &sid;
00164         map.xid.id = state->request.data.dual_idmapset.id;
00165         map.xid.type = state->request.data.dual_idmapset.type;
00166         map.status = ID_MAPPED;
00167 
00168         result = idmap_set_mapping(&map);
00169         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
00170 }
00171 
00172 static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success,
00173                                    struct winbindd_response *response,
00174                                    void *c, void *private_data)
00175 {
00176         void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
00177 
00178         if (!success) {
00179                 DEBUG(5, ("Could not trigger idmap_set_hwm\n"));
00180                 cont(private_data, False);
00181                 return;
00182         }
00183 
00184         if (response->result != WINBINDD_OK) {
00185                 DEBUG(5, ("idmap_set_hwm returned an error\n"));
00186                 cont(private_data, False);
00187                 return;
00188         }
00189 
00190         cont(private_data, True);
00191 }
00192 
00193 void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid,
00194                              void (*cont)(void *private_data, BOOL success),
00195                              void *private_data)
00196 {
00197         struct winbindd_request request;
00198         ZERO_STRUCT(request);
00199         request.cmd = WINBINDD_DUAL_SET_HWM;
00200         request.data.dual_idmapset.id = xid->id;
00201         request.data.dual_idmapset.type = xid->type;
00202 
00203         do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv,
00204                  (void *)cont, private_data);
00205 }
00206 
00207 enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain,
00208                                             struct winbindd_cli_state *state)
00209 {
00210         struct unixid xid;
00211         NTSTATUS result;
00212 
00213         DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid));
00214 
00215         xid.id = state->request.data.dual_idmapset.id;
00216         xid.type = state->request.data.dual_idmapset.type;
00217 
00218         switch (xid.type) {
00219         case ID_TYPE_UID:
00220                 result = idmap_set_uid_hwm(&xid);
00221                 break;
00222         case ID_TYPE_GID:
00223                 result = idmap_set_gid_hwm(&xid);
00224                 break;
00225         default:
00226                 return WINBINDD_ERROR;
00227         }
00228         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
00229 }
00230 
00231 static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success,
00232                                struct winbindd_response *response,
00233                                void *c, void *private_data)
00234 {
00235         void (*cont)(void *priv, BOOL succ, void *, int) =
00236                 (void (*)(void *, BOOL, void *, int))c;
00237 
00238         if (!success) {
00239                 DEBUG(5, ("Could not trigger sids2xids\n"));
00240                 cont(private_data, False, NULL, 0);
00241                 return;
00242         }
00243 
00244         if (response->result != WINBINDD_OK) {
00245                 DEBUG(5, ("sids2xids returned an error\n"));
00246                 cont(private_data, False, NULL, 0);
00247                 return;
00248         }
00249 
00250         cont(private_data, True, response->extra_data.data, response->length - sizeof(response));
00251 }
00252                          
00253 void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size,
00254                          void (*cont)(void *private_data, BOOL success, void *data, int len),
00255                          void *private_data)
00256 {
00257         struct winbindd_request request;
00258         ZERO_STRUCT(request);
00259         request.cmd = WINBINDD_DUAL_SIDS2XIDS;
00260         request.extra_data.data = (char *)sids;
00261         request.extra_len = size;
00262         do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv,
00263                  (void *)cont, private_data);
00264 }
00265 
00266 enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain,
00267                                            struct winbindd_cli_state *state)
00268 {
00269         DOM_SID *sids;
00270         struct unixid *xids;
00271         struct id_map **ids;
00272         NTSTATUS result;
00273         int num, i;
00274 
00275         DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid));
00276 
00277         if (state->request.extra_len == 0) {
00278                 DEBUG(0, ("Invalid buffer size!\n"));
00279                 return WINBINDD_ERROR;
00280         }
00281 
00282         sids = (DOM_SID *)state->request.extra_data.data;
00283         num = state->request.extra_len / sizeof(DOM_SID);
00284 
00285         ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1);
00286         if ( ! ids) {
00287                 DEBUG(0, ("Out of memory!\n"));
00288                 return WINBINDD_ERROR;
00289         }
00290         for (i = 0; i < num; i++) {
00291                 ids[i] = TALLOC_P(ids, struct id_map);
00292                 if ( ! ids[i]) {
00293                         DEBUG(0, ("Out of memory!\n"));
00294                         talloc_free(ids);
00295                         return WINBINDD_ERROR;
00296                 }
00297                 ids[i]->sid = &sids[i];
00298         }
00299 
00300         result = idmap_sids_to_unixids(ids);
00301 
00302         if (NT_STATUS_IS_OK(result)) {
00303 
00304                 xids = SMB_MALLOC_ARRAY(struct unixid, num);
00305                 if ( ! xids) {
00306                         DEBUG(0, ("Out of memory!\n"));
00307                         talloc_free(ids);
00308                         return WINBINDD_ERROR;
00309                 }
00310                 
00311                 for (i = 0; i < num; i++) {
00312                         if (ids[i]->status == ID_MAPPED) {
00313                                 xids[i].type = ids[i]->xid.type;
00314                                 xids[i].id = ids[i]->xid.id;
00315                         } else {
00316                                 xids[i].type = -1;
00317                         }
00318                 }
00319 
00320                 state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num);
00321                 state->response.extra_data.data = xids;
00322 
00323         } else {
00324                 DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result)));
00325                 talloc_free(ids);
00326                 return WINBINDD_ERROR;
00327         }
00328 
00329         talloc_free(ids);
00330         return WINBINDD_OK;
00331 }
00332 
00333 static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00334                                struct winbindd_response *response,
00335                                void *c, void *private_data)
00336 {
00337         void (*cont)(void *priv, BOOL succ, uid_t uid) =
00338                 (void (*)(void *, BOOL, uid_t))c;
00339 
00340         if (!success) {
00341                 DEBUG(5, ("Could not trigger sid2uid\n"));
00342                 cont(private_data, False, 0);
00343                 return;
00344         }
00345 
00346         if (response->result != WINBINDD_OK) {
00347                 DEBUG(5, ("sid2uid returned an error\n"));
00348                 cont(private_data, False, 0);
00349                 return;
00350         }
00351 
00352         cont(private_data, True, response->data.uid);
00353 }
00354                          
00355 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
00356                          void (*cont)(void *private_data, BOOL success, uid_t uid),
00357                          void *private_data)
00358 {
00359         struct winbindd_request request;
00360         ZERO_STRUCT(request);
00361         request.cmd = WINBINDD_DUAL_SID2UID;
00362         sid_to_string(request.data.dual_sid2id.sid, sid);
00363         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv,
00364                  (void *)cont, private_data);
00365 }
00366 
00367 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
00368                                            struct winbindd_cli_state *state)
00369 {
00370         DOM_SID sid;
00371         NTSTATUS result;
00372 
00373         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
00374                   state->request.data.dual_sid2id.sid));
00375 
00376         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
00377                 DEBUG(1, ("Could not get convert sid %s from string\n",
00378                           state->request.data.dual_sid2id.sid));
00379                 return WINBINDD_ERROR;
00380         }
00381 
00382         /* Find uid for this sid and return it, possibly ask the slow remote idmap */
00383 
00384         result = idmap_sid_to_uid(&sid, &(state->response.data.uid));
00385 
00386         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
00387 }
00388 
00389 #if 0   /* not used */
00390 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
00391                           struct winbindd_response *response,
00392                           void *c, void *private_data);
00393 
00394 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
00395                              void (*cont)(void *private_data, BOOL success,
00396                                           const char *name),
00397                              void *private_data)
00398 {
00399         struct winbindd_request request;
00400         ZERO_STRUCT(request);
00401         request.cmd = WINBINDD_DUAL_UID2NAME;
00402         request.data.uid = uid;
00403         do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
00404                  (void *)cont, private_data);
00405 }
00406 #endif  /* not used */
00407 
00408 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
00409                                             struct winbindd_cli_state *state)
00410 {
00411         struct passwd *pw;
00412 
00413         DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, 
00414                   (unsigned long)state->request.data.uid));
00415 
00416         pw = getpwuid(state->request.data.uid);
00417         if (pw == NULL) {
00418                 DEBUG(5, ("User %lu not found\n",
00419                           (unsigned long)state->request.data.uid));
00420                 return WINBINDD_ERROR;
00421         }
00422 
00423         fstrcpy(state->response.data.name.name, pw->pw_name);
00424         return WINBINDD_OK;
00425 }
00426 
00427 #if 0   /* not used */
00428 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
00429                           struct winbindd_response *response,
00430                           void *c, void *private_data)
00431 {
00432         void (*cont)(void *priv, BOOL succ, const char *name) =
00433                 (void (*)(void *, BOOL, const char *))c;
00434 
00435         if (!success) {
00436                 DEBUG(5, ("Could not trigger uid2name\n"));
00437                 cont(private_data, False, NULL);
00438                 return;
00439         }
00440 
00441         if (response->result != WINBINDD_OK) {
00442                 DEBUG(5, ("uid2name returned an error\n"));
00443                 cont(private_data, False, NULL);
00444                 return;
00445         }
00446 
00447         cont(private_data, True, response->data.name.name);
00448 }
00449 
00450 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00451                           struct winbindd_response *response,
00452                           void *c, void *private_data);
00453 
00454 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
00455                                     void (*cont)(void *private_data, BOOL success,
00456                                                  uid_t uid),
00457                                     void *private_data)
00458 {
00459         struct winbindd_request request;
00460         ZERO_STRUCT(request);
00461         request.cmd = WINBINDD_DUAL_NAME2UID;
00462         fstrcpy(request.data.username, name);
00463         do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
00464                  (void *)cont, private_data);
00465 }
00466 #endif  /* not used */
00467 
00468 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
00469                                             struct winbindd_cli_state *state)
00470 {
00471         struct passwd *pw;
00472 
00473         /* Ensure null termination */
00474         state->request.data.username
00475                 [sizeof(state->request.data.username)-1] = '\0';
00476 
00477         DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, 
00478                   state->request.data.username));
00479 
00480         pw = getpwnam(state->request.data.username);
00481         if (pw == NULL) {
00482                 return WINBINDD_ERROR;
00483         }
00484 
00485         state->response.data.uid = pw->pw_uid;
00486         return WINBINDD_OK;
00487 }
00488 
00489 #if 0   /* not used */
00490 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00491                           struct winbindd_response *response,
00492                           void *c, void *private_data)
00493 {
00494         void (*cont)(void *priv, BOOL succ, uid_t uid) =
00495                 (void (*)(void *, BOOL, uid_t))c;
00496 
00497         if (!success) {
00498                 DEBUG(5, ("Could not trigger name2uid\n"));
00499                 cont(private_data, False, 0);
00500                 return;
00501         }
00502 
00503         if (response->result != WINBINDD_OK) {
00504                 DEBUG(5, ("name2uid returned an error\n"));
00505                 cont(private_data, False, 0);
00506                 return;
00507         }
00508 
00509         cont(private_data, True, response->data.uid);
00510 }
00511 #endif  /* not used */
00512 
00513 static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00514                                struct winbindd_response *response,
00515                                void *c, void *private_data)
00516 {
00517         void (*cont)(void *priv, BOOL succ, gid_t gid) =
00518                 (void (*)(void *, BOOL, gid_t))c;
00519 
00520         if (!success) {
00521                 DEBUG(5, ("Could not trigger sid2gid\n"));
00522                 cont(private_data, False, 0);
00523                 return;
00524         }
00525 
00526         if (response->result != WINBINDD_OK) {
00527                 DEBUG(5, ("sid2gid returned an error\n"));
00528                 cont(private_data, False, 0);
00529                 return;
00530         }
00531 
00532         cont(private_data, True, response->data.gid);
00533 }
00534                          
00535 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
00536                          void (*cont)(void *private_data, BOOL success, gid_t gid),
00537                          void *private_data)
00538 {
00539         struct winbindd_request request;
00540         ZERO_STRUCT(request);
00541         request.cmd = WINBINDD_DUAL_SID2GID;
00542         sid_to_string(request.data.dual_sid2id.sid, sid);
00543 
00544         DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n", 
00545                 request.data.dual_sid2id.sid));
00546 
00547         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv,
00548                  (void *)cont, private_data);
00549 }
00550 
00551 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
00552                                            struct winbindd_cli_state *state)
00553 {
00554         DOM_SID sid;
00555         NTSTATUS result;
00556 
00557         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
00558                   state->request.data.dual_sid2id.sid));
00559 
00560         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
00561                 DEBUG(1, ("Could not get convert sid %s from string\n",
00562                           state->request.data.dual_sid2id.sid));
00563                 return WINBINDD_ERROR;
00564         }
00565 
00566         /* Find gid for this sid and return it, possibly ask the slow remote idmap */
00567 
00568         result = idmap_sid_to_gid(&sid, &state->response.data.gid);
00569         
00570         DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid));
00571 
00572         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
00573 }
00574 
00575 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
00576                           struct winbindd_response *response,
00577                           void *c, void *private_data)
00578 {
00579         void (*cont)(void *priv, BOOL succ, const char *name) =
00580                 (void (*)(void *, BOOL, const char *))c;
00581 
00582         if (!success) {
00583                 DEBUG(5, ("Could not trigger gid2name\n"));
00584                 cont(private_data, False, NULL);
00585                 return;
00586         }
00587 
00588         if (response->result != WINBINDD_OK) {
00589                 DEBUG(5, ("gid2name returned an error\n"));
00590                 cont(private_data, False, NULL);
00591                 return;
00592         }
00593 
00594         cont(private_data, True, response->data.name.name);
00595 }
00596 
00597 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
00598                              void (*cont)(void *private_data, BOOL success,
00599                                           const char *name),
00600                              void *private_data)
00601 {
00602         struct winbindd_request request;
00603         ZERO_STRUCT(request);
00604         request.cmd = WINBINDD_DUAL_GID2NAME;
00605         request.data.gid = gid;
00606         do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
00607                  (void *)cont, private_data);
00608 }
00609 
00610 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
00611                                             struct winbindd_cli_state *state)
00612 {
00613         struct group *gr;
00614 
00615         DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, 
00616                   (unsigned long)state->request.data.gid));
00617 
00618         gr = getgrgid(state->request.data.gid);
00619         if (gr == NULL)
00620                 return WINBINDD_ERROR;
00621 
00622         fstrcpy(state->response.data.name.name, gr->gr_name);
00623         return WINBINDD_OK;
00624 }
00625 
00626 #if 0   /* not used */
00627 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00628                           struct winbindd_response *response,
00629                           void *c, void *private_data);
00630 
00631 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
00632                                     void (*cont)(void *private_data, BOOL success,
00633                                                  gid_t gid),
00634                                     void *private_data)
00635 {
00636         struct winbindd_request request;
00637         ZERO_STRUCT(request);
00638         request.cmd = WINBINDD_DUAL_NAME2GID;
00639         fstrcpy(request.data.groupname, name);
00640         do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
00641                  (void *)cont, private_data);
00642 }
00643 #endif  /* not used */
00644 
00645 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
00646                                             struct winbindd_cli_state *state)
00647 {
00648         struct group *gr;
00649 
00650         /* Ensure null termination */
00651         state->request.data.groupname
00652                 [sizeof(state->request.data.groupname)-1] = '\0';
00653 
00654         DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, 
00655                   state->request.data.groupname));
00656 
00657         gr = getgrnam(state->request.data.groupname);
00658         if (gr == NULL) {
00659                 return WINBINDD_ERROR;
00660         }
00661 
00662         state->response.data.gid = gr->gr_gid;
00663         return WINBINDD_OK;
00664 }
00665 
00666 #if 0   /* not used */
00667 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00668                           struct winbindd_response *response,
00669                           void *c, void *private_data)
00670 {
00671         void (*cont)(void *priv, BOOL succ, gid_t gid) =
00672                 (void (*)(void *, BOOL, gid_t))c;
00673 
00674         if (!success) {
00675                 DEBUG(5, ("Could not trigger name2gid\n"));
00676                 cont(private_data, False, 0);
00677                 return;
00678         }
00679 
00680         if (response->result != WINBINDD_OK) {
00681                 DEBUG(5, ("name2gid returned an error\n"));
00682                 cont(private_data, False, 0);
00683                 return;
00684         }
00685 
00686         cont(private_data, True, response->data.gid);
00687 }
00688 #endif  /* not used */
00689 
00690 static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
00691                            struct winbindd_response *response,
00692                            void *c, void *private_data)
00693 {
00694         void (*cont)(void *priv, BOOL succ, const char *dom_name,
00695                      const char *name, enum lsa_SidType type) =
00696                 (void (*)(void *, BOOL, const char *, const char *,
00697                           enum lsa_SidType))c;
00698 
00699         if (!success) {
00700                 DEBUG(5, ("Could not trigger lookupsid\n"));
00701                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
00702                 return;
00703         }
00704 
00705         if (response->result != WINBINDD_OK) {
00706                 DEBUG(5, ("lookupsid returned an error\n"));
00707                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
00708                 return;
00709         }
00710 
00711         cont(private_data, True, response->data.name.dom_name,
00712              response->data.name.name,
00713              (enum lsa_SidType)response->data.name.type);
00714 }
00715 
00716 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
00717                               void (*cont)(void *private_data, BOOL success,
00718                                            const char *dom_name,
00719                                            const char *name,
00720                                            enum lsa_SidType type),
00721                               void *private_data)
00722 {
00723         struct winbindd_domain *domain;
00724         struct winbindd_request request;
00725 
00726         domain = find_lookup_domain_from_sid(sid);
00727         if (domain == NULL) {
00728                 DEBUG(5, ("Could not find domain for sid %s\n",
00729                           sid_string_static(sid)));
00730                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
00731                 return;
00732         }
00733 
00734         ZERO_STRUCT(request);
00735         request.cmd = WINBINDD_LOOKUPSID;
00736         fstrcpy(request.data.sid, sid_string_static(sid));
00737 
00738         do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
00739                         (void *)cont, private_data);
00740 }
00741 
00742 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
00743                                              struct winbindd_cli_state *state)
00744 {
00745         enum lsa_SidType type;
00746         DOM_SID sid;
00747         char *name;
00748         char *dom_name;
00749 
00750         /* Ensure null termination */
00751         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
00752 
00753         DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
00754                   state->request.data.sid));
00755 
00756         /* Lookup sid from PDC using lsa_lookup_sids() */
00757 
00758         if (!string_to_sid(&sid, state->request.data.sid)) {
00759                 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
00760                 return WINBINDD_ERROR;
00761         }
00762 
00763         /* Lookup the sid */
00764 
00765         if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, &dom_name, &name,
00766                                          &type)) {
00767                 TALLOC_FREE(dom_name);
00768                 TALLOC_FREE(name);
00769                 return WINBINDD_ERROR;
00770         }
00771 
00772         fstrcpy(state->response.data.name.dom_name, dom_name);
00773         fstrcpy(state->response.data.name.name, name);
00774         state->response.data.name.type = type;
00775 
00776         TALLOC_FREE(dom_name);
00777         TALLOC_FREE(name);
00778         return WINBINDD_OK;
00779 }
00780 
00781 /********************************************************************
00782  This is the second callback after contacting the forest root
00783 ********************************************************************/
00784 
00785 struct lookupname_state {
00786         char *dom_name;
00787         char *name;
00788         void *caller_private_data;
00789 };
00790 
00791 static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success,
00792                             struct winbindd_response *response,
00793                             void *c, void *private_data)
00794 {
00795         void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
00796                      enum lsa_SidType type) =
00797                 (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
00798         DOM_SID sid;
00799         struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state);
00800 
00801         if (!success) {
00802                 DEBUG(5, ("Could not trigger lookup_name\n"));
00803                 cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00804                 return;
00805         }
00806 
00807         if (response->result != WINBINDD_OK) {
00808                 DEBUG(5, ("lookup_name returned an error\n"));
00809                 cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00810                 return;
00811         }
00812 
00813         if (!string_to_sid(&sid, response->data.sid.sid)) {
00814                 DEBUG(0, ("Could not convert string %s to sid\n",
00815                           response->data.sid.sid));
00816                 cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00817                 return;
00818         }
00819 
00820         cont(s->caller_private_data, True, &sid,
00821              (enum lsa_SidType)response->data.sid.type);
00822 }
00823 
00824 /********************************************************************
00825  This is the first callback after contacting our own domain 
00826 ********************************************************************/
00827 
00828 static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
00829                             struct winbindd_response *response,
00830                             void *c, void *private_data)
00831 {
00832         void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
00833                      enum lsa_SidType type) =
00834                 (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
00835         DOM_SID sid;
00836         struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state);
00837 
00838         if (!success) {
00839                 DEBUG(5, ("lookupname_recv: lookup_name() failed!\n"));
00840                 cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00841                 return;
00842         }
00843 
00844         if (response->result != WINBINDD_OK) {
00845                 /* Try again using the forest root */
00846                 struct winbindd_domain *root_domain = find_root_domain();
00847                 struct winbindd_request request;
00848 
00849                 if ( !root_domain ) {
00850                         DEBUG(5,("lookupname_recv: unable to determine forest root\n"));
00851                         cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00852                         return;
00853                 }
00854 
00855                 ZERO_STRUCT(request);
00856                 request.cmd = WINBINDD_LOOKUPNAME;
00857                 fstrcpy(request.data.name.dom_name, s->dom_name);
00858                 fstrcpy(request.data.name.name, s->name);
00859 
00860                 do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2,
00861                                 (void *)cont, s);
00862 
00863                 return;
00864         }
00865 
00866         if (!string_to_sid(&sid, response->data.sid.sid)) {
00867                 DEBUG(0, ("Could not convert string %s to sid\n",
00868                           response->data.sid.sid));
00869                 cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
00870                 return;
00871         }
00872 
00873         cont(s->caller_private_data, True, &sid,
00874              (enum lsa_SidType)response->data.sid.type);
00875 }
00876 
00877 /********************************************************************
00878  The lookup name call first contacts a DC in its own domain
00879  and fallbacks to contact a DC in the forest in our domain doesn't
00880  know the name.
00881 ********************************************************************/
00882 
00883 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
00884                                const char *dom_name, const char *name,
00885                                void (*cont)(void *private_data, BOOL success,
00886                                             const DOM_SID *sid,
00887                                             enum lsa_SidType type),
00888                                void *private_data)
00889 {
00890         struct winbindd_request request;
00891         struct winbindd_domain *domain;
00892         struct lookupname_state *s;
00893 
00894         if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) {
00895                 DEBUG(5, ("Could not find domain for name %s\n", dom_name));
00896                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
00897                 return;
00898         }
00899 
00900         ZERO_STRUCT(request);
00901         request.cmd = WINBINDD_LOOKUPNAME;
00902         fstrcpy(request.data.name.dom_name, dom_name);
00903         fstrcpy(request.data.name.name, name);
00904 
00905         if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupname_state)) == NULL ) {
00906                 DEBUG(0, ("winbindd_lookupname_async: talloc failed\n"));
00907                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
00908                 return;
00909         }
00910 
00911         s->dom_name = talloc_strdup( s, dom_name );
00912         s->name     = talloc_strdup( s, name );
00913         if (!s->dom_name || !s->name) {
00914                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
00915                 return;
00916         }
00917 
00918         s->caller_private_data = private_data;
00919 
00920         do_async_domain(mem_ctx, domain, &request, lookupname_recv,
00921                         (void *)cont, s);
00922 }
00923 
00924 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
00925                                               struct winbindd_cli_state *state)
00926 {
00927         enum lsa_SidType type;
00928         char *name_domain, *name_user;
00929         DOM_SID sid;
00930         char *p;
00931 
00932         /* Ensure null termination */
00933         state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0';
00934 
00935         /* Ensure null termination */
00936         state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0';
00937 
00938         /* cope with the name being a fully qualified name */
00939         p = strstr(state->request.data.name.name, lp_winbind_separator());
00940         if (p) {
00941                 *p = 0;
00942                 name_domain = state->request.data.name.name;
00943                 name_user = p+1;
00944         } else {
00945                 name_domain = state->request.data.name.dom_name;
00946                 name_user = state->request.data.name.name;
00947         }
00948 
00949         DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
00950                   name_domain, lp_winbind_separator(), name_user));
00951 
00952         /* Lookup name from DC using lsa_lookup_names() */
00953         if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
00954                                          name_user, &sid, &type)) {
00955                 return WINBINDD_ERROR;
00956         }
00957 
00958         sid_to_string(state->response.data.sid.sid, &sid);
00959         state->response.data.sid.type = type;
00960 
00961         return WINBINDD_OK;
00962 }
00963 
00964 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
00965                    size_t num_sids, char **result, ssize_t *len)
00966 {
00967         size_t i;
00968         size_t buflen = 0;
00969 
00970         *len = 0;
00971         *result = NULL;
00972         for (i=0; i<num_sids; i++) {
00973                 sprintf_append(mem_ctx, result, len, &buflen,
00974                                "%s\n", sid_string_static(&sids[i]));
00975         }
00976 
00977         if ((num_sids != 0) && (*result == NULL)) {
00978                 return False;
00979         }
00980 
00981         return True;
00982 }
00983 
00984 static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
00985                           DOM_SID **sids, size_t *num_sids)
00986 {
00987         char *p, *q;
00988 
00989         p = sidstr;
00990         if (p == NULL)
00991                 return False;
00992 
00993         while (p[0] != '\0') {
00994                 DOM_SID sid;
00995                 q = strchr(p, '\n');
00996                 if (q == NULL) {
00997                         DEBUG(0, ("Got invalid sidstr: %s\n", p));
00998                         return False;
00999                 }
01000                 *q = '\0';
01001                 q += 1;
01002                 if (!string_to_sid(&sid, p)) {
01003                         DEBUG(0, ("Could not parse sid %s\n", p));
01004                         return False;
01005                 }
01006                 if (!add_sid_to_array(mem_ctx, &sid, sids, num_sids)) {
01007                         return False;
01008                 }
01009                 p = q;
01010         }
01011         return True;
01012 }
01013 
01014 static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
01015                           uint32 **rids, size_t *num_rids)
01016 {
01017         char *p;
01018 
01019         p = ridstr;
01020         if (p == NULL)
01021                 return False;
01022 
01023         while (p[0] != '\0') {
01024                 uint32 rid;
01025                 char *q;
01026                 rid = strtoul(p, &q, 10);
01027                 if (*q != '\n') {
01028                         DEBUG(0, ("Got invalid ridstr: %s\n", p));
01029                         return False;
01030                 }
01031                 p = q+1;
01032                 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
01033         }
01034         return True;
01035 }
01036 
01037 enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
01038                                               struct winbindd_cli_state *state)
01039 {
01040         uint32 *rids = NULL;
01041         size_t i, buflen, num_rids = 0;
01042         ssize_t len;
01043         DOM_SID domain_sid;
01044         char *domain_name;
01045         char **names;
01046         enum lsa_SidType *types;
01047         NTSTATUS status;
01048         char *result;
01049 
01050         DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
01051                    state->request.domain_name,
01052                    state->request.data.sid));
01053 
01054         if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
01055                            &rids, &num_rids)) {
01056                 DEBUG(5, ("Could not parse ridlist\n"));
01057                 return WINBINDD_ERROR;
01058         }
01059 
01060         if (!string_to_sid(&domain_sid, state->request.data.sid)) {
01061                 DEBUG(5, ("Could not parse domain sid %s\n",
01062                           state->request.data.sid));
01063                 return WINBINDD_ERROR;
01064         }
01065 
01066         status = domain->methods->rids_to_names(domain, state->mem_ctx,
01067                                                 &domain_sid, rids, num_rids,
01068                                                 &domain_name,
01069                                                 &names, &types);
01070 
01071         if (!NT_STATUS_IS_OK(status) &&
01072             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
01073                 return WINBINDD_ERROR;
01074         }
01075 
01076         len = 0;
01077         buflen = 0;
01078         result = NULL;
01079 
01080         for (i=0; i<num_rids; i++) {
01081                 sprintf_append(state->mem_ctx, &result, &len, &buflen,
01082                                "%d %s\n", types[i], names[i]);
01083         }
01084 
01085         fstrcpy(state->response.data.domain_name, domain_name);
01086 
01087         if (result != NULL) {
01088                 state->response.extra_data.data = SMB_STRDUP(result);
01089                 if (!state->response.extra_data.data) {
01090                         return WINBINDD_ERROR;
01091                 }
01092                 state->response.length += len+1;
01093         }
01094 
01095         return WINBINDD_OK;
01096 }
01097 
01098 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
01099                                struct winbindd_response *response,
01100                                void *c, void *private_data)
01101 {
01102         void (*cont)(void *priv, BOOL succ,
01103                      DOM_SID *aliases, size_t num_aliases) =
01104                 (void (*)(void *, BOOL, DOM_SID *, size_t))c;
01105         char *aliases_str;
01106         DOM_SID *sids = NULL;
01107         size_t num_sids = 0;
01108 
01109         if (!success) {
01110                 DEBUG(5, ("Could not trigger getsidaliases\n"));
01111                 cont(private_data, success, NULL, 0);
01112                 return;
01113         }
01114 
01115         if (response->result != WINBINDD_OK) {
01116                 DEBUG(5, ("getsidaliases returned an error\n"));
01117                 cont(private_data, False, NULL, 0);
01118                 return;
01119         }
01120 
01121         aliases_str = (char *)response->extra_data.data;
01122 
01123         if (aliases_str == NULL) {
01124                 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
01125                 cont(private_data, True, NULL, 0);
01126                 return;
01127         }
01128 
01129         if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
01130                 DEBUG(0, ("Could not parse sids\n"));
01131                 cont(private_data, False, NULL, 0);
01132                 return;
01133         }
01134 
01135         SAFE_FREE(response->extra_data.data);
01136 
01137         cont(private_data, True, sids, num_sids);
01138 }
01139 
01140 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
01141                                   TALLOC_CTX *mem_ctx,
01142                                   const DOM_SID *sids, size_t num_sids,
01143                                   void (*cont)(void *private_data,
01144                                                BOOL success,
01145                                                const DOM_SID *aliases,
01146                                                size_t num_aliases),
01147                                   void *private_data)
01148 {
01149         struct winbindd_request request;
01150         char *sidstr = NULL;
01151         ssize_t len;
01152 
01153         if (num_sids == 0) {
01154                 cont(private_data, True, NULL, 0);
01155                 return;
01156         }
01157 
01158         if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
01159                 cont(private_data, False, NULL, 0);
01160                 return;
01161         }
01162 
01163         ZERO_STRUCT(request);
01164         request.cmd = WINBINDD_DUAL_GETSIDALIASES;
01165         request.extra_len = len;
01166         request.extra_data.data = sidstr;
01167 
01168         do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
01169                         (void *)cont, private_data);
01170 }
01171 
01172 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
01173                                                  struct winbindd_cli_state *state)
01174 {
01175         DOM_SID *sids = NULL;
01176         size_t num_sids = 0;
01177         char *sidstr = NULL;
01178         ssize_t len;
01179         size_t i;
01180         uint32 num_aliases;
01181         uint32 *alias_rids;
01182         NTSTATUS result;
01183 
01184         DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
01185 
01186         sidstr = state->request.extra_data.data;
01187         if (sidstr == NULL) {
01188                 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
01189                 if (!sidstr) {
01190                         DEBUG(0, ("Out of memory\n"));
01191                         return WINBINDD_ERROR;
01192                 }
01193         }
01194 
01195         DEBUG(10, ("Sidlist: %s\n", sidstr));
01196 
01197         if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
01198                 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
01199                 return WINBINDD_ERROR;
01200         }
01201 
01202         num_aliases = 0;
01203         alias_rids = NULL;
01204 
01205         result = domain->methods->lookup_useraliases(domain,
01206                                                      state->mem_ctx,
01207                                                      num_sids, sids,
01208                                                      &num_aliases,
01209                                                      &alias_rids);
01210 
01211         if (!NT_STATUS_IS_OK(result)) {
01212                 DEBUG(3, ("Could not lookup_useraliases: %s\n",
01213                           nt_errstr(result)));
01214                 return WINBINDD_ERROR;
01215         }
01216 
01217         num_sids = 0;
01218         sids = NULL;
01219         sidstr = NULL;
01220 
01221         DEBUG(10, ("Got %d aliases\n", num_aliases));
01222 
01223         for (i=0; i<num_aliases; i++) {
01224                 DOM_SID sid;
01225                 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
01226                 sid_copy(&sid, &domain->sid);
01227                 sid_append_rid(&sid, alias_rids[i]);
01228                 if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) {
01229                         return WINBINDD_ERROR;
01230                 }
01231         }
01232 
01233 
01234         if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
01235                 DEBUG(0, ("Could not print_sidlist\n"));
01236                 state->response.extra_data.data = NULL;
01237                 return WINBINDD_ERROR;
01238         }
01239 
01240         state->response.extra_data.data = NULL;
01241 
01242         if (sidstr) {
01243                 state->response.extra_data.data = SMB_STRDUP(sidstr);
01244                 if (!state->response.extra_data.data) {
01245                         DEBUG(0, ("Out of memory\n"));
01246                         return WINBINDD_ERROR;
01247                 }
01248                 DEBUG(10, ("aliases_list: %s\n",
01249                            (char *)state->response.extra_data.data));
01250                 state->response.length += len+1;
01251         }
01252         
01253         return WINBINDD_OK;
01254 }
01255 
01256 struct gettoken_state {
01257         TALLOC_CTX *mem_ctx;
01258         DOM_SID user_sid;
01259         struct winbindd_domain *alias_domain;
01260         struct winbindd_domain *local_alias_domain;
01261         struct winbindd_domain *builtin_domain;
01262         DOM_SID *sids;
01263         size_t num_sids;
01264         void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
01265         void *private_data;
01266 };
01267 
01268 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
01269                                    struct winbindd_response *response,
01270                                    void *c, void *private_data);
01271 static void gettoken_recvaliases(void *private_data, BOOL success,
01272                                  const DOM_SID *aliases,
01273                                  size_t num_aliases);
01274                                  
01275 
01276 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
01277                              void (*cont)(void *private_data, BOOL success,
01278                                           DOM_SID *sids, size_t num_sids),
01279                              void *private_data)
01280 {
01281         struct winbindd_domain *domain;
01282         struct winbindd_request request;
01283         struct gettoken_state *state;
01284 
01285         state = TALLOC_ZERO_P(mem_ctx, struct gettoken_state);
01286         if (state == NULL) {
01287                 DEBUG(0, ("talloc failed\n"));
01288                 cont(private_data, False, NULL, 0);
01289                 return;
01290         }
01291 
01292         state->mem_ctx = mem_ctx;
01293         sid_copy(&state->user_sid, user_sid);
01294         state->alias_domain = find_our_domain();
01295         state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
01296         state->builtin_domain = find_builtin_domain();
01297         state->cont = cont;
01298         state->private_data = private_data;
01299 
01300         domain = find_domain_from_sid_noinit(user_sid);
01301         if (domain == NULL) {
01302                 DEBUG(5, ("Could not find domain from SID %s\n",
01303                           sid_string_static(user_sid)));
01304                 cont(private_data, False, NULL, 0);
01305                 return;
01306         }
01307 
01308         ZERO_STRUCT(request);
01309         request.cmd = WINBINDD_GETUSERDOMGROUPS;
01310         fstrcpy(request.data.sid, sid_string_static(user_sid));
01311 
01312         do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
01313                         NULL, state);
01314 }
01315 
01316 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
01317                                    struct winbindd_response *response,
01318                                    void *c, void *private_data)
01319 {
01320         struct gettoken_state *state =
01321                 talloc_get_type_abort(private_data, struct gettoken_state);
01322         char *sids_str;
01323         
01324         if (!success) {
01325                 DEBUG(10, ("Could not get domain groups\n"));
01326                 state->cont(state->private_data, False, NULL, 0);
01327                 return;
01328         }
01329 
01330         sids_str = (char *)response->extra_data.data;
01331 
01332         if (sids_str == NULL) {
01333                 /* This could be normal if we are dealing with a
01334                    local user and local groups */
01335 
01336                 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
01337                         DEBUG(10, ("Received no domain groups\n"));
01338                         state->cont(state->private_data, True, NULL, 0);
01339                         return;
01340                 }
01341         }
01342 
01343         state->sids = NULL;
01344         state->num_sids = 0;
01345 
01346         if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
01347                          &state->num_sids)) {
01348                 DEBUG(0, ("Out of memory\n"));
01349                 state->cont(state->private_data, False, NULL, 0);
01350                 return;
01351         }
01352 
01353         if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
01354                            &state->num_sids)) {
01355                 DEBUG(0, ("Could not parse sids\n"));
01356                 state->cont(state->private_data, False, NULL, 0);
01357                 return;
01358         }
01359 
01360         SAFE_FREE(response->extra_data.data);
01361 
01362         if (state->alias_domain == NULL) {
01363                 DEBUG(10, ("Don't expand domain local groups\n"));
01364                 state->cont(state->private_data, True, state->sids,
01365                             state->num_sids);
01366                 return;
01367         }
01368 
01369         winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
01370                                      state->sids, state->num_sids,
01371                                      gettoken_recvaliases, state);
01372 }
01373 
01374 static void gettoken_recvaliases(void *private_data, BOOL success,
01375                                  const DOM_SID *aliases,
01376                                  size_t num_aliases)
01377 {
01378         struct gettoken_state *state = (struct gettoken_state *)private_data;
01379         size_t i;
01380 
01381         if (!success) {
01382                 DEBUG(10, ("Could not receive domain local groups\n"));
01383                 state->cont(state->private_data, False, NULL, 0);
01384                 return;
01385         }
01386 
01387         for (i=0; i<num_aliases; i++) {
01388                 if (!add_sid_to_array(state->mem_ctx, &aliases[i],
01389                                  &state->sids, &state->num_sids)) {
01390                         DEBUG(0, ("Out of memory\n"));
01391                         state->cont(state->private_data, False, NULL, 0);
01392                         return;
01393                 }
01394         }
01395 
01396         if (state->local_alias_domain != NULL) {
01397                 struct winbindd_domain *local_domain = state->local_alias_domain;
01398                 DEBUG(10, ("Expanding our own local groups\n"));
01399                 state->local_alias_domain = NULL;
01400                 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
01401                                              state->sids, state->num_sids,
01402                                              gettoken_recvaliases, state);
01403                 return;
01404         }
01405 
01406         if (state->builtin_domain != NULL) {
01407                 struct winbindd_domain *builtin_domain = state->builtin_domain;
01408                 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
01409                 state->builtin_domain = NULL;
01410                 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
01411                                              state->sids, state->num_sids,
01412                                              gettoken_recvaliases, state);
01413                 return;
01414         }
01415 
01416         state->cont(state->private_data, True, state->sids, state->num_sids);
01417 }
01418 
01419 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
01420                             struct winbindd_response *response,
01421                             void *c, void *private_data)
01422 {
01423         void (*cont)(void *priv, BOOL succ, const char *acct_name,
01424                      const char *full_name, const char *homedir, 
01425                      const char *shell, uint32 gid, uint32 group_rid) =
01426                 (void (*)(void *, BOOL, const char *, const char *,
01427                           const char *, const char *, uint32, uint32))c;
01428 
01429         if (!success) {
01430                 DEBUG(5, ("Could not trigger query_user\n"));
01431                 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
01432                 return;
01433         }
01434 
01435         if (response->result != WINBINDD_OK) {
01436                 DEBUG(5, ("query_user returned an error\n"));
01437                 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
01438                 return;
01439         }
01440 
01441         cont(private_data, True, response->data.user_info.acct_name,
01442              response->data.user_info.full_name,
01443              response->data.user_info.homedir,
01444              response->data.user_info.shell,
01445              response->data.user_info.primary_gid,
01446              response->data.user_info.group_rid);
01447 }
01448 
01449 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
01450                       const DOM_SID *sid,
01451                       void (*cont)(void *private_data, BOOL success,
01452                                    const char *acct_name,
01453                                    const char *full_name,
01454                                    const char *homedir,
01455                                    const char *shell,
01456                                    gid_t gid,
01457                                    uint32 group_rid),
01458                       void *private_data)
01459 {
01460         struct winbindd_request request;
01461         ZERO_STRUCT(request);
01462         request.cmd = WINBINDD_DUAL_USERINFO;
01463         sid_to_string(request.data.sid, sid);
01464         do_async_domain(mem_ctx, domain, &request, query_user_recv,
01465                         (void *)cont, private_data);
01466 }
01467 
01468 /* The following uid2sid/gid2sid functions has been contributed by
01469  * Keith Reynolds <Keith.Reynolds@centrify.com> */
01470 
01471 static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
01472                                   struct winbindd_response *response,
01473                                   void *c, void *private_data)
01474 {
01475         void (*cont)(void *priv, BOOL succ, const char *sid) =
01476                 (void (*)(void *, BOOL, const char *))c;
01477 
01478         if (!success) {
01479                 DEBUG(5, ("Could not trigger uid2sid\n"));
01480                 cont(private_data, False, NULL);
01481                 return;
01482         }
01483 
01484         if (response->result != WINBINDD_OK) {
01485                 DEBUG(5, ("uid2sid returned an error\n"));
01486                 cont(private_data, False, NULL);
01487                 return;
01488         }
01489 
01490         cont(private_data, True, response->data.sid.sid);
01491 }
01492 
01493 void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
01494                             void (*cont)(void *private_data, BOOL success, const char *sid),
01495                             void *private_data)
01496 {
01497         struct winbindd_request request;
01498 
01499         ZERO_STRUCT(request);
01500         request.cmd = WINBINDD_DUAL_UID2SID;
01501         request.data.uid = uid;
01502         do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv,
01503                  (void *)cont, private_data);
01504 }
01505 
01506 enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
01507                                            struct winbindd_cli_state *state)
01508 {
01509         DOM_SID sid;
01510         NTSTATUS result;
01511 
01512         DEBUG(3,("[%5lu]: uid to sid %lu\n",
01513                  (unsigned long)state->pid,
01514                  (unsigned long) state->request.data.uid));
01515 
01516         /* Find sid for this uid and return it, possibly ask the slow remote idmap */
01517         result = idmap_uid_to_sid(&sid, state->request.data.uid);
01518 
01519         if (NT_STATUS_IS_OK(result)) {
01520                 sid_to_string(state->response.data.sid.sid, &sid);
01521                 state->response.data.sid.type = SID_NAME_USER;
01522                 return WINBINDD_OK;
01523         }
01524 
01525         return WINBINDD_ERROR;
01526 }
01527 
01528 static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
01529                                   struct winbindd_response *response,
01530                                   void *c, void *private_data)
01531 {
01532         void (*cont)(void *priv, BOOL succ, const char *sid) =
01533                 (void (*)(void *, BOOL, const char *))c;
01534 
01535         if (!success) {
01536                 DEBUG(5, ("Could not trigger gid2sid\n"));
01537                 cont(private_data, False, NULL);
01538                 return;
01539         }
01540 
01541         if (response->result != WINBINDD_OK) {
01542                 DEBUG(5, ("gid2sid returned an error\n"));
01543                 cont(private_data, False, NULL);
01544                 return;
01545         }
01546 
01547         cont(private_data, True, response->data.sid.sid);
01548 }
01549 
01550 void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
01551                             void (*cont)(void *private_data, BOOL success, const char *sid),
01552                             void *private_data)
01553 {
01554         struct winbindd_request request;
01555 
01556         ZERO_STRUCT(request);
01557         request.cmd = WINBINDD_DUAL_GID2SID;
01558         request.data.gid = gid;
01559         do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv,
01560                  (void *)cont, private_data);
01561 }
01562 
01563 enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
01564                                            struct winbindd_cli_state *state)
01565 {
01566         DOM_SID sid;
01567         NTSTATUS result;
01568 
01569         DEBUG(3,("[%5lu]: gid %lu to sid\n",
01570                 (unsigned long)state->pid,
01571                 (unsigned long) state->request.data.gid));
01572 
01573         /* Find sid for this gid and return it, possibly ask the slow remote idmap */
01574         result = idmap_gid_to_sid(&sid, state->request.data.gid);
01575 
01576         if (NT_STATUS_IS_OK(result)) {
01577                 sid_to_string(state->response.data.sid.sid, &sid);
01578                 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
01579                            (unsigned long)state->pid,
01580                            state->response.data.sid.sid));
01581                 state->response.data.sid.type = SID_NAME_DOM_GRP;
01582                 return WINBINDD_OK;
01583         }
01584 
01585         return WINBINDD_ERROR;
01586 }
01587 
01588 static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success,
01589                                struct winbindd_response *response,
01590                                void *c, void *private_data)
01591 {
01592         void (*cont)(void *priv, BOOL succ) =
01593                 (void (*)(void *, BOOL))c;
01594 
01595         if (!success) {
01596                 DEBUG(5, ("Could not trigger a map dump\n"));
01597                 cont(private_data, False);
01598                 return;
01599         }
01600 
01601         if (response->result != WINBINDD_OK) {
01602                 DEBUG(5, ("idmap dump maps returned an error\n"));
01603                 cont(private_data, False);
01604                 return;
01605         }
01606 
01607         cont(private_data, True);
01608 }
01609                          
01610 void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size,
01611                          void (*cont)(void *private_data, BOOL success),
01612                          void *private_data)
01613 {
01614         struct winbindd_request request;
01615         ZERO_STRUCT(request);
01616         request.cmd = WINBINDD_DUAL_DUMP_MAPS;
01617         request.extra_data.data = (char *)data;
01618         request.extra_len = size;
01619         do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv,
01620                  (void *)cont, private_data);
01621 }
01622 
01623 enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain,
01624                                            struct winbindd_cli_state *state)
01625 {
01626         DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid));
01627 
01628         idmap_dump_maps((char *)state->request.extra_data.data);
01629 
01630         return WINBINDD_OK;
01631 }
01632 

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