RIP BOOL. Convert BOOL -> bool. I found a few interesting
[samba.git] / source3 / nsswitch / wb_client.c
index 5005f72457a02f4be056c0e4c229bfb352aa3c9f..3e3c140fae85534e8eb72eabadb761ee91eee362 100644 (file)
@@ -7,19 +7,17 @@
    Copyright (C) Andrew Tridgell 2000
    
    This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public
+   modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
-   version 2 of the License, or (at your option) any later version.
+   version 3 of the License, or (at your option) any later version.
    
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.
    
-   You should have received a copy of the GNU Library General Public
-   License along with this library; if not, write to the
-   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA  02111-1307, USA.   
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-NSS_STATUS winbindd_request(int req_type,
+NSS_STATUS winbindd_request_response(int req_type,
                                  struct winbindd_request *request,
                                  struct winbindd_response *response);
 
 /* Call winbindd to convert a name to a sid */
 
-BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, 
-                         enum SID_NAME_USE *name_type)
+bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, 
+                         enum lsa_SidType *name_type)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -52,11 +50,11 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
        fstrcpy(request.data.name.dom_name, dom_name);
        fstrcpy(request.data.name.name, name);
 
-       if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, 
+       if ((result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, 
                                       &response)) == NSS_STATUS_SUCCESS) {
                if (!string_to_sid(sid, response.data.sid.sid))
                        return False;
-               *name_type = (enum SID_NAME_USE)response.data.sid.type;
+               *name_type = (enum lsa_SidType)response.data.sid.type;
        }
 
        return result == NSS_STATUS_SUCCESS;
@@ -64,44 +62,168 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
 
 /* Call winbindd to convert sid to name */
 
-BOOL winbind_lookup_sid(const DOM_SID *sid, 
-                       fstring dom_name, fstring name, 
-                        enum SID_NAME_USE *name_type)
+bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, 
+                       const char **domain, const char **name,
+                        enum lsa_SidType *name_type)
 {
        struct winbindd_request request;
        struct winbindd_response response;
        NSS_STATUS result;
-       fstring sid_str;
        
        /* Initialise request */
 
        ZERO_STRUCT(request);
        ZERO_STRUCT(response);
 
-       sid_to_string(sid_str, sid);
-       fstrcpy(request.data.sid, sid_str);
+       fstrcpy(request.data.sid, sid_string_static(sid));
        
        /* Make request */
 
-       result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
+       result = winbindd_request_response(WINBINDD_LOOKUPSID, &request,
+                                          &response);
+
+       if (result != NSS_STATUS_SUCCESS) {
+               return False;
+       }
 
        /* Copy out result */
 
-       if (result == NSS_STATUS_SUCCESS) {
-               fstrcpy(dom_name, response.data.name.dom_name);
-               fstrcpy(name, response.data.name.name);
-               *name_type = (enum SID_NAME_USE)response.data.name.type;
+       if (domain != NULL) {
+               *domain = talloc_strdup(mem_ctx, response.data.name.dom_name);
+               if (*domain == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       return False;
+               }
+       }
+       if (name != NULL) {
+               *name = talloc_strdup(mem_ctx, response.data.name.name);
+               if (*name == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       return False;
+               }
+       }
+
+       *name_type = (enum lsa_SidType)response.data.name.type;
+
+       DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", 
+                  sid_string_static(sid), response.data.name.dom_name,
+                  response.data.name.name));
+       return True;
+}
 
-               DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", 
-                           sid_str, dom_name, name));
+bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+                        const DOM_SID *domain_sid,
+                        int num_rids, uint32 *rids,
+                        const char **domain_name,
+                        const char ***names, enum lsa_SidType **types)
+{
+       size_t i, buflen;
+       ssize_t len;
+       char *ridlist;
+       char *p;
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+
+       if (num_rids == 0) {
+               return False;
        }
 
-       return (result == NSS_STATUS_SUCCESS);
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       fstrcpy(request.data.sid, sid_string_static(domain_sid));
+       
+       len = 0;
+       buflen = 0;
+       ridlist = NULL;
+
+       for (i=0; i<num_rids; i++) {
+               sprintf_append(mem_ctx, &ridlist, &len, &buflen,
+                              "%ld\n", rids[i]);
+       }
+
+       if (ridlist == NULL) {
+               return False;
+       }
+
+       request.extra_data.data = ridlist;
+       request.extra_len = strlen(ridlist)+1;
+
+       result = winbindd_request_response(WINBINDD_LOOKUPRIDS,
+                                          &request, &response);
+
+       TALLOC_FREE(ridlist);
+
+       if (result != NSS_STATUS_SUCCESS) {
+               return False;
+       }
+
+       *domain_name = talloc_strdup(mem_ctx, response.data.domain_name);
+
+       *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+       *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+
+       if ((*names == NULL) || (*types == NULL)) {
+               goto fail;
+       }
+
+       p = (char *)response.extra_data.data;
+
+       for (i=0; i<num_rids; i++) {
+               char *q;
+
+               if (*p == '\0') {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+                       
+               (*types)[i] = (enum lsa_SidType)strtoul(p, &q, 10);
+
+               if (*q != ' ') {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+
+               p = q+1;
+
+               q = strchr(p, '\n');
+               if (q == NULL) {
+                       DEBUG(10, ("Got invalid reply: %s\n",
+                                  (char *)response.extra_data.data));
+                       goto fail;
+               }
+
+               *q = '\0';
+
+               (*names)[i] = talloc_strdup(*names, p);
+
+               p = q+1;
+       }
+
+       if (*p != '\0') {
+               DEBUG(10, ("Got invalid reply: %s\n",
+                          (char *)response.extra_data.data));
+               goto fail;
+       }
+
+       SAFE_FREE(response.extra_data.data);
+
+       return True;
+
+ fail:
+       TALLOC_FREE(*names);
+       TALLOC_FREE(*types);
+       return False;
 }
 
 /* Call winbindd to convert SID to uid */
 
-BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
+bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -121,7 +243,7 @@ BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
        
        /* Make request */
 
-       result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
+       result = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response);
 
        /* Copy out result */
 
@@ -134,7 +256,7 @@ BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
 
 /* Call winbindd to convert uid to sid */
 
-BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
+bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -152,7 +274,7 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
 
        /* Make request */
 
-       result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
+       result = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response);
 
        /* Copy out result */
 
@@ -168,7 +290,7 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
 
 /* Call winbindd to convert SID to gid */
 
-BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
+bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -188,7 +310,7 @@ BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
        
        /* Make request */
 
-       result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
+       result = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response);
 
        /* Copy out result */
 
@@ -201,7 +323,7 @@ BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
 
 /* Call winbindd to convert gid to sid */
 
-BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
+bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -219,7 +341,7 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
 
        /* Make request */
 
-       result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
+       result = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response);
 
        /* Copy out result */
 
@@ -233,163 +355,197 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
        return (result == NSS_STATUS_SUCCESS);
 }
 
-BOOL winbind_allocate_rid(uint32 *rid)
+/* Call winbindd to convert SID to uid */
+
+bool winbind_sids_to_unixids(struct id_map *ids, int num_ids)
 {
        struct winbindd_request request;
        struct winbindd_response response;
        int result;
+       DOM_SID *sids;
+       int i;
 
        /* Initialise request */
 
        ZERO_STRUCT(request);
        ZERO_STRUCT(response);
 
-       /* Make request */
+       request.extra_len = num_ids * sizeof(DOM_SID);
 
-       result = winbindd_request(WINBINDD_ALLOCATE_RID, &request, &response);
+       sids = (DOM_SID *)SMB_MALLOC(request.extra_len);
+       for (i = 0; i < num_ids; i++) {
+               sid_copy(&sids[i], ids[i].sid);
+       }
 
-       if (result != NSS_STATUS_SUCCESS)
-               return False;
+       request.extra_data.data = (char *)sids;
+       
+       /* Make request */
+
+       result = winbindd_request_response(WINBINDD_SIDS_TO_XIDS, &request, &response);
 
        /* Copy out result */
-       *rid = response.data.rid;
 
-       return True;
+       if (result == NSS_STATUS_SUCCESS) {
+               struct unixid *wid = (struct unixid *)response.extra_data.data;
+               
+               for (i = 0; i < num_ids; i++) {
+                       if (wid[i].type == -1) {
+                               ids[i].status = ID_UNMAPPED;
+                       } else {
+                               ids[i].status = ID_MAPPED;
+                               ids[i].xid.type = wid[i].type;
+                               ids[i].xid.id = wid[i].id;
+                       }
+               }
+       }
+
+       SAFE_FREE(request.extra_data.data);
+       SAFE_FREE(response.extra_data.data);
+
+       return (result == NSS_STATUS_SUCCESS);
 }
 
-/* Fetch the list of groups a user is a member of from winbindd.  This is
-   used by winbind_getgroups. */
+bool winbind_idmap_dump_maps(TALLOC_CTX *memctx, const char *file)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
 
-static int wb_getgroups(const char *user, gid_t **groups)
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       request.extra_data.data = SMB_STRDUP(file);
+       request.extra_len = strlen(request.extra_data.data) + 1;
+
+       result = winbindd_request_response(WINBINDD_DUMP_MAPS, &request, &response);
+
+       SAFE_FREE(request.extra_data.data);
+       return (result == NSS_STATUS_SUCCESS);
+}
+
+bool winbind_allocate_uid(uid_t *uid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
        int result;
 
-       /* Call winbindd */
+       /* Initialise request */
 
        ZERO_STRUCT(request);
-       fstrcpy(request.data.username, user);
-
        ZERO_STRUCT(response);
 
-       result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
+       /* Make request */
 
-       if (result == NSS_STATUS_SUCCESS) {
-               
-               /* Return group list.  Don't forget to free the group list
-                  when finished. */
+       result = winbindd_request_response(WINBINDD_ALLOCATE_UID,
+                                          &request, &response);
 
-               *groups = (gid_t *)response.extra_data;
-               return response.data.num_entries;
-       }
+       if (result != NSS_STATUS_SUCCESS)
+               return False;
 
-       return -1;
-}
+       /* Copy out result */
+       *uid = response.data.uid;
 
-/* Call winbindd to initialise group membership.  This is necessary for
-   some systems (i.e RH5.2) that do not have an initgroups function as part
-   of the nss extension.  In RH5.2 this is implemented using getgrent()
-   which can be amazingly inefficient as well as having problems with
-   username case. */
+       return True;
+}
 
-int winbind_initgroups(char *user, gid_t gid)
+bool winbind_allocate_gid(gid_t *gid)
 {
-       gid_t *tgr, *groups = NULL;
+       struct winbindd_request request;
+       struct winbindd_response response;
        int result;
 
-       /* Call normal initgroups if we are a local user */
+       /* Initialise request */
 
-       if (!strchr(user, *lp_winbind_separator())) {
-               return initgroups(user, gid);
-       }
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       /* Make request */
 
-       result = wb_getgroups(user, &groups);
+       result = winbindd_request_response(WINBINDD_ALLOCATE_GID,
+                                          &request, &response);
 
-       DEBUG(10,("winbind_getgroups: %s: result = %s\n", user, 
-                 result == -1 ? "FAIL" : "SUCCESS"));
+       if (result != NSS_STATUS_SUCCESS)
+               return False;
 
-       if (result != -1) {
-               int ngroups = result, i;
-               BOOL is_member = False;
+       /* Copy out result */
+       *gid = response.data.gid;
 
-               /* Check to see if the passed gid is already in the list */
+       return True;
+}
 
-               for (i = 0; i < ngroups; i++) {
-                       if (groups[i] == gid) {
-                               is_member = True;
-                       }
-               }
+bool winbind_set_mapping(const struct id_map *map)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
 
-               /* Add group to list if necessary */
+       /* Initialise request */
 
-               if (!is_member) {
-                       tgr = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
-                       
-                       if (!tgr) {
-                               errno = ENOMEM;
-                               result = -1;
-                               goto done;
-                       }
-                       else groups = tgr;
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
 
-                       groups[ngroups] = gid;
-                       ngroups++;
-               }
+       /* Make request */
 
-               /* Set the groups */
+       request.data.dual_idmapset.id = map->xid.id;
+       request.data.dual_idmapset.type = map->xid.type;
+       sid_to_string(request.data.dual_idmapset.sid, map->sid);
 
-               if (sys_setgroups(ngroups, groups) == -1) {
-                       errno = EPERM;
-                       result = -1;
-                       goto done;
-               }
+       result = winbindd_request_response(WINBINDD_SET_MAPPING, &request, &response);
 
-       } else {
-               
-               /* The call failed.  Set errno to something so we don't get
-                  a bogus value from the last failed system call. */
+       return (result == NSS_STATUS_SUCCESS);
+}
 
-               errno = EIO;
-       }
+bool winbind_set_uid_hwm(unsigned long id)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
 
-       /* Free response data if necessary */
+       /* Initialise request */
 
- done:
-       SAFE_FREE(groups);
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
 
-       return result;
-}
+       /* Make request */
 
-/* Return a list of groups the user is a member of.  This function is
-   useful for large systems where inverting the group database would be too
-   time consuming.  If size is zero, list is not modified and the total
-   number of groups for the user is returned. */
+       request.data.dual_idmapset.id = id;
+       request.data.dual_idmapset.type = ID_TYPE_UID;
 
-int winbind_getgroups(const char *user, gid_t **list)
+       result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
+
+       return (result == NSS_STATUS_SUCCESS);
+}
+
+bool winbind_set_gid_hwm(unsigned long id)
 {
-       /*
-        * Don't do the lookup if the name has no separator _and_ we are not in
-        * 'winbind use default domain' mode.
-        */
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
+
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
 
-       if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
-               return -1;
+       /* Make request */
 
-       /* Fetch list of groups */
+       request.data.dual_idmapset.id = id;
+       request.data.dual_idmapset.type = ID_TYPE_GID;
 
-       return wb_getgroups(user, list);
+       result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
+
+       return (result == NSS_STATUS_SUCCESS);
 }
 
 /**********************************************************************
  simple wrapper function to see if winbindd is alive
 **********************************************************************/
 
-BOOL winbind_ping( void )
+bool winbind_ping( void )
 {
        NSS_STATUS result;
 
-       result = winbindd_request(WINBINDD_PING, NULL, NULL);
+       result = winbindd_request_response(WINBINDD_PING, NULL, NULL);
 
        return result == NSS_STATUS_SUCCESS;
 }
@@ -424,5 +580,5 @@ NSS_STATUS wb_is_trusted_domain(const char *domain)
 
        fstrcpy(request.domain_name, domain);
 
-       return winbindd_request(WINBINDD_DOMAIN_INFO, &request, &response);
+       return winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response);
 }