From 1a74d8d1f0758d15c5c35d20e33d9868565812cf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jan 2002 14:30:58 +0000 Subject: This is another *BIG* change... Samba now features a pluggable passdb interface, along the same lines as the one in use in the auth subsystem. In this case, only one backend may be active at a time by the 'normal' interface, and only one backend per passdb_context is permitted outside that. This pluggable interface is designed to allow any number of passdb backends to be compiled in, with the selection at runtime. The 'passdb backend' paramater has been created (and documented!) to support this. As such, configure has been modfied to allow (for example) --with-ldap and the old smbpasswd to be selected at the same time. This patch also introduces two new backends: smbpasswd_nua and tdbsam_nua. These two backends accept 'non unix accounts', where the user does *not* exist in /etc/passwd. These accounts' don't have UIDs in the unix sense, but to avoid conflicts in the algroitmic mapping of RIDs, they use the values specified in the 'non unix account range' paramter - in the same way as the winbind ranges are specifed. While I was at it, I cleaned up some of the code in pdb_tdb (code copied directly from smbpasswd and not really considered properly). Most of this was to do with % macro expansion on stored data. It isn't easy to get the macros into the tdb, and the first password change will 'expand' them. tdbsam needs to use a similar system to pdb_ldap in this regard. This patch only makes minor adjustments to pdb_nisplus and pdb_ldap, becouse I don't have the test facilities for these. I plan to incoroprate at least pdb_ldap into this scheme after consultation with Jerry. Each (converted) passdb module now no longer has any 'static' variables, and only exports 1 init function outside its .c file. The non-unix-account support in this patch has been proven! It is now possible to join a win2k machine to a Samba PDC without an account in /etc/passwd! Other changes: Minor interface adjustments: pdb_delete_sam_account() now takes a SAM_ACCOUNT, not a char*. pdb_update_sam_account() no longer takes the 'override' argument that was being ignored so often (every other passdb backend). Extra checks have been added in some places. Minor code changes: smbpasswd no longer attempts to initialise the passdb at startup, this is now done on first use. pdbedit has lost some of its 'machine account' logic, as this behaviour is now controlled by the passdb subsystem directly. The samr subsystem no longer calls 'local password change', but does the pdb interactions directly. This allow the ACB_ flags specifed to be transferred direct to the backend, without interference. Doco: I've updated the doco to reflect some of the changes, and removed some paramters no longer applicable to HEAD. (This used to be commit ff354c99c585068af6dc1ff35a1f109a806b326b) --- docs/docbook/manpages/smb.conf.5.sgml | 94 +++- docs/docbook/manpages/smbpasswd.8.sgml | 61 +-- source3/Makefile.in | 2 +- source3/acconfig.h | 4 - source3/auth/auth_unix.c | 4 +- source3/configure | 133 +++--- source3/configure.in | 19 - source3/include/config.h.in | 4 - source3/include/includes.h | 2 + source3/include/passdb.h | 67 +++ source3/param/loadparm.c | 43 +- source3/passdb/passdb.c | 80 ++-- source3/passdb/pdb_interface.c | 368 ++++++++++++++++ source3/passdb/pdb_ldap.c | 14 +- source3/passdb/pdb_nisplus.c | 16 +- source3/passdb/pdb_smbpasswd.c | 532 ++++++++++++++--------- source3/passdb/pdb_tdb.c | 421 ++++++++++-------- source3/rpc_server/srv_netlog_nt.c | 7 +- source3/rpc_server/srv_samr_nt.c | 116 +++-- source3/smbd/chgpasswd.c | 4 +- source3/tdb/tdbutil.c | 2 +- source3/utils/pdbedit.c | 61 ++- source3/utils/smbpasswd.c | 5 - testsuite/build_farm/basicsmb-domainsec-nt4.test | 10 +- testsuite/build_farm/basicsmb-domainsec.test | 11 +- testsuite/build_farm/basicsmb.smb.conf.template | 4 + 26 files changed, 1363 insertions(+), 721 deletions(-) create mode 100644 source3/passdb/pdb_interface.c diff --git a/docs/docbook/manpages/smb.conf.5.sgml b/docs/docbook/manpages/smb.conf.5.sgml index 7aa9ea3b9c..a464643234 100644 --- a/docs/docbook/manpages/smb.conf.5.sgml +++ b/docs/docbook/manpages/smb.conf.5.sgml @@ -594,6 +594,7 @@ allow trusted domains announce as announce version + auth methods auto services bind interfaces only browse list @@ -679,8 +680,8 @@ netbios name netbios scope nis homedir + non unix account range nt pipe support - nt smb support null passwords obey pam restrictions oplock break wait time @@ -688,6 +689,7 @@ os2 driver map pam password change panic action + passdb backend passwd chat passwd chat debug passwd program @@ -1205,6 +1207,24 @@ + + auth methods (G) + This option allows the administrator to chose what + authentication methods smbd will use when authenticating + a user. This option defaults to sensible values based on + security. + + Each entry in the list attempts to authenticate the user in turn, until + the user authenticates. In practice only one method will ever actually + be able to complete the authentication. + + + Default: auth methods = <empty string> + Example: auth methods = guest sam ntdomain + + + + available (S) This parameter lets you "turn off" a service. If @@ -2490,7 +2510,7 @@ file (see the smbpasswd(8) program for information on how to set up and maintain this file), or set the security = [server|domain] parameter which + linkend="SECURITY">security = [server|domain|ads] parameter which causes smbd to authenticate against another server. @@ -4918,6 +4938,40 @@ + + non unix account range (G) + The non unix account range parameter specifies + the range of 'user ids' that are allocated by the various 'non unix + account' passdb backends. These backends allow + the storage of passwords for users who don't exist in /etc/passwd. + This is most often used for machine account creation. + This range of ids should have no existing local or NIS users within + it as strange conflicts can occur otherwise. + + NOTE: These userids never appear on the system and Samba will never + 'become' these users. They are used only to ensure that the algorithmic + RID mapping does not conflict with normal users. + + Default: non unix account range = <empty string> + + + Example: non unix account range = 10000-20000 + + + + + This boolean parameter controls whether + smbd(8) will attempt to map + UNIX permissions into Windows NT access control lists. + This parameter was formally a global parameter in releases + prior to 2.2.2. + + Default: nt acl support = yes + + + + + nt acl support (S) This boolean parameter controls whether @@ -4946,27 +5000,6 @@ - - nt smb support (G) - This boolean parameter controls whether smbd(8) will negotiate NT specific SMB - support with Windows NT clients. Although this is a developer - debugging option and should be left alone, benchmarking has discovered - that Windows NT clients give faster performance with this option - set to no. This is still being investigated. - If this option is set to no then Samba offers - exactly the same SMB calls that versions prior to Samba 2.0 offered. - This information may be of use if any users are having problems - with NT SMB support. - - You should not need to ever disable this parameter. - - Default: nt smb support = yes - - - - - null passwords (G) Allow or disallow client access to accounts @@ -5191,6 +5224,21 @@ + + passdb backend (G) + This option allows the administrator to chose what + backend in which to store passwords. This allows (for example) both + smbpasswd and tdbsam to be used without a recompile. Only one can + be used at a time however, and experimental backends must still be selected + (eg --with-tdbsam) at configure time. + + + Default: passdb backend = smbpasswd + Example: passdb backend = tdbsam + + + + passwd chat (G) This string controls the "chat" diff --git a/docs/docbook/manpages/smbpasswd.8.sgml b/docs/docbook/manpages/smbpasswd.8.sgml index 098e874cc8..3c7a6a5150 100644 --- a/docs/docbook/manpages/smbpasswd.8.sgml +++ b/docs/docbook/manpages/smbpasswd.8.sgml @@ -86,9 +86,10 @@ new password typed (type <Enter> for the old password). This option is ignored if the username following already exists in the smbpasswd file and it is treated like a regular change - password command. Note that the user to be added must already exist - in the system password file (usually /etc/passwd) - else the request to add the user will fail. + password command. Note that the default passdb backends require + the user to already exist in the system password file (usually + /etc/passwd), else the request to add the + user will fail. This option is only available when running smbpasswd as root. @@ -119,8 +120,7 @@ If the smbpasswd file is in the 'old' format (pre-Samba 2.0 format) there is no space in the user's password entry to write - this information and so the user is disabled by writing 'X' characters - into the password space in the smbpasswd file. See smbpasswd(5) + this information and the command will FAIL. See smbpasswd(5) for details on the 'old' and new password file formats. @@ -138,10 +138,8 @@ the user will be able to authenticate via SMB once again. If the smbpasswd file is in the 'old' format, then - smbpasswd will prompt for a new password for this user, - otherwise the account will be enabled by removing the 'D' - flag from account control space in the - smbpasswd file. See smbpasswd (5) for + smbpasswd will FAIL to enable the account. + See smbpasswd (5) for details on the 'old' and new password file formats. This option is only available when running smbpasswd as root. @@ -274,45 +272,6 @@ - - -j DOMAIN - This option is used to add a Samba server - into a Windows NT Domain, as a Domain member capable of authenticating - user accounts to any Domain Controller in the same way as a Windows - NT Server. See the security = domain option in - the smb.conf(5) man page. - - In order to be used in this way, the Administrator for - the Windows NT Domain must have used the program "Server Manager - for Domains" to add the primary NetBIOS name of the Samba server - as a member of the Domain. - - After this has been done, to join the Domain invoke - smbpasswd with this parameter. smbpasswd will then - look up the Primary Domain Controller for the Domain (found in - the smb.conf file in the parameter - password server and change the machine account - password used to create the secure Domain communication. This - password is then stored by smbpasswd in a TDB, writeable only by root, - called secrets.tdb - - Once this operation has been performed the - smb.conf file may be updated to set the - security = domain option and all future logins - to the Samba server will be authenticated to the Windows NT - PDC. - - Note that even though the authentication is being - done to the PDC all users accessing the Samba server must still - have a valid UNIX account on that machine. - - - This option is only available when running smbpasswd as root. - - - - - -U username This option may only be used in conjunction @@ -395,7 +354,7 @@ VERSION - This man page is correct for version 2.2 of + This man page is correct for version 3.0 of the Samba suite. @@ -424,3 +383,7 @@ + + + + diff --git a/source3/Makefile.in b/source3/Makefile.in index a024ba664e..6d3a25b4d2 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -184,7 +184,7 @@ RPC_CLIENT_OBJ = rpc_client/cli_netlogon.o rpc_client/cli_pipe.o \ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o -PASSDB_OBJ = passdb/passdb.o passdb/pdb_get_set.o \ +PASSDB_OBJ = passdb/passdb.o passdb/pdb_interface.o passdb/pdb_get_set.o \ passdb/machine_sid.o passdb/pdb_smbpasswd.o \ passdb/pdb_tdb.o passdb/pdb_ldap.o \ passdb/pdb_nisplus.o diff --git a/source3/acconfig.h b/source3/acconfig.h index 5265979efb..8ebb45f3c7 100644 --- a/source3/acconfig.h +++ b/source3/acconfig.h @@ -60,9 +60,6 @@ #undef WITH_PROFILE #undef WITH_SSL #undef SSL_DIR -#undef WITH_LDAP -#undef WITH_NISPLUS -#undef WITH_TDBPWD #undef WITH_PAM #undef WITH_NISPLUS_HOME #undef WITH_AUTOMOUNT @@ -169,7 +166,6 @@ #undef HAVE_CUPS #undef WITH_LDAP_SAM #undef WITH_NISPLUS_SAM -#undef WITH_SMBPASSWD_SAM #undef WITH_TDB_SAM #undef LINUX_QUOTAS_1 #undef LINUX_QUOTAS_2 diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index 73a4c51b4f..b2e202552c 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -60,9 +60,7 @@ static BOOL update_smbpassword_file(char *user, char *password) /* Now write it into the file. */ become_root(); - /* Here, the override flag is True, because we want to ignore the - XXXXXXX'd out password */ - ret = pdb_update_sam_account (sampass, True); + ret = pdb_update_sam_account (sampass); unbecome_root(); diff --git a/source3/configure b/source3/configure index f6bf9bcc46..d0da6e0f1f 100755 --- a/source3/configure +++ b/source3/configure @@ -12368,14 +12368,10 @@ fi ## ######################################################################################## -## set the with_smbpasswd_sam as the default -with_smbpasswd_sam=yes - - ################################################# # check for a TDB password database echo $ac_n "checking whether to use TDB SAM database""... $ac_c" 1>&6 -echo "configure:12379: checking whether to use TDB SAM database" >&5 +echo "configure:12375: checking whether to use TDB SAM database" >&5 # Check whether --with-tdbsam or --without-tdbsam was given. if test "${with_tdbsam+set}" = set; then withval="$with_tdbsam" @@ -12386,7 +12382,6 @@ if test "${with_tdbsam+set}" = set; then #define WITH_TDB_SAM 1 EOF - with_smbpasswd_sam=no ;; *) echo "$ac_t""no" 1>&6 @@ -12401,7 +12396,7 @@ fi ################################################# # check for a LDAP password database echo $ac_n "checking whether to use LDAP SAM database""... $ac_c" 1>&6 -echo "configure:12405: checking whether to use LDAP SAM database" >&5 +echo "configure:12400: checking whether to use LDAP SAM database" >&5 # Check whether --with-ldapsam or --without-ldapsam was given. if test "${with_ldapsam+set}" = set; then withval="$with_ldapsam" @@ -12413,7 +12408,6 @@ if test "${with_ldapsam+set}" = set; then EOF LIBS="-lldap -llber $LIBS" - with_smbpasswd_sam=no ;; *) echo "$ac_t""no" 1>&6 @@ -12428,7 +12422,7 @@ fi ################################################# # check for a NISPLUS password database echo $ac_n "checking whether to use NISPLUS SAM database""... $ac_c" 1>&6 -echo "configure:12432: checking whether to use NISPLUS SAM database" >&5 +echo "configure:12426: checking whether to use NISPLUS SAM database" >&5 # Check whether --with-nisplussam or --without-nisplussam was given. if test "${with_nisplussam+set}" = set; then withval="$with_nisplussam" @@ -12439,7 +12433,6 @@ if test "${with_nisplussam+set}" = set; then #define WITH_NISPLUS_SAM 1 EOF - with_smbpasswd_sam=no ;; *) echo "$ac_t""no" 1>&6 @@ -12451,22 +12444,6 @@ else fi -################################################ -# This test should come last because the -# smbpasswd SAM is only used if another format -# has not been defined -echo $ac_n "checking whether to use traditional smbpasswd file""... $ac_c" 1>&6 -echo "configure:12460: checking whether to use traditional smbpasswd file" >&5 -if test $with_smbpasswd_sam = yes; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define WITH_SMBPASSWD_SAM 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi - ######################################################################################## ## ## END OF TESTS FOR SAM BACKENDS. @@ -12476,7 +12453,7 @@ fi ################################################# # check for a NISPLUS_HOME support echo $ac_n "checking whether to use NISPLUS_HOME""... $ac_c" 1>&6 -echo "configure:12480: checking whether to use NISPLUS_HOME" >&5 +echo "configure:12457: checking whether to use NISPLUS_HOME" >&5 # Check whether --with-nisplus-home or --without-nisplus-home was given. if test "${with_nisplus_home+set}" = set; then withval="$with_nisplus_home" @@ -12501,7 +12478,7 @@ fi ################################################# # check for the secure socket layer echo $ac_n "checking whether to use SSL""... $ac_c" 1>&6 -echo "configure:12505: checking whether to use SSL" >&5 +echo "configure:12482: checking whether to use SSL" >&5 # Check whether --with-ssl or --without-ssl was given. if test "${with_ssl+set}" = set; then withval="$with_ssl" @@ -12575,7 +12552,7 @@ fi ################################################# # check for syslog logging echo $ac_n "checking whether to use syslog logging""... $ac_c" 1>&6 -echo "configure:12579: checking whether to use syslog logging" >&5 +echo "configure:12556: checking whether to use syslog logging" >&5 # Check whether --with-syslog or --without-syslog was given. if test "${with_syslog+set}" = set; then withval="$with_syslog" @@ -12600,7 +12577,7 @@ fi ################################################# # check for a shared memory profiling support echo $ac_n "checking whether to use profiling""... $ac_c" 1>&6 -echo "configure:12604: checking whether to use profiling" >&5 +echo "configure:12581: checking whether to use profiling" >&5 # Check whether --with-profiling-data or --without-profiling-data was given. if test "${with_profiling_data+set}" = set; then withval="$with_profiling_data" @@ -12628,7 +12605,7 @@ fi QUOTAOBJS=smbd/noquotas.o echo $ac_n "checking whether to support disk-quotas""... $ac_c" 1>&6 -echo "configure:12632: checking whether to support disk-quotas" >&5 +echo "configure:12609: checking whether to support disk-quotas" >&5 # Check whether --with-quotas or --without-quotas was given. if test "${with_quotas+set}" = set; then withval="$with_quotas" @@ -12639,13 +12616,13 @@ if test "${with_quotas+set}" = set; then *linux*) # Check for kernel 2.4.x quota braindamage... echo $ac_n "checking for linux 2.4.x quota braindamage..""... $ac_c" 1>&6 -echo "configure:12643: checking for linux 2.4.x quota braindamage.." >&5 +echo "configure:12620: checking for linux 2.4.x quota braindamage.." >&5 if eval "test \"`echo '$''{'samba_cv_linux_2_4_quota_braindamage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12657,7 +12634,7 @@ int main() { struct mem_dqblk D; ; return 0; } EOF -if { (eval echo configure:12661: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:12638: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* samba_cv_linux_2_4_quota_braindamage=yes else @@ -12706,7 +12683,7 @@ fi # check for experimental utmp accounting echo $ac_n "checking whether to support utmp accounting""... $ac_c" 1>&6 -echo "configure:12710: checking whether to support utmp accounting" >&5 +echo "configure:12687: checking whether to support utmp accounting" >&5 # Check whether --with-utmp or --without-utmp was given. if test "${with_utmp+set}" = set; then withval="$with_utmp" @@ -12806,7 +12783,7 @@ fi ################################################# # choose native language(s) of man pages echo $ac_n "checking chosen man pages' language(s)""... $ac_c" 1>&6 -echo "configure:12810: checking chosen man pages' language(s)" >&5 +echo "configure:12787: checking chosen man pages' language(s)" >&5 # Check whether --with-manpages-langs or --without-manpages-langs was given. if test "${with_manpages_langs+set}" = set; then withval="$with_manpages_langs" @@ -12834,14 +12811,14 @@ fi ################################################# # these tests are taken from the GNU fileutils package echo "checking how to get filesystem space usage" 1>&6 -echo "configure:12838: checking how to get filesystem space usage" >&5 +echo "configure:12815: checking how to get filesystem space usage" >&5 space=no # Test for statvfs64. if test $space = no; then # SVR4 echo $ac_n "checking statvfs64 function (SVR4)""... $ac_c" 1>&6 -echo "configure:12845: checking statvfs64 function (SVR4)" >&5 +echo "configure:12822: checking statvfs64 function (SVR4)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -12849,7 +12826,7 @@ else fu_cv_sys_stat_statvfs64=cross else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:12844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_statvfs64=yes else @@ -12896,12 +12873,12 @@ fi if test $space = no; then # SVR4 echo $ac_n "checking statvfs function (SVR4)""... $ac_c" 1>&6 -echo "configure:12900: checking statvfs function (SVR4)" >&5 +echo "configure:12877: checking statvfs function (SVR4)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -12909,7 +12886,7 @@ int main() { struct statvfs fsd; statvfs (0, &fsd); ; return 0; } EOF -if { (eval echo configure:12913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12890: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* fu_cv_sys_stat_statvfs=yes else @@ -12934,7 +12911,7 @@ fi if test $space = no; then # DEC Alpha running OSF/1 echo $ac_n "checking for 3-argument statfs function (DEC OSF/1)""... $ac_c" 1>&6 -echo "configure:12938: checking for 3-argument statfs function (DEC OSF/1)" >&5 +echo "configure:12915: checking for 3-argument statfs function (DEC OSF/1)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs3_osf1'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -12942,7 +12919,7 @@ else fu_cv_sys_stat_statfs3_osf1=no else cat > conftest.$ac_ext < @@ -12955,7 +12932,7 @@ else exit (statfs (".", &fsd, sizeof (struct statfs))); } EOF -if { (eval echo configure:12959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:12936: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_statfs3_osf1=yes else @@ -12982,7 +12959,7 @@ fi if test $space = no; then # AIX echo $ac_n "checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)""... $ac_c" 1>&6 -echo "configure:12986: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5 +echo "configure:12963: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_bsize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -12990,7 +12967,7 @@ else fu_cv_sys_stat_statfs2_bsize=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:12990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_statfs2_bsize=yes else @@ -13036,7 +13013,7 @@ fi if test $space = no; then # SVR3 echo $ac_n "checking for four-argument statfs (AIX-3.2.5, SVR3)""... $ac_c" 1>&6 -echo "configure:13040: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5 +echo "configure:13017: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs4'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13044,7 +13021,7 @@ else fu_cv_sys_stat_statfs4=no else cat > conftest.$ac_ext < #include @@ -13054,7 +13031,7 @@ else exit (statfs (".", &fsd, sizeof fsd, 0)); } EOF -if { (eval echo configure:13058: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:13035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_statfs4=yes else @@ -13081,7 +13058,7 @@ fi if test $space = no; then # 4.4BSD and NetBSD echo $ac_n "checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)""... $ac_c" 1>&6 -echo "configure:13085: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5 +echo "configure:13062: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_fsize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13089,7 +13066,7 @@ else fu_cv_sys_stat_statfs2_fsize=no else cat > conftest.$ac_ext < #ifdef HAVE_SYS_PARAM_H @@ -13105,7 +13082,7 @@ else exit (statfs (".", &fsd)); } EOF -if { (eval echo configure:13109: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:13086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_statfs2_fsize=yes else @@ -13132,7 +13109,7 @@ fi if test $space = no; then # Ultrix echo $ac_n "checking for two-argument statfs with struct fs_data (Ultrix)""... $ac_c" 1>&6 -echo "configure:13136: checking for two-argument statfs with struct fs_data (Ultrix)" >&5 +echo "configure:13113: checking for two-argument statfs with struct fs_data (Ultrix)" >&5 if eval "test \"`echo '$''{'fu_cv_sys_stat_fs_data'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13140,7 +13117,7 @@ else fu_cv_sys_stat_fs_data=no else cat > conftest.$ac_ext < #ifdef HAVE_SYS_PARAM_H @@ -13160,7 +13137,7 @@ else exit (statfs (".", &fsd) != 1); } EOF -if { (eval echo configure:13164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:13141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then fu_cv_sys_stat_fs_data=yes else @@ -13193,9 +13170,9 @@ fi # file support. # echo $ac_n "checking if large file support can be enabled""... $ac_c" 1>&6 -echo "configure:13197: checking if large file support can be enabled" >&5 +echo "configure:13174: checking if large file support can be enabled" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13189: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* samba_cv_HAVE_EXPLICIT_LARGEFILE_SUPPORT=yes else @@ -13273,7 +13250,7 @@ fi # check for ACL support echo $ac_n "checking whether to support ACLs""... $ac_c" 1>&6 -echo "configure:13277: checking whether to support ACLs" >&5 +echo "configure:13254: checking whether to support ACLs" >&5 # Check whether --with-acl-support or --without-acl-support was given. if test "${with_acl_support+set}" = set; then withval="$with_acl_support" @@ -13326,7 +13303,7 @@ EOF ;; *) echo $ac_n "checking for acl_get_file in -lacl""... $ac_c" 1>&6 -echo "configure:13330: checking for acl_get_file in -lacl" >&5 +echo "configure:13307: checking for acl_get_file in -lacl" >&5 ac_lib_var=`echo acl'_'acl_get_file | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -13334,7 +13311,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lacl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -13373,13 +13350,13 @@ else fi echo $ac_n "checking for ACL support""... $ac_c" 1>&6 -echo "configure:13377: checking for ACL support" >&5 +echo "configure:13354: checking for ACL support" >&5 if eval "test \"`echo '$''{'samba_cv_HAVE_POSIX_ACLS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -13387,7 +13364,7 @@ int main() { acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p); ; return 0; } EOF -if { (eval echo configure:13391: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13368: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* samba_cv_HAVE_POSIX_ACLS=yes else @@ -13407,13 +13384,13 @@ echo "$ac_t""$samba_cv_HAVE_POSIX_ACLS" 1>&6 EOF echo $ac_n "checking for acl_get_perm_np""... $ac_c" 1>&6 -echo "configure:13411: checking for acl_get_perm_np" >&5 +echo "configure:13388: checking for acl_get_perm_np" >&5 if eval "test \"`echo '$''{'samba_cv_HAVE_ACL_GET_PERM_NP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -13421,7 +13398,7 @@ int main() { acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm); ; return 0; } EOF -if { (eval echo configure:13425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* samba_cv_HAVE_ACL_GET_PERM_NP=yes else @@ -13468,7 +13445,7 @@ fi # (WINBIND_STARGETS) and shared libraries (WINBIND_LTARGETS). echo $ac_n "checking whether to build winbind""... $ac_c" 1>&6 -echo "configure:13472: checking whether to build winbind" >&5 +echo "configure:13449: checking whether to build winbind" >&5 # Initially, the value of $host_os decides whether winbind is supported @@ -13557,7 +13534,7 @@ fi if test x"$INCLUDED_POPT" != x"yes"; then echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6 -echo "configure:13561: checking for poptGetContext in -lpopt" >&5 +echo "configure:13538: checking for poptGetContext in -lpopt" >&5 ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -13565,7 +13542,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpopt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13557: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -13600,7 +13577,7 @@ fi fi echo $ac_n "checking whether to use included popt""... $ac_c" 1>&6 -echo "configure:13604: checking whether to use included popt" >&5 +echo "configure:13581: checking whether to use included popt" >&5 if test x"$INCLUDED_POPT" = x"yes"; then echo "$ac_t""$srcdir/popt" 1>&6 BUILD_POPT='$(POPT_OBJS)' @@ -13620,11 +13597,11 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:13605: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "configure OK"; else diff --git a/source3/configure.in b/source3/configure.in index 9bf64384e1..9b2f950b9c 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1911,10 +1911,6 @@ fi ## ######################################################################################## -## set the with_smbpasswd_sam as the default -with_smbpasswd_sam=yes - - ################################################# # check for a TDB password database AC_MSG_CHECKING(whether to use TDB SAM database) @@ -1924,7 +1920,6 @@ AC_ARG_WITH(tdbsam, yes) AC_MSG_RESULT(yes) AC_DEFINE(WITH_TDB_SAM) - with_smbpasswd_sam=no ;; *) AC_MSG_RESULT(no) @@ -1943,7 +1938,6 @@ AC_ARG_WITH(ldapsam, AC_MSG_RESULT(yes) AC_DEFINE(WITH_LDAP_SAM) LIBS="-lldap -llber $LIBS" - with_smbpasswd_sam=no ;; *) AC_MSG_RESULT(no) @@ -1961,7 +1955,6 @@ AC_ARG_WITH(nisplussam, yes) AC_MSG_RESULT(yes) AC_DEFINE(WITH_NISPLUS_SAM) - with_smbpasswd_sam=no ;; *) AC_MSG_RESULT(no) @@ -1970,18 +1963,6 @@ AC_ARG_WITH(nisplussam, AC_MSG_RESULT(no) ) -################################################ -# This test should come last because the -# smbpasswd SAM is only used if another format -# has not been defined -AC_MSG_CHECKING(whether to use traditional smbpasswd file) -if test $with_smbpasswd_sam = yes; then - AC_MSG_RESULT(yes) - AC_DEFINE(WITH_SMBPASSWD_SAM) -else - AC_MSG_RESULT(no) -fi - ######################################################################################## ## ## END OF TESTS FOR SAM BACKENDS. diff --git a/source3/include/config.h.in b/source3/include/config.h.in index fe4ff0df38..310ef32b2f 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -126,9 +126,6 @@ #undef WITH_PROFILE #undef WITH_SSL #undef SSL_DIR -#undef WITH_LDAP -#undef WITH_NISPLUS -#undef WITH_TDBPWD #undef WITH_PAM #undef WITH_NISPLUS_HOME #undef WITH_AUTOMOUNT @@ -235,7 +232,6 @@ #undef HAVE_CUPS #undef WITH_LDAP_SAM #undef WITH_NISPLUS_SAM -#undef WITH_SMBPASSWD_SAM #undef WITH_TDB_SAM #undef LINUX_QUOTAS_1 #undef LINUX_QUOTAS_2 diff --git a/source3/include/includes.h b/source3/include/includes.h index 0ea387c19c..7f913ba830 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -735,6 +735,8 @@ extern int errno; #include "auth.h" +#include "passdb.h" + #include "session.h" #include "asn_1.h" diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 4e50ff7da5..178b3a4359 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -24,5 +24,72 @@ #define _PASSDB_H +/***************************************************************** + Functions to be implemented by the new (v2) passdb API +****************************************************************/ + +typedef struct pdb_context +{ + struct pdb_methods *pdb_selected; + + /* These functions are wrappers for the functions listed above. + They may do extra things like re-reading a SAM_ACCOUNT on update */ + + BOOL (*pdb_setsampwent)(struct pdb_context *, BOOL update); + + void (*pdb_endsampwent)(struct pdb_context *); + + BOOL (*pdb_getsampwent)(struct pdb_context *, SAM_ACCOUNT *user); + + BOOL (*pdb_getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username); + + BOOL (*pdb_getsampwrid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, uint32 rid); + + BOOL (*pdb_add_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass); + + BOOL (*pdb_update_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass); + + BOOL (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username); + + void (*free_fn)(struct pdb_context **); + + TALLOC_CTX *mem_ctx; + +} PDB_CONTEXT; + +typedef struct pdb_methods +{ + char *name; /* What name got this module */ + + BOOL (*setsampwent)(struct pdb_context *, BOOL update); + + void (*endsampwent)(struct pdb_context *); + + BOOL (*getsampwent)(struct pdb_context *, SAM_ACCOUNT *user); + + BOOL (*getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username); + + BOOL (*getsampwrid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, uint32 rid); + + BOOL (*add_sam_account)(struct pdb_context *, const SAM_ACCOUNT *sampass); + + BOOL (*update_sam_account)(struct pdb_context *, const SAM_ACCOUNT *sampass); + + BOOL (*delete_sam_account)(struct pdb_context *, const SAM_ACCOUNT *username); + + void *private_data; /* Private data of some kind */ + + void (*free_private_data)(void **); + +} PDB_METHODS; + + +struct pdb_init_function { + char *name; + /* Function to create a member of the authmethods list */ + NTSTATUS (*init)(struct pdb_context *pdb_context, + struct pdb_methods **pdb_method, + const char *location); +}; #endif /* _PASSDB_H */ diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index fce5fcde49..af8a5df897 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -111,6 +111,7 @@ typedef struct char *szSMBPasswdFile; char *szPrivateDir; char *szPassdbModulePath; + char *szPassdbBackend; char *szPasswordServer; char *szSocketOptions; char *szWorkGroup; @@ -150,6 +151,7 @@ typedef struct char *szSourceEnv; char *szWinbindUID; char *szWinbindGID; + char *szNonUnixAccountRange; char *szTemplateHomedir; char *szTemplateShell; char *szWinbindSeparator; @@ -525,6 +527,7 @@ static BOOL handle_source_env(char *pszParmValue, char **ptr); static BOOL handle_netbios_name(char *pszParmValue, char **ptr); static BOOL handle_winbind_uid(char *pszParmValue, char **ptr); static BOOL handle_winbind_gid(char *pszParmValue, char **ptr); +static BOOL handle_non_unix_account_range(char *pszParmValue, char **ptr); static BOOL handle_wins_server_list(char *pszParmValue, char **ptr); static BOOL handle_debug_list( char *pszParmValue, char **ptr ); @@ -693,6 +696,8 @@ static struct parm_struct parm_table[] = { {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, 0}, {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, 0}, {"passdb module path", P_STRING, P_GLOBAL, &Globals.szPassdbModulePath, NULL, NULL, 0}, + {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, 0}, + {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, 0}, {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0}, {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0}, {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0}, @@ -1200,6 +1205,7 @@ static void init_globals(void) string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE); string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR); string_set(&Globals.szPassdbModulePath, ""); + string_set(&Globals.szPassdbBackend, "smbpasswd"); string_set(&Globals.szGuestaccount, GUEST_ACCOUNT); @@ -1454,6 +1460,7 @@ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile) FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile) FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir) FN_GLOBAL_STRING(lp_passdb_module_path, &Globals.szPassdbModulePath) +FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend) FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString) FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname) FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand) @@ -2444,7 +2451,7 @@ static BOOL handle_copy(char *pszParmValue, char **ptr) } /*************************************************************************** - Handle winbind uid and gid allocation parameters. The format of these + Handle winbind/non unix account uid and gid allocation parameters. The format of these parameters is: [global] @@ -2461,6 +2468,7 @@ static BOOL handle_copy(char *pszParmValue, char **ptr) static uid_t winbind_uid_low, winbind_uid_high; static gid_t winbind_gid_low, winbind_gid_high; +static uint32 non_unix_account_low, non_unix_account_high; BOOL lp_winbind_uid(uid_t *low, uid_t *high) { @@ -2490,6 +2498,20 @@ BOOL lp_winbind_gid(gid_t *low, gid_t *high) return True; } +BOOL lp_non_unix_account_range(uint32 *low, uint32 *high) +{ + if (non_unix_account_low == 0 || non_unix_account_high == 0) + return False; + + if (low) + *low = non_unix_account_low; + + if (high) + *high = non_unix_account_high; + + return True; +} + /* Do some simple checks on "winbind [ug]id" parameter values */ static BOOL handle_winbind_uid(char *pszParmValue, char **ptr) @@ -2526,6 +2548,25 @@ static BOOL handle_winbind_gid(char *pszParmValue, char **ptr) return True; } +/* Do some simple checks on "non unix account range" parameter values */ + +static BOOL handle_non_unix_account_range(char *pszParmValue, char **ptr) +{ + uint32 low, high; + + if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low) + return False; + + /* Parse OK */ + + string_set(ptr, pszParmValue); + + non_unix_account_low = low; + non_unix_account_high = high; + + return True; +} + /*************************************************************************** Handle the WINS SERVER list ***************************************************************************/ diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 4460af0545..2bb4ee0a75 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -32,28 +32,6 @@ extern DOM_SID global_sam_sid; -struct passdb_ops *pdb_ops; - -#if 0 /* JERRY */ -static void* pdb_handle = NULL; -#endif - -/*************************************************************** - Initialize the password db operations. -***************************************************************/ - -BOOL initialize_password_db(BOOL reload) -{ - /* - * This function is unfinished right now, so just - * ignore the details and always return True. It - * is here only as a placeholder --jerry - */ - return True; - -} - - /************************************************************ Fill the SAM_ACCOUNT with default values. ***********************************************************/ @@ -639,6 +617,7 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, DOM_SID local_sid; fstring user; fstring domain; + SAM_ACCOUNT *sam_account = NULL; *psid_name_use = SID_NAME_UNKNOWN; @@ -671,9 +650,20 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, (void)map_username(user); - if((pass = Get_Pwnam(user))) { + if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { + return False; + } + + if (pdb_getsampwnam(sam_account, user)) { + sid_append_rid( &local_sid, pdb_get_user_rid(sam_account)); + *psid_name_use = SID_NAME_USER; + pdb_free_sam(&sam_account); + + } else if((pass = Get_Pwnam(user))) { sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid)); *psid_name_use = SID_NAME_USER; + pdb_free_sam(&sam_account); + } else { /* * Maybe it was a group ? @@ -681,6 +671,8 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, struct group *grp; GROUP_MAP map; + pdb_free_sam(&sam_account); + /* check if it's a mapped group */ if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { if (map.gid!=-1) { @@ -1021,29 +1013,33 @@ BOOL local_password_change(const char *user_name, int local_flags, pdb_free_sam(&sam_pass); if (local_flags & LOCAL_ADD_USER) { - /* - * Check for a local account - if we're adding only. - */ - - if(!(pwd = getpwnam_alloc(user_name))) { - slprintf(err_str, err_str_len - 1, "User %s does not \ -exist in system password file (usually /etc/passwd). Cannot add \ -account without a valid local system user.\n", user_name); - return False; - } + pwd = getpwnam_alloc(user_name); } else { slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name); return False; } - - if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){ - slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); + + if (pwd) { + /* Local user found, so init from this */ + if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){ + slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); + passwd_free(&pwd); + return False; + } + passwd_free(&pwd); - return False; + } else { + if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_pass))){ + slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); + return False; + } + + if (!pdb_set_username(sam_pass, user_name)) { + slprintf(err_str, err_str_len - 1, "Failed to set username for user %s.\n", user_name); + pdb_free_sam(&sam_pass); + return False; + } } - - passwd_free(&pwd); - if (local_flags & LOCAL_TRUST_ACCOUNT) { if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST)) { slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name); @@ -1135,14 +1131,14 @@ account without a valid local system user.\n", user_name); return False; } } else if (local_flags & LOCAL_DELETE_USER) { - if (!pdb_delete_sam_account(user_name)) { + if (!pdb_delete_sam_account(sam_pass)) { slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name); pdb_free_sam(&sam_pass); return False; } slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name); } else { - if(!pdb_update_sam_account(sam_pass, True)) { + if(!pdb_update_sam_account(sam_pass)) { slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name); pdb_free_sam(&sam_pass); return False; diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c new file mode 100644 index 0000000000..b5e7273520 --- /dev/null +++ b/source3/passdb/pdb_interface.c @@ -0,0 +1,368 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Password and authentication handling + Copyright (C) Andrew Bartlett 2002 + + 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 "includes.h" + +/** List of various built-in passdb modules */ + +const struct pdb_init_function builtin_pdb_init_functions[] = { + { "smbpasswd", pdb_init_smbpasswd }, + { "smbpasswd_nua", pdb_init_smbpasswd_nua }, + { "tdbsam", pdb_init_tdbsam }, + { "tdbsam_nua", pdb_init_tdbsam_nua }, +#if 0 + { "ldap", pdb_init_ldap }, + { "nisplus", pdb_init_nisplus }, + { "unix", pdb_init_unix }, +#endif + { NULL, NULL} +}; + +static BOOL context_setsampwent(struct pdb_context *context, BOOL update) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_selected->setsampwent(context, update); +} + +static void context_endsampwent(struct pdb_context *context) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return; + } + + context->pdb_selected->endsampwent(context); +} + +static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_selected->getsampwent(context, user); +} + +static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_selected->getsampwnam(context, sam_acct, username); +} + +static BOOL context_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, uint32 rid) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_selected->getsampwrid(context, sam_acct, rid); +} + +static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + /** @todo This is where a 're-read on add' should be done */ + + return context->pdb_selected->add_sam_account(context, sam_acct); +} + +static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + /** @todo This is where a 're-read on update' should be done */ + + return context->pdb_selected->update_sam_account(context, sam_acct); +} + +static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) +{ + if ((!context) || (!context->pdb_selected)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_selected->delete_sam_account(context, sam_acct); +} + +static void free_pdb_context(struct pdb_context **context) +{ + if (((*context)->pdb_selected) && ((*context)->pdb_selected->free_private_data)) { + (*context)->pdb_selected->free_private_data((*context)->pdb_selected->private_data); + } + + talloc_destroy((*context)->mem_ctx); + *context = NULL; +} + +/****************************************************************** + Make a pdb_context from scratch. +*******************************************************************/ + +static NTSTATUS make_pdb_context(struct pdb_context **context) +{ + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init_named("pdb_context internal allocation context"); + + if (!mem_ctx) { + DEBUG(0, ("make_pdb_context: talloc init failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + *context = talloc(mem_ctx, sizeof(**context)); + if (!*context) { + DEBUG(0, ("make_pdb_context: talloc failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCTP(*context); + + (*context)->mem_ctx = mem_ctx; + + (*context)->pdb_setsampwent = context_setsampwent; + (*context)->pdb_endsampwent = context_endsampwent; + (*context)->pdb_getsampwent = context_getsampwent; + (*context)->pdb_getsampwnam = context_getsampwnam; + (*context)->pdb_getsampwrid = context_getsampwrid; + (*context)->pdb_add_sam_account = context_add_sam_account; + (*context)->pdb_update_sam_account = context_update_sam_account; + (*context)->pdb_delete_sam_account = context_delete_sam_account; + + (*context)->free_fn = free_pdb_context; + + return NT_STATUS_OK; +} + + +/****************************************************************** + Make a pdb_context, given a text string. +*******************************************************************/ + +NTSTATUS make_pdb_context_name(struct pdb_context **context, char *selected) +{ + /* HINT: Don't store 'selected' becouse its often an lp_ string and will 'go away' */ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + int i; + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) { + return nt_status; + } + + DEBUG(5,("Attempting to find an passdb backend to match %s\n", selected)); + for (i = 0; builtin_pdb_init_functions[i].name; i++) + { + if (strequal(builtin_pdb_init_functions[i].name, selected)) + { + DEBUG(5,("Found pdb backend %s (at pos %d)\n", selected, i)); + if (NT_STATUS_IS_OK(nt_status + = builtin_pdb_init_functions[i].init(*context, &(*context)->pdb_selected, NULL))) { + DEBUG(5,("pdb backend %s has a valid init\n", selected)); + (*context)->pdb_selected->name = builtin_pdb_init_functions[i].name; + } else { + DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, get_nt_error_msg(nt_status))); + (*context)->pdb_selected = NULL; + } + break; + } + } + + if (!(*context)->pdb_selected) { + DEBUG(0,("failed to select passdb backed!\n")); + talloc_destroy((*context)->mem_ctx); + *context = NULL; + return nt_status; + } + + return NT_STATUS_OK; +} + + +/****************************************************************** + Return an already initilised pdb_context, to facilitate backward + compatiablity (see functions below). +*******************************************************************/ + +static struct pdb_context *pdb_get_static_context(BOOL reload) +{ + static struct pdb_context *pdb_context = NULL; + + if ((pdb_context) && (reload)) { + pdb_context->free_fn(&pdb_context); + if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) { + return NULL; + } + } + + if (!pdb_context) { + if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) { + return NULL; + } + } + + return pdb_context; +} + +#if !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) + +/****************************************************************** + Backward compatability functions for the original passdb interface +*******************************************************************/ + +BOOL pdb_setsampwent(BOOL update) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_setsampwent(pdb_context, update); +} + +void pdb_endsampwent(void) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return; + } + + pdb_context->pdb_endsampwent(pdb_context); +} + +BOOL pdb_getsampwent(SAM_ACCOUNT *user) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_getsampwent(pdb_context, user); +} + +BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username); +} + +BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_getsampwrid(pdb_context, sam_acct, rid); +} + +BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_add_sam_account(pdb_context, sam_acct); +} + +BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_update_sam_account(pdb_context, sam_acct); +} + +BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct); +} + +#endif /* !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) */ + +/*************************************************************** + Initialize the static context (at smbd startup etc). + + If uninitialised, context will auto-init on first use. +***************************************************************/ + +BOOL initialize_password_db(BOOL reload) +{ + return (pdb_get_static_context(reload) != NULL); +} + + +NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) +{ + *methods = talloc(mem_ctx, sizeof(struct pdb_methods)); + + if (!*methods) { + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCTP(*methods); + + return NT_STATUS_OK; +} + + + + + + + + diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index b687f494cc..4e602cae40 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -840,14 +840,22 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) /********************************************************************** Delete entry from LDAP for username *********************************************************************/ -BOOL pdb_delete_sam_account(const char *sname) +BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct) { + const char *sname; int rc; char *dn; LDAP *ldap_struct; LDAPMessage *entry; LDAPMessage *result; + if (!sam_acct) { + DEBUG(0, ("sam_acct was NULL!\n")); + return False; + } + + sname = pdb_get_username(sam_acct); + if (!ldap_open_connection (&ldap_struct)) return False; @@ -891,7 +899,7 @@ BOOL pdb_delete_sam_account(const char *sname) /********************************************************************** Update SAM_ACCOUNT *********************************************************************/ -BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override) +BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) { int rc; char *dn; @@ -952,7 +960,7 @@ BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override) /********************************************************************** Add SAM_ACCOUNT to LDAP *********************************************************************/ -BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd) +BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) { int rc; pstring filter; diff --git a/source3/passdb/pdb_nisplus.c b/source3/passdb/pdb_nisplus.c index 446ba0ce39..687115733a 100644 --- a/source3/passdb/pdb_nisplus.c +++ b/source3/passdb/pdb_nisplus.c @@ -1039,14 +1039,22 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) /************************************************************************* Routine to remove entry from the nisplus smbpasswd table *************************************************************************/ -BOOL pdb_delete_sam_account(const char *sname) +BOOL pdb_delete_sam_account(SAM_ACCOUNT * user) { + const char *sname; char *pfile = lp_smb_passwd_file(); pstring nisname; nis_result *result, *delresult; nis_object *obj; int i; - + + if (!user) { + DEBUG(0, ("no SAM_ACCOUNT specified!\n")); + return False; + } + + suser = pdb_get_username(user); + if (!*pfile) { DEBUG(0, ("no SMB password file set\n")); @@ -1095,7 +1103,7 @@ BOOL pdb_delete_sam_account(const char *sname) /************************************************************************ Routine to add an entry to the nisplus passwd file. *************************************************************************/ -BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd) +BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) { int local_user = 0; char *pfile; @@ -1290,7 +1298,7 @@ BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd) /************************************************************************ Routine to modify the nisplus passwd entry. ************************************************************************/ -BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override) +BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) { nis_result *result, *addresult; nis_object *obj; diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index a464312ad6..3039e6681c 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -4,6 +4,7 @@ * Copyright (C) Andrew Tridgell 1992-1998 * Modified by Jeremy Allison 1995. * Modified by Gerald (Jerry) Carter 2000-2001 + * Modified by Andrew Bartlett 2002. * * 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 @@ -22,8 +23,6 @@ #include "includes.h" -#ifdef WITH_SMBPASSWD_SAM - /* smb_passwd is analogous to sam_passwd used everywhere @@ -33,7 +32,8 @@ struct smb_passwd { - uid_t smb_userid; /* this is actually the unix uid_t */ + BOOL smb_userid_set; /* this is actually the unix uid_t */ + uint32 smb_userid; /* this is actually the unix uid_t */ const char *smb_name; /* username string */ const unsigned char *smb_passwd; /* Null if no password */ @@ -43,13 +43,29 @@ struct smb_passwd time_t pass_last_set_time; /* password last set time */ }; +struct smbpasswd_privates +{ + /* used for maintain locks on the smbpasswd file */ + int pw_file_lock_depth; + + /* Global File pointer */ + FILE *pw_file; + + /* formerly static variables */ + struct smb_passwd pw_buf; + pstring user_name; + unsigned char smbpwd[16]; + unsigned char smbntpwd[16]; -extern struct passdb_ops pdb_ops; + /* retrive-once info */ + const char *smbpasswd_file; -/* used for maintain locks on the smbpasswd file */ -static int pw_file_lock_depth; -static void *global_vp; + BOOL permit_non_unix_accounts; + uint32 low_nua_userid; + uint32 high_nua_userid; + +}; enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE }; @@ -116,7 +132,7 @@ static void pdb_init_smb(struct smb_passwd *user) been granted to prevent race conditions. JRA. ****************************************************************/ -static void *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth) +static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth) { FILE *fp = NULL; const char *open_mode = NULL; @@ -238,15 +254,14 @@ Error was %s\n.", pfile, strerror(errno) )); } /* We have a lock on the file. */ - return (void *)fp; + return fp; } /*************************************************************** End enumeration of the smbpasswd list. ****************************************************************/ -static void endsmbfilepwent(void *vp, int *lock_depth) +static void endsmbfilepwent(FILE *fp, int *lock_depth) { - FILE *fp = (FILE *)vp; pw_file_unlock(fileno(fp), lock_depth); fclose(fp); @@ -257,14 +272,13 @@ static void endsmbfilepwent(void *vp, int *lock_depth) Routine to return the next entry in the smbpasswd list. *************************************************************************/ -static struct smb_passwd *getsmbfilepwent(void *vp) +static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp) { /* Static buffers we will return. */ - static struct smb_passwd pw_buf; - static pstring user_name; - static unsigned char smbpwd[16]; - static unsigned char smbntpwd[16]; - FILE *fp = (FILE *)vp; + struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf; + char *user_name = smbpasswd_state->user_name; + unsigned char *smbpwd = smbpasswd_state->smbpwd; + unsigned char *smbntpwd = smbpasswd_state->smbntpwd; char linebuf[256]; unsigned char c; unsigned char *p; @@ -276,9 +290,9 @@ static struct smb_passwd *getsmbfilepwent(void *vp) return NULL; } - pdb_init_smb(&pw_buf); + pdb_init_smb(pw_buf); - pw_buf.acct_ctrl = ACB_NORMAL; + pw_buf->acct_ctrl = ACB_NORMAL; /* * Scan the file, a line at a time and check if the name matches. @@ -370,8 +384,8 @@ static struct smb_passwd *getsmbfilepwent(void *vp) continue; } - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; + pw_buf->smb_name = user_name; + pw_buf->smb_userid = uidval; /* * Now get the password value - this should be 32 hex digits @@ -385,10 +399,10 @@ static struct smb_passwd *getsmbfilepwent(void *vp) if (*p == '*' || *p == 'X') { /* Password deliberately invalid - end here. */ DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name)); - pw_buf.smb_nt_passwd = NULL; - pw_buf.smb_passwd = NULL; - pw_buf.acct_ctrl |= ACB_DISABLED; - return &pw_buf; + pw_buf->smb_nt_passwd = NULL; + pw_buf->smb_passwd = NULL; + pw_buf->acct_ctrl |= ACB_DISABLED; + return pw_buf; } if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { @@ -402,28 +416,28 @@ static struct smb_passwd *getsmbfilepwent(void *vp) } if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { - pw_buf.smb_passwd = NULL; - pw_buf.acct_ctrl |= ACB_PWNOTREQ; + pw_buf->smb_passwd = NULL; + pw_buf->acct_ctrl |= ACB_PWNOTREQ; } else { if (!pdb_gethexpwd((char *)p, smbpwd)) { DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); continue; } - pw_buf.smb_passwd = smbpwd; + pw_buf->smb_passwd = smbpwd; } /* * Now check if the NT compatible password is * available. */ - pw_buf.smb_nt_passwd = NULL; + pw_buf->smb_nt_passwd = NULL; p += 33; /* Move to the first character of the line after the lanman password. */ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { if (*p != '*' && *p != 'X') { if(pdb_gethexpwd((char *)p,smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; + pw_buf->smb_nt_passwd = smbntpwd; } p += 33; /* Move to the first character of the line after the NT password. */ @@ -435,11 +449,11 @@ static struct smb_passwd *getsmbfilepwent(void *vp) if (*p == '[') { unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']'); - pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p); + pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p); /* Must have some account type set. */ - if(pw_buf.acct_ctrl == 0) - pw_buf.acct_ctrl = ACB_NORMAL; + if(pw_buf->acct_ctrl == 0) + pw_buf->acct_ctrl = ACB_NORMAL; /* Now try and get the last change time. */ if(end_p) @@ -459,7 +473,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp) * read into a time_t as the seconds since * 1970 that the password was last changed. */ - pw_buf.pass_last_set_time = (time_t)strtol((char *)p, NULL, 16); + pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16); } } } @@ -470,13 +484,13 @@ static struct smb_passwd *getsmbfilepwent(void *vp) * password file as 'normal accounts'. If this changes * we will have to fix this code. JRA. */ - if(pw_buf.smb_name[strlen(pw_buf.smb_name) - 1] == '$') { - pw_buf.acct_ctrl &= ~ACB_NORMAL; - pw_buf.acct_ctrl |= ACB_WSTRUST; + if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') { + pw_buf->acct_ctrl &= ~ACB_NORMAL; + pw_buf->acct_ctrl |= ACB_WSTRUST; } } - return &pw_buf; + return pw_buf; } DEBUG(5,("getsmbfilepwent: end of file reached.\n")); @@ -547,9 +561,9 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd) Routine to add an entry to the smbpasswd file. *************************************************************************/ -static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd) +static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd) { - char *pfile = lp_smb_passwd_file(); + const char *pfile = smbpasswd_state->smbpasswd_file; struct smb_passwd *pwd = NULL; FILE *fp = NULL; int wr_len; @@ -557,13 +571,14 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd) size_t new_entry_length; char *new_entry; SMB_OFF_T offpos; - + uint32 max_found_uid = 0; + /* Open the smbpassword file - for update. */ - fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth); + fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL && errno == ENOENT) { /* Try again - create. */ - fp = startsmbfilepwent(pfile, PWF_CREATE, &pw_file_lock_depth); + fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth)); } if (fp == NULL) { @@ -575,18 +590,45 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd) * Scan the file, a line at a time and check if the name matches. */ - while ((pwd = getsmbfilepwent(fp)) != NULL) + while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) { if (strequal(newpwd->smb_name, pwd->smb_name)) { DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name)); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); return False; } - } + + /* Look for a free uid for use in non-unix accounts */ + if (pwd->smb_userid > max_found_uid) { + max_found_uid = pwd->smb_userid; + } + } /* Ok - entry doesn't exist. We can add it */ + /* Account not in /etc/passwd hack!!! */ + if (!newpwd->smb_userid_set) { + if (!smbpasswd_state->permit_non_unix_accounts) { + DEBUG(0, ("add_smbfilepwd_entry: cannot add account %s without unix identity\n", pwd->smb_name)); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); + return False; + } + + if (max_found_uid < smbpasswd_state->low_nua_userid) { + newpwd->smb_userid = smbpasswd_state->low_nua_userid; + newpwd->smb_userid_set = True; + } else if (max_found_uid >= smbpasswd_state->high_nua_userid) { + DEBUG(0, ("add_smbfilepwd_entry: cannot add machine %s, no uids are free! \n", newpwd->smb_name)); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); + return False; + } else { + newpwd->smb_userid = max_found_uid + 1; + newpwd->smb_userid_set = True; + } + } + + /* Create a new smb passwd entry and set it to the given password. */ /* * The add user write needs to be atomic - so get the fd from @@ -598,7 +640,7 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd) { DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); return False; } @@ -606,7 +648,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); { DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); return False; } @@ -630,13 +672,13 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", newpwd->smb_name, strerror(errno))); } - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); free(new_entry); return False; } free(new_entry); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); return True; } @@ -649,10 +691,10 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", override = True, override XXXXXXXX'd out password or NO PASS ************************************************************************/ -static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) +static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd) { /* Static buffers we will return. */ - static pstring user_name; + char * user_name = smbpasswd_state->user_name; char linebuf[256]; char readbuf[1024]; @@ -663,7 +705,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) size_t linebuf_len = 0; FILE *fp; int lockfd; - char *pfile = lp_smb_passwd_file(); + const char *pfile = smbpasswd_state->smbpasswd_file; BOOL found_entry = False; BOOL got_pass_last_set_time = False; @@ -690,7 +732,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) lockfd = fileno(fp); - if (!pw_file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) { + if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) { DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile)); fclose(fp); return False; @@ -710,7 +752,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) fgets(linebuf, sizeof(linebuf), fp); if (ferror(fp)) { - pw_file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -779,7 +821,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) } if (!found_entry) { - pw_file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -791,7 +833,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) if (!isdigit(*p)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n")); - pw_file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -800,7 +842,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) p++; if (*p != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n")); - pw_file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -815,30 +857,16 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) /* Record exact password position */ pwd_seekpos += PTR_DIFF(p, linebuf); - if (!override && (*p == '*' || *p == 'X')) { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("mod_smbfilepwd_entry: entry invalidated for user %s\n", user_name)); - pw_file_unlock(lockfd, &pw_file_lock_depth); - fclose(fp); - return False; - } - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n")); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return (False); } if (p[32] != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n")); - pw_file_unlock(lockfd,&pw_file_lock_depth); - fclose(fp); - return False; - } - - if (!override && (*p == '*' || *p == 'X')) { - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -849,14 +877,14 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) the lanman password. */ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n")); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return (False); } if (p[32] != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n")); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -966,7 +994,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) if(wr_len > sizeof(linebuf)) { DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return (False); } @@ -984,7 +1012,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) { DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } @@ -992,33 +1020,33 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) /* Sanity check - ensure the areas we are writing are framed by ':' */ if (read(fd, linebuf, wr_len+1) != wr_len+1) { DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) { DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) { DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } if (write(fd, ascii_p16, wr_len) != wr_len) { DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile)); - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return False; } - pw_file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth)); fclose(fp); return True; } @@ -1027,9 +1055,9 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override) Routine to delete an entry in the smbpasswd file by name. *************************************************************************/ -static BOOL del_smbfilepwd_entry(const char *name) +static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name) { - char *pfile = lp_smb_passwd_file(); + const char *pfile = smbpasswd_state->smbpasswd_file; pstring pfile2; struct smb_passwd *pwd = NULL; FILE *fp = NULL; @@ -1044,7 +1072,7 @@ static BOOL del_smbfilepwd_entry(const char *name) * it. */ - if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth)) == NULL) { + if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) { DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile)); return False; } @@ -1054,7 +1082,7 @@ static BOOL del_smbfilepwd_entry(const char *name) */ if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) { DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile)); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); return False; } @@ -1062,7 +1090,7 @@ static BOOL del_smbfilepwd_entry(const char *name) * Scan the file, a line at a time and check if the name matches. */ - while ((pwd = getsmbfilepwent(fp)) != NULL) { + while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) { char *new_entry; size_t new_entry_length; @@ -1080,7 +1108,7 @@ static BOOL del_smbfilepwd_entry(const char *name) DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); endsmbfilepwent(fp_write, &pfile2_lockdepth); return False; } @@ -1092,7 +1120,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); endsmbfilepwent(fp_write, &pfile2_lockdepth); free(new_entry); return False; @@ -1108,7 +1136,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); if(fflush(fp_write) != 0) { DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno))); - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); endsmbfilepwent(fp_write,&pfile2_lockdepth); return False; } @@ -1121,7 +1149,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); } - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); endsmbfilepwent(fp_write,&pfile2_lockdepth); return True; } @@ -1134,21 +1162,27 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass) { uid_t uid; - gid_t gid; if (sampass == NULL) return False; - uid = pdb_get_uid(sampass); - gid = pdb_get_gid(sampass); - if (!IS_SAM_UNIX_USER(sampass)) { - DEBUG(0,("build_sam_pass: Failing attempt to store user without a UNIX uid or gid. \n")); - return False; - } + ZERO_STRUCTP(smb_pw); + + if (!IS_SAM_UNIX_USER(sampass)) { + smb_pw->smb_userid_set = False; + DEBUG(5,("build_sam_pass: storing user without a UNIX uid or gid. \n")); + } else { + smb_pw->smb_userid_set = True; + uid = pdb_get_uid(sampass); - ZERO_STRUCTP(smb_pw); + if (uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) { + DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); + return False; + } + + smb_pw->smb_userid=uid; + } - smb_pw->smb_userid=uid; smb_pw->smb_name=(const char*)pdb_get_username(sampass); smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass); @@ -1157,11 +1191,6 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass); smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass); - if (uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) { - DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); - return False; - } - #if 0 /* * ifdef'out by JFM on 11/29/2001. @@ -1187,7 +1216,7 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas /********************************************************************* Create a SAM_ACCOUNT from a smb_passwd struct ********************************************************************/ -static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) +static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) { struct passwd *pwfile; @@ -1196,34 +1225,76 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw return False; } - /* Verify in system password file... - FIXME!!! This is where we should look up an internal - mapping of allocated uid for machine accounts as well - --jerry */ - pwfile = getpwnam_alloc(pw_buf->smb_name); - if (pwfile == NULL) { - DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s not in unix passwd database!\n", pw_buf->smb_name)); - return False; - } - - pdb_set_uid (sam_pass, pwfile->pw_uid); - pdb_set_gid (sam_pass, pwfile->pw_gid); + if ((smbpasswd_state->permit_non_unix_accounts) + && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid) + && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) { + + pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pw_buf->smb_userid)); + + /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. + + This was down the bottom for machines, but it looks pretty good as + a general default for non-unix users. --abartlet 2002-01-08 + */ + pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); - pdb_set_fullname(sam_pass, pwfile->pw_gecos); - - pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid)); + } else { - { - uint32 rid; + uint32 grid; GROUP_MAP map; + /* Verify in system password file... + FIXME!!! This is where we should look up an internal + mapping of allocated uid for machine accounts as well + --jerry */ + pwfile = getpwnam_alloc(pw_buf->smb_name); + if (pwfile == NULL) { + DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s not in unix passwd database!\n", pw_buf->smb_name)); + return False; + } + + pdb_set_uid (sam_pass, pwfile->pw_uid); + pdb_set_gid (sam_pass, pwfile->pw_gid); + + pdb_set_fullname(sam_pass, pwfile->pw_gecos); + + pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid)); + if (get_group_map_from_gid(pwfile->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &rid); + sid_peek_rid(&map.sid, &grid); + } else { + grid=pdb_gid_to_group_rid(pwfile->pw_gid); } - else - rid=pdb_gid_to_group_rid(pwfile->pw_gid); - pdb_set_group_rid(sam_pass, rid); + pdb_set_group_rid(sam_pass, grid); + + /* check if this is a user account or a machine account */ + if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') + { + pstring str; + + pstrcpy(str, lp_logon_path()); + standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); + pdb_set_profile_path(sam_pass, str, False); + + pstrcpy(str, lp_logon_home()); + standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); + pdb_set_homedir(sam_pass, str, False); + + pstrcpy(str, lp_logon_drive()); + standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); + pdb_set_dir_drive(sam_pass, str, False); + + pstrcpy(str, lp_logon_script()); + standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); + pdb_set_logon_script(sam_pass, str, False); + + } else { + /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ + /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */ + } + + passwd_free(&pwfile); } pdb_set_username (sam_pass, pw_buf->smb_name); @@ -1243,84 +1314,61 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw */ pdb_set_pass_must_change_time (sam_pass, pw_buf->pass_last_set_time + MAX_PASSWORD_AGE); #endif - /* check if this is a user account or a machine account */ - if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') - { - pstring str; - - pstrcpy(str, lp_logon_path()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_profile_path(sam_pass, str, False); - - pstrcpy(str, lp_logon_home()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_homedir(sam_pass, str, False); - - pstrcpy(str, lp_logon_drive()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_dir_drive(sam_pass, str, False); - - pstrcpy(str, lp_logon_script()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_logon_script(sam_pass, str, False); - - } else { - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */ - } - - passwd_free(&pwfile); - return True; } + /***************************************************************** Functions to be implemented by the new passdb API ****************************************************************/ -BOOL pdb_setsampwent (BOOL update) +static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update) { - global_vp = startsmbfilepwent(lp_smb_passwd_file(), - update ? PWF_UPDATE : PWF_READ, - &pw_file_lock_depth); + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + + smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, + update ? PWF_UPDATE : PWF_READ, + &(smbpasswd_state->pw_file_lock_depth)); /* did we fail? Should we try to create it? */ - if (!global_vp && update && errno == ENOENT) + if (!smbpasswd_state->pw_file && update && errno == ENOENT) { FILE *fp; /* slprintf(msg_str,msg_str_len-1, - "smbpasswd file did not exist - attempting to create it.\n"); */ + "smbpasswd file did not exist - attempting to create it.\n"); */ DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n")); - fp = sys_fopen(lp_smb_passwd_file(), "w"); + fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w"); if (fp) { fprintf(fp, "# Samba SMB password file\n"); fclose(fp); } - global_vp = startsmbfilepwent(lp_smb_passwd_file(), - update ? PWF_UPDATE : PWF_READ, - &pw_file_lock_depth); + smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, + update ? PWF_UPDATE : PWF_READ, + &(smbpasswd_state->pw_file_lock_depth)); } - return (global_vp != NULL); + return (smbpasswd_state->pw_file != NULL); } -void pdb_endsampwent (void) +static void smbpasswd_endsampwent (struct pdb_context *context) { - endsmbfilepwent(global_vp, &pw_file_lock_depth); + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth)); } /***************************************************************** ****************************************************************/ -BOOL pdb_getsampwent(SAM_ACCOUNT *user) +static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) { + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; struct smb_passwd *pw_buf=NULL; BOOL done = False; DEBUG(5,("pdb_getsampwent\n")); if (user==NULL) { - DEBUG(5,("pdb_getsampwent: user is NULL\n")); + DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n")); #if 0 - smb_panic("NULL pointer passed to pdb_getsampwent\n"); + smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n"); #endif return False; } @@ -1328,18 +1376,18 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) while (!done) { /* do we have an entry? */ - pw_buf = getsmbfilepwent(global_vp); + pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file); if (pw_buf == NULL) return False; /* build the SAM_ACCOUNT entry from the smb_passwd struct. We loop in case the user in the pdb does not exist in the local system password file */ - if (build_sam_account(user, pw_buf)) + if (build_sam_account(smbpasswd_state, user, pw_buf)) done = True; } - DEBUG(5,("pdb_getsampwent:done\n")); + DEBUG(5,("getsampwent (smbpasswd): done\n")); /* success */ return True; @@ -1351,15 +1399,16 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) call getpwnam() for unix account information until we have found the correct entry ***************************************************************/ -BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) +static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username) { + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; struct smb_passwd *smb_pw; void *fp = NULL; char *domain = NULL; char *user = NULL; fstring name; - DEBUG(10, ("pdb_getsampwnam: search by name: %s\n", username)); + DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username)); /* break the username from the domain if we have @@ -1379,7 +1428,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) /* startsmbfilepwent() is used here as we don't want to lookup the UNIX account in the local system password file until we have a match. */ - fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth); + fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { DEBUG(0, ("unable to open passdb database.\n")); @@ -1391,20 +1440,20 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) if ( domain ) map_username(user); - while ( ((smb_pw=getsmbfilepwent(fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) ) + while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) ) /* do nothing....another loop */ ; - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); /* did we locate the username in smbpasswd */ if (smb_pw == NULL) return False; - DEBUG(10, ("pdb_getsampwnam: found by name: %s\n", smb_pw->smb_name)); + DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name)); if (!sam_acct) { - DEBUG(10,("pdb_getsampwnam:SAM_ACCOUNT is NULL\n")); + DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n")); #if 0 smb_panic("NULL pointer passed to pdb_getsampwnam\n"); #endif @@ -1412,7 +1461,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) } /* now build the SAM_ACCOUNT */ - if (!build_sam_account(sam_acct, smb_pw)) + if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw)) return False; /* success */ @@ -1420,35 +1469,36 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) } -BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct,uint32 rid) +static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct,uint32 rid) { + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; struct smb_passwd *smb_pw; void *fp = NULL; DEBUG(10, ("pdb_getsampwrid: search by rid: %d\n", rid)); /* Open the sam password file - not for update. */ - fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth); + fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { DEBUG(0, ("unable to open passdb database.\n")); return False; } - while ( ((smb_pw=getsmbfilepwent(fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) ) + while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) ) /* do nothing */ ; - endsmbfilepwent(fp, &pw_file_lock_depth); + endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); /* did we locate the username in smbpasswd */ if (smb_pw == NULL) return False; - DEBUG(10, ("pdb_getsampwrid: found by name: %s\n", smb_pw->smb_name)); + DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name)); if (!sam_acct) { - DEBUG(10,("pdb_getsampwrid:SAM_ACCOUNT is NULL\n")); + DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n")); #if 0 smb_panic("NULL pointer passed to pdb_getsampwrid\n"); #endif @@ -1456,15 +1506,16 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct,uint32 rid) } /* now build the SAM_ACCOUNT */ - if (!build_sam_account (sam_acct, smb_pw)) + if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw)) return False; /* success */ return True; } -BOOL pdb_add_sam_account(const SAM_ACCOUNT *sampass) +static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass) { + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ @@ -1473,15 +1524,16 @@ BOOL pdb_add_sam_account(const SAM_ACCOUNT *sampass) } /* add the entry */ - if(!add_smbfilepwd_entry(&smb_pw)) { + if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) { return False; } - + return True; } -BOOL pdb_update_sam_account(const SAM_ACCOUNT *sampass, BOOL override) +static BOOL smbpasswd_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass) { + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ @@ -1489,19 +1541,97 @@ BOOL pdb_update_sam_account(const SAM_ACCOUNT *sampass, BOOL override) return False; /* update the entry */ - if(!mod_smbfilepwd_entry(&smb_pw, override)) + if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) return False; return True; } -BOOL pdb_delete_sam_account (const char* username) +static BOOL smbpasswd_delete_sam_account (struct pdb_context *context, const SAM_ACCOUNT *sampass) { - return del_smbfilepwd_entry(username); + struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data; + + const char *username = pdb_get_username(sampass); + + return del_smbfilepwd_entry(smbpasswd_state, username); +} + +static void free_private_data(void **vp) +{ + struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp; + + endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth)); + + *privates = NULL; + /* No need to free any further, as it is talloc()ed */ } -#else - /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */ - void smbpass_dummy_function(void) { } /* stop some compilers complaining */ -#endif /* WTH_SMBPASSWD_SAM*/ +NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct smbpasswd_privates *privates; + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->setsampwent = smbpasswd_setsampwent; + (*pdb_method)->endsampwent = smbpasswd_endsampwent; + (*pdb_method)->getsampwent = smbpasswd_getsampwent; + (*pdb_method)->getsampwnam = smbpasswd_getsampwnam; + (*pdb_method)->getsampwrid = smbpasswd_getsampwrid; + (*pdb_method)->add_sam_account = smbpasswd_add_sam_account; + (*pdb_method)->update_sam_account = smbpasswd_update_sam_account; + (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account; + + /* Setup private data and free function */ + + privates = talloc_zero(pdb_context->mem_ctx, sizeof(struct smbpasswd_privates)); + + if (!privates) { + DEBUG(0, ("talloc() failed for smbpasswd private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* Store some config details */ + + if (location) { + privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location); + } else { + privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file()); + } + + if (!privates->smbpasswd_file) { + DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n")); + return NT_STATUS_NO_MEMORY; + } + + (*pdb_method)->private_data = privates; + + + (*pdb_method)->free_private_data = free_private_data; + + return NT_STATUS_OK; +} + +NTSTATUS pdb_init_smbpasswd_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct smbpasswd_privates *privates; + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_smbpasswd(pdb_context, pdb_method, location))) { + return nt_status; + } + + privates = (*pdb_method)->private_data; + + privates->permit_non_unix_accounts = True; + + if (!lp_non_unix_account_range(&privates->low_nua_userid, &privates->high_nua_userid)) { + DEBUG(0, ("cannot use smbpasswd_nua without 'non unix account range' in smb.conf!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index b33e684c7a..0e0bf541e3 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -4,6 +4,7 @@ * Copyright (C) Simo Sorce 2000 * Copyright (C) Gerald Carter 2000 * Copyright (C) Jeremy Allison 2001 + * Copyright (C) Andrew Bartlett 2002 * * 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 @@ -30,21 +31,25 @@ #define USERPREFIX "USER_" #define RIDPREFIX "RID_" -extern int DEBUGLEVEL; - -struct tdb_enum_info { +struct tdbsam_privates { TDB_CONTEXT *passwd_tdb; TDB_DATA key; -}; -static struct tdb_enum_info global_tdb_ent; -/*static SAM_ACCOUNT global_sam_pass;*/ + /* retrive-once info */ + const char *tdbsam_location; + + BOOL permit_non_unix_accounts; + + uint32 low_nua_rid; + uint32 high_nua_rid; +}; /********************************************************************** Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len *********************************************************************/ -static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) +static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, + SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { /* times are stored as 32bit integer @@ -150,8 +155,6 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 bufle goto done; } - /*pdb_set_uid(sampass, uid); - pdb_set_gid(sampass, gid);*/ pdb_set_user_rid(sampass, user_rid); pdb_set_group_rid(sampass, group_rid); pdb_set_unknown_3(sampass, unknown_3); @@ -162,6 +165,28 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 bufle pdb_set_logon_divs(sampass, logon_divs); pdb_set_hours(sampass, hours); + if ((tdb_state->permit_non_unix_accounts) + && (pdb_get_user_rid(sampass) >= tdb_state->low_nua_rid) + && (pdb_get_user_rid(sampass) <= tdb_state->high_nua_rid)) { + + } else { + struct passwd *pw; + /* validate the account and fill in UNIX uid and gid. sys_getpwnam() + is used instaed of Get_Pwnam() as we do not need to try case + permutations */ + + if ((pw=getpwnam_alloc(pdb_get_username(sampass))) == NULL) { + DEBUG(0,("init_sam_from_buffer: (tdbsam) getpwnam(%s) return NULL. User does not exist!\n", + pdb_get_username(sampass))); + return False; + } + + pdb_set_uid(sampass, pw->pw_uid); + pdb_set_gid(sampass, pw->pw_gid); + + passwd_free(&pw); + } + done: SAFE_FREE(username); @@ -182,7 +207,8 @@ done: /********************************************************************** Intialize a BYTE buffer from a SAM_ACCOUNT struct *********************************************************************/ -static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass) +static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state, uint8 **buf, + const SAM_ACCOUNT *sampass, uint32 user_rid, uint32 group_rid) { size_t len, buflen; @@ -321,8 +347,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass) workstations_len, workstations, unknown_str_len, unknown_str, munged_dial_len, munged_dial, - pdb_get_user_rid(sampass), - pdb_get_group_rid(sampass), + user_rid, + group_rid, lm_pw_len, lm_pw, nt_pw_len, nt_pw, pdb_get_acct_ctrl(sampass), @@ -360,8 +386,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass) workstations_len, workstations, unknown_str_len, unknown_str, munged_dial_len, munged_dial, - pdb_get_user_rid(sampass), - pdb_get_group_rid(sampass), + user_rid, + group_rid, lm_pw_len, lm_pw, nt_pw_len, nt_pw, pdb_get_acct_ctrl(sampass), @@ -375,6 +401,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass) /* check to make sure we got it correct */ if (buflen != len) { + DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", + buflen, len)); /* error */ SAFE_FREE (*buf); return (-1); @@ -387,35 +415,38 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass) Open the TDB passwd database for SAM account enumeration. ****************************************************************/ -BOOL pdb_setsampwent(BOOL update) +static BOOL tdbsam_setsampwent(struct pdb_context *context, BOOL update) { - pstring tdbfile; - - get_private_directory(tdbfile); - pstrcat (tdbfile, PASSDB_FILE_NAME); + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; /* Open tdb passwd */ - if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600))) + if (!(tdb_state->passwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600))) { DEBUG(0, ("Unable to open/create TDB passwd\n")); return False; } - global_tdb_ent.key = tdb_firstkey(global_tdb_ent.passwd_tdb); + tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb); return True; } +static void close_tdb(struct tdbsam_privates *tdb_state) +{ + if (tdb_state->passwd_tdb) { + tdb_close(tdb_state->passwd_tdb); + tdb_state->passwd_tdb = NULL; + } +} + /*************************************************************** End enumeration of the TDB passwd list. ****************************************************************/ -void pdb_endsampwent(void) +static void tdbsam_endsampwent(struct pdb_context *context) { - if (global_tdb_ent.passwd_tdb) { - tdb_close(global_tdb_ent.passwd_tdb); - global_tdb_ent.passwd_tdb = NULL; - } + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; + close_tdb(tdb_state); DEBUG(7, ("endtdbpwent: closed sam database.\n")); } @@ -424,17 +455,13 @@ void pdb_endsampwent(void) Get one SAM_ACCOUNT from the TDB (next in line) *****************************************************************/ -BOOL pdb_getsampwent(SAM_ACCOUNT *user) +static BOOL tdbsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) { + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; TDB_DATA data; - struct passwd *pw; - uid_t uid; - gid_t gid; char *prefix = USERPREFIX; int prefixlen = strlen (prefix); - const char *sam_user; - pstring sam_subst; if (user==NULL) { DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n")); @@ -442,62 +469,32 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) } /* skip all non-USER entries (eg. RIDs) */ - while ((global_tdb_ent.key.dsize != 0) && (strncmp(global_tdb_ent.key.dptr, prefix, prefixlen))) + while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) /* increment to next in line */ - global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key); + tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key); /* do we have an valid interation pointer? */ - if(global_tdb_ent.passwd_tdb == NULL) { + if(tdb_state->passwd_tdb == NULL) { DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n")); return False; } - data = tdb_fetch(global_tdb_ent.passwd_tdb, global_tdb_ent.key); + data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key); if (!data.dptr) { DEBUG(5,("pdb_getsampwent: database entry not found.\n")); return False; } /* unpack the buffer */ - if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); return False; } SAFE_FREE(data.dptr); - /* validate the account and fill in UNIX uid and gid. sys_getpwnam() - is used instaed of Get_Pwnam() as we do not need to try case - permutations */ - if ((pw=getpwnam_alloc(pdb_get_username(user))) == NULL) { - DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n", - pdb_get_username(user))); - return False; - } - - uid = pw->pw_uid; - gid = pw->pw_gid; - pdb_set_uid(user, uid); - pdb_set_gid(user, gid); - - passwd_free(&pw); - - /* 21 days from present */ - pdb_set_pass_must_change_time(user, time(NULL)+1814400); - - sam_user = pdb_get_username(user); - pstrcpy(sam_subst, pdb_get_logon_script(user)); - standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst); - if (!pdb_set_logon_script(user, sam_subst, True)) return False; - pstrcpy(sam_subst, pdb_get_profile_path(user)); - standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst); - if (!pdb_set_profile_path(user, sam_subst, True)) return False; - pstrcpy(sam_subst, pdb_get_homedir(user)); - standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst); - if (!pdb_set_homedir(user, sam_subst, True)) return False; - /* increment to next in line */ - global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key); + tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key); return True; } @@ -506,19 +503,13 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) Lookup a name in the SAM TDB ******************************************************************/ -BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname) +static BOOL tdbsam_getsampwnam (struct pdb_context *context, SAM_ACCOUNT *user, const char *sname) { + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; TDB_CONTEXT *pwd_tdb; TDB_DATA data, key; fstring keystr; - struct passwd *pw; - pstring tdbfile; fstring name; - uid_t uid; - gid_t gid; - - const char *sam_user; - pstring sam_subst; if (user==NULL) { DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n")); @@ -528,17 +519,14 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname) /* Data is stored in all lower-case */ unix_strlower(sname, -1, name, sizeof(name)); - get_private_directory(tdbfile); - pstrcat(tdbfile, PASSDB_FILE_NAME); - /* set search key */ slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name); key.dptr = keystr; key.dsize = strlen(keystr) + 1; /* open the accounts TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) { - DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd!\n")); + if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) { + DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location)); return False; } @@ -547,12 +535,13 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname) if (!data.dptr) { DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); + DEBUGADD(5, (" Key: %s\n", keystr)); tdb_close(pwd_tdb); return False; } /* unpack the buffer */ - if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); tdb_close(pwd_tdb); @@ -563,37 +552,6 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname) /* no further use for database, close it now */ tdb_close(pwd_tdb); - /* validate the account and fill in UNIX uid and gid. sys_getpwnam() - is used instead of Get_Pwnam() as we do not need to try case - permutations */ - if ((pw=getpwnam_alloc(pdb_get_username(user)))) { - uid = pw->pw_uid; - gid = pw->pw_gid; - pdb_set_uid(user, uid); - pdb_set_gid(user, gid); - - /* 21 days from present */ - pdb_set_pass_must_change_time(user, time(NULL)+1814400); - - sam_user = pdb_get_username(user); - pstrcpy(sam_subst, pdb_get_logon_script(user)); - standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst); - if (!pdb_set_logon_script(user, sam_subst, True)) return False; - pstrcpy(sam_subst, pdb_get_profile_path(user)); - standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst); - if (!pdb_set_profile_path(user, sam_subst, True)) return False; - pstrcpy(sam_subst, pdb_get_homedir(user)); - standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst); - if (!pdb_set_homedir(user, sam_subst, True)) return False; - } - else { - DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n", - pdb_get_username(user))); - return False; - } - - passwd_free(&pw); - return True; } @@ -601,12 +559,12 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname) Search by rid **************************************************************************/ -BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) +static BOOL tdbsam_getsampwrid (struct pdb_context *context, SAM_ACCOUNT *user, uint32 rid) { + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; TDB_CONTEXT *pwd_tdb; TDB_DATA data, key; fstring keystr; - pstring tdbfile; fstring name; if (user==NULL) { @@ -614,16 +572,13 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) return False; } - get_private_directory(tdbfile); - pstrcat (tdbfile, PASSDB_FILE_NAME); - /* set search key */ slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid); key.dptr = keystr; key.dsize = strlen (keystr) + 1; /* open the accounts TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) { + if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) { DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n")); return False; } @@ -642,30 +597,26 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) tdb_close (pwd_tdb); - return pdb_getsampwnam (user, name); + return tdbsam_getsampwnam (context, user, name); } /*************************************************************************** Delete a SAM_ACCOUNT ****************************************************************************/ -BOOL pdb_delete_sam_account(const char *sname) +static BOOL tdbsam_delete_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sam_pass) { - SAM_ACCOUNT *sam_pass = NULL; + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; TDB_CONTEXT *pwd_tdb; - TDB_DATA key, data; + TDB_DATA key; fstring keystr; - pstring tdbfile; uint32 rid; fstring name; - unix_strlower(sname, -1, name, sizeof(name)); + unix_strlower(pdb_get_username(sam_pass), -1, name, sizeof(name)); - get_private_directory(tdbfile); - pstrcat (tdbfile, PASSDB_FILE_NAME); - /* open the TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) { + if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR, 0600))) { DEBUG(0, ("Unable to open TDB passwd!")); return False; } @@ -675,33 +626,8 @@ BOOL pdb_delete_sam_account(const char *sname) key.dptr = keystr; key.dsize = strlen (keystr) + 1; - /* get the record */ - data = tdb_fetch (pwd_tdb, key); - if (!data.dptr) { - DEBUG(5,("pdb_delete_sam_account (TDB): error fetching database.\n")); - DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); - tdb_close (pwd_tdb); - return False; - } - - /* unpack the buffer */ - if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pass))) { - tdb_close (pwd_tdb); - return False; - } - - if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) { - DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); - tdb_close (pwd_tdb); - SAFE_FREE(data.dptr); - return False; - } - SAFE_FREE(data.dptr); - rid = pdb_get_user_rid(sam_pass); - pdb_free_sam (&sam_pass); - /* it's outaa here! 8^) */ if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) { DEBUG(5, ("Error deleting entry from tdb passwd database!\n")); @@ -734,27 +660,62 @@ BOOL pdb_delete_sam_account(const char *sname) Update the TDB SAM ****************************************************************************/ -static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag) +static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpwd, int flag) { + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data; TDB_CONTEXT *pwd_tdb = NULL; TDB_DATA key, data; uint8 *buf = NULL; fstring keystr; - pstring tdbfile; fstring name; BOOL ret = True; - - get_private_directory(tdbfile); - pstrcat (tdbfile, PASSDB_FILE_NAME); - - /* if we don't have a RID, then FAIL */ - if (!pdb_get_user_rid(newpwd)) - DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd))); - if (!pdb_get_group_rid(newpwd)) - DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd))); + uint32 user_rid; + uint32 group_rid; + int32 tdb_ret; + + /* invalidate the existing TDB iterator if it is open */ + if (tdb_state->passwd_tdb) { + tdb_close(tdb_state->passwd_tdb); + tdb_state->passwd_tdb = NULL; + } + + /* open the account TDB passwd*/ + pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600); + if (!pwd_tdb) + { + DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location)); + return False; + } + + /* if we don't have a RID, then make them up. */ + if (!(user_rid = pdb_get_user_rid(newpwd))) { + if (!tdb_state->permit_non_unix_accounts) { + DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd))); + ret = False; + goto done; + } else { + user_rid = tdb_state->low_nua_rid; + tdb_ret = tdb_change_int32_atomic(pwd_tdb, "NUA_NEXT_RID", &user_rid, RID_MULTIPLIER); + if (tdb_ret == -1) { + ret = False; + goto done; + } + } + } + + if (!(group_rid = pdb_get_group_rid(newpwd))) { + if (!tdb_state->permit_non_unix_accounts) { + DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd))); + ret = False; + goto done; + } else { + /* This seems like a good default choice for non-unix users */ + group_rid = DOMAIN_GROUP_RID_USERS; + } + } /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */ - if ((data.dsize=init_buffer_from_sam (&buf, newpwd)) == -1) { + if ((data.dsize=init_buffer_from_sam (tdb_state, &buf, newpwd, user_rid, group_rid)) == -1) { DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n")); ret = False; goto done; @@ -763,29 +724,18 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag) unix_strlower(pdb_get_username(newpwd), -1, name, sizeof(name)); + DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid)); + /* setup the USER index key */ slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name); key.dptr = keystr; key.dsize = strlen (keystr) + 1; - /* invalidate the existing TDB iterator if it is open */ - if (global_tdb_ent.passwd_tdb) { - tdb_close(global_tdb_ent.passwd_tdb); - global_tdb_ent.passwd_tdb = NULL; - } - - /* open the account TDB passwd*/ - pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600); - if (!pwd_tdb) - { - DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n")); - return False; - } - /* add the account */ if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) { DEBUG(0, ("Unable to modify passwd TDB!")); - DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb))); + DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb))); + DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr)); ret = False; goto done; } @@ -795,7 +745,7 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag) data.dptr = name; /* setup the RID index key */ - slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd)); + slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid); key.dptr = keystr; key.dsize = strlen (keystr) + 1; @@ -803,6 +753,7 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag) if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) { DEBUG(0, ("Unable to modify TDB passwd !")); DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb))); + DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr)); ret = False; goto done; } @@ -819,21 +770,113 @@ done: Modifies an existing SAM_ACCOUNT ****************************************************************************/ -BOOL pdb_update_sam_account (const SAM_ACCOUNT *newpwd, BOOL override) +static BOOL tdbsam_update_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd) { - return (tdb_update_sam(newpwd, override, TDB_MODIFY)); + return (tdb_update_sam(context, newpwd, TDB_MODIFY)); } /*************************************************************************** Adds an existing SAM_ACCOUNT ****************************************************************************/ -BOOL pdb_add_sam_account (const SAM_ACCOUNT *newpwd) +static BOOL tdbsam_add_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd) +{ + return (tdb_update_sam(context, newpwd, TDB_INSERT)); +} + +static void free_private_data(void **vp) { - return (tdb_update_sam(newpwd, True, TDB_INSERT)); + struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp; + close_tdb(*tdb_state); + *tdb_state = NULL; + + /* No need to free any further, as it is talloc()ed */ } + +NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct tdbsam_privates *tdb_state; + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->setsampwent = tdbsam_setsampwent; + (*pdb_method)->endsampwent = tdbsam_endsampwent; + (*pdb_method)->getsampwent = tdbsam_getsampwent; + (*pdb_method)->getsampwnam = tdbsam_getsampwnam; + (*pdb_method)->getsampwrid = tdbsam_getsampwrid; + (*pdb_method)->add_sam_account = tdbsam_add_sam_account; + (*pdb_method)->update_sam_account = tdbsam_update_sam_account; + (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account; + + /* TODO: Setup private data and free */ + + tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates)); + + if (!tdb_state) { + DEBUG(0, ("talloc() failed for tdbsam private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (location) { + tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location); + } else { + pstring tdbfile; + get_private_directory(tdbfile); + pstrcat (tdbfile, PASSDB_FILE_NAME); + tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile); + } + + (*pdb_method)->private_data = tdb_state; + + (*pdb_method)->free_private_data = free_private_data; + + return NT_STATUS_OK; +} + +NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct tdbsam_privates *tdb_state; + uint32 low_nua_uid, high_nua_uid; + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_tdbsam(pdb_context, pdb_method, location))) { + return nt_status; + } + + tdb_state = (*pdb_method)->private_data; + + tdb_state->permit_non_unix_accounts = True; + + if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) { + DEBUG(0, ("cannot use tdbsam_nua without 'non unix account range' in smb.conf!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + tdb_state->low_nua_rid=pdb_uid_to_user_rid(low_nua_uid); + + tdb_state->high_nua_rid=pdb_uid_to_user_rid(high_nua_uid); + + return NT_STATUS_OK; +} + + #else - /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */ - void samtdb_dummy_function(void) { } /* stop some compilers complaining */ -#endif /* WITH_TDB_SAM */ + +NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + DEBUG(0, ("tdbsam not compiled in!\n")); + return NT_STATUS_UNSUCCESSFUL; +} + +NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + DEBUG(0, ("tdbsam_nua not compiled in!\n")); + return NT_STATUS_UNSUCCESSFUL; +} + + +#endif diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 1ae1b65fdd..077dbb0e2b 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -410,6 +410,11 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET * return NT_STATUS_NO_SUCH_USER; } + if (!(pdb_get_acct_ctrl(sampass) & ACB_DISABLED)) { + pdb_free_sam(&sampass); + return NT_STATUS_ACCOUNT_DISABLED; + } + DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < 16; i++) DEBUG(100,("%02X ", q_u->pwd[i])); @@ -441,7 +446,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET * } become_root(); - ret = pdb_update_sam_account (sampass,False); + ret = pdb_update_sam_account (sampass); unbecome_root(); if (ret) diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index cf9be78f3d..d079403455 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1869,9 +1869,6 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ { SAM_ACCOUNT *sam_pass=NULL; fstring account; - pstring err_str; - pstring msg_str; - int local_flags=0; DOM_SID sid; pstring add_script; POLICY_HND dom_pol = q_u->domain_pol; @@ -1880,6 +1877,8 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ POLICY_HND *user_pol = &r_u->user_pol; struct samr_info *info = NULL; BOOL ret; + NTSTATUS nt_status; + struct passwd *pw; /* find the policy handle. open a policy on it. */ if (!find_policy_by_hnd(p, &dom_pol, NULL)) @@ -1905,8 +1904,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ return NT_STATUS_USER_EXISTS; } - local_flags=LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_SET_NO_PASSWORD; - local_flags|= (acb_info & ACB_WSTRUST) ? LOCAL_TRUST_ACCOUNT:0; + pdb_free_sam(&sam_pass); /* * NB. VERY IMPORTANT ! This call must be done as the current pipe user, @@ -1955,32 +1953,54 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ pstrcpy(add_script, lp_adduser_script()); if(*add_script) { - int add_ret; - all_string_sub(add_script, "%u", account, sizeof(account)); - add_ret = smbrun(add_script,NULL); - DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n",add_script,add_ret)); - } + int add_ret; + all_string_sub(add_script, "%u", account, sizeof(account)); + add_ret = smbrun(add_script,NULL); + DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); + } + + pw = getpwnam_alloc(account); - /* add the user in the smbpasswd file or the Samba authority database */ - if (!local_password_change(account, local_flags, NULL, err_str, - sizeof(err_str), msg_str, sizeof(msg_str))) { - DEBUG(0, ("%s\n", err_str)); - pdb_free_sam(&sam_pass); - return NT_STATUS_ACCESS_DENIED; + if (pw) { + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sam_pass, pw))) { + passwd_free(&pw); + return nt_status; + } + passwd_free(&pw); /* done with this now */ + } else { + DEBUG(3,("attempting to create non-unix account %s\n", account)); + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sam_pass))) { + return nt_status; + } + + if (!pdb_set_username(sam_pass, account)) { + pdb_free_sam(&sam_pass); + return NT_STATUS_NO_MEMORY; + } } - become_root(); - ret = pdb_getsampwnam(sam_pass, account); - unbecome_root(); - if (ret == False) { - /* account doesn't exist: say so */ - pdb_free_sam(&sam_pass); - return NT_STATUS_ACCESS_DENIED; - } + pdb_set_acct_ctrl(sam_pass, acb_info); + + if (!pdb_add_sam_account(sam_pass)) { + pdb_free_sam(&sam_pass); + DEBUG(0, ("could not add user/computer %s to passdb. Check permissions?\n", + account)); + return NT_STATUS_ACCESS_DENIED; + } - /* Get the domain SID stored in the domain policy */ - if(!get_lsa_policy_samr_sid(p, &dom_pol, &sid)) { - pdb_free_sam(&sam_pass); + pdb_reset_sam(sam_pass); + + if (!pdb_getsampwnam(sam_pass, account)) { + pdb_free_sam(&sam_pass); + DEBUG(0, ("could not find user/computer %s just added to passdb?!?\n", + account)); + return NT_STATUS_ACCESS_DENIED; + } + + /* Get the domain SID stored in the domain policy */ + if(!get_lsa_policy_samr_sid(p, &dom_pol, &sid)) { + pdb_free_sam(&sam_pass); return NT_STATUS_INVALID_HANDLE; } @@ -2214,7 +2234,7 @@ static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, uint32 rid) return False; } - if(!pdb_update_sam_account(pwd, True)) { + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; } @@ -2258,7 +2278,7 @@ static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, uint32 rid) return False; } - if(!pdb_update_sam_account(pwd, True)) { + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; } @@ -2297,7 +2317,7 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid) */ /* write the change out */ - if(!pdb_update_sam_account(pwd, True)) { + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; } @@ -2330,6 +2350,9 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid) return False; } + DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n", + pdb_get_username(pwd))); + acct_ctrl = pdb_get_acct_ctrl(pwd); copy_id23_to_sam_passwd(pwd, id23); @@ -2345,10 +2368,11 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid) } /* if it's a trust account, don't update /etc/passwd */ - if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || - ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || - ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { - DEBUG(5, ("Changing trust account password, not updating /etc/passwd\n")); + if ( (!IS_SAM_UNIX_USER(pwd)) || + ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || + ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || + ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { + DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n")); } else { /* update the UNIX password */ if (lp_unix_password_sync() ) @@ -2360,7 +2384,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid) ZERO_STRUCT(plaintext_buf); - if(!pdb_update_sam_account(pwd, True)) { + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; } @@ -2388,6 +2412,9 @@ static BOOL set_user_info_pw(char *pass, uint32 rid) return False; } + DEBUG(5, ("Attempting administrator password change for user %s\n", + pdb_get_username(pwd))); + acct_ctrl = pdb_get_acct_ctrl(pwd); ZERO_STRUCT(plaintext_buf); @@ -2403,25 +2430,27 @@ static BOOL set_user_info_pw(char *pass, uint32 rid) } /* if it's a trust account, don't update /etc/passwd */ - if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || - ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || - ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { - DEBUG(5, ("Changing trust account password, not updating /etc/passwd\n")); + if ( (!IS_SAM_UNIX_USER(pwd)) || + ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || + ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || + ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { + DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n")); } else { /* update the UNIX password */ - if (lp_unix_password_sync()) + if (lp_unix_password_sync()) { if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) { pdb_free_sam(&pwd); return False; } + } } ZERO_STRUCT(plaintext_buf); - DEBUG(5,("set_user_info_pw: pdb_update_sam_account()\n")); + DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n")); /* update the SAMBA password */ - if(!pdb_update_sam_account(pwd, True)) { + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; } @@ -2442,7 +2471,6 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE POLICY_HND *pol = &q_u->pol; uint16 switch_value = q_u->switch_value; SAM_USERINFO_CTR *ctr = q_u->ctr; - BOOL ret; DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__)); @@ -3052,7 +3080,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM smb_delete_user(pdb_get_username(sam_pass)); /* and delete the samba side */ - if (!pdb_delete_sam_account(pdb_get_username(sam_pass))) { + if (!pdb_delete_sam_account(sam_pass)) { DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass))); pdb_free_sam(&sam_pass); return NT_STATUS_CANNOT_DELETE; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5e646b6225..9a30838cac 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -718,7 +718,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar * pass1, /* Now flush the sam_passwd struct to persistent storage */ become_root(); - ret = pdb_update_sam_account (sampass, False); + ret = pdb_update_sam_account (sampass); unbecome_root(); return ret; @@ -928,7 +928,7 @@ BOOL change_oem_password(SAM_ACCOUNT *hnd, char *new_passwd) /* Now write it into the file. */ become_root(); - ret = pdb_update_sam_account (hnd, False); + ret = pdb_update_sam_account (hnd); unbecome_root(); return ret; diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index 87dabf165d..9ca4430136 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -481,7 +481,7 @@ static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) the samba DEBUG() system. ****************************************************************************/ -TDB_CONTEXT *tdb_open_log(char *name, int hash_size, int tdb_flags, +TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) { TDB_CONTEXT *tdb; diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index ae600f6a6a..33b62ebd42 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -21,14 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* base uid for trust accounts is set to 60000 ! - * May be we should add the defines in smb.h to make it possible having - * different values on different platforms? - */ - -#define BASE_MACHINE_UID 60000 -#define MAX_MACHINE_UID 65500 /* 5500 trust accounts aren't enough? */ - #include "includes.h" extern pstring global_myname; @@ -213,7 +205,7 @@ static int set_user_info (char *username, char *fullname, char *homedir, char *d if (profile) pdb_set_profile_path (sam_pwent, profile, True); - if (pdb_update_sam_account (sam_pwent, True)) + if (pdb_update_sam_account (sam_pwent)) print_user_info (username, True, False); else { fprintf (stderr, "Unable to modify entry!\n"); @@ -284,10 +276,8 @@ static int new_user (char *username, char *fullname, char *homedir, char *drive, static int new_machine (char *machinename) { SAM_ACCOUNT *sam_pwent=NULL; - SAM_ACCOUNT *sam_trust=NULL; char name[16]; char *password = NULL; - uid_t uid; pdb_init_sam (&sam_pwent); @@ -304,23 +294,6 @@ static int new_machine (char *machinename) pdb_set_username (sam_pwent, name); - for (uid=BASE_MACHINE_UID; uid<=MAX_MACHINE_UID; uid++) { - pdb_init_sam (&sam_trust); - if (pdb_getsampwrid (sam_trust, pdb_uid_to_user_rid (uid))) { - pdb_free_sam (&sam_trust); - } else { - break; - } - } - - if (uid>MAX_MACHINE_UID) { - fprintf (stderr, "No more free UIDs available to Machine accounts!\n"); - pdb_free_sam(&sam_pwent); - return -1; - } - - pdb_set_user_rid (sam_pwent,pdb_uid_to_user_rid (uid)); - pdb_set_group_rid (sam_pwent, pdb_gid_to_group_rid (BASE_MACHINE_UID)); pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST); if (pdb_add_sam_account (sam_pwent)) { @@ -340,7 +313,16 @@ static int new_machine (char *machinename) static int delete_user_entry (char *username) { - return pdb_delete_sam_account (username); + SAM_ACCOUNT *samaccount; + + pdb_init_sam(&samaccount); + + if (!pdb_getsampwnam(samaccount, username)) { + fprintf (stderr, "user %s does not exist in the passdb\n", username); + return -1; + } + + return pdb_delete_sam_account (samaccount); } /********************************************************* @@ -350,11 +332,20 @@ static int delete_user_entry (char *username) static int delete_machine_entry (char *machinename) { char name[16]; + SAM_ACCOUNT *samaccount; safe_strcpy (name, machinename, 16); if (name[strlen(name)] != '$') safe_strcat (name, "$", 16); - return pdb_delete_sam_account (name); + + pdb_init_sam(&samaccount); + + if (!pdb_getsampwnam(samaccount, name)) { + fprintf (stderr, "user %s does not exist in the passdb\n", name); + return -1; + } + + return pdb_delete_sam_account (samaccount); } /********************************************************* @@ -564,11 +555,6 @@ int main (int argc, char **argv) return 0; } - if(!initialize_password_db(True)) { - fprintf(stderr, "Can't setup password database vectors.\n"); - exit(1); - } - DEBUGLEVEL = 1; AllowDebugChange = False; @@ -578,6 +564,11 @@ int main (int argc, char **argv) exit(1); } + if(!initialize_password_db(True)) { + fprintf(stderr, "Can't setup password database vectors.\n"); + exit(1); + } + while ((ch = getopt(argc, argv, "ad:f:h:i:lmp:s:u:vwx")) != EOF) { switch(ch) { case 'a': diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 6a20e71d96..a4abca2ce6 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -575,11 +575,6 @@ int main(int argc, char **argv) setup_logging("smbpasswd", True); - if(!initialize_password_db(True)) { - fprintf(stderr, "Can't setup password database vectors.\n"); - exit(1); - } - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); diff --git a/testsuite/build_farm/basicsmb-domainsec-nt4.test b/testsuite/build_farm/basicsmb-domainsec-nt4.test index 933f8f9804..5bf3305516 100644 --- a/testsuite/build_farm/basicsmb-domainsec-nt4.test +++ b/testsuite/build_farm/basicsmb-domainsec-nt4.test @@ -6,15 +6,15 @@ fi test_joindomain_nt4() { - smbpasswd -a -m buildfarm$ + smbpasswd -L -a -m buildfarm$ - echo $prefix/bin/smbpasswd -L -j TESTWG - $prefix/bin/smbpasswd -L -j TESTWG + echo $prefix/bin/net rpc join oldstyle -S localhost + $prefix/bin/net rpc join oldstyle -S localhost status=$? if [ $status = 0 ]; then - echo "smbpasswd correctly joined the domain ($workgroup)" + echo "'net rpc join oldstyle' correctly joined the domain ($workgroup)" else - echo "smbpasswd failed to join the domain ($workgroup)! (status $status)" + echo "'net rpc join oldstyle' failed to join the domain ($workgroup)! (status $status)" return 1 fi return 0 diff --git a/testsuite/build_farm/basicsmb-domainsec.test b/testsuite/build_farm/basicsmb-domainsec.test index ff184c4c7f..5dd005a6ee 100644 --- a/testsuite/build_farm/basicsmb-domainsec.test +++ b/testsuite/build_farm/basicsmb-domainsec.test @@ -1,19 +1,16 @@ -if [ $whoami != "root" ]; then - exit 0; -fi . basicsmb.fns test_joindomain() { test_joindomain_password="$1" - echo "$prefix/bin/smbpasswd -L -j TESTWG -U $whoami%$test_join_domain_password" - $prefix/bin/smbpasswd -L -j TESTWG -U $whoami%$test_join_domain_password + echo "$prefix/bin/net rpc join -S localhost -U $whoami%$test_join_domain_password" + $prefix/bin/net rpc join -S localhost -U $whoami%$test_join_domain_password status=$? if [ $status = 0 ]; then - echo "smbpasswd correctly joined the domain ($workgroup)" + echo "'net rpc join' correctly joined the domain ($workgroup)" else - echo "smbpasswd failed to join the domain ($workgroup)! (status $status)" + echo "'net rpc join' failed to join the domain ($workgroup)! (status $status)" return 1 fi return 0 diff --git a/testsuite/build_farm/basicsmb.smb.conf.template b/testsuite/build_farm/basicsmb.smb.conf.template index ff837bbb09..8b75f299a2 100644 --- a/testsuite/build_farm/basicsmb.smb.conf.template +++ b/testsuite/build_farm/basicsmb.smb.conf.template @@ -17,6 +17,10 @@ panic action = echo bt | gdb PREFIX/sbin/smbd %d + passdb backend = smbpasswd_nua + + non unix account range = 10000-20000 + [test] path = PREFIX/testdir read only = no -- cgit