/*
- Unix SMB/Netbios implementation.
- Version 2.0
+ Unix SMB/CIFS implementation.
winbind client code
*/
#include "includes.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,
+ struct winbindd_response *response);
/* Call winbindd to convert a name to a sid */
-BOOL winbind_lookup_name(char *name, DOM_SID *sid, uint8 *name_type)
+BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
+ enum SID_NAME_USE *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
- enum nss_status result;
+ NSS_STATUS result;
if (!sid || !name_type)
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- fstrcpy(request.data.name, name);
+ fstrcpy(request.data.name.dom_name, dom_name);
+ fstrcpy(request.data.name.name, name);
+
if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
&response)) == NSS_STATUS_SUCCESS) {
- string_to_sid(sid, response.data.sid.sid);
- *name_type = response.data.sid.type;
+ if (!string_to_sid(sid, response.data.sid.sid))
+ return False;
+ *name_type = (enum SID_NAME_USE)response.data.sid.type;
}
return result == NSS_STATUS_SUCCESS;
/* Call winbindd to convert sid to name */
-BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name,
- uint8 *name_type)
+BOOL winbind_lookup_sid(const DOM_SID *sid,
+ fstring dom_name, fstring name,
+ enum SID_NAME_USE *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
- enum nss_status result;
- DOM_SID tmp_sid;
- uint32 rid;
+ NSS_STATUS result;
fstring sid_str;
- if (!name_type)
- return False;
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ sid_to_string(sid_str, sid);
+ fstrcpy(request.data.sid, sid_str);
+
+ /* Make request */
- /* Check if this is our own sid. This should perhaps be done by
- winbind? For the moment handle it here. */
+ result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
- if (sid->num_auths == 5) {
- sid_copy(&tmp_sid, sid);
- sid_split_rid(&tmp_sid, &rid);
+ /* Copy out result */
- if (sid_equal(&global_sam_sid, &tmp_sid)) {
+ 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;
- return map_domain_sid_to_name(&tmp_sid, dom_name) &&
- local_lookup_rid(rid, name, name_type);
- }
+ DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
+ sid_str, dom_name, name));
}
+ return (result == NSS_STATUS_SUCCESS);
+}
+
+/* Call winbindd to convert SID to uid */
+
+BOOL winbind_sid_to_uid(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);
/* Make request */
- result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
+ result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
/* Copy out result */
if (result == NSS_STATUS_SUCCESS) {
- parse_domain_user(response.data.name.name, dom_name, name);
- *name_type = response.data.name.type;
+ *puid = response.data.uid;
}
return (result == NSS_STATUS_SUCCESS);
/* 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);
}
return (result == NSS_STATUS_SUCCESS);
}
-/* Call winbindd to convert uid to sid */
+/* 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, 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);
+
+ /* 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 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)
{
/* 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);
}
return (result == NSS_STATUS_SUCCESS);
}
+/* Fetch the list of groups a user is a member of from winbindd. This is
+ used by winbind_getgroups. */
+static int wb_getgroups(const char *user, gid_t **groups)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
-/*****************************************************************
- *THE CANNONICAL* convert name to SID function.
- Tries winbind first - then uses local lookup.
-*****************************************************************/
+ /* Call winbindd */
-BOOL lookup_name(char *name, DOM_SID *psid, uint8 *name_type)
-{
- extern pstring global_myname;
+ fstrcpy(request.data.username, user);
+
+ ZERO_STRUCT(response);
- if (!winbind_lookup_name(name, psid, name_type)) {
+ result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
- DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name ));
+ if (result == NSS_STATUS_SUCCESS) {
+
+ /* Return group list. Don't forget to free the group list
+ when finished. */
- return local_lookup_name(global_myname, name, psid, name_type);
+ *groups = (gid_t *)response.extra_data;
+ return response.data.num_entries;
}
- return True;
+
+ return -1;
}
-/*****************************************************************
- *THE CANNONICAL* convert SID to name function.
- Tries winbind first - then uses local lookup.
-*****************************************************************/
+/* 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. */
-BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, uint8 *name_type)
+int winbind_getgroups(const char *user, gid_t **list)
{
- if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
- fstring sid_str;
- DOM_SID tmp_sid;
- uint32 rid;
+ /*
+ * Don't do the lookup if the name has no separator _and_ we are not in
+ * 'winbind use default domain' mode.
+ */
- DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
+ if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
+ return -1;
- sid_copy(&tmp_sid, sid);
- sid_split_rid(&tmp_sid, &rid);
- return map_domain_sid_to_name(&tmp_sid, dom_name) &&
- lookup_known_rid(&tmp_sid, rid, name, name_type);
- }
- return True;
+ /* Fetch list of groups */
+
+ return wb_getgroups(user, list);
}
-/*****************************************************************
- *THE CANNONICAL* convert uid_t to SID function.
- Tries winbind first - then uses local lookup.
- Returns SID pointer.
-*****************************************************************/
+/**********************************************************************
+ simple wrapper function to see if winbindd is alive
+**********************************************************************/
-DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid)
+BOOL winbind_ping( void )
{
- if (!winbind_uid_to_sid(psid, uid)) {
- DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid ));
+ NSS_STATUS result;
- return local_uid_to_sid(psid, uid);
- }
+ result = winbindd_request(WINBINDD_PING, NULL, NULL);
- return psid;
+ return result == NSS_STATUS_SUCCESS;
}
-/*****************************************************************
- *THE CANNONICAL* convert gid_t to SID function.
- Tries winbind first - then uses local lookup.
- Returns SID pointer.
-*****************************************************************/
+/**********************************************************************
+ Ask winbindd to create a local user
+**********************************************************************/
-DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid)
+BOOL winbind_create_user( const char *name )
{
- if (!winbind_gid_to_sid(psid, gid)) {
- DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid ));
+ 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));
- return local_gid_to_sid(psid, gid);
- }
+ 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));
- return psid;
+ 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;
+}
+
+
+