summaryrefslogtreecommitdiffstats
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-07-09 16:44:47 +0000
committerGerald Carter <jerry@samba.org>2003-07-09 16:44:47 +0000
commit16ff7b26f6b9d288cbd1d39e075b637e24da13a6 (patch)
treeb20088c7adac8df8823defc6649db0a9607c0c6a /source3/nsswitch
parent816724fb39ba1d13f553704b2deaa3e8e716c5ab (diff)
downloadsamba-16ff7b26f6b9d288cbd1d39e075b637e24da13a6.tar.gz
samba-16ff7b26f6b9d288cbd1d39e075b637e24da13a6.tar.xz
samba-16ff7b26f6b9d288cbd1d39e075b637e24da13a6.zip
Large set of changes to add UNIX account/group management
to winbindd. See README.idmap-and-winbind-changes for details. (This used to be commit 1111bc7b0c7165e1cdf8d90eb49f4c368d2eded6)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/wb_client.c144
-rw-r--r--source3/nsswitch/wbinfo.c175
-rw-r--r--source3/nsswitch/winbindd.c11
-rw-r--r--source3/nsswitch/winbindd_acct.c946
-rw-r--r--source3/nsswitch/winbindd_group.c87
-rw-r--r--source3/nsswitch/winbindd_idmap.c194
-rw-r--r--source3/nsswitch/winbindd_idmap_tdb.c459
-rw-r--r--source3/nsswitch/winbindd_nss.h55
-rw-r--r--source3/nsswitch/winbindd_pam.c8
-rw-r--r--source3/nsswitch/winbindd_passdb.c360
-rw-r--r--source3/nsswitch/winbindd_user.c34
-rw-r--r--source3/nsswitch/winbindd_util.c16
12 files changed, 1430 insertions, 1059 deletions
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index 67548592b2c..26a0e58191f 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -367,3 +367,147 @@ BOOL winbind_ping( void )
return result == NSS_STATUS_SUCCESS;
}
+/**********************************************************************
+ Ask winbindd to create a local user
+**********************************************************************/
+
+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;
+}
+
+
+
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 9be74c12de7..6ebf6effa76 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -511,6 +511,151 @@ static BOOL wbinfo_auth_crap(char *username)
return result == NSS_STATUS_SUCCESS;
}
+/******************************************************************
+ create a winbindd user
+******************************************************************/
+
+static BOOL wbinfo_create_user(char *username)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.acct_mgt.username, username);
+
+ result = winbindd_request(WINBINDD_CREATE_USER, &request, &response);
+
+ if (response.data.auth.nt_status)
+ d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/******************************************************************
+ create a winbindd group
+******************************************************************/
+
+static BOOL wbinfo_create_group(char *groupname)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.acct_mgt.groupname, groupname);
+
+ result = winbindd_request(WINBINDD_CREATE_GROUP, &request, &response);
+
+ if (response.data.auth.nt_status)
+ d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/******************************************************************
+ parse a string in the form user:group
+******************************************************************/
+
+static BOOL parse_user_group( const char *string, fstring user, fstring group )
+{
+ char *p;
+
+ if ( !string )
+ return False;
+
+ if ( !(p = strchr( string, ':' )) )
+ return False;
+
+ *p = '\0';
+ p++;
+
+ fstrcpy( user, string );
+ fstrcpy( group, p );
+
+ return True;
+}
+
+/******************************************************************
+ add a user to a winbindd group
+******************************************************************/
+
+static BOOL wbinfo_add_user_to_group(char *string)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if ( !parse_user_group( string, request.data.acct_mgt.username,
+ request.data.acct_mgt.groupname))
+ {
+ d_printf("Can't parse user:group from %s\n", string);
+ return False;
+ }
+
+ result = winbindd_request(WINBINDD_ADD_USER_TO_GROUP, &request, &response);
+
+ if (response.data.auth.nt_status)
+ d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/******************************************************************
+ remove a user from a winbindd group
+******************************************************************/
+
+static BOOL wbinfo_remove_user_from_group(char *string)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if ( !parse_user_group( string, request.data.acct_mgt.username,
+ request.data.acct_mgt.groupname))
+ {
+ d_printf("Can't parse user:group from %s\n", string);
+ return False;
+ }
+
+ result = winbindd_request(WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
+
+ if (response.data.auth.nt_status)
+ d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
/* Print domain users */
static BOOL print_domain_users(void)
@@ -705,6 +850,10 @@ int main(int argc, char **argv)
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
+ { "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" },
+ { "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
+ { "add-to-group", 'o', POPT_ARG_STRING, &string_arg, 'o', "Add user to group", "user:group" },
+ { "del-from-group", 'O', POPT_ARG_STRING, &string_arg, 'O', "Remove user from group", "user:group" },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
{ "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
@@ -863,7 +1012,31 @@ int main(int argc, char **argv)
goto done;
break;
}
- case 'p':
+ case 'c':
+ if ( !wbinfo_create_user(string_arg) ) {
+ d_printf("Could not create user account\n");
+ goto done;
+ }
+ break;
+ case 'C':
+ if ( !wbinfo_create_group(string_arg) ) {
+ d_printf("Could not create group\n");
+ goto done;
+ }
+ break;
+ case 'o':
+ if ( !wbinfo_add_user_to_group(string_arg) ) {
+ d_printf("Could not add user to group\n");
+ goto done;
+ }
+ break;
+ case 'O':
+ if ( !wbinfo_remove_user_from_group(string_arg) ) {
+ d_printf("Could not remove user kfrom group\n");
+ goto done;
+ }
+ break;
+ case 'P':
if (!wbinfo_ping()) {
d_printf("could not ping winbindd!\n");
goto done;
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index e65b03c30e3..507b5f7ef7a 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -268,7 +268,16 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
{ WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },
-
+
+ /* UNIX account management functions */
+ { WINBINDD_CREATE_USER, winbindd_create_user, "CREATE_USER" },
+ { WINBINDD_CREATE_GROUP, winbindd_create_group, "CREATE_GROUP" },
+ { WINBINDD_ADD_USER_TO_GROUP, winbindd_add_user_to_group, "ADD_USER_TO_GROUP" },
+ { WINBINDD_REMOVE_USER_FROM_GROUP, winbindd_remove_user_from_group,"REMOVE_USER_FROM_GROUP"},
+ { WINBINDD_SET_USER_PRIMARY_GROUP, winbindd_set_user_primary_group,"SET_USER_PRIMARY_GROUP"},
+ { WINBINDD_DELETE_USER, winbindd_delete_user, "DELETE_USER" },
+ { WINBINDD_DELETE_GROUP, winbindd_delete_group, "DELETE_GROUP" },
+
/* End of list */
{ WINBINDD_NUM_CMDS, NULL, "NONE" }
diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c
new file mode 100644
index 00000000000..7f4353c0ee7
--- /dev/null
+++ b/source3/nsswitch/winbindd_acct.c
@@ -0,0 +1,946 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Winbind account management functions
+
+ Copyright (C) by Gerald (Jerry) Carter 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#define WBKEY_PASSWD "WBA_PASSWD"
+#define WBKEY_GROUP "WBA_GROUP"
+
+#define NUM_PW_FIELDS 7
+#define NUM_GRP_FIELDS 4
+
+/* Globals */
+
+static TDB_CONTEXT *account_tdb;
+
+extern userdom_struct current_user_info;
+
+/*****************************************************************************
+ Initialise auto-account database.
+*****************************************************************************/
+
+static BOOL winbindd_accountdb_init(void)
+{
+ /* see if we've already opened the tdb */
+
+ if ( account_tdb )
+ return True;
+
+ /* Nope. Try to open it */
+
+ if (!(account_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
+ TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
+ {
+ /* last chance -- maybe idmap has already opened it */
+ if ( !(account_tdb = idmap_tdb_handle()) ) {
+
+ DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
+ return False;
+ }
+ }
+
+ /* yeah! */
+
+ return True;
+}
+
+/**********************************************************************
+ Convert a string in /etc/passwd format to a struct passwd* entry
+**********************************************************************/
+
+static WINBINDD_PW* string2passwd( char *string )
+{
+ static WINBINDD_PW pw;
+ char *p, *str;
+ char *fields[NUM_PW_FIELDS];
+ int i;
+
+ if ( !string )
+ return NULL;
+
+ ZERO_STRUCTP( &pw );
+
+ DEBUG(10,("string2passwd: converting \"%s\"\n", string));
+
+ ZERO_STRUCT( fields );
+
+ for ( i=0, str=string; i<NUM_PW_FIELDS-1; i++ ) {
+ if ( !(p = strchr( str, ':' )) ) {
+ DEBUG(0,("string2passwd: parsing failure\n"));
+ return NULL;
+ }
+ *p = '\0';
+ if ( str )
+ fields[i] = str;
+ str = p + 1;
+ }
+ if ( str )
+ fields[i] = str;
+
+ /* copy fields */
+
+ fstrcpy( pw.pw_name, fields[0] );
+ fstrcpy( pw.pw_passwd, fields[1] );
+ pw.pw_uid = atoi( fields[2] );
+ pw.pw_gid = atoi( fields[3] );
+ fstrcpy( pw.pw_gecos, fields[4] );
+ fstrcpy( pw.pw_dir, fields[5] );
+ fstrcpy( pw.pw_shell, fields[6] );
+
+
+ /* last minute sanity checks */
+
+ if ( pw.pw_uid==0 || pw.pw_gid==0 ) {
+ DEBUG(0,("string2passwd: Failure! uid==%d, gid==%d\n",
+ pw.pw_uid, pw.pw_gid));
+ return NULL;
+ }
+
+ DEBUG(10,("string2passwd: Success\n"));
+
+ return &pw;
+}
+
+/**********************************************************************
+ Convert a struct passwd* to a string formatted for /etc/passwd
+**********************************************************************/
+
+static char* passwd2string( const WINBINDD_PW *pw )
+{
+ static pstring string;
+ int ret;
+
+ if ( !pw || !pw->pw_name )
+ return NULL;
+
+ DEBUG(10,("passwd2string: converting passwd struct for %s\n",
+ pw->pw_name));
+
+ ret = snprintf( string, sizeof(string), "%s:%s:%d:%d:%s:%s:%s",
+ pw->pw_name,
+ pw->pw_passwd ? pw->pw_passwd : "x",
+ pw->pw_uid,
+ pw->pw_gid,
+ pw->pw_gecos,
+ pw->pw_dir,
+ pw->pw_shell );
+
+ if ( ret < 0 ) {
+ DEBUG(0,("passwd2string: snprintf() failed!\n"));
+ return NULL;
+ }
+
+ return string;
+}
+
+/**********************************************************************
+ Convert a string in /etc/group format to a struct group* entry
+**********************************************************************/
+
+static WINBINDD_GR* string2group( char *string )
+{
+ static WINBINDD_GR grp;
+ char *p, *str;
+ char *fields[NUM_GRP_FIELDS];
+ int i;
+ char **gr_members = NULL;
+ int num_gr_members = 0;
+
+ if ( !string )
+ return NULL;
+
+ ZERO_STRUCTP( &grp );
+
+ DEBUG(10,("string2group: converting \"%s\"\n", string));
+
+ ZERO_STRUCT( fields );
+
+ for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
+ if ( !(p = strchr( str, ':' )) ) {
+ DEBUG(0,("string2group: parsing failure\n"));
+ return NULL;
+ }
+ *p = '\0';
+ if ( str )
+ fields[i] = str;
+ str = p + 1;
+ }
+
+ /* group members */
+
+ if ( *str ) {
+ /* we already know we have a non-empty string */
+
+ num_gr_members = count_chars(str, ',') + 1;
+
+ /* if there was at least one comma, then there
+ are n+1 members */
+ if ( num_gr_members ) {
+ fstring buffer;
+
+ gr_members = (char**)smb_xmalloc(sizeof(char*)*num_gr_members+1);
+
+ i = 0;
+ while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
+ gr_members[i++] = smb_xstrdup(buffer);
+ }
+
+ gr_members[i] = NULL;
+ }
+ }
+
+
+ /* copy fields */
+
+ fstrcpy( grp.gr_name, fields[0] );
+ fstrcpy( grp.gr_passwd, fields[1] );
+ grp.gr_gid = atoi( fields[2] );
+
+ grp.num_gr_mem = num_gr_members;
+ grp.gr_mem = gr_members;
+
+ /* last minute sanity checks */
+
+ if ( grp.gr_gid == 0 ) {
+ DEBUG(0,("string2group: Failure! gid==%d\n", grp.gr_gid));
+ SAFE_FREE( gr_members );
+ return NULL;
+ }
+
+ DEBUG(10,("string2group: Success\n"));
+
+ return &grp;
+}
+
+/**********************************************************************
+ Convert a struct group* to a string formatted for /etc/group
+**********************************************************************/
+
+static char* group2string( const WINBINDD_GR *grp )
+{
+ static pstring string;
+ int ret;
+ char *member, *gr_mem_str;
+ int num_members;
+ int i, size;
+
+ if ( !grp || !grp->gr_name )
+ return NULL;
+
+ DEBUG(10,("group2string: converting passwd struct for %s\n",
+ grp->gr_name));
+
+ if ( grp->num_gr_mem ) {
+ int idx = 0;
+
+ member = grp->gr_mem[0];
+ size = 0;
+ num_members = 0;
+
+ while ( member ) {
+ size += strlen(member) + 1;
+ num_members++;
+ member = grp->gr_mem[num_members];
+ }
+
+ gr_mem_str = smb_xmalloc(size);
+
+ for ( i=0; i<num_members; i++ ) {
+ snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
+ idx += strlen(grp->gr_mem[i]) + 1;
+ }
+ /* add trailing NULL (also removes trailing ',' */
+ gr_mem_str[size-1] = '\0';
+ }
+ else {
+ /* no members */
+ gr_mem_str = smb_xmalloc(sizeof(fstring));
+ fstrcpy( gr_mem_str, "" );
+ }
+
+ ret = snprintf( string, sizeof(string)-1, "%s:%s:%d:%s",
+ grp->gr_name,
+ grp->gr_passwd ? grp->gr_passwd : "*",
+ grp->gr_gid,
+ gr_mem_str );
+
+ SAFE_FREE( gr_mem_str );
+
+ if ( ret < 0 ) {
+ DEBUG(0,("group2string: snprintf() failed!\n"));
+ return NULL;
+ }
+
+ return string;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static char* acct_userkey_byname( const char *name )
+{
+ static fstring key;
+
+ snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_PASSWD, name );
+
+ return key;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static char* acct_userkey_byuid( uid_t uid )
+{
+ static fstring key;
+
+ snprintf( key, sizeof(key), "%s/UID/%d", WBKEY_PASSWD, uid );
+
+ return key;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static char* acct_groupkey_byname( const char *name )
+{
+ static fstring key;
+
+ snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_GROUP, name );
+
+ return key;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static char* acct_groupkey_bygid( gid_t gid )
+{
+ static fstring key;
+
+ snprintf( key, sizeof(key), "%s/GID/%d", WBKEY_GROUP, gid );
+
+ return key;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+WINBINDD_PW* wb_getpwnam( const char * name )
+{
+ char *keystr;
+ TDB_DATA data;
+ static WINBINDD_PW *pw;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
+ return NULL;
+ }
+
+
+ keystr = acct_userkey_byname( name );
+
+ data = tdb_fetch_by_string( account_tdb, keystr );
+
+ pw = NULL;
+
+ if ( data.dptr ) {
+ pw = string2passwd( data.dptr );
+ SAFE_FREE( data.dptr );
+ }
+
+ DEBUG(5,("wb_getpwnam: %s user (%s)\n",
+ (pw ? "Found" : "Did not find"), name ));
+
+ return pw;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+WINBINDD_PW* wb_getpwuid( const uid_t uid )
+{
+ char *keystr;
+ TDB_DATA data;
+ static WINBINDD_PW *pw;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
+ return NULL;
+ }
+
+ data = tdb_fetch_by_string( account_tdb, acct_userkey_byuid(uid) );
+ if ( !data.dptr ) {
+ DEBUG(4,("wb_getpwuid: failed to locate uid == %d\n", uid));
+ return NULL;
+ }
+ keystr = acct_userkey_byname( data.dptr );
+
+ SAFE_FREE( data.dptr );
+
+ data = tdb_fetch_by_string( account_tdb, keystr );
+
+ pw = NULL;
+
+ if ( data.dptr ) {
+ pw = string2passwd( data.dptr );
+ SAFE_FREE( data.dptr );
+ }
+
+ DEBUG(5,("wb_getpwuid: %s user (uid == %d)\n",
+ (pw ? "Found" : "Did not find"), uid ));
+
+ return pw;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+BOOL wb_storepwnam( const WINBINDD_PW *pw )
+{
+ char *namekey, *uidkey;
+ TDB_DATA data;
+ char *str;
+ int ret = 0;
+ fstring username;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
+ return False;
+ }
+
+ namekey = acct_userkey_byname( pw->pw_name );
+
+ /* lock the main entry first */
+
+ if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
+ DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
+ return False;
+ }
+
+ str = passwd2string( pw );
+
+ data.dptr = str;
+ data.dsize = strlen(str) + 1;
+
+ if ( (tdb_store_by_string(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
+ DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
+ ret = -1;
+ goto done;
+ }
+
+ /* store the uid index */
+
+ uidkey = acct_userkey_byuid(pw->pw_uid);
+
+ fstrcpy( username, pw->pw_name );
+ data.dptr = username;
+ data.dsize = strlen(username) + 1;
+
+ if ( (tdb_store_by_string(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
+ DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
+ tdb_delete_by_string(account_tdb, namekey);
+ ret = -1;
+ goto done;
+ }
+
+ DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
+
+done:
+ tdb_unlock_bystring( account_tdb, namekey );
+
+ return ( ret == 0 );
+}
+
+/**********************************************************************
+**********************************************************************/
+
+WINBINDD_GR* wb_getgrnam( const char * name )
+{
+ char *keystr;
+ TDB_DATA data;
+ static WINBINDD_GR *grp;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
+ return NULL;
+ }
+
+
+ keystr = acct_groupkey_byname( name );
+
+ data = tdb_fetch_by_string( account_tdb, keystr );
+
+ grp = NULL;
+
+ if ( data.dptr ) {
+ grp = string2group( data.dptr );
+ SAFE_FREE( data.dptr );
+ }
+
+ DEBUG(5,("wb_getgrnam: %s group (%s)\n",
+ (grp ? "Found" : "Did not find"), name ));
+
+ return grp;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+WINBINDD_GR* wb_getgrgid( gid_t gid )
+{
+ char *keystr;
+ TDB_DATA data;
+ static WINBINDD_GR *grp;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
+ return NULL;
+ }
+
+ data = tdb_fetch_by_string( account_tdb, acct_groupkey_bygid(gid) );
+ if ( !data.dptr ) {
+ DEBUG(4,("wb_getgrgid: failed to locate gid == %d\n", gid));
+ return NULL;
+ }
+ keystr = acct_groupkey_byname( data.dptr );
+
+ SAFE_FREE( data.dptr );
+
+ data = tdb_fetch_by_string( account_tdb, keystr );
+
+ grp = NULL;
+
+ if ( data.dptr ) {
+ grp = string2group( data.dptr );
+ SAFE_FREE( data.dptr );
+ }
+
+ DEBUG(5,("wb_getgrgid: %s group (gid == %d)\n",
+ (grp ? "Found" : "Did not find"), gid ));
+
+ return grp;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+BOOL wb_storegrnam( const WINBINDD_GR *grp )
+{
+ char *namekey, *gidkey;
+ TDB_DATA data;
+ char *str;
+ int ret = 0;
+ fstring groupname;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
+ return False;
+ }
+
+ namekey = acct_groupkey_byname( grp->gr_name );
+
+ /* lock the main entry first */
+
+ if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
+ DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
+ return False;
+ }
+
+ str = group2string( grp );
+
+ data.dptr = str;
+ data.dsize = strlen(str) + 1;
+
+ if ( (tdb_store_by_string(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
+ DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
+ ret = -1;
+ goto done;
+ }
+
+ /* store the gid index */
+
+ gidkey = acct_groupkey_bygid(grp->gr_gid);
+
+ fstrcpy( groupname, grp->gr_name );
+ data.dptr = groupname;
+ data.dsize = strlen(groupname) + 1;
+
+ if ( (tdb_store_by_string(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
+ DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
+ tdb_delete_by_string(account_tdb, namekey);
+ ret = -1;
+ goto done;
+ }
+
+ DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
+
+done:
+ tdb_unlock_bystring( account_tdb, namekey );
+
+ return ( ret == 0 );
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
+{
+ int i;
+ char **members;
+
+ if ( !grp || !user )
+ return False;
+
+ for ( i=0; i<grp->num_gr_mem; i++ ) {
+ if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
+ return True;
+ }
+
+ /* add one new slot and keep an extra for the terminating NULL */
+ members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
+ if ( !members )
+ return False;
+
+ grp->gr_mem = members;
+ grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
+ grp->gr_mem[grp->num_gr_mem] = NULL;
+
+ return True;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
+{
+ int i;
+ BOOL found = False;
+
+ if ( !grp || !user )
+ return False;
+
+ for ( i=0; i<grp->num_gr_mem && !found; i++ ) {
+ if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
+ found = True;
+ }
+
+ if ( !found )
+ return False;
+
+ memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
+ grp->num_gr_mem--;
+
+ return True;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+static void free_winbindd_gr( WINBINDD_GR *grp )
+{
+ int i;
+
+ if ( !grp )
+ return;
+
+ for ( i=0; i<grp->num_gr_mem; i++ )
+ SAFE_FREE( grp->gr_mem[i] );
+
+ SAFE_FREE( grp->gr_mem );
+
+ return;
+}
+
+/**********************************************************************
+ Create a new "UNIX" user for the system given a username
+**********************************************************************/
+
+enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
+{
+ char *user, *group;
+ unid_t id;
+ WINBINDD_PW pw;
+ WINBINDD_GR *wb_grp;
+ struct group *unix_grp;
+ gid_t primary_gid;
+
+ if ( !state->privileged ) {
+ DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Ensure null termination */
+ state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
+ state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
+
+ user = state->request.data.acct_mgt.username;
+ group = state->request.data.acct_mgt.groupname;
+
+ DEBUG(3, ("[%5d]: create_user user=>(%s), group=>(%s)\n",
+ state->pid, user, group));
+
+ if ( !*group )
+ group = lp_template_primary_group();
+
+ /* validate the primary group
+ 1) lookup in local tdb first
+ 2) call getgrnam() as a last resort */
+
+ if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
+ primary_gid = wb_grp->gr_gid;
+ free_winbindd_gr( wb_grp );
+ }
+ else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
+ primary_gid = unix_grp->gr_gid;
+ }
+ else {
+ DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
+ return WINBINDD_ERROR;
+ }
+
+ /* get a new uid */
+
+ if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
+ DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* The substitution of %U and %D in the 'template homedir' is done
+ by lp_string() calling standard_sub_basic(). */
+
+ fstrcpy( current_user_info.smb_name, user );
+ sub_set_smb_name( user );
+ fstrcpy( current_user_info.domain, get_global_sam_name() );
+
+ /* fill in the passwd struct */
+
+ fstrcpy( pw.pw_name, user );
+ fstrcpy( pw.pw_passwd, "x" );
+ fstrcpy( pw.pw_gecos, user);
+ fstrcpy( pw.pw_dir, lp_template_homedir() );
+ fstrcpy( pw.pw_shell, lp_template_shell() );
+
+ pw.pw_uid = id.uid;
+ pw.pw_gid = primary_gid;
+
+ return ( wb_storepwnam(&pw) ? WINBINDD_OK : WINBINDD_ERROR );
+}
+
+/**********************************************************************
+ Create a new "UNIX" group for the system given a username
+**********************************************************************/
+
+enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
+{
+ char *group;
+ unid_t id;
+ WINBINDD_GR grp;
+
+ if ( !state->privileged ) {
+ DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Ensure null termination */
+ state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
+ group = state->request.data.acct_mgt.groupname;
+
+ DEBUG(3, ("[%5d]: create_group (%s)\n", state->pid, group));
+
+ /* get a new uid */
+
+ if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
+ DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* fill in the group struct */
+
+ fstrcpy( grp.gr_name, group );
+ fstrcpy( grp.gr_passwd, "*" );
+
+ grp.gr_gid = id.gid;
+ grp.gr_mem = NULL; /* start with no members */
+ grp.num_gr_mem = 0;
+
+ return ( wb_storegrnam(&grp) ? WINBINDD_OK : WINBINDD_ERROR );
+}
+
+/**********************************************************************
+ Add a user to the membership for a group.
+**********************************************************************/
+
+enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
+{
+ WINBINDD_PW *pw;
+ WINBINDD_GR *grp;
+ char *user, *group;
+ BOOL ret;
+
+ if ( !state->privileged ) {
+ DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Ensure null termination */
+ state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
+ state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
+ group = state->request.data.acct_mgt.groupname;
+ user = state->request.data.acct_mgt.username;
+
+ DEBUG(3, ("[%5d]: add_user_to_group add %s to %s\n", state->pid,
+ user, group));
+
+ /* make sure it is a valid user */
+
+ if ( !(pw = wb_getpwnam( user )) ) {
+ DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* make sure it is a valid group */
+
+ if ( !(grp = wb_getgrnam( group )) ) {
+ DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
+ return WINBINDD_ERROR;
+ }
+
+ if ( !wb_addgrpmember( grp, user ) )
+ return WINBINDD_ERROR;
+
+ ret = wb_storegrnam(grp);
+
+ free_winbindd_gr( grp );
+
+ return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
+}
+
+/**********************************************************************
+ Remove a user from the membership of a group
+**********************************************************************/
+
+enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
+{
+ WINBINDD_GR *grp;
+ char *user, *group;
+ BOOL ret;
+
+ if ( !state->privileged ) {
+ DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Ensure null termination */
+ state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
+ state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
+ group = state->request.data.acct_mgt.groupname;
+ user = state->request.data.acct_mgt.username;
+
+ DEBUG(3, ("[%5d]: remove_user_to_group delete %s from %s\n", state->pid,
+ user, group));
+
+ /* don't worry about checking the username since we're removing it anyways */
+
+ /* make sure it is a valid group */
+
+ if ( !(grp = wb_getgrnam( group )) ) {
+ DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
+ return WINBINDD_ERROR;
+ }
+
+ if ( !wb_delgrpmember( grp, user ) )
+ return WINBINDD_ERROR;
+
+ ret = wb_storegrnam(grp);
+
+ free_winbindd_gr( grp );
+
+ return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
+}
+
+/**********************************************************************
+ Set the primary group membership of a user
+**********************************************************************/
+
+enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
+{
+ WINBINDD_PW *pw;
+ WINBINDD_GR *grp;
+ char *user, *group;
+
+ if ( !state->privileged ) {
+ DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Ensure null termination */
+ state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
+ state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
+ group = state->request.data.acct_mgt.groupname;
+ user = state->request.data.acct_mgt.username;
+
+ DEBUG(3, ("[%5d]: set_user_primary_group group %s for user %s\n", state->pid,
+ group, user));
+
+ /* make sure it is a valid user */
+
+ if ( !(pw = wb_getpwnam( user )) ) {
+ DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* make sure it is a valid group */
+
+ if ( !(grp = wb_getgrnam( group )) ) {
+ DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
+ return WINBINDD_ERROR;
+ }
+
+ pw->pw_gid = grp->gr_gid;
+
+ free_winbindd_gr( grp );
+
+ return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
+}
+
+/**********************************************************************
+ Set the primary group membership of a user
+**********************************************************************/
+
+enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
+{
+ return WINBINDD_ERROR;
+}
+
+/**********************************************************************
+ Set the primary group membership of a user
+**********************************************************************/
+
+enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
+{
+ return WINBINDD_ERROR;
+}
+
+
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 9a969abeaa9..d67d48d5066 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -27,6 +27,34 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+/*********************************************************************
+*********************************************************************/
+
+static int gr_mem_buffer( char **buffer, char **members, int num_members )
+{
+ int i;
+ int len = 0;
+ int idx = 0;
+
+ if ( num_members == 0 ) {
+ *buffer = NULL;
+ return 0;
+ }
+
+ for ( i=0; i<num_members; i++ )
+ len += strlen(members[i])+1;
+
+ *buffer = (char*)smb_xmalloc(len);
+ for ( i=0; i<num_members; i++ ) {
+ snprintf( &(*buffer)[idx], len-idx, "%s,", members[i]);
+ idx += strlen(members[i])+1;
+ }
+ /* terminate with NULL */
+ (*buffer)[len-1] = '\0';
+
+ return len;
+}
+
/***************************************************************
Empty static struct for negative caching.
****************************************************************/
@@ -193,6 +221,7 @@ done:
enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
{
DOM_SID group_sid;
+ WINBINDD_GR *grp;
struct winbindd_domain *domain;
enum SID_NAME_USE name_type;
fstring name_domain, name_group;
@@ -211,18 +240,38 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
memset(name_group, 0, sizeof(fstring));
tmp = state->request.data.groupname;
- if (!parse_domain_user(tmp, name_domain, name_group))
- return WINBINDD_ERROR;
+
+ parse_domain_user(tmp, name_domain, name_group);
+
+ /* if no domain or our local domain, then do a local tdb search */
+
+ if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
+ char *buffer = NULL;
+
+ if ( !(grp=wb_getgrnam(name_group)) ) {
+ DEBUG(5,("winbindd_getgrnam: lookup for %s\\%s failed\n",
+ name_domain, name_group));
+ return WINBINDD_ERROR;
+ }
+ memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) );
- /* don't handle our own domain if we are a DC ( or a member of a Samba domain
- that shares UNIX accounts). This code handles cases where
- the account doesn't exist anywhere and gets passed on down the NSS layer */
+ gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
+
+ state->response.data.gr.gr_mem_ofs = 0;
+ state->response.length += gr_mem_len;
+ state->response.extra_data = buffer; /* give the memory away */
+
+ return WINBINDD_OK;
+ }
- if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
- DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
+ /* should we deal with users for our domain? */
+
+ if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
+ DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n",
name_domain, name_group));
return WINBINDD_ERROR;
}
+
/* Get info for the domain */
@@ -277,6 +326,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
{
struct winbindd_domain *domain;
+ WINBINDD_GR *grp;
DOM_SID group_sid;
enum SID_NAME_USE name_type;
fstring dom_name;
@@ -293,6 +343,21 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
(state->request.data.gid > server_state.gid_high))
return WINBINDD_ERROR;
+ /* alway try local tdb lookup first */
+ if ( ( grp=wb_getgrgid(state->request.data.gid)) != NULL ) {
+ char *buffer = NULL;
+
+ memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) );
+
+ gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
+
+ state->response.data.gr.gr_mem_ofs = 0;
+ state->response.length += gr_mem_len;
+ state->response.extra_data = buffer; /* give away the memory */
+
+ return WINBINDD_OK;
+ }
+
/* Get rid from gid */
if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) {
DEBUG(1, ("could not convert gid %d to rid\n",
@@ -859,8 +924,12 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
/* Parse domain and username */
- if (!parse_domain_user(state->request.data.username, name_domain,
- name_user))
+ parse_domain_user(state->request.data.username,
+ name_domain, name_user);
+
+ /* bail if there is no domain */
+
+ if ( !*name_domain )
goto done;
/* Get info for the domain */
diff --git a/source3/nsswitch/winbindd_idmap.c b/source3/nsswitch/winbindd_idmap.c
deleted file mode 100644
index 3b23089200f..00000000000
--- a/source3/nsswitch/winbindd_idmap.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Winbind ID Mapping
- Copyright (C) Tim Potter 2000
- Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "winbindd.h"
-
-static struct {
- const char *name;
- /* Function to create a member of the idmap_methods list */
- BOOL (*reg_meth)(struct winbindd_idmap_methods **methods);
- struct winbindd_idmap_methods *methods;
-} builtin_winbindd_idmap_functions[] = {
- { "tdb", winbind_idmap_reg_tdb, NULL },
- { NULL, NULL, NULL }
-};
-
-/* singleton pattern: uberlazy evaluation */
-static struct winbindd_idmap_methods *impl;
-
-static struct winbindd_idmap_methods *get_impl(const char *name)
-{
- int i = 0;
- struct winbindd_idmap_methods *ret = NULL;
-
- while (builtin_winbindd_idmap_functions[i].name &&
- strcmp(builtin_winbindd_idmap_functions[i].name, name)) {
- i++;
- }
-
- if (builtin_winbindd_idmap_functions[i].name) {
- if (!builtin_winbindd_idmap_functions[i].methods) {
- builtin_winbindd_idmap_functions[i].reg_meth(&builtin_winbindd_idmap_functions[i].methods);
- }
-
- ret = builtin_winbindd_idmap_functions[i].methods;
- }
-
- return ret;
-}
-
-/* Initialize backend */
-BOOL winbindd_idmap_init(void)
-{
- BOOL ret = False;
-
- DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n",
- lp_winbind_backend()));
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- if (!impl) {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
- }
-
- if (impl) {
- ret = impl->init();
- }
-
- DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false"));
-
- return ret;
-}
-
-/* Get UID from SID */
-BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
-{
- BOOL ret = False;
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- if (!impl) {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
- }
-
- if (impl) {
- ret = impl->get_uid_from_sid(sid, uid);
- }
-
- return ret;
-}
-
-/* Get GID from SID */
-BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
-{
- BOOL ret = False;
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- if (!impl) {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
- }
-
- if (impl) {
- ret = impl->get_gid_from_sid(sid, gid);
- }
-
- return ret;
-}
-
-/* Get SID from UID */
-BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
-{
- BOOL ret = False;
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- if (!impl) {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
- }
-
- if (impl) {
- ret = impl->get_sid_from_uid(uid, sid);
- }
-
- return ret;
-}
-
-/* Get SID from GID */
-BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
-{
- BOOL ret = False;
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- }
-
- if (impl) {
- ret = impl->get_sid_from_gid(gid, sid);
- } else {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
-
- return ret;
-}
-
-/* Close backend */
-BOOL winbindd_idmap_close(void)
-{
- BOOL ret = False;
-
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- }
-
- if (impl) {
- ret = impl->close();
- } else {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
-
- return ret;
-}
-
-/* Dump backend status */
-void winbindd_idmap_status(void)
-{
- if (!impl) {
- impl = get_impl(lp_winbind_backend());
- }
-
- if (impl) {
- impl->status();
- } else {
- DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
- lp_winbind_backend()));
- }
-}
diff --git a/source3/nsswitch/winbindd_idmap_tdb.c b/source3/nsswitch/winbindd_idmap_tdb.c
deleted file mode 100644
index 12d6972bae3..00000000000
--- a/source3/nsswitch/winbindd_idmap_tdb.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind daemon - user related function
-
- Copyright (C) Tim Potter 2000
- Copyright (C) Anthony Liguori 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "winbindd.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_WINBIND
-
-/* High water mark keys */
-#define HWM_GROUP "GROUP HWM"
-#define HWM_USER "USER HWM"
-
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
-
-/* Globals */
-static TDB_CONTEXT *idmap_tdb;
-
-/* convert one record to the new format */
-static int tdb_convert_fn(TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
- void *ignored)
-{
- struct winbindd_domain *domain;
- char *p;
- DOM_SID sid;
- uint32 rid;
- fstring keystr;
- fstring dom_name;
- TDB_DATA key2;
-
- p = strchr(key.dptr, '/');
- if (!p)
- return 0;
-
- *p = 0;
- fstrcpy(dom_name, key.dptr);
- *p++ = '/';
-
- domain = find_domain_from_name(dom_name);
- if (!domain) {
- /* We must delete the old record. */
- DEBUG(0,
- ("winbindd: tdb_convert_fn : Unable to find domain %s\n",
- dom_name));
- DEBUG(0,
- ("winbindd: tdb_convert_fn : deleting record %s\n",
- key.dptr));
- tdb_delete(idmap_tdb, key);
- return 0;
- }
-
- rid = atoi(p);
-
- sid_copy(&sid, &domain->sid);
- sid_append_rid(&sid, rid);
-
- sid_to_string(keystr, &sid);
- key2.dptr = keystr;
- key2.dsize = strlen(keystr) + 1;
-
- if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) {
- /* not good! */
- DEBUG(0,
- ("winbindd: tdb_convert_fn : Unable to update record %s\n",
- key2.dptr));
- DEBUG(0,
- ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n"));
- return -1;
- }
-
- if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) {
- /* not good! */
- DEBUG(0,
- ("winbindd: tdb_convert_fn : Unable to update record %s\n",
- data.dptr));
- DEBUG(0,
- ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n"));
- return -1;
- }
-
- tdb_delete(idmap_tdb, key);
-
- return 0;
-}
-
-/*****************************************************************************
- Convert the idmap database from an older version.
-*****************************************************************************/
-static BOOL tdb_idmap_convert(void)
-{
- int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
- BOOL bigendianheader =
- (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
-
- if (vers == IDMAP_VERSION)
- return True;
-
- if (((vers == -1) && bigendianheader)
- || (IREV(vers) == IDMAP_VERSION)) {
- /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
- /*
- * high and low records were created on a
- * big endian machine and will need byte-reversing.
- */
-
- int32 wm;
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
-
- if (wm != -1) {
- wm = IREV(wm);
- } else
- wm = server_state.uid_low;
-
- if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
- DEBUG(0,
- ("tdb_idmap_convert: Unable to byteswap user hwm in idmap database\n"));
- return False;
- }
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
- if (wm != -1) {
- wm = IREV(wm);
- } else
- wm = server_state.gid_low;
-
- if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
- DEBUG(0,
- ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n"));
- return False;
- }
- }
-
- /* the old format stored as DOMAIN/rid - now we store the SID direct */
- tdb_traverse(idmap_tdb, tdb_convert_fn, NULL);
-
- if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) ==
- -1) {
- DEBUG(0,
- ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n"));
- return False;
- }
-
- return True;
-}
-
-/* Allocate either a user or group id from the pool */
-static BOOL tdb_allocate_id(uid_t * id, BOOL isgroup)
-{
- int hwm;
-
- /* Get current high water mark */
- if ((hwm = tdb_fetch_int32(idmap_tdb,
- isgroup ? HWM_GROUP : HWM_USER)) ==
- -1) {
- return False;
- }
-
- /* Return next available uid in list */
- if ((isgroup && (hwm > server_state.gid_high)) ||
- (!isgroup && (hwm > server_state.uid_high))) {
- DEBUG(0,
- ("winbind %sid range full!\n", isgroup ? "g" : "u"));
- return False;
- }
-
- if (id) {
- *id = hwm;
- }
-
- hwm++;
-
- /* Store new high water mark */
- tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm);
-
- return True;
-}
-
-/* Get a sid from an id */
-static BOOL tdb_get_sid_from_id(int id, DOM_SID * sid, BOOL isgroup)
-{
- TDB_DATA key, data;
- fstring keystr;
- BOOL result = False;
-
- slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID",
- id);
-
- key.dptr = keystr;
- key.dsize = strlen(keystr) + 1;
-
- data = tdb_fetch(idmap_tdb, key);
-
- if (data.dptr) {
- result = string_to_sid(sid, data.dptr);
- SAFE_FREE(data.dptr);
- }
-
- return result;
-}
-
-/* Get an id from a sid */
-static BOOL tdb_get_id_from_sid(DOM_SID * sid, uid_t * id, BOOL isgroup)
-{
- TDB_DATA data, key;
- fstring keystr;
- BOOL result = False;
-
- /* Check if sid is present in database */
- sid_to_string(keystr, sid);
-
- key.dptr = keystr;
- key.dsize = strlen(keystr) + 1;
-
- data = tdb_fetch(idmap_tdb, key);
-
- if (data.dptr) {
- fstring scanstr;
- int the_id;
-
- /* Parse and return existing uid */
- fstrcpy(scanstr, isgroup ? "GID" : "UID");
- fstrcat(scanstr, " %d");
-
- if (sscanf(data.dptr, scanstr, &the_id) == 1) {
- /* Store uid */
- if (id) {
- *id = the_id;
- }
-
- result = True;
- }
-
- SAFE_FREE(data.dptr);
- } else {
-
- /* Allocate a new id for this sid */
- if (id && tdb_allocate_id(id, isgroup)) {
- fstring keystr2;
-
- /* Store new id */
- slprintf(keystr2, sizeof(keystr2), "%s %d",
- isgroup ? "GID" : "UID", *id);
-
- data.dptr = keystr2;
- data.dsize = strlen(keystr2) + 1;
-
- tdb_store(idmap_tdb, key, data, TDB_REPLACE);
- tdb_store(idmap_tdb, data, key, TDB_REPLACE);
-
- result = True;
- }
- }
-
- return result;
-}
-
-/*****************************************************************************
- Initialise idmap database.
-*****************************************************************************/
-static BOOL tdb_idmap_init(void)
-{
- SMB_STRUCT_STAT stbuf;
-
- /* move to the new database on first startup */
- if (!file_exist(lock_path("idmap.tdb"), &stbuf)) {
- if (file_exist(lock_path("winbindd_idmap.tdb"), &stbuf)) {
- char *cmd = NULL;
-
- /* lazy file copy */
- if (asprintf(&cmd, "cp -p %s/winbindd_idmap.tdb %s/idmap.tdb", lp_lockdir(), lp_lockdir()) != -1) {
- system(cmd);
- free(cmd);
- }
- if (!file_exist(lock_path("idmap.tdb"), &stbuf)) {
- DEBUG(0, ("idmap_init: Unable to make a new database copy\n"));
- return False;
- }
- }
- }
-
- /* Open tdb cache */
- if (!(idmap_tdb = tdb_open_log(lock_path("idmap.tdb"), 0,
- TDB_DEFAULT, O_RDWR | O_CREAT,
- 0600))) {
- DEBUG(0,
- ("winbindd_idmap_init: Unable to open idmap database\n"));
- return False;
- }
-
- /* possibly convert from an earlier version */
- if (!tdb_idmap_convert()) {
- DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
- return False;
- }
-
- /* Create high water marks for group and user id */
- if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) {
- if (tdb_store_int32
- (idmap_tdb, HWM_USER, server_state.uid_low) == -1) {
- DEBUG(0,
- ("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n"));
- return False;
- }
- }
-
- if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) {
- if (tdb_store_int32
- (idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) {
- DEBUG(0,
- ("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n"));
- return False;
- }
- }
-
- return True;
-}
-
-/* Get a sid from a uid */
-static BOOL tdb_get_sid_from_uid(uid_t uid, DOM_SID * sid)
-{
- return tdb_get_sid_from_id((int) uid, sid, False);
-}
-
-/* Get a sid from a gid */
-static BOOL tdb_get_sid_from_gid(gid_t gid, DOM_SID * sid)
-{
- return tdb_get_sid_from_id((int) gid, sid, True);
-}
-
-/* Get a uid from a sid */
-static BOOL tdb_get_uid_from_sid(DOM_SID * sid, uid_t * uid)
-{
- return tdb_get_id_from_sid(sid, uid, False);
-}
-
-/* Get a gid from a group sid */
-static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid)
-{
- return tdb_get_id_from_sid(sid, gid, True);
-}
-
-/* Close the tdb */
-static BOOL tdb_idmap_close(void)
-{
- if (idmap_tdb)
- return (tdb_close(idmap_tdb) == 0);
- return True;
-}
-
-
-/* Dump status information to log file. Display different stuff based on
- the debug level:
-
- Debug Level Information Displayed
- =================================================================
- 0 Percentage of [ug]id range allocated
- 0 High water marks (next allocated ids)
-*/
-
-#define DUMP_INFO 0
-
-static void tdb_idmap_status(void)
-{
- int user_hwm, group_hwm;
-
- DEBUG(0, ("winbindd idmap status:\n"));
-
- /* Get current high water marks */
-
- if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
- DEBUG(DUMP_INFO,
- ("\tCould not get userid high water mark!\n"));
- }
-
- if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
- DEBUG(DUMP_INFO,
- ("\tCould not get groupid high water mark!\n"));
- }
-
- /* Display next ids to allocate */
-
- if (user_hwm != -1) {
- DEBUG(DUMP_INFO,
- ("\tNext userid to allocate is %d\n", user_hwm));
- }
-
- if (group_hwm != -1) {
- DEBUG(DUMP_INFO,
- ("\tNext groupid to allocate is %d\n", group_hwm));
- }
-
- /* Display percentage of id range already allocated. */
-
- if (user_hwm != -1) {
- int num_users = user_hwm - server_state.uid_low;
- int total_users =
- server_state.uid_high - server_state.uid_low;
-
- DEBUG(DUMP_INFO,
- ("\tUser id range is %d%% full (%d of %d)\n",
- num_users * 100 / total_users, num_users,
- total_users));
- }
-
- if (group_hwm != -1) {
- int num_groups = group_hwm - server_state.gid_low;
- int total_groups =
- server_state.gid_high - server_state.gid_low;
-
- DEBUG(DUMP_INFO,
- ("\tGroup id range is %d%% full (%d of %d)\n",
- num_groups * 100 / total_groups, num_groups,
- total_groups));
- }
-
- /* Display complete mapping of users and groups to rids */
-}
-
-struct winbindd_idmap_methods tdb_idmap_methods = {
- tdb_idmap_init,
-
- tdb_get_sid_from_uid,
- tdb_get_sid_from_gid,
-
- tdb_get_uid_from_sid,
- tdb_get_gid_from_sid,
-
- tdb_idmap_close,
-
- tdb_idmap_status
-};
-
-BOOL winbind_idmap_reg_tdb(struct winbindd_idmap_methods **meth)
-{
- *meth = &tdb_idmap_methods;
-
- return True;
-}
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index 1ddfb2174ef..a2d9e82c7c7 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -36,7 +36,7 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 7
+#define WINBIND_INTERFACE_VERSION 8
/* Socket commands */
@@ -99,6 +99,16 @@ enum winbindd_cmd {
WINBINDD_WINS_BYIP,
WINBINDD_WINS_BYNAME,
+ /* account management commands */
+
+ WINBINDD_CREATE_USER,
+ WINBINDD_CREATE_GROUP,
+ WINBINDD_ADD_USER_TO_GROUP,
+ WINBINDD_REMOVE_USER_FROM_GROUP,
+ WINBINDD_SET_USER_PRIMARY_GROUP,
+ WINBINDD_DELETE_USER,
+ WINBINDD_DELETE_GROUP,
+
/* this is like GETGRENT but gives an empty group list */
WINBINDD_GETGRLST,
@@ -111,6 +121,27 @@ enum winbindd_cmd {
WINBINDD_NUM_CMDS
};
+typedef struct winbindd_pw {
+ fstring pw_name;
+ fstring pw_passwd;
+ uid_t pw_uid;
+ gid_t pw_gid;
+ fstring pw_gecos;
+ fstring pw_dir;
+ fstring pw_shell;
+} WINBINDD_PW;
+
+
+typedef struct winbindd_gr {
+ fstring gr_name;
+ fstring gr_passwd;
+ gid_t gr_gid;
+ int num_gr_mem;
+ int gr_mem_ofs; /* offset to group membership */
+ char **gr_mem;
+} WINBINDD_GR;
+
+
#define WBFLAG_PAM_INFO3_NDR 0x0001
#define WBFLAG_PAM_INFO3_TEXT 0x0002
#define WBFLAG_PAM_NTKEY 0x0004
@@ -160,6 +191,10 @@ struct winbindd_request {
fstring name;
} name;
uint32 num_entries; /* getpwent, getgrent */
+ struct {
+ fstring username;
+ fstring groupname;
+ } acct_mgt;
} data;
char null_term;
};
@@ -189,25 +224,11 @@ struct winbindd_response {
/* getpwnam, getpwuid */
- struct winbindd_pw {
- fstring pw_name;
- fstring pw_passwd;
- uid_t pw_uid;
- gid_t pw_gid;
- fstring pw_gecos;
- fstring pw_dir;
- fstring pw_shell;
- } pw;
+ struct winbindd_pw pw;
/* getgrnam, getgrgid */
- struct winbindd_gr {
- fstring gr_name;
- fstring gr_passwd;
- gid_t gr_gid;
- int num_gr_mem;
- int gr_mem_ofs; /* offset to group membership */
- } gr;
+ struct winbindd_gr gr;
uint32 num_entries; /* getpwent, getgrent */
struct winbindd_sid {
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 6aaf3bc7150..8df0f621c0f 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -142,8 +142,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
/* Parse domain and username */
- if (!parse_domain_user(state->request.data.auth.user, name_domain,
- name_user)) {
+ parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+ if ( !name_domain ) {
DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user));
result = NT_STATUS_INVALID_PARAMETER;
goto done;
@@ -444,8 +444,8 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
if (state == NULL)
return WINBINDD_ERROR;
- if (!parse_domain_user(state->request.data.chauthtok.user, domain,
- user)) {
+ parse_domain_user(state->request.data.chauthtok.user, domain, user);
+ if ( !*domain ) {
result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c
deleted file mode 100644
index 456b1afeabf..00000000000
--- a/source3/nsswitch/winbindd_passdb.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind rpc backend functions
-
- Copyright (C) Tim Potter 2000-2001,2003
- Copyright (C) Simo Sorce 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "winbindd.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_WINBIND
-
-
-/* Query display info for a domain. This returns enough information plus a
- bit extra to give an overview of domain users for the User Manager
- application. */
-static NTSTATUS query_user_list(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- WINBIND_USERINFO **info)
-{
- SAM_ACCOUNT *sam_account = NULL;
- NTSTATUS result;
- uint32 i;
-
- DEBUG(3,("pdb: query_user_list\n"));
-
- if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
- return result;
- }
-
- i = 0;
- *info = NULL;
-
- if (pdb_setsampwent(False)) {
-
- while (pdb_getsampwent(sam_account)) {
-
- /* we return only nua accounts, or we will have duplicates */
- if (!idmap_check_sid_is_in_free_range(pdb_get_user_sid(sam_account))) {
- continue;
- }
-
- *info = talloc_realloc(mem_ctx, *info, (i + 1) * sizeof(WINBIND_USERINFO));
- if (!(*info)) {
- DEBUG(0,("query_user_list: out of memory!\n"));
- result = NT_STATUS_NO_MEMORY;
- break;
- }
-
- (*info)[i].user_sid = talloc(mem_ctx, sizeof(DOM_SID));
- (*info)[i].group_sid = talloc(mem_ctx, sizeof(DOM_SID));
- if (!((*info)[i].user_sid) || !((*info)[i].group_sid)) {
- DEBUG(0,("query_user_list: out of memory!\n"));
- result = NT_STATUS_NO_MEMORY;
- break;
- }
- sid_copy((*info)[i].user_sid, pdb_get_user_sid(sam_account));
- sid_copy((*info)[i].group_sid, pdb_get_group_sid(sam_account));
-
- (*info)[i].acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
- (*info)[i].full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
- if (!((*info)[i].acct_name) || !((*info)[i].full_name)) {
- DEBUG(0,("query_user_list: out of memory!\n"));
- result = NT_STATUS_NO_MEMORY;
- break;
- }
-
- i++;
-
- if (!NT_STATUS_IS_OK(pdb_reset_sam(sam_account))) {
- result = NT_STATUS_UNSUCCESSFUL;
- break;
- }
- }
-
- *num_entries = i;
- result = NT_STATUS_OK;
-
- } else {
- result = NT_STATUS_UNSUCCESSFUL;
- }
-
- pdb_free_sam(&sam_account);
- return result;
-}
-
-/* list all domain groups */
-static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- struct acct_info **info)
-{
- NTSTATUS result = NT_STATUS_OK;
-
- DEBUG(3,("pdb: enum_dom_groups (group support not implemented)\n"));
-
- *num_entries = 0;
- *info = 0;
-
- return result;
-}
-
-/* List all domain groups */
-
-static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- struct acct_info **info)
-{
- NTSTATUS result = NT_STATUS_OK;
-
- DEBUG(3,("pdb: enum_local_groups (group support not implemented)\n"));
-
- *num_entries = 0;
- *info = 0;
-
- return result;
-}
-
-/* convert a single name to a sid in a domain */
-static NTSTATUS name_to_sid(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const char *name,
- DOM_SID *sid,
- enum SID_NAME_USE *type)
-{
- SAM_ACCOUNT *sam_account = NULL;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
- DEBUG(3,("pdb: name_to_sid name=%s (group support not implemented)\n", name));
-
- if (NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
- if (!pdb_getsampwnam(sam_account, name)) {
- result = NT_STATUS_UNSUCCESSFUL;
- } else { /* it is a sam user */
- sid_copy(sid, pdb_get_user_sid(sam_account));
- *type = SID_NAME_USER;
- result = NT_STATUS_OK;
- }
- }
-
- pdb_free_sam(&sam_account);
- return result;
-}
-
-/*
- convert a domain SID to a user or group name
-*/
-static NTSTATUS sid_to_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **name,
- enum SID_NAME_USE *type)
-{
- SAM_ACCOUNT *sam_account = NULL;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint32 id;
-
- DEBUG(3,("pdb: sid_to_name sid=%s\n", sid_string_static(sid)));
-
- if (NT_STATUS_IS_OK(idmap_sid_to_uid(sid, &id, 0))) { /* this is a user */
-
- if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
- return result;
- }
-
- if (!pdb_getsampwsid(sam_account, sid)) {
- pdb_free_sam(&sam_account);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
- if (!(*name)) {
- DEBUG(0,("query_user: out of memory!\n"));
- pdb_free_sam(&sam_account);
- return NT_STATUS_NO_MEMORY;
- }
-
- pdb_free_sam(&sam_account);
- *type = SID_NAME_USER;
- result = NT_STATUS_OK;
-
- } else if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &id, 0))) { /* this is a group */
-
- DEBUG(3,("pdb: sid_to_name: group support not implemented\n"));
- result = NT_STATUS_UNSUCCESSFUL;
- }
-
- return result;
-}
-
-/* Lookup user information from a rid or username. */
-static NTSTATUS query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
- WINBIND_USERINFO *user_info)
-{
- SAM_ACCOUNT *sam_account = NULL;
- NTSTATUS result;
-
- DEBUG(3,("pdb: query_user sid=%s\n", sid_string_static(user_sid)));
-
- if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
- return result;
- }
-
- if (!pdb_getsampwsid(sam_account, user_sid)) {
- pdb_free_sam(&sam_account);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* we return only nua accounts, or we will have duplicates */
- if (!idmap_check_sid_is_in_free_range(user_sid)) {
- pdb_free_sam(&sam_account);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- user_info->user_sid = talloc(mem_ctx, sizeof(DOM_SID));
- user_info->group_sid = talloc(mem_ctx, sizeof(DOM_SID));
- if (!(user_info->user_sid) || !(user_info->group_sid)) {
- DEBUG(0,("query_user: out of memory!\n"));
- pdb_free_sam(&sam_account);
- return NT_STATUS_NO_MEMORY;
- }
- sid_copy(user_info->user_sid, pdb_get_user_sid(sam_account));
- sid_copy(user_info->group_sid, pdb_get_group_sid(sam_account));
-
- user_info->acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
- user_info->full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
- if (!(user_info->acct_name) || !(user_info->full_name)) {
- DEBUG(0,("query_user: out of memory!\n"));
- pdb_free_sam(&sam_account);
- return NT_STATUS_NO_MEMORY;
- }
-
- pdb_free_sam(&sam_account);
- return NT_STATUS_OK;
-}
-
-/* Lookup groups a user is a member of. I wish Unix had a call like this! */
-static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
- uint32 *num_groups, DOM_SID ***user_gids)
-{
- NTSTATUS result = NT_STATUS_OK;
-
- DEBUG(3,("pdb: lookup_usergroups (group support not implemented)\n"));
-
- num_groups = 0;
- user_gids = 0;
-
- return result;
-}
-
-
-/* Lookup group membership given a rid. */
-static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid, uint32 *num_names,
- DOM_SID ***sid_mem, char ***names,
- uint32 **name_types)
-{
- NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
-
- DEBUG(3,("pdb: lookup_groupmem (group support not implemented)\n"));
-
- num_names = 0;
- sid_mem = 0;
- names = 0;
- name_types = 0;
-
- return result;
-}
-
-/* find the sequence number for a domain */
-static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
-{
- /* FIXME: we fake up the seq_num untill our passdb support it */
- static uint32 seq_num;
-
- DEBUG(3,("pdb: sequence_number\n"));
-
- *seq = seq_num++;
-
- return NT_STATUS_OK;
-}
-
-/* get a list of trusted domains */
-static NTSTATUS trusted_domains(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_domains,
- char ***names,
- char ***alt_names,
- DOM_SID **dom_sids)
-{
- NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
-
- DEBUG(3,("pdb: trusted_domains (todo!)\n"));
-
- return result;
-}
-
-/* find the domain sid for a domain */
-static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
-{
- DEBUG(3,("pdb: domain_sid\n"));
-
- if (strcmp(domain->name, lp_workgroup())) {
- return NT_STATUS_INVALID_PARAMETER;
- } else {
- sid_copy(sid, get_global_sam_sid());
- return NT_STATUS_OK;
- }
-}
-
-/* find alternate names list for the domain
- * should we look for netbios aliases??
- SSS */
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- DEBUG(3,("pdb: alternate_name\n"));
-
- return NT_STATUS_OK;
-}
-
-
-/* the rpc backend methods are exposed via this structure */
-struct winbindd_methods passdb_methods = {
- False,
- query_user_list,
- enum_dom_groups,
- enum_local_groups,
- name_to_sid,
- sid_to_name,
- query_user,
- lookup_usergroups,
- lookup_groupmem,
- sequence_number,
- trusted_domains,
- domain_sid,
- alternate_name
-};
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 37d92450759..7c95ba84705 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -97,6 +97,7 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
{
WINBIND_USERINFO user_info;
+ WINBINDD_PW *pw;
DOM_SID user_sid;
NTSTATUS status;
fstring name_domain, name_user;
@@ -112,16 +113,25 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* Parse domain and username */
- if (!parse_domain_user(state->request.data.username, name_domain,
- name_user))
- return WINBINDD_ERROR;
+ parse_domain_user(state->request.data.username,
+ name_domain, name_user);
+
+ /* if this is our local domain (or no domain), the do a local tdb search */
- /* don't handle our own domain if we are a DC ( or a member of a Samba domain
- that shares UNIX accounts). This code handles cases where
- the account doesn't exist anywhere and gets passed on down the NSS layer */
+ if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
+ if ( !(pw = wb_getpwnam(name_user)) ) {
+ DEBUG(5,("winbindd_getpwnam: lookup for %s\\%s failed\n",
+ name_domain, name_user));
+ return WINBINDD_ERROR;
+ }
+ memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) );
+ return WINBINDD_OK;
+ }
- if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
- DEBUG(7,("winbindd_getpwnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
+ /* should we deal with users for our domain? */
+
+ if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
+ DEBUG(7,("winbindd_getpenam: My domain -- rejecting getpwnam() for %s\\%s.\n",
name_domain, name_user));
return WINBINDD_ERROR;
}
@@ -184,6 +194,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
{
DOM_SID user_sid;
struct winbindd_domain *domain;
+ WINBINDD_PW *pw;
fstring dom_name;
fstring user_name;
enum SID_NAME_USE name_type;
@@ -200,6 +211,13 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid,
state->request.data.uid));
+
+ /* always try local tdb first */
+
+ if ( (pw = wb_getpwuid(state->request.data.uid)) != NULL ) {
+ memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) );
+ return WINBINDD_OK;
+ }
/* Get rid from uid */
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 28da415b9c3..1f123e896fe 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -415,18 +415,22 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
{
char *p = strchr(domuser,*lp_winbind_separator());
- if (!(p || lp_winbind_use_default_domain()))
- return False;
-
- if(!p && lp_winbind_use_default_domain()) {
+ if ( !p ) {
fstrcpy(user, domuser);
- fstrcpy(domain, lp_workgroup());
- } else {
+
+ if ( lp_winbind_use_default_domain() )
+ fstrcpy(domain, lp_workgroup());
+ else
+ fstrcpy( domain, "" );
+ }
+ else {
fstrcpy(user, p+1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
}
+
strupper_m(domain);
+
return True;
}