Large set of changes to add UNIX account/group management
[samba.git] / source3 / nsswitch / wb_client.c
index 87c16f959a7f100521f058aa891f758b7fd2abd9..26a0e58191f4357cd3745686da25c8e0de162a21 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 2.0
+   Unix SMB/CIFS implementation.
 
    winbind client code
 
 */
 
 #include "includes.h"
-#include "nsswitch/nss.h"
+#include "nsswitch/winbind_nss.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+extern DOM_SID global_sid_NULL;                        /* NULL sid */
 
 NSS_STATUS winbindd_request(int req_type,
                                  struct winbindd_request *request,
@@ -52,7 +56,8 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
 
        if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, 
                                       &response)) == NSS_STATUS_SUCCESS) {
-               string_to_sid(sid, response.data.sid.sid);
+               if (!string_to_sid(sid, response.data.sid.sid))
+                       return False;
                *name_type = (enum SID_NAME_USE)response.data.sid.type;
        }
 
@@ -61,7 +66,7 @@ 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(DOM_SID *sid, 
+BOOL winbind_lookup_sid(const DOM_SID *sid, 
                        fstring dom_name, fstring name, 
                         enum SID_NAME_USE *name_type)
 {
@@ -98,7 +103,7 @@ BOOL winbind_lookup_sid(DOM_SID *sid,
 
 /* Call winbindd to convert SID to uid */
 
-BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
+BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -154,7 +159,8 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
        /* Copy out result */
 
        if (result == NSS_STATUS_SUCCESS) {
-               string_to_sid(sid, response.data.sid.sid);
+               if (!string_to_sid(sid, response.data.sid.sid))
+                       return False;
        } else {
                sid_copy(sid, &global_sid_NULL);
        }
@@ -162,9 +168,44 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
        return (result == NSS_STATUS_SUCCESS);
 }
 
+/* Call winbindd to convert SID to uid. Do not allocate */
+
+BOOL winbind_sid_to_uid_query(uid_t *puid, const DOM_SID *sid)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
+       fstring sid_str;
+
+       if (!puid)
+               return False;
+
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       sid_to_string(sid_str, sid);
+       fstrcpy(request.data.sid, sid_str);
+
+       request.flags = WBFLAG_QUERY_ONLY;
+       
+       /* Make request */
+
+       result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
+
+       /* Copy out result */
+
+       if (result == NSS_STATUS_SUCCESS) {
+               *puid = response.data.uid;
+       }
+
+       return (result == NSS_STATUS_SUCCESS);
+}
+
 /* Call winbindd to convert SID to gid */
 
-BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
+BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -195,6 +236,41 @@ BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
        return (result == NSS_STATUS_SUCCESS);
 }
 
+/* Call winbindd to convert SID to gid.  Do not allocate */
+
+BOOL winbind_sid_to_gid_query(gid_t *pgid, const DOM_SID *sid)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       int result;
+       fstring sid_str;
+
+       if (!pgid)
+               return False;
+
+       /* Initialise request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       sid_to_string(sid_str, sid);
+       fstrcpy(request.data.sid, sid_str);
+       
+       request.flags = WBFLAG_QUERY_ONLY;
+
+       /* Make request */
+
+       result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
+
+       /* Copy out result */
+
+       if (result == NSS_STATUS_SUCCESS) {
+               *pgid = response.data.gid;
+       }
+
+       return (result == NSS_STATUS_SUCCESS);
+}
+
 /* Call winbindd to convert gid to sid */
 
 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
@@ -220,7 +296,8 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
        /* Copy out result */
 
        if (result == NSS_STATUS_SUCCESS) {
-               string_to_sid(sid, response.data.sid.sid);
+               if (!string_to_sid(sid, response.data.sid.sid))
+                       return False;
        } else {
                sid_copy(sid, &global_sid_NULL);
        }
@@ -262,11 +339,8 @@ static int wb_getgroups(const char *user, gid_t **groups)
    time consuming.  If size is zero, list is not modified and the total
    number of groups for the user is returned. */
 
-int winbind_getgroups(const char *user, int size, gid_t *list)
+int winbind_getgroups(const char *user, gid_t **list)
 {
-       gid_t *groups = NULL;
-       int result, i;
-
        /*
         * Don't do the lookup if the name has no separator _and_ we are not in
         * 'winbind use default domain' mode.
@@ -277,24 +351,163 @@ int winbind_getgroups(const char *user, int size, gid_t *list)
 
        /* Fetch list of groups */
 
-       result = wb_getgroups(user, &groups);
+       return wb_getgroups(user, list);
+}
 
-       if (size == 0)
-               goto done;
+/**********************************************************************
+ simple wrapper function to see if winbindd is alive
+**********************************************************************/
 
-       if (result > size) {
-               result = -1;
-               errno = EINVAL; /* This is what getgroups() does */
-               goto done;
-       }
+BOOL winbind_ping( void )
+{
+       NSS_STATUS result;
 
-       /* Copy list of groups across */
+       result = winbindd_request(WINBINDD_PING, NULL, NULL);
 
-       for (i = 0; i < result; i++) {
-               list[i] = groups[i];
-       }
+       return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to create a local user
+**********************************************************************/
 
- done:
-       SAFE_FREE(groups);
-       return result;
+BOOL winbind_create_user( const char *name )
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       
+       if ( !lp_winbind_enable_local_accounts() )
+               return False;
+       
+       if ( !name )
+               return False;
+               
+       DEBUG(10,("winbind_create_user: %s\n", name));
+
+       fstrcpy( request.data.acct_mgt.username, name );
+       fstrcpy( request.data.acct_mgt.groupname, "" );
+       
+       ZERO_STRUCT(response);
+       
+       result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
+       
+       return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to create a local group
+**********************************************************************/
+
+BOOL winbind_create_group( const char *name )
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       
+       if ( !lp_winbind_enable_local_accounts() )
+               return False;
+               
+       if ( !name )
+               return False;
+               
+       DEBUG(10,("winbind_create_group: %s\n", name));
+
+       fstrcpy( request.data.acct_mgt.groupname, name );
+       
+       ZERO_STRUCT(response);
+       
+       result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
+       
+       return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to add a user to a local group
+**********************************************************************/
+
+BOOL winbind_add_user_to_group( const char *user, const char *group )
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       
+       if ( !lp_winbind_enable_local_accounts() )
+               return False;
+               
+       if ( !user || !group )
+               return False;
+               
+       DEBUG(10,("winbind_add_user_to_group: user(%s), group(%s) \n", 
+               user, group));
+               
+       fstrcpy( request.data.acct_mgt.username, user );
+       fstrcpy( request.data.acct_mgt.groupname, group );
+       
+       ZERO_STRUCT(response);
+       
+       result = winbindd_request( WINBINDD_ADD_USER_TO_GROUP, &request, &response);
+       
+       return result == NSS_STATUS_SUCCESS;
 }
+
+/**********************************************************************
+ Ask winbindd to remove a user to a local group
+**********************************************************************/
+
+BOOL winbind_remove_user_from_group( const char *user, const char *group )
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       
+       if ( !lp_winbind_enable_local_accounts() )
+               return False;
+               
+       if ( !user || !group )
+               return False;
+               
+       DEBUG(10,("winbind_remove_user_from_group: user(%s), group(%s) \n", 
+               user, group));
+               
+       fstrcpy( request.data.acct_mgt.username, user );
+       fstrcpy( request.data.acct_mgt.groupname, group );
+       
+       ZERO_STRUCT(response);
+       
+       result = winbindd_request( WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
+       
+       return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to set the primary group for a user local user
+**********************************************************************/
+
+BOOL winbind_set_user_primary_group( const char *user, const char *group )
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       
+       if ( !lp_winbind_enable_local_accounts() )
+               return False;
+               
+       if ( !user || !group )
+               return False;
+               
+       DEBUG(10,("winbind_set_user_primary_group: user(%s), group(%s) \n", 
+               user, group));
+
+       fstrcpy( request.data.acct_mgt.username, user );
+       fstrcpy( request.data.acct_mgt.groupname, group );
+       
+       ZERO_STRUCT(response);
+       
+       result = winbindd_request( WINBINDD_SET_USER_PRIMARY_GROUP, &request, &response);
+       
+       return result == NSS_STATUS_SUCCESS;
+}
+
+
+